Merge "Revert "Fix potential OOB write in btm_read_remote_ext_features_complete"" into oc-mr1-dev am: c5cbe3c7fb am: 274af11d49

Change-Id: I1cbe42de33365dec1cd292ad8ed97c26a40eecce
diff --git a/Android.bp b/Android.bp
index fb0fdd9..49af99c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -3,8 +3,12 @@
     "build",
     "btif",
     "btcore",
+    "common",
     "audio_a2dp_hw",
+    "audio_bluetooth_hw",
+    "audio_hal_interface",
     "audio_hearing_aid_hw",
+    "gd",
     "hci",
     "utils",
     "device",
@@ -22,3 +26,10 @@
     "tools",
     "proto",
 ]
+
+filegroup {
+  name: "BluetoothTestConfigTemplate",
+  srcs: [
+    "AndroidTestTemplate.xml"
+  ]
+}
diff --git a/Android.mk b/Android.mk
deleted file mode 100644
index 5053e7d..0000000
--- a/Android.mk
+++ /dev/null
@@ -1 +0,0 @@
-include $(call all-subdir-makefiles)
diff --git a/AndroidTestTemplate.xml b/AndroidTestTemplate.xml
new file mode 100644
index 0000000..601be93
--- /dev/null
+++ b/AndroidTestTemplate.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 The Android Open Source Project
+
+     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.
+-->
+<configuration description="Runs {MODULE}.">
+  <option name="test-suite-tag" value="apct" />
+  <option name="test-suite-tag" value="apct-native" />
+  <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+    <option name="cleanup" value="true" />
+    <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+  </target_preparer>
+  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+    <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+    <option name="run-command" value="svc bluetooth disable" />
+  </target_preparer>
+  <target_preparer class="com.android.tradefed.targetprep.FolderSaver">
+    <option name="device-path" value="/data/vendor/ssrdump" />
+  </target_preparer>
+  <test class="com.android.tradefed.testtype.GTest" >
+    <option name="native-test-device-path" value="/data/local/tmp" />
+    <option name="module-name" value="{MODULE}" />
+    <option name="run-test-as" value="0" />
+  </test>
+</configuration>
diff --git a/BUILD.gn b/BUILD.gn
index 04c32a1..456fbeb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -39,10 +39,3 @@
     "//device:net_test_device",
   ]
 }
-
-group("test_tools") {
-  testonly = true
-  deps = [
-    "//tools/mcap_tool:mcap_tool"
-  ]
-}
diff --git a/OWNERS b/OWNERS
index 2ddc791..5596ce1 100644
--- a/OWNERS
+++ b/OWNERS
@@ -1,8 +1,12 @@
 set noparent
 
 # Project owners
-eisenbach@google.com
+zachoverflow@google.com
 apanicke@google.com
+cmanton@google.com
+hsz@google.com
 jpawlowski@google.com
 mylesgw@google.com
-pavlin@google.com
+optedoblivion@google.com
+siyuanh@google.com
+stng@google.com
diff --git a/PREUPLOAD.cfg b/PREUPLOAD.cfg
index 7fb1636..380216c 100644
--- a/PREUPLOAD.cfg
+++ b/PREUPLOAD.cfg
@@ -4,3 +4,6 @@
 [Builtin Hooks]
 clang_format = true
 
+[Hook Scripts]
+aosp_first = ${REPO_ROOT}/frameworks/base/tools/aosp/aosp_sha.sh ${PREUPLOAD_COMMIT} ".*$"
+
diff --git a/TEST_MAPPING b/TEST_MAPPING
new file mode 100644
index 0000000..5f6e378
--- /dev/null
+++ b/TEST_MAPPING
@@ -0,0 +1,81 @@
+{
+  "postsubmit" : [
+    {
+      "name" : "bluetooth_test_common"
+    },
+    {
+      "name" : "bluetoothtbd_test"
+    },
+    {
+      "name" : "net_test_audio_a2dp_hw"
+    },
+    {
+      "name" : "net_test_avrcp"
+    },
+    {
+      "name" : "net_test_btcore"
+    },
+    {
+      "name" : "net_test_btif"
+    },
+    {
+      "name" : "net_test_btif_profile_queue"
+    },
+    {
+      "name" : "net_test_btpackets"
+    },
+    {
+      "name" : "net_test_device"
+    },
+    {
+      "name" : "net_test_hci"
+    },
+    {
+      "name" : "net_test_performance"
+    },
+    {
+      "name" : "net_test_stack"
+    },
+    {
+      "name" : "net_test_stack_ad_parser"
+    },
+    {
+      "name" : "net_test_stack_multi_adv"
+    },
+    {
+      "name" : "net_test_stack_rfcomm"
+    },
+    {
+      "name" : "net_test_stack_smp"
+    },
+    {
+      "name" : "net_test_types"
+    }
+  ],
+  "presubmit" : [
+    {
+      "name" : "bluetooth_test_common",
+      "host" : true
+    },
+    {
+      "name" : "bluetoothtbd_test",
+      "host" : true
+    },
+    {
+      "name" : "net_test_avrcp",
+      "host" : true
+    },
+    {
+      "name" : "net_test_btcore",
+      "host" : true
+    },
+    {
+      "name" : "net_test_btpackets",
+      "host" : true
+    },
+    {
+      "name" : "net_test_types",
+      "host" : true
+    }
+  ]
+}
diff --git a/audio_a2dp_hw/src/audio_a2dp_hw.cc b/audio_a2dp_hw/src/audio_a2dp_hw.cc
index 0e1a3c2..2fb139f 100644
--- a/audio_a2dp_hw/src/audio_a2dp_hw.cc
+++ b/audio_a2dp_hw/src/audio_a2dp_hw.cc
@@ -700,8 +700,8 @@
       codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
       break;
     case AUDIO_FORMAT_PCM_8_24_BIT:
-    // FALLTHROUGH
-    // All 24-bit audio is expected in AUDIO_FORMAT_PCM_24_BIT_PACKED format
+      // All 24-bit audio is expected in AUDIO_FORMAT_PCM_24_BIT_PACKED format
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     default:
       ERROR("Invalid audio format: 0x%x", common->cfg.format);
       return -1;
diff --git a/audio_bluetooth_hw/Android.bp b/audio_bluetooth_hw/Android.bp
new file mode 100644
index 0000000..9cdd64a
--- /dev/null
+++ b/audio_bluetooth_hw/Android.bp
@@ -0,0 +1,50 @@
+// The format of the name is audio.<type>.<hardware/etc>.so
+
+cc_library_shared {
+    name: "audio.bluetooth.default",
+    relative_install_path: "hw",
+    proprietary: true,
+    srcs: [
+        "audio_bluetooth_hw.cc",
+        "stream_apis.cc",
+        "device_port_proxy.cc",
+        "utils.cc",
+    ],
+    header_libs: ["libhardware_headers"],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "libaudioutils",
+        "libbase",
+        "libbluetooth_audio_session",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
+}
+
+cc_test {
+    name: "audio_bluetooth_hw_test",
+    srcs: [
+        "utils.cc",
+        "utils_unittest.cc",
+    ],
+    shared_libs: [
+        "libbase",
+        "libcutils",
+        "liblog",
+        "libutils",
+    ],
+    cflags: [
+        "-Wall",
+        "-Werror",
+        "-Wno-unused-parameter",
+    ],
+}
diff --git a/audio_bluetooth_hw/audio_bluetooth_hw.cc b/audio_bluetooth_hw/audio_bluetooth_hw.cc
new file mode 100644
index 0000000..e32d88b
--- /dev/null
+++ b/audio_bluetooth_hw/audio_bluetooth_hw.cc
@@ -0,0 +1,140 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioHw"
+
+#include <android-base/logging.h>
+#include <errno.h>
+#include <hardware/audio.h>
+#include <hardware/hardware.h>
+#include <log/log.h>
+#include <malloc.h>
+#include <string.h>
+#include <system/audio.h>
+
+#include "stream_apis.h"
+#include "utils.h"
+
+static int adev_set_parameters(struct audio_hw_device* dev,
+                               const char* kvpairs) {
+  LOG(VERBOSE) << __func__ << ": kevpairs=[" << kvpairs << "]";
+  return -ENOSYS;
+}
+
+static char* adev_get_parameters(const struct audio_hw_device* dev,
+                                 const char* keys) {
+  LOG(VERBOSE) << __func__ << ": keys=[" << keys << "]";
+  return strdup("");
+}
+
+static int adev_init_check(const struct audio_hw_device* dev) { return 0; }
+
+static int adev_set_voice_volume(struct audio_hw_device* dev, float volume) {
+  LOG(VERBOSE) << __func__ << ": volume=" << volume;
+  return -ENOSYS;
+}
+
+static int adev_set_master_volume(struct audio_hw_device* dev, float volume) {
+  LOG(VERBOSE) << __func__ << ": volume=" << volume;
+  return -ENOSYS;
+}
+
+static int adev_get_master_volume(struct audio_hw_device* dev, float* volume) {
+  return -ENOSYS;
+}
+
+static int adev_set_master_mute(struct audio_hw_device* dev, bool muted) {
+  LOG(VERBOSE) << __func__ << ": mute=" << muted;
+  return -ENOSYS;
+}
+
+static int adev_get_master_mute(struct audio_hw_device* dev, bool* muted) {
+  return -ENOSYS;
+}
+
+static int adev_set_mode(struct audio_hw_device* dev, audio_mode_t mode) {
+  LOG(VERBOSE) << __func__ << ": mode=" << mode;
+  return 0;
+}
+
+static int adev_set_mic_mute(struct audio_hw_device* dev, bool state) {
+  LOG(VERBOSE) << __func__ << ": state=" << state;
+  return -ENOSYS;
+}
+
+static int adev_get_mic_mute(const struct audio_hw_device* dev, bool* state) {
+  return -ENOSYS;
+}
+
+static int adev_dump(const audio_hw_device_t* device, int fd) { return 0; }
+
+static int adev_close(hw_device_t* device) {
+  free(device);
+  return 0;
+}
+
+static int adev_open(const hw_module_t* module, const char* name,
+                     hw_device_t** device) {
+  LOG(VERBOSE) << __func__ << ": name=[" << name << "]";
+  if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
+
+  struct audio_hw_device* adev =
+      (struct audio_hw_device*)calloc(1, sizeof(struct audio_hw_device));
+  if (!adev) return -ENOMEM;
+
+  adev->common.tag = HARDWARE_DEVICE_TAG;
+  adev->common.version = AUDIO_DEVICE_API_VERSION_2_0;
+  adev->common.module = (struct hw_module_t*)module;
+  adev->common.close = adev_close;
+
+  adev->init_check = adev_init_check;
+  adev->set_voice_volume = adev_set_voice_volume;
+  adev->set_master_volume = adev_set_master_volume;
+  adev->get_master_volume = adev_get_master_volume;
+  adev->set_mode = adev_set_mode;
+  adev->set_mic_mute = adev_set_mic_mute;
+  adev->get_mic_mute = adev_get_mic_mute;
+  adev->set_parameters = adev_set_parameters;
+  adev->get_parameters = adev_get_parameters;
+  adev->get_input_buffer_size = adev_get_input_buffer_size;
+  adev->open_output_stream = adev_open_output_stream;
+  adev->close_output_stream = adev_close_output_stream;
+  adev->open_input_stream = adev_open_input_stream;
+  adev->close_input_stream = adev_close_input_stream;
+  adev->dump = adev_dump;
+  adev->set_master_mute = adev_set_master_mute;
+  adev->get_master_mute = adev_get_master_mute;
+
+  *device = &adev->common;
+  return 0;
+}
+
+static struct hw_module_methods_t hal_module_methods = {
+    .open = adev_open,
+};
+
+struct audio_module HAL_MODULE_INFO_SYM = {
+    .common =
+        {
+            .tag = HARDWARE_MODULE_TAG,
+            .module_api_version = AUDIO_MODULE_API_VERSION_0_1,
+            .hal_api_version = HARDWARE_HAL_API_VERSION,
+            .id = AUDIO_HARDWARE_MODULE_ID,
+            .name = "Bluetooth Audio HW HAL",
+            .author = "The Android Open Source Project",
+            .methods = &hal_module_methods,
+        },
+};
diff --git a/audio_bluetooth_hw/device_port_proxy.cc b/audio_bluetooth_hw/device_port_proxy.cc
new file mode 100644
index 0000000..6e1fda2
--- /dev/null
+++ b/audio_bluetooth_hw/device_port_proxy.cc
@@ -0,0 +1,445 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioHalDeviceProxy"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <audio_utils/primitives.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <stdlib.h>
+
+#include "BluetoothAudioSessionControl.h"
+#include "device_port_proxy.h"
+#include "stream_apis.h"
+#include "utils.h"
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+using ::android::base::StringPrintf;
+using ::android::bluetooth::audio::BluetoothAudioSessionControl;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+using ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using BluetoothAudioStatus =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+using ControlResultCallback = std::function<void(
+    uint16_t cookie, bool start_resp, const BluetoothAudioStatus& status)>;
+using SessionChangedCallback = std::function<void(uint16_t cookie)>;
+
+namespace {
+
+unsigned int SampleRateToAudioFormat(SampleRate sample_rate) {
+  switch (sample_rate) {
+    case SampleRate::RATE_16000:
+      return 16000;
+    case SampleRate::RATE_24000:
+      return 24000;
+    case SampleRate::RATE_44100:
+      return 44100;
+    case SampleRate::RATE_48000:
+      return 48000;
+    case SampleRate::RATE_88200:
+      return 88200;
+    case SampleRate::RATE_96000:
+      return 96000;
+    case SampleRate::RATE_176400:
+      return 176400;
+    case SampleRate::RATE_192000:
+      return 192000;
+    default:
+      return kBluetoothDefaultSampleRate;
+  }
+}
+audio_channel_mask_t ChannelModeToAudioFormat(ChannelMode channel_mode) {
+  switch (channel_mode) {
+    case ChannelMode::MONO:
+      return AUDIO_CHANNEL_OUT_MONO;
+    case ChannelMode::STEREO:
+      return AUDIO_CHANNEL_OUT_STEREO;
+    default:
+      return kBluetoothDefaultOutputChannelModeMask;
+  }
+}
+
+audio_format_t BitsPerSampleToAudioFormat(BitsPerSample bits_per_sample) {
+  switch (bits_per_sample) {
+    case BitsPerSample::BITS_16:
+      return AUDIO_FORMAT_PCM_16_BIT;
+    case BitsPerSample::BITS_24:
+      return AUDIO_FORMAT_PCM_24_BIT_PACKED;
+    case BitsPerSample::BITS_32:
+      return AUDIO_FORMAT_PCM_32_BIT;
+    default:
+      return kBluetoothDefaultAudioFormatBitsPerSample;
+  }
+}
+
+// The maximum time to wait in std::condition_variable::wait_for()
+constexpr unsigned int kMaxWaitingTimeMs = 4500;
+
+}  // namespace
+
+BluetoothAudioPortOut::BluetoothAudioPortOut()
+    : state_(BluetoothStreamState::DISABLED),
+      session_type_(SessionType::UNKNOWN),
+      cookie_(android::bluetooth::audio::kObserversCookieUndefined) {}
+
+bool BluetoothAudioPortOut::SetUp(audio_devices_t devices) {
+  if (!init_session_type(devices)) return false;
+
+  state_ = BluetoothStreamState::STANDBY;
+
+  auto control_result_cb = [port = this](uint16_t cookie, bool start_resp,
+                                         const BluetoothAudioStatus& status) {
+    if (!port->in_use()) {
+      LOG(ERROR) << "control_result_cb: BluetoothAudioPortOut is not in use";
+      return;
+    }
+    if (port->cookie_ != cookie) {
+      LOG(ERROR) << "control_result_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie)
+                 << ") is corrupted";
+      return;
+    }
+    port->ControlResultHandler(status);
+  };
+  auto session_changed_cb = [port = this](uint16_t cookie) {
+    if (!port->in_use()) {
+      LOG(ERROR) << "session_changed_cb: BluetoothAudioPortOut is not in use";
+      return;
+    }
+    if (port->cookie_ != cookie) {
+      LOG(ERROR) << "session_changed_cb: proxy of device port (cookie=" << StringPrintf("%#hx", cookie)
+                 << ") is corrupted";
+      return;
+    }
+    port->SessionChangedHandler();
+  };
+  ::android::bluetooth::audio::PortStatusCallbacks cbacks = {
+      .control_result_cb_ = control_result_cb,
+      .session_changed_cb_ = session_changed_cb};
+  cookie_ = BluetoothAudioSessionControl::RegisterControlResultCback(
+      session_type_, cbacks);
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
+
+  return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
+}
+
+bool BluetoothAudioPortOut::init_session_type(audio_devices_t device) {
+  switch (device) {
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP:
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES:
+    case AUDIO_DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER:
+      LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_BLUETOOTH_A2DP (HEADPHONES/SPEAKER) ("
+                   << StringPrintf("%#x", device) << ")";
+      session_type_ = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+      break;
+    case AUDIO_DEVICE_OUT_HEARING_AID:
+      LOG(VERBOSE) << __func__ << ": device=AUDIO_DEVICE_OUT_HEARING_AID (MEDIA/VOICE) (" << StringPrintf("%#x", device)
+                   << ")";
+      session_type_ = SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH;
+      break;
+    default:
+      LOG(ERROR) << __func__ << ": unknown device=" << StringPrintf("%#x", device);
+      return false;
+  }
+
+  if (!BluetoothAudioSessionControl::IsSessionReady(session_type_)) {
+    LOG(ERROR) << __func__ << ": device=" << StringPrintf("%#x", device) << ", session_type=" << toString(session_type_)
+               << " is not ready";
+    return false;
+  }
+  return true;
+}
+
+void BluetoothAudioPortOut::TearDown() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_) << " unknown monitor";
+    return;
+  }
+
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_);
+  BluetoothAudioSessionControl::UnregisterControlResultCback(session_type_,
+                                                             cookie_);
+  cookie_ = android::bluetooth::audio::kObserversCookieUndefined;
+}
+
+void BluetoothAudioPortOut::ControlResultHandler(
+    const BluetoothAudioStatus& status) {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return;
+  }
+  std::unique_lock<std::mutex> port_lock(cv_mutex_);
+  BluetoothStreamState previous_state = state_;
+  LOG(INFO) << "control_result_cb: session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state
+            << ", status=" << toString(status);
+
+  switch (previous_state) {
+    case BluetoothStreamState::STARTING:
+      if (status == BluetoothAudioStatus::SUCCESS) {
+        state_ = BluetoothStreamState::STARTED;
+      } else {
+        // Set to standby since the stack may be busy switching between outputs
+        LOG(WARNING) << "control_result_cb: status=" << toString(status)
+                     << " failure for session_type=" << toString(session_type_)
+                     << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
+        state_ = BluetoothStreamState::STANDBY;
+      }
+      break;
+    case BluetoothStreamState::SUSPENDING:
+      if (status == BluetoothAudioStatus::SUCCESS) {
+        state_ = BluetoothStreamState::STANDBY;
+      } else {
+        // It will be failed if the headset is disconnecting, and set to disable
+        // to wait for re-init again
+        LOG(WARNING) << "control_result_cb: status=" << toString(status)
+                     << " failure for session_type=" << toString(session_type_)
+                     << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
+        state_ = BluetoothStreamState::DISABLED;
+      }
+      break;
+    default:
+      LOG(ERROR) << "control_result_cb: unexpected status=" << toString(status)
+                 << " for session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+                 << ", previous_state=" << previous_state;
+      return;
+  }
+  port_lock.unlock();
+  internal_cv_.notify_all();
+}
+
+void BluetoothAudioPortOut::SessionChangedHandler() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return;
+  }
+  std::unique_lock<std::mutex> port_lock(cv_mutex_);
+  BluetoothStreamState previous_state = state_;
+  LOG(INFO) << "session_changed_cb: session_type=" << toString(session_type_)
+            << ", cookie=" << StringPrintf("%#hx", cookie_) << ", previous_state=" << previous_state;
+  if (previous_state != BluetoothStreamState::DISABLED) {
+    state_ = BluetoothStreamState::DISABLED;
+  } else {
+    state_ = BluetoothStreamState::STANDBY;
+  }
+  port_lock.unlock();
+  internal_cv_.notify_all();
+}
+
+bool BluetoothAudioPortOut::in_use() const {
+  return (cookie_ != android::bluetooth::audio::kObserversCookieUndefined);
+}
+
+bool BluetoothAudioPortOut::LoadAudioConfig(audio_config_t* audio_cfg) const {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
+    audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
+    audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
+    return false;
+  }
+
+  const AudioConfiguration& hal_audio_cfg =
+      BluetoothAudioSessionControl::GetAudioConfig(session_type_);
+  if (hal_audio_cfg.getDiscriminator() !=
+      AudioConfiguration::hidl_discriminator::pcmConfig) {
+    audio_cfg->sample_rate = kBluetoothDefaultSampleRate;
+    audio_cfg->channel_mask = kBluetoothDefaultOutputChannelModeMask;
+    audio_cfg->format = kBluetoothDefaultAudioFormatBitsPerSample;
+    return false;
+  }
+  const PcmParameters& pcm_cfg = hal_audio_cfg.pcmConfig();
+  LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", PcmConfig=["
+               << toString(pcm_cfg) << "]";
+  if (pcm_cfg.sampleRate == SampleRate::RATE_UNKNOWN ||
+      pcm_cfg.channelMode == ChannelMode::UNKNOWN ||
+      pcm_cfg.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+    return false;
+  }
+  audio_cfg->sample_rate = SampleRateToAudioFormat(pcm_cfg.sampleRate);
+  audio_cfg->channel_mask =
+      (is_stereo_to_mono_ ? AUDIO_CHANNEL_OUT_STEREO : ChannelModeToAudioFormat(pcm_cfg.channelMode));
+  audio_cfg->format = BitsPerSampleToAudioFormat(pcm_cfg.bitsPerSample);
+  return true;
+}
+
+bool BluetoothAudioPortOut::CondwaitState(BluetoothStreamState state) {
+  bool retval;
+  std::unique_lock<std::mutex> port_lock(cv_mutex_);
+  switch (state) {
+    case BluetoothStreamState::STARTING:
+      LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
+                   << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for STARTED";
+      retval = internal_cv_.wait_for(
+          port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
+          [this] { return this->state_ != BluetoothStreamState::STARTING; });
+      retval = retval && state_ == BluetoothStreamState::STARTED;
+      break;
+    case BluetoothStreamState::SUSPENDING:
+      LOG(VERBOSE) << __func__ << ": session_type=" << toString(session_type_)
+                   << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for SUSPENDED";
+      retval = internal_cv_.wait_for(
+          port_lock, std::chrono::milliseconds(kMaxWaitingTimeMs),
+          [this] { return this->state_ != BluetoothStreamState::SUSPENDING; });
+      retval = retval && state_ == BluetoothStreamState::STANDBY;
+      break;
+    default:
+      LOG(WARNING) << __func__ << ": session_type=" << toString(session_type_)
+                   << ", cookie=" << StringPrintf("%#hx", cookie_) << " waiting for KNOWN";
+      return false;
+  }
+
+  return retval;  // false if any failure like timeout
+}
+
+bool BluetoothAudioPortOut::Start() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return false;
+  }
+
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " request";
+  bool retval = false;
+  if (state_ == BluetoothStreamState::STANDBY) {
+    state_ = BluetoothStreamState::STARTING;
+    if (BluetoothAudioSessionControl::StartStream(session_type_)) {
+      retval = CondwaitState(BluetoothStreamState::STARTING);
+    } else {
+      LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
+                 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails";
+    }
+  }
+
+  if (retval) {
+    LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_
+              << ", mono=" << (is_stereo_to_mono_ ? "true" : "false") << " done";
+  } else {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure";
+  }
+
+  return retval;  // false if any failure like timeout
+}
+
+bool BluetoothAudioPortOut::Suspend() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return false;
+  }
+
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << " request";
+  bool retval = false;
+  if (state_ == BluetoothStreamState::STARTED) {
+    state_ = BluetoothStreamState::SUSPENDING;
+    if (BluetoothAudioSessionControl::SuspendStream(session_type_)) {
+      retval = CondwaitState(BluetoothStreamState::SUSPENDING);
+    } else {
+      LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
+                 << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " Hal fails";
+    }
+  }
+
+  if (retval) {
+    LOG(INFO) << __func__ << ": session_type=" << toString(session_type_)
+              << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " done";
+  } else {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << " failure";
+  }
+
+  return retval;  // false if any failure like timeout
+}
+
+void BluetoothAudioPortOut::Stop() {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return;
+  }
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << " request";
+  state_ = BluetoothStreamState::DISABLED;
+  BluetoothAudioSessionControl::StopStream(session_type_);
+  LOG(INFO) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+            << ", state=" << state_ << " done";
+}
+
+size_t BluetoothAudioPortOut::WriteData(const void* buffer, size_t bytes) const {
+  if (!in_use()) return 0;
+  if (!is_stereo_to_mono_) {
+    return BluetoothAudioSessionControl::OutWritePcmData(session_type_, buffer, bytes);
+  }
+
+  // WAR to mix the stereo into Mono (16 bits per sample)
+  const size_t write_frames = bytes >> 2;
+  if (write_frames == 0) return 0;
+  auto src = static_cast<const int16_t*>(buffer);
+  std::unique_ptr<int16_t[]> dst{new int16_t[write_frames]};
+  downmix_to_mono_i16_from_stereo_i16(dst.get(), src, write_frames);
+  // a frame is 16 bits, and the size of a mono frame is equal to half a stereo.
+  return BluetoothAudioSessionControl::OutWritePcmData(session_type_, dst.get(), write_frames * 2) * 2;
+}
+
+bool BluetoothAudioPortOut::GetPresentationPosition(uint64_t* delay_ns,
+                                                    uint64_t* bytes,
+                                                    timespec* timestamp) const {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return false;
+  }
+  bool retval = BluetoothAudioSessionControl::GetPresentationPosition(
+      session_type_, delay_ns, bytes, timestamp);
+  LOG(VERBOSE) << __func__ << ": session_type=" << StringPrintf("%#hhx", session_type_)
+               << ", cookie=" << StringPrintf("%#hx", cookie_) << ", state=" << state_ << ", delay=" << *delay_ns
+               << "ns, data=" << *bytes << " bytes, timestamp=" << timestamp->tv_sec << "."
+               << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
+
+  return retval;
+}
+
+void BluetoothAudioPortOut::UpdateMetadata(
+    const source_metadata* source_metadata) const {
+  if (!in_use()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioPortOut is not in use";
+    return;
+  }
+  LOG(DEBUG) << __func__ << ": session_type=" << toString(session_type_) << ", cookie=" << StringPrintf("%#hx", cookie_)
+             << ", state=" << state_ << ", " << source_metadata->track_count << " track(s)";
+  if (source_metadata->track_count == 0) return;
+  BluetoothAudioSessionControl::UpdateTracksMetadata(session_type_,
+                                                     source_metadata);
+}
+
+BluetoothStreamState BluetoothAudioPortOut::GetState() const { return state_; }
+
+void BluetoothAudioPortOut::SetState(BluetoothStreamState state) {
+  state_ = state;
+}
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/audio_bluetooth_hw/device_port_proxy.h b/audio_bluetooth_hw/device_port_proxy.h
new file mode 100644
index 0000000..16db274
--- /dev/null
+++ b/audio_bluetooth_hw/device_port_proxy.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <android/hardware/bluetooth/audio/2.0/types.h>
+#include <hardware/audio.h>
+#include <condition_variable>
+#include <mutex>
+#include <unordered_map>
+
+enum class BluetoothStreamState : uint8_t;
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+
+// Proxy for Bluetooth Audio HW Module to communicate with Bluetooth Audio
+// Session Control. All methods are not thread safe, so users must acquire a
+// lock. Note: currently, in stream_apis.cc, if GetState() is only used for
+// verbose logging, it is not locked, so the state may not be synchronized.
+class BluetoothAudioPortOut {
+ public:
+  BluetoothAudioPortOut();
+  ~BluetoothAudioPortOut() = default;
+
+  // Fetch output control / data path of BluetoothAudioPortOut and setup
+  // callbacks into BluetoothAudioProvider. If SetUp() returns false, the audio
+  // HAL must delete this BluetoothAudioPortOut and return EINVAL to caller
+  bool SetUp(audio_devices_t devices);
+
+  // Unregister this BluetoothAudioPortOut from BluetoothAudioSessionControl.
+  // Audio HAL must delete this BluetoothAudioPortOut after calling this.
+  void TearDown();
+
+  // When the Audio framework / HAL tries to query audio config about format,
+  // channel mask and sample rate, it uses this function to fetch from the
+  // Bluetooth stack
+  bool LoadAudioConfig(audio_config_t* audio_cfg) const;
+
+  // WAR to support Mono mode / 16 bits per sample
+  void ForcePcmStereoToMono(bool force) {
+    is_stereo_to_mono_ = force;
+  }
+
+  // When the Audio framework / HAL wants to change the stream state, it invokes
+  // these 3 functions to control the Bluetooth stack (Audio Control Path).
+  // Note: Both Start() and Suspend() will return ture when there are no errors.
+  // Called by Audio framework / HAL to start the stream
+  bool Start();
+  // Called by Audio framework / HAL to suspend the stream
+  bool Suspend();
+  // Called by Audio framework / HAL to stop the stream
+  void Stop();
+
+  // The audio data path to the Bluetooth stack (Software encoding)
+  size_t WriteData(const void* buffer, size_t bytes) const;
+
+  // Called by the Audio framework / HAL to fetch informaiton about audio frames
+  // presented to an external sink.
+  bool GetPresentationPosition(uint64_t* delay_ns, uint64_t* bytes,
+                               timespec* timestamp) const;
+
+  // Called by the Audio framework / HAL when the metadata of the stream's
+  // source has been changed.
+  void UpdateMetadata(const source_metadata* source_metadata) const;
+
+  // Return the current BluetoothStreamState
+  BluetoothStreamState GetState() const;
+
+  // Set the current BluetoothStreamState
+  void SetState(BluetoothStreamState state);
+
+ private:
+  BluetoothStreamState state_;
+  ::android::hardware::bluetooth::audio::V2_0::SessionType session_type_;
+  uint16_t cookie_;
+  mutable std::mutex cv_mutex_;
+  std::condition_variable internal_cv_;
+  // WR to support Mono: True if fetching Stereo and mixing into Mono
+  bool is_stereo_to_mono_ = false;
+
+  // Check and initialize session type for |devices| If failed, this
+  // BluetoothAudioPortOut is not initialized and must be deleted.
+  bool init_session_type(audio_devices_t device);
+
+  bool in_use() const;
+
+  bool CondwaitState(BluetoothStreamState state);
+
+  void ControlResultHandler(
+      const ::android::hardware::bluetooth::audio::V2_0::Status& status);
+  void SessionChangedHandler();
+};
+
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/audio_bluetooth_hw/stream_apis.cc b/audio_bluetooth_hw/stream_apis.cc
new file mode 100644
index 0000000..74b6f2a
--- /dev/null
+++ b/audio_bluetooth_hw/stream_apis.cc
@@ -0,0 +1,691 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioHalStream"
+
+#include <android-base/logging.h>
+#include <android-base/stringprintf.h>
+#include <cutils/properties.h>
+#include <errno.h>
+#include <inttypes.h>
+#include <log/log.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include "stream_apis.h"
+#include "utils.h"
+
+using ::android::base::StringPrintf;
+using ::android::bluetooth::audio::BluetoothAudioPortOut;
+using ::android::bluetooth::audio::utils::GetAudioParamString;
+using ::android::bluetooth::audio::utils::ParseAudioParams;
+
+namespace {
+
+constexpr unsigned int kMinimumDelayMs = 100;
+constexpr unsigned int kMaximumDelayMs = 1000;
+constexpr int kExtraAudioSyncMs = 200;
+
+std::ostream& operator<<(std::ostream& os, const audio_config& config) {
+  return os << "audio_config[sample_rate=" << config.sample_rate
+            << ", channels=" << StringPrintf("%#x", config.channel_mask) << ", format=" << config.format << "]";
+}
+
+}  // namespace
+
+std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state) {
+  switch (state) {
+    case BluetoothStreamState::DISABLED:
+      return os << "DISABLED";
+    case BluetoothStreamState::STANDBY:
+      return os << "STANDBY";
+    case BluetoothStreamState::STARTING:
+      return os << "STARTING";
+    case BluetoothStreamState::STARTED:
+      return os << "STARTED";
+    case BluetoothStreamState::SUSPENDING:
+      return os << "SUSPENDING";
+    case BluetoothStreamState::UNKNOWN:
+      return os << "UNKNOWN";
+    default:
+      return os << StringPrintf("%#hhx", state);
+  }
+}
+
+static uint32_t out_get_sample_rate(const struct audio_stream* stream) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  audio_config_t audio_cfg;
+  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " audio_cfg=" << audio_cfg;
+    return audio_cfg.sample_rate;
+  } else {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << ", sample_rate=" << out->sample_rate_ << " failed";
+    return out->sample_rate_;
+  }
+}
+
+static int out_set_sample_rate(struct audio_stream* stream, uint32_t rate) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", sample_rate=" << out->sample_rate_;
+  return (rate == out->sample_rate_ ? 0 : -1);
+}
+
+static size_t out_get_buffer_size(const struct audio_stream* stream) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  size_t buffer_size =
+      out->frames_count_ * audio_stream_out_frame_size(&out->stream_out_);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", buffer_size=" << buffer_size;
+  return buffer_size;
+}
+
+static audio_channel_mask_t out_get_channels(
+    const struct audio_stream* stream) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  audio_config_t audio_cfg;
+  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " audio_cfg=" << audio_cfg;
+    return audio_cfg.channel_mask;
+  } else {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << ", channels=" << StringPrintf("%#x", out->channel_mask_) << " failure";
+    return out->channel_mask_;
+  }
+}
+
+static audio_format_t out_get_format(const struct audio_stream* stream) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  audio_config_t audio_cfg;
+  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " audio_cfg=" << audio_cfg;
+    return audio_cfg.format;
+  } else {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << ", format=" << out->format_ << " failure";
+    return out->format_;
+  }
+}
+
+static int out_set_format(struct audio_stream* stream, audio_format_t format) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", format=" << out->format_;
+  return (format == out->format_ ? 0 : -1);
+}
+
+static int out_standby(struct audio_stream* stream) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  int retval = 0;
+
+  // out->last_write_time_us_ = 0; unnecessary as a stale write time has same
+  // effect
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " being standby (suspend)";
+  if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) {
+    out->frames_rendered_ = 0;
+    retval = (out->bluetooth_output_.Suspend() ? 0 : -EIO);
+  } else if (out->bluetooth_output_.GetState() ==
+                 BluetoothStreamState::STARTING ||
+             out->bluetooth_output_.GetState() ==
+                 BluetoothStreamState::SUSPENDING) {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " NOT ready to be standby";
+    retval = -EBUSY;
+  } else {
+    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " standby already";
+  }
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " standby (suspend) retval=" << retval;
+
+  return retval;
+}
+
+static int out_dump(const struct audio_stream* stream, int fd) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState();
+  return 0;
+}
+
+static int out_set_parameters(struct audio_stream* stream,
+                              const char* kvpairs) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  int retval = 0;
+
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", kvpairs=[" << kvpairs << "]";
+
+  std::unordered_map<std::string, std::string> params =
+      ParseAudioParams(kvpairs);
+  if (params.empty()) return retval;
+
+  LOG(VERBOSE) << __func__ << ": ParamsMap=[" << GetAudioParamString(params)
+               << "]";
+
+  audio_config_t audio_cfg;
+  if (params.find(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES) != params.end() ||
+      params.find(AUDIO_PARAMETER_STREAM_SUP_CHANNELS) != params.end() ||
+      params.find(AUDIO_PARAMETER_STREAM_SUP_FORMATS) != params.end()) {
+    if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
+      out->sample_rate_ = audio_cfg.sample_rate;
+      out->channel_mask_ = audio_cfg.channel_mask;
+      out->format_ = audio_cfg.format;
+      LOG(VERBOSE) << "state=" << out->bluetooth_output_.GetState() << ", sample_rate=" << out->sample_rate_
+                   << ", channels=" << StringPrintf("%#x", out->channel_mask_) << ", format=" << out->format_;
+    } else {
+      LOG(WARNING) << __func__
+                   << ": state=" << out->bluetooth_output_.GetState()
+                   << " failed to get audio config";
+    }
+  }
+
+  if (params.find("routing") != params.end()) {
+    auto routing_param = params.find("routing");
+    LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+              << ", stream param '" << routing_param->first.c_str() << "="
+              << routing_param->second.c_str() << "'";
+  }
+
+  if (params.find("A2dpSuspended") != params.end()) {
+    if (params["A2dpSuspended"] == "true") {
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                << " stream param stopped";
+      if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+        out->frames_rendered_ = 0;
+        out->bluetooth_output_.Stop();
+      }
+    } else {
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                << " stream param standby";
+      if (out->bluetooth_output_.GetState() == BluetoothStreamState::DISABLED) {
+        out->bluetooth_output_.SetState(BluetoothStreamState::STANDBY);
+      }
+    }
+  }
+
+  if (params.find("closing") != params.end()) {
+    if (params["closing"] == "true") {
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                << " stream param closing, disallow any writes?";
+      if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+        out->frames_rendered_ = 0;
+        out->frames_presented_ = 0;
+        out->bluetooth_output_.Stop();
+      }
+    }
+  }
+
+  if (params.find("exiting") != params.end()) {
+    if (params["exiting"] == "1") {
+      LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                << " stream param exiting";
+      if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+        out->frames_rendered_ = 0;
+        out->frames_presented_ = 0;
+        out->bluetooth_output_.Stop();
+      }
+    }
+  }
+
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", kvpairs=[" << kvpairs << "], retval=" << retval;
+  return retval;
+}
+
+static char* out_get_parameters(const struct audio_stream* stream,
+                                const char* keys) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", keys=[" << keys << "]";
+
+  std::unordered_map<std::string, std::string> params = ParseAudioParams(keys);
+  if (params.empty()) return strdup("");
+
+  audio_config_t audio_cfg;
+  if (out->bluetooth_output_.LoadAudioConfig(&audio_cfg)) {
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " audio_cfg=" << audio_cfg;
+  } else {
+    LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " failed to get audio config";
+  }
+
+  std::unordered_map<std::string, std::string> return_params;
+  if (params.find(AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES) != params.end()) {
+    std::string param;
+    if (audio_cfg.sample_rate == 16000) {
+      param = "16000";
+    }
+    if (audio_cfg.sample_rate == 24000) {
+      param = "24000";
+    }
+    if (audio_cfg.sample_rate == 44100) {
+      param = "44100";
+    }
+    if (audio_cfg.sample_rate == 48000) {
+      param = "48000";
+    }
+    if (audio_cfg.sample_rate == 88200) {
+      param = "88200";
+    }
+    if (audio_cfg.sample_rate == 96000) {
+      param = "96000";
+    }
+    if (audio_cfg.sample_rate == 176400) {
+      param = "176400";
+    }
+    if (audio_cfg.sample_rate == 192000) {
+      param = "192000";
+    }
+    return_params[AUDIO_PARAMETER_STREAM_SUP_SAMPLING_RATES] = param;
+  }
+
+  if (params.find(AUDIO_PARAMETER_STREAM_SUP_CHANNELS) != params.end()) {
+    std::string param;
+    if (audio_cfg.channel_mask == AUDIO_CHANNEL_OUT_MONO) {
+      param = "AUDIO_CHANNEL_OUT_MONO";
+    }
+    if (audio_cfg.channel_mask == AUDIO_CHANNEL_OUT_STEREO) {
+      param = "AUDIO_CHANNEL_OUT_STEREO";
+    }
+    return_params[AUDIO_PARAMETER_STREAM_SUP_CHANNELS] = param;
+  }
+
+  if (params.find(AUDIO_PARAMETER_STREAM_SUP_FORMATS) != params.end()) {
+    std::string param;
+    if (audio_cfg.format == AUDIO_FORMAT_PCM_16_BIT) {
+      param = "AUDIO_FORMAT_PCM_16_BIT";
+    }
+    if (audio_cfg.format == AUDIO_FORMAT_PCM_24_BIT_PACKED) {
+      param = "AUDIO_FORMAT_PCM_24_BIT_PACKED";
+    }
+    if (audio_cfg.format == AUDIO_FORMAT_PCM_32_BIT) {
+      param = "AUDIO_FORMAT_PCM_32_BIT";
+    }
+    return_params[AUDIO_PARAMETER_STREAM_SUP_FORMATS] = param;
+  }
+
+  std::string result;
+  for (const auto& ptr : return_params) {
+    result += ptr.first + "=" + ptr.second + ";";
+  }
+
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", result=[" << result << "]";
+  return strdup(result.c_str());
+}
+
+static uint32_t out_get_latency_ms(const struct audio_stream_out* stream) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  /***
+   * audio_a2dp_hw:
+   *   frames_count = buffer_size / frame_size
+   *   latency (sec.) = frames_count / sample_rate
+   */
+  uint32_t latency_ms = out->frames_count_ * 1000 / out->sample_rate_;
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", latency_ms=" << latency_ms;
+  // Sync from audio_a2dp_hw to add extra +200ms
+  return latency_ms + kExtraAudioSyncMs;
+}
+
+static int out_set_volume(struct audio_stream_out* stream, float left,
+                          float right) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", Left=" << left << ", Right=" << right;
+  return -1;
+}
+
+static ssize_t out_write(struct audio_stream_out* stream, const void* buffer,
+                         size_t bytes) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  size_t totalWritten = 0;
+
+  if (out->bluetooth_output_.GetState() != BluetoothStreamState::STARTED) {
+    LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+              << " first time bytes=" << bytes;
+    lock.unlock();
+    if (stream->resume(stream)) {
+      LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " failed to resume";
+      usleep(kBluetoothDefaultOutputBufferMs * 1000);
+      return totalWritten;
+    }
+    lock.lock();
+  }
+  lock.unlock();
+  totalWritten = out->bluetooth_output_.WriteData(buffer, bytes);
+  lock.lock();
+
+  struct timespec ts = {.tv_sec = 0, .tv_nsec = 0};
+  clock_gettime(CLOCK_MONOTONIC, &ts);
+  if (totalWritten) {
+    const size_t frames = bytes / audio_stream_out_frame_size(stream);
+    out->frames_rendered_ += frames;
+    out->frames_presented_ += frames;
+    out->last_write_time_us_ = (ts.tv_sec * 1000000000LL + ts.tv_nsec) / 1000;
+  } else {
+    const int64_t now = (ts.tv_sec * 1000000000LL + ts.tv_nsec) / 1000;
+    const int64_t elapsed_time_since_last_write =
+        now - out->last_write_time_us_;
+    // frames_count = written_data / frame_size
+    // play_time (ms) = frames_count / (sample_rate (Sec.) / 1000000)
+    // sleep_time (ms) = play_time - elapsed_time
+    int64_t sleep_time = bytes * 1000000LL /
+                             audio_stream_out_frame_size(stream) /
+                             out_get_sample_rate(&stream->common) -
+                         elapsed_time_since_last_write;
+    if (sleep_time > 0) {
+      LOG(VERBOSE) << __func__ << ": sleep " << (sleep_time / 1000)
+                   << " ms when writting FMQ datapath";
+      lock.unlock();
+      usleep(sleep_time);
+      lock.lock();
+    } else {
+      // we don't sleep when we exit standby (this is typical for a real alsa
+      // buffer).
+      sleep_time = 0;
+    }
+    out->last_write_time_us_ = now + sleep_time;
+  }
+  return totalWritten;
+}
+
+static int out_get_render_position(const struct audio_stream_out* stream,
+                                   uint32_t* dsp_frames) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+
+  if (dsp_frames == nullptr) return -EINVAL;
+
+  /* frames = (latency (ms) / 1000) * sample_per_seconds */
+  uint64_t latency_frames =
+      (uint64_t)out_get_latency_ms(stream) * out->sample_rate_ / 1000;
+  if (out->frames_rendered_ >= latency_frames) {
+    *dsp_frames = (uint32_t)(out->frames_rendered_ - latency_frames);
+  } else {
+    *dsp_frames = 0;
+  }
+
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", dsp_frames=" << *dsp_frames;
+  return 0;
+}
+
+static int out_add_audio_effect(const struct audio_stream* stream,
+                                effect_handle_t effect) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", effect=" << effect;
+  return 0;
+}
+
+static int out_remove_audio_effect(const struct audio_stream* stream,
+                                   effect_handle_t effect) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", effect=" << effect;
+  return 0;
+}
+
+static int out_get_next_write_timestamp(const struct audio_stream_out* stream,
+                                        int64_t* timestamp) {
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  *timestamp = 0;
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", timestamp=" << *timestamp;
+  return -EINVAL;
+}
+
+static int out_pause(struct audio_stream_out* stream) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  int retval = 0;
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", pausing (suspend)";
+  if (out->bluetooth_output_.GetState() == BluetoothStreamState::STARTED) {
+    out->frames_rendered_ = 0;
+    retval = (out->bluetooth_output_.Suspend() ? 0 : -EIO);
+  } else if (out->bluetooth_output_.GetState() ==
+                 BluetoothStreamState::STARTING ||
+             out->bluetooth_output_.GetState() ==
+                 BluetoothStreamState::SUSPENDING) {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " NOT ready to pause?!";
+    retval = -EBUSY;
+  } else {
+    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " paused already";
+  }
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", pausing (suspend) retval=" << retval;
+
+  return retval;
+}
+
+static int out_resume(struct audio_stream_out* stream) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  int retval = 0;
+
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", resuming (start)";
+  if (out->bluetooth_output_.GetState() == BluetoothStreamState::STANDBY) {
+    retval = (out->bluetooth_output_.Start() ? 0 : -EIO);
+  } else if (out->bluetooth_output_.GetState() ==
+                 BluetoothStreamState::STARTING ||
+             out->bluetooth_output_.GetState() ==
+                 BluetoothStreamState::SUSPENDING) {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " NOT ready to resume?!";
+    retval = -EBUSY;
+  } else if (out->bluetooth_output_.GetState() ==
+             BluetoothStreamState::DISABLED) {
+    LOG(WARNING) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+                 << " NOT allow to resume?!";
+    retval = -EINVAL;
+  } else {
+    LOG(DEBUG) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " resumed already";
+  }
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", resuming (start) retval=" << retval;
+
+  return retval;
+}
+
+static int out_get_presentation_position(const struct audio_stream_out* stream,
+                                         uint64_t* frames,
+                                         struct timespec* timestamp) {
+  if (frames == nullptr || timestamp == nullptr) {
+    return -EINVAL;
+  }
+
+  // bytes is the total number of bytes sent by the Bluetooth stack to a
+  // remote headset
+  uint64_t bytes = 0;
+  // delay_report is the audio delay from the remote headset receiving data to
+  // the headset playing sound in units of nanoseconds
+  uint64_t delay_report_ns = 0;
+  const auto* out = reinterpret_cast<const BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+
+  if (out->bluetooth_output_.GetPresentationPosition(&delay_report_ns, &bytes,
+                                                     timestamp)) {
+    // assume kMinimumDelayMs (100ms) < delay_report_ns < kMaximumDelayMs
+    // (1000ms), or it is invalid / ignored and use old delay calculated
+    // by ourselves.
+    if (delay_report_ns > kMinimumDelayMs * 1000000 &&
+        delay_report_ns < kMaximumDelayMs * 1000000) {
+      *frames = bytes / audio_stream_out_frame_size(stream);
+      timestamp->tv_nsec += delay_report_ns;
+      if (timestamp->tv_nsec > 1000000000) {
+        timestamp->tv_sec += static_cast<int>(timestamp->tv_nsec / 1000000000);
+        timestamp->tv_nsec %= 1000000000;
+      }
+      LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() << ", frames=" << *frames << " ("
+                   << bytes << " bytes), timestamp=" << timestamp->tv_sec << "."
+                   << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
+      return 0;
+    } else if (delay_report_ns >= kMaximumDelayMs * 1000000) {
+      LOG(WARNING) << __func__
+                   << ": state=" << out->bluetooth_output_.GetState()
+                   << ", delay_report=" << delay_report_ns << "ns abnormal";
+    }
+  }
+
+  // default to old delay if any failure is found when fetching from ports
+  if (out->frames_presented_ >= out->frames_count_) {
+    clock_gettime(CLOCK_MONOTONIC, timestamp);
+    *frames = out->frames_presented_ - out->frames_count_;
+    LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState() << ", frames=" << *frames << " ("
+                 << bytes << " bytes), timestamp=" << timestamp->tv_sec << "."
+                 << StringPrintf("%09ld", timestamp->tv_nsec) << "s";
+    return 0;
+  }
+
+  *frames = 0;
+  *timestamp = {};
+  return -EWOULDBLOCK;
+}
+
+static void out_update_source_metadata(
+    struct audio_stream_out* stream,
+    const struct source_metadata* source_metadata) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  std::unique_lock<std::mutex> lock(out->mutex_);
+  if (source_metadata == nullptr || source_metadata->track_count == 0) {
+    return;
+  }
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", " << source_metadata->track_count << " track(s)";
+  out->bluetooth_output_.UpdateMetadata(source_metadata);
+}
+
+static size_t samples_per_ticks(size_t milliseconds, uint32_t sample_rate,
+                                size_t channel_count) {
+  return milliseconds * sample_rate * channel_count / 1000;
+}
+
+int adev_open_output_stream(struct audio_hw_device* dev,
+                            audio_io_handle_t handle, audio_devices_t devices,
+                            audio_output_flags_t flags,
+                            struct audio_config* config,
+                            struct audio_stream_out** stream_out,
+                            const char* address __unused) {
+  *stream_out = nullptr;
+  auto* out = new BluetoothStreamOut;
+  if (!out->bluetooth_output_.SetUp(devices)) {
+    delete out;
+    return -EINVAL;
+  }
+  LOG(VERBOSE) << __func__ << ": device=" << StringPrintf("%#x", devices);
+
+  out->stream_out_.common.get_sample_rate = out_get_sample_rate;
+  out->stream_out_.common.set_sample_rate = out_set_sample_rate;
+  out->stream_out_.common.get_buffer_size = out_get_buffer_size;
+  out->stream_out_.common.get_channels = out_get_channels;
+  out->stream_out_.common.get_format = out_get_format;
+  out->stream_out_.common.set_format = out_set_format;
+  out->stream_out_.common.standby = out_standby;
+  out->stream_out_.common.dump = out_dump;
+  out->stream_out_.common.set_parameters = out_set_parameters;
+  out->stream_out_.common.get_parameters = out_get_parameters;
+  out->stream_out_.common.add_audio_effect = out_add_audio_effect;
+  out->stream_out_.common.remove_audio_effect = out_remove_audio_effect;
+  out->stream_out_.get_latency = out_get_latency_ms;
+  out->stream_out_.set_volume = out_set_volume;
+  out->stream_out_.write = out_write;
+  out->stream_out_.get_render_position = out_get_render_position;
+  out->stream_out_.get_next_write_timestamp = out_get_next_write_timestamp;
+  out->stream_out_.pause = out_pause;
+  out->stream_out_.resume = out_resume;
+  out->stream_out_.get_presentation_position = out_get_presentation_position;
+  out->stream_out_.update_source_metadata = out_update_source_metadata;
+
+  if (!out->bluetooth_output_.LoadAudioConfig(config)) {
+    LOG(ERROR) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << " failed to get audio config";
+  }
+  // WAR to support Mono / 16 bits per sample as the Bluetooth stack required
+  if (config->channel_mask == AUDIO_CHANNEL_OUT_MONO && config->format == AUDIO_FORMAT_PCM_16_BIT) {
+    LOG(INFO) << __func__ << ": force channels=" << StringPrintf("%#x", out->channel_mask_)
+              << " to be AUDIO_CHANNEL_OUT_STEREO";
+    out->bluetooth_output_.ForcePcmStereoToMono(true);
+    config->channel_mask = AUDIO_CHANNEL_OUT_STEREO;
+  }
+  out->sample_rate_ = config->sample_rate;
+  out->channel_mask_ = config->channel_mask;
+  out->format_ = config->format;
+  // frame is number of samples per channel
+  out->frames_count_ =
+      samples_per_ticks(kBluetoothDefaultOutputBufferMs, out->sample_rate_, 1);
+  out->frames_rendered_ = 0;
+  out->frames_presented_ = 0;
+
+  *stream_out = &out->stream_out_;
+  LOG(INFO) << __func__ << ": state=" << out->bluetooth_output_.GetState() << ", sample_rate=" << out->sample_rate_
+            << ", channels=" << StringPrintf("%#x", out->channel_mask_) << ", format=" << out->format_
+            << ", frames=" << out->frames_count_;
+  return 0;
+}
+
+void adev_close_output_stream(struct audio_hw_device* dev,
+                              struct audio_stream_out* stream) {
+  auto* out = reinterpret_cast<BluetoothStreamOut*>(stream);
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", stopping";
+  if (out->bluetooth_output_.GetState() != BluetoothStreamState::DISABLED) {
+    out->frames_rendered_ = 0;
+    out->frames_presented_ = 0;
+    out->bluetooth_output_.Stop();
+  }
+  out->bluetooth_output_.TearDown();
+  LOG(VERBOSE) << __func__ << ": state=" << out->bluetooth_output_.GetState()
+               << ", stopped";
+  delete out;
+}
+
+size_t adev_get_input_buffer_size(const struct audio_hw_device* dev,
+                                  const struct audio_config* config) {
+  return 320;
+}
+
+int adev_open_input_stream(struct audio_hw_device* dev,
+                           audio_io_handle_t handle, audio_devices_t devices,
+                           struct audio_config* config,
+                           struct audio_stream_in** stream_in,
+                           audio_input_flags_t flags __unused,
+                           const char* address __unused,
+                           audio_source_t source __unused) {
+  return -EINVAL;
+}
+
+void adev_close_input_stream(struct audio_hw_device* dev,
+                             struct audio_stream_in* stream_in) {}
diff --git a/audio_bluetooth_hw/stream_apis.h b/audio_bluetooth_hw/stream_apis.h
new file mode 100644
index 0000000..14a955c
--- /dev/null
+++ b/audio_bluetooth_hw/stream_apis.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <hardware/audio.h>
+#include <system/audio.h>
+
+#include "device_port_proxy.h"
+
+constexpr unsigned int kBluetoothDefaultSampleRate = 44100;
+constexpr audio_format_t kBluetoothDefaultAudioFormatBitsPerSample =
+    AUDIO_FORMAT_PCM_16_BIT;
+
+constexpr unsigned int kBluetoothDefaultInputBufferMs = 20;
+
+constexpr unsigned int kBluetoothDefaultOutputBufferMs = 10;
+constexpr audio_channel_mask_t kBluetoothDefaultOutputChannelModeMask =
+    AUDIO_CHANNEL_OUT_STEREO;
+
+enum class BluetoothStreamState : uint8_t {
+  DISABLED = 0,  // This stream is closing or set param "suspend=true"
+  STANDBY,
+  STARTING,
+  STARTED,
+  SUSPENDING,
+  UNKNOWN,
+};
+
+std::ostream& operator<<(std::ostream& os, const BluetoothStreamState& state);
+
+struct BluetoothStreamOut {
+  // Must be the first member so it can be cast from audio_stream
+  // or audio_stream_out pointer
+  audio_stream_out stream_out_;
+  ::android::bluetooth::audio::BluetoothAudioPortOut bluetooth_output_;
+  int64_t last_write_time_us_;
+  // Audio PCM Configs
+  uint32_t sample_rate_;
+  audio_channel_mask_t channel_mask_;
+  audio_format_t format_;
+  // frame is the number of samples per channel
+  // frames count per tick
+  size_t frames_count_;
+  // total frames written, reset on standby
+  uint64_t frames_rendered_;
+  // total frames written after opened, never reset
+  uint64_t frames_presented_;
+  mutable std::mutex mutex_;
+};
+
+int adev_open_output_stream(struct audio_hw_device* dev,
+                            audio_io_handle_t handle, audio_devices_t devices,
+                            audio_output_flags_t flags,
+                            struct audio_config* config,
+                            struct audio_stream_out** stream_out,
+                            const char* address __unused);
+
+void adev_close_output_stream(struct audio_hw_device* dev,
+                              struct audio_stream_out* stream);
+
+size_t adev_get_input_buffer_size(const struct audio_hw_device* dev,
+                                  const struct audio_config* config);
+
+int adev_open_input_stream(struct audio_hw_device* dev,
+                           audio_io_handle_t handle, audio_devices_t devices,
+                           struct audio_config* config,
+                           struct audio_stream_in** stream_in,
+                           audio_input_flags_t flags __unused,
+                           const char* address __unused,
+                           audio_source_t source __unused);
+
+void adev_close_input_stream(struct audio_hw_device* dev,
+                             struct audio_stream_in* in);
diff --git a/audio_bluetooth_hw/utils.cc b/audio_bluetooth_hw/utils.cc
new file mode 100644
index 0000000..b3ac7a5
--- /dev/null
+++ b/audio_bluetooth_hw/utils.cc
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioHalUtils"
+
+#include "utils.h"
+
+#include <android-base/logging.h>
+#include <android-base/strings.h>
+#include <log/log.h>
+#include <stdlib.h>
+#include <sstream>
+#include <vector>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+namespace utils {
+
+std::unordered_map<std::string, std::string> ParseAudioParams(
+    const std::string& params) {
+  std::vector<std::string> segments = android::base::Split(params, ";");
+  std::unordered_map<std::string, std::string> params_map;
+  for (const auto& segment : segments) {
+    if (segment.length() == 0) {
+      continue;
+    }
+    std::vector<std::string> kv = android::base::Split(segment, "=");
+    if (kv[0].empty()) {
+      LOG(WARNING) << __func__ << ": Invalid audio parameter " << segment;
+      continue;
+    }
+    params_map[kv[0]] = (kv.size() > 1 ? kv[1] : "");
+  }
+  return params_map;
+}
+
+std::string GetAudioParamString(
+    std::unordered_map<std::string, std::string>& params_map) {
+  std::ostringstream sout;
+  for (const auto& ptr : params_map) {
+    sout << "key: '" << ptr.first << "' value: '" << ptr.second << "'\n";
+  }
+  return sout.str();
+}
+
+}  // namespace utils
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/audio_bluetooth_hw/utils.h b/audio_bluetooth_hw/utils.h
new file mode 100644
index 0000000..817a432
--- /dev/null
+++ b/audio_bluetooth_hw/utils.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <string>
+#include <unordered_map>
+
+namespace android {
+namespace bluetooth {
+namespace audio {
+namespace utils {
+
+// Creates a hash map based on the |params| string containing key and value
+// pairs.  Pairs are expected in the form "key=value" separated by the ';'
+// character.  Both ';' and '=' characters are invalid in keys or values.
+// Examples:
+//   "key0"                      -> map: [key0]=""
+//   "key0=value0;key1=value1;"  -> map: [key0]="value0" [key1]="value1"
+//   "key0=;key1=value1;"        -> map: [key0]="" [key1]="value1"
+//   "=value0;key1=value1;"      -> map: [key1]="value1"
+std::unordered_map<std::string, std::string> ParseAudioParams(
+    const std::string& params);
+
+// Dumps the contents of the hash_map to the log for debugging purposes.
+// If |map| is not NULL, all entries of |map| will be dumped, otherwise
+// nothing will be dumped. Note that this function does not take the ownership
+// of the |map|.
+std::string GetAudioParamString(
+    std::unordered_map<std::string, std::string>& params_map);
+
+}  // namespace utils
+}  // namespace audio
+}  // namespace bluetooth
+}  // namespace android
diff --git a/audio_bluetooth_hw/utils_unittest.cc b/audio_bluetooth_hw/utils_unittest.cc
new file mode 100644
index 0000000..a457797
--- /dev/null
+++ b/audio_bluetooth_hw/utils_unittest.cc
@@ -0,0 +1,136 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <unordered_map>
+
+#include "utils.h"
+
+namespace {
+
+using ::android::bluetooth::audio::utils::ParseAudioParams;
+
+class UtilsTest : public testing::Test {
+ protected:
+  virtual void SetUp() {}
+  virtual void TearDown() { map_.clear(); }
+
+  std::unordered_map<std::string, std::string> map_;
+};
+
+TEST_F(UtilsTest, HashMapEmptyParams) {
+  std::string params = "";
+  map_ = ParseAudioParams(params);
+  // map = {}
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_F(UtilsTest, HashMapDelimitOnly) {
+  std::string params = ";";
+  map_ = ParseAudioParams(params);
+  // map = {}
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_F(UtilsTest, HashMapNotKeyValuePair) {
+  std::string params = "key0";
+  map_ = ParseAudioParams(params);
+  // map = {[key0]=""}
+  EXPECT_EQ(map_.size(), 1);
+  EXPECT_NE(map_.find("key0"), map_.end());
+  EXPECT_EQ(map_["key0"].length(), 0);
+}
+
+TEST_F(UtilsTest, HashMapEmptyValue) {
+  std::string params = "key0=";
+  map_ = ParseAudioParams(params);
+  // map = {[key0]=""}
+  EXPECT_EQ(map_.size(), 1);
+  EXPECT_NE(map_.find("key0"), map_.end());
+  EXPECT_EQ(map_["key0"].length(), 0);
+}
+
+TEST_F(UtilsTest, HashMapEmptyValueWithDelimit) {
+  std::string params = "key0=;";
+  map_ = ParseAudioParams(params);
+  // map = {[key0]=""}
+  EXPECT_EQ(map_.size(), 1);
+  EXPECT_NE(map_.find("key0"), map_.end());
+  EXPECT_EQ(map_["key0"].length(), 0);
+}
+
+TEST_F(UtilsTest, HashMapOneKeyValuePair) {
+  std::string params = "key0=value0";
+  map_ = ParseAudioParams(params);
+  // map = {[key0]="value0"}
+  EXPECT_EQ(map_.size(), 1);
+  EXPECT_EQ(map_["key0"], "value0");
+}
+
+TEST_F(UtilsTest, HashMapOneKeyValuePairWithDelimit) {
+  std::string params = "key0=value0;";
+  map_ = ParseAudioParams(params);
+  // map = {[key0]="value0"}
+  EXPECT_EQ(map_.size(), 1);
+  EXPECT_EQ(map_["key0"], "value0");
+}
+
+TEST_F(UtilsTest, HashMapTwoKeyValuePairs) {
+  std::string params = "key0=value0;key1=value1";
+  map_ = ParseAudioParams(params);
+  // map = {[key0]="value0", [key1]="value1"}
+  EXPECT_EQ(map_.size(), 2);
+  EXPECT_EQ(map_["key0"], "value0");
+  EXPECT_EQ(map_["key1"], "value1");
+}
+
+TEST_F(UtilsTest, HashMapEmptyKey) {
+  std::string params = "=value";
+  map_ = ParseAudioParams(params);
+  // map = {}
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_F(UtilsTest, HashMapEmptyKeyWithDelimit) {
+  std::string params = "=value;";
+  map_ = ParseAudioParams(params);
+  // map = {}
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_F(UtilsTest, HashMapEquivalentOnly) {
+  std::string params = "=";
+  map_ = ParseAudioParams(params);
+  // map = {}
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_F(UtilsTest, HashMapNoKeyValuePair) {
+  std::string params = "=;";
+  map_ = ParseAudioParams(params);
+  // map = {}
+  EXPECT_TRUE(map_.empty());
+}
+
+TEST_F(UtilsTest, HashMapTwoPairsWithFirstKeyEmpty) {
+  std::string params = "=value0;key1=value1";
+  map_ = ParseAudioParams(params);
+  // map = {[key1]="value1"}
+  EXPECT_EQ(map_.size(), 1);
+  EXPECT_EQ(map_["key1"], "value1");
+}
+
+}  // namespace
diff --git a/audio_hal_interface/Android.bp b/audio_hal_interface/Android.bp
new file mode 100644
index 0000000..4b10435
--- /dev/null
+++ b/audio_hal_interface/Android.bp
@@ -0,0 +1,60 @@
+// Bluetooth Audio library for target
+// ========================================================
+cc_library_static {
+    name: "libbt-audio-hal-interface",
+    defaults: ["fluoride_defaults"],
+    include_dirs: [
+        "system/bt",
+        "system/bt/bta/include",
+        "system/bt/bta/sys",
+        "system/bt/btif/include",
+        "system/bt/stack/include",
+    ],
+    srcs: [
+        "a2dp_encoding.cc",
+        "client_interface.cc",
+        "hearing_aid_software_encoding.cc",
+    ],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "libfmq",
+        "libhidlbase",
+        "libhidltransport",
+    ],
+    static_libs: [
+        "libosi",
+        "libbt-common",
+    ],
+    cflags: [
+        "-DBUILDCFG",
+    ],
+}
+
+// Bluetooth Audio client interface library unit tests for target and host
+// ========================================================
+cc_test {
+    name: "bluetooth-test-audio-hal-interface",
+    defaults: ["fluoride_defaults"],
+    include_dirs: [
+        "system/bt",
+    ],
+    srcs: [
+        "client_interface_unittest.cc",
+    ],
+    shared_libs: [
+        "android.hardware.bluetooth.audio@2.0",
+        "libcutils",
+        "libfmq",
+        "libhidlbase",
+        "libhidltransport",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "libbt-audio-hal-interface",
+        "libbt-common",
+    ],
+    cflags: [
+        "-DBUILDCFG",
+    ],
+}
diff --git a/audio_hal_interface/a2dp_encoding.cc b/audio_hal_interface/a2dp_encoding.cc
new file mode 100644
index 0000000..fc61128
--- /dev/null
+++ b/audio_hal_interface/a2dp_encoding.cc
@@ -0,0 +1,743 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "a2dp_encoding.h"
+#include "client_interface.h"
+
+#include "a2dp_aac_constants.h"
+#include "a2dp_sbc_constants.h"
+#include "a2dp_vendor_ldac_constants.h"
+#include "bta/av/bta_av_int.h"
+#include "btif_a2dp_source.h"
+#include "btif_av.h"
+#include "btif_av_co.h"
+#include "btif_hf.h"
+#include "osi/include/properties.h"
+
+namespace {
+
+using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using ::bluetooth::audio::AudioConfiguration;
+using ::bluetooth::audio::BitsPerSample;
+using ::bluetooth::audio::BluetoothAudioCtrlAck;
+using ::bluetooth::audio::ChannelMode;
+using ::bluetooth::audio::CodecConfiguration;
+using ::bluetooth::audio::PcmParameters;
+using ::bluetooth::audio::SampleRate;
+using ::bluetooth::audio::SessionType;
+
+const CodecConfiguration kInvalidCodecConfiguration = {
+    .codecType = CodecType::UNKNOWN,
+    .encodedAudioBitrate = 0x00000000,
+    .peerMtu = 0xffff,
+    .isScmstEnabled = false,
+    .config = {}};
+
+BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack);
+
+// Provide call-in APIs for the Bluetooth Audio HAL
+class A2dpTransport : public ::bluetooth::audio::IBluetoothTransportInstance {
+ public:
+  A2dpTransport(SessionType sessionType)
+      : IBluetoothTransportInstance(sessionType, {}),
+        a2dp_pending_cmd_(A2DP_CTRL_CMD_NONE),
+        remote_delay_report_(0),
+        total_bytes_read_(0),
+        data_position_({}){};
+
+  BluetoothAudioCtrlAck StartRequest() override {
+    // Check if a previous request is not finished
+    if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_START) {
+      LOG(INFO) << __func__ << ": A2DP_CTRL_CMD_START in progress";
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_PENDING);
+    } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) {
+      LOG(WARNING) << __func__ << ": busy in pending_cmd=" << a2dp_pending_cmd_;
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_FAILURE);
+    }
+
+    // Don't send START request to stack while we are in a call
+    if (!bluetooth::headset::IsCallIdle()) {
+      LOG(ERROR) << __func__ << ": call state is busy";
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_INCALL_FAILURE);
+    }
+
+    if (btif_a2dp_source_is_streaming()) {
+      LOG(ERROR) << __func__ << ": source is busy streaming";
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_FAILURE);
+    }
+
+    if (btif_av_stream_ready()) {
+      /*
+       * Post start event and wait for audio path to open.
+       * If we are the source, the ACK will be sent after the start
+       * procedure is completed, othewise send it now.
+       */
+      a2dp_pending_cmd_ = A2DP_CTRL_CMD_START;
+      btif_av_stream_start();
+      if (btif_av_get_peer_sep() != AVDT_TSEP_SRC) {
+        LOG(INFO) << __func__ << ": accepted";
+        return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_PENDING);
+      }
+      a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE;
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_SUCCESS);
+    }
+
+    if (btif_av_stream_started_ready()) {
+      // Already started, ACK back immediately.
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_SUCCESS);
+    }
+    LOG(ERROR) << __func__ << ": AV stream is not ready to start";
+    return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_FAILURE);
+  }
+
+  BluetoothAudioCtrlAck SuspendRequest() override {
+    // Previous request is not finished
+    if (a2dp_pending_cmd_ == A2DP_CTRL_CMD_SUSPEND) {
+      LOG(INFO) << __func__ << ": A2DP_CTRL_CMD_SUSPEND in progress";
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_PENDING);
+    } else if (a2dp_pending_cmd_ != A2DP_CTRL_CMD_NONE) {
+      LOG(WARNING) << __func__ << ": busy in pending_cmd=" << a2dp_pending_cmd_;
+      return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_FAILURE);
+    }
+    // Local suspend
+    if (btif_av_stream_started_ready()) {
+      LOG(INFO) << __func__ << ": accepted";
+      a2dp_pending_cmd_ = A2DP_CTRL_CMD_SUSPEND;
+      btif_av_stream_suspend();
+      return BluetoothAudioCtrlAck::PENDING;
+    }
+    /* 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.
+     */
+    btif_av_clear_remote_suspend_flag();
+    return a2dp_ack_to_bt_audio_ctrl_ack(A2DP_CTRL_ACK_SUCCESS);
+  }
+
+  void StopRequest() override {
+    if (btif_av_get_peer_sep() == AVDT_TSEP_SNK &&
+        !btif_a2dp_source_is_streaming()) {
+      return;
+    }
+    LOG(INFO) << __func__ << ": handling";
+    a2dp_pending_cmd_ = A2DP_CTRL_CMD_STOP;
+    btif_av_stream_stop(RawAddress::kEmpty);
+  }
+
+  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
+                               uint64_t* total_bytes_read,
+                               timespec* data_position) override {
+    *remote_delay_report_ns = remote_delay_report_ * 100000u;
+    *total_bytes_read = total_bytes_read_;
+    *data_position = data_position_;
+    VLOG(2) << __func__ << ": delay=" << remote_delay_report_
+            << "/10ms, data=" << total_bytes_read_
+            << " byte(s), timestamp=" << data_position_.tv_sec << "."
+            << data_position_.tv_nsec << "s";
+    return true;
+  }
+
+  void MetadataChanged(const source_metadata_t& source_metadata) override {
+    auto track_count = source_metadata.track_count;
+    auto tracks = source_metadata.tracks;
+    VLOG(1) << __func__ << ": " << track_count << " track(s) received";
+    while (track_count) {
+      VLOG(2) << __func__ << ": usage=" << tracks->usage
+              << ", content_type=" << tracks->content_type
+              << ", gain=" << tracks->gain;
+      --track_count;
+      ++tracks;
+    }
+  }
+
+  tA2DP_CTRL_CMD GetPendingCmd() const { return a2dp_pending_cmd_; }
+
+  void ResetPendingCmd() { a2dp_pending_cmd_ = A2DP_CTRL_CMD_NONE; }
+
+  void ResetPresentationPosition() override {
+    remote_delay_report_ = 0;
+    total_bytes_read_ = 0;
+    data_position_ = {};
+  }
+
+  void LogBytesRead(size_t bytes_read) override {
+    if (bytes_read != 0) {
+      total_bytes_read_ += bytes_read;
+      clock_gettime(CLOCK_MONOTONIC, &data_position_);
+    }
+  }
+
+  // delay reports from AVDTP is based on 1/10 ms (100us)
+  void SetRemoteDelay(uint16_t delay_report) {
+    remote_delay_report_ = delay_report;
+  }
+
+ private:
+  tA2DP_CTRL_CMD a2dp_pending_cmd_;
+  uint16_t remote_delay_report_;
+  uint64_t total_bytes_read_;
+  timespec data_position_;
+};
+
+A2dpTransport* a2dp_sink = nullptr;
+
+// Common interface to call-out into Bluetooth Audio HAL
+bluetooth::audio::BluetoothAudioClientInterface* a2dp_hal_clientif = nullptr;
+auto session_type = SessionType::UNKNOWN;
+
+// Save the value if the remote reports its delay before a2dp_sink is
+// initialized
+uint16_t remote_delay = 0;
+
+bool btaudio_a2dp_disabled = false;
+bool is_configured = false;
+
+BluetoothAudioCtrlAck a2dp_ack_to_bt_audio_ctrl_ack(tA2DP_CTRL_ACK ack) {
+  switch (ack) {
+    case A2DP_CTRL_ACK_SUCCESS:
+      return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
+    case A2DP_CTRL_ACK_PENDING:
+      return BluetoothAudioCtrlAck::PENDING;
+    case A2DP_CTRL_ACK_INCALL_FAILURE:
+      return BluetoothAudioCtrlAck::FAILURE_BUSY;
+    case A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS:
+      return BluetoothAudioCtrlAck::FAILURE_DISCONNECTING;
+    case A2DP_CTRL_ACK_UNSUPPORTED: /* Offloading but resource failure */
+      return BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED;
+    case A2DP_CTRL_ACK_FAILURE:
+      return BluetoothAudioCtrlAck::FAILURE;
+    default:
+      return BluetoothAudioCtrlAck::FAILURE;
+  }
+}
+
+SampleRate a2dp_codec_to_hal_sample_rate(
+    const btav_a2dp_codec_config_t& a2dp_codec_config) {
+  switch (a2dp_codec_config.sample_rate) {
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
+      return SampleRate::RATE_44100;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_48000:
+      return SampleRate::RATE_48000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_88200:
+      return SampleRate::RATE_88200;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_96000:
+      return SampleRate::RATE_96000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_176400:
+      return SampleRate::RATE_176400;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_192000:
+      return SampleRate::RATE_192000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
+      return SampleRate::RATE_16000;
+    case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
+      return SampleRate::RATE_24000;
+    default:
+      return SampleRate::RATE_UNKNOWN;
+  }
+}
+
+BitsPerSample a2dp_codec_to_hal_bits_per_sample(
+    const btav_a2dp_codec_config_t& a2dp_codec_config) {
+  switch (a2dp_codec_config.bits_per_sample) {
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
+      return BitsPerSample::BITS_16;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
+      return BitsPerSample::BITS_24;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
+      return BitsPerSample::BITS_32;
+    default:
+      return BitsPerSample::BITS_UNKNOWN;
+  }
+}
+
+ChannelMode a2dp_codec_to_hal_channel_mode(
+    const btav_a2dp_codec_config_t& a2dp_codec_config) {
+  switch (a2dp_codec_config.channel_mode) {
+    case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
+      return ChannelMode::MONO;
+    case BTAV_A2DP_CODEC_CHANNEL_MODE_STEREO:
+      return ChannelMode::STEREO;
+    default:
+      return ChannelMode::UNKNOWN;
+  }
+}
+
+bool a2dp_get_selected_hal_codec_config(CodecConfiguration* codec_config) {
+  A2dpCodecConfig* a2dp_codec_configs = bta_av_get_a2dp_current_codec();
+  if (a2dp_codec_configs == nullptr) {
+    LOG(WARNING) << __func__ << ": failure to get A2DP codec config";
+    *codec_config = kInvalidCodecConfiguration;
+    return false;
+  }
+  btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig();
+  tBT_A2DP_OFFLOAD a2dp_offload;
+  a2dp_codec_configs->getCodecSpecificConfig(&a2dp_offload);
+  switch (current_codec.codec_type) {
+    case BTAV_A2DP_CODEC_INDEX_SOURCE_SBC:
+      [[fallthrough]];
+    case BTAV_A2DP_CODEC_INDEX_SINK_SBC: {
+      codec_config->codecType = CodecType::SBC;
+      codec_config->config.sbcConfig({});
+      auto sbc_config = codec_config->config.sbcConfig();
+      sbc_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
+      if (sbc_config.sampleRate == SampleRate::RATE_UNKNOWN) {
+        LOG(ERROR) << __func__
+                   << ": Unknown SBC sample_rate=" << current_codec.sample_rate;
+        return false;
+      }
+      uint8_t channel_mode = a2dp_offload.codec_info[3] & A2DP_SBC_IE_CH_MD_MSK;
+      switch (channel_mode) {
+        case A2DP_SBC_IE_CH_MD_JOINT:
+          sbc_config.channelMode = SbcChannelMode::JOINT_STEREO;
+          break;
+        case A2DP_SBC_IE_CH_MD_STEREO:
+          sbc_config.channelMode = SbcChannelMode::STEREO;
+          break;
+        case A2DP_SBC_IE_CH_MD_DUAL:
+          sbc_config.channelMode = SbcChannelMode::DUAL;
+          break;
+        case A2DP_SBC_IE_CH_MD_MONO:
+          sbc_config.channelMode = SbcChannelMode::MONO;
+          break;
+        default:
+          LOG(ERROR) << __func__
+                     << ": Unknown SBC channel_mode=" << channel_mode;
+          sbc_config.channelMode = SbcChannelMode::UNKNOWN;
+          return false;
+      }
+      uint8_t block_length =
+          a2dp_offload.codec_info[0] & A2DP_SBC_IE_BLOCKS_MSK;
+      switch (block_length) {
+        case A2DP_SBC_IE_BLOCKS_4:
+          sbc_config.blockLength = SbcBlockLength::BLOCKS_4;
+          break;
+        case A2DP_SBC_IE_BLOCKS_8:
+          sbc_config.blockLength = SbcBlockLength::BLOCKS_8;
+          break;
+        case A2DP_SBC_IE_BLOCKS_12:
+          sbc_config.blockLength = SbcBlockLength::BLOCKS_12;
+          break;
+        case A2DP_SBC_IE_BLOCKS_16:
+          sbc_config.blockLength = SbcBlockLength::BLOCKS_16;
+          break;
+        default:
+          LOG(ERROR) << __func__
+                     << ": Unknown SBC block_length=" << block_length;
+          return false;
+      }
+      uint8_t sub_bands = a2dp_offload.codec_info[0] & A2DP_SBC_IE_SUBBAND_MSK;
+      switch (sub_bands) {
+        case A2DP_SBC_IE_SUBBAND_4:
+          sbc_config.numSubbands = SbcNumSubbands::SUBBAND_4;
+          break;
+        case A2DP_SBC_IE_SUBBAND_8:
+          sbc_config.numSubbands = SbcNumSubbands::SUBBAND_8;
+          break;
+        default:
+          LOG(ERROR) << __func__ << ": Unknown SBC Subbands=" << sub_bands;
+          return false;
+      }
+      uint8_t alloc_method =
+          a2dp_offload.codec_info[0] & A2DP_SBC_IE_ALLOC_MD_MSK;
+      switch (alloc_method) {
+        case A2DP_SBC_IE_ALLOC_MD_S:
+          sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_S;
+          break;
+        case A2DP_SBC_IE_ALLOC_MD_L:
+          sbc_config.allocMethod = SbcAllocMethod::ALLOC_MD_L;
+          break;
+        default:
+          LOG(ERROR) << __func__
+                     << ": Unknown SBC alloc_method=" << alloc_method;
+          return false;
+      }
+      sbc_config.minBitpool = a2dp_offload.codec_info[1];
+      sbc_config.maxBitpool = a2dp_offload.codec_info[2];
+      sbc_config.bitsPerSample =
+          a2dp_codec_to_hal_bits_per_sample(current_codec);
+      if (sbc_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown SBC bits_per_sample="
+                   << current_codec.bits_per_sample;
+        return false;
+      }
+      codec_config->config.sbcConfig(sbc_config);
+      break;
+    }
+    case BTAV_A2DP_CODEC_INDEX_SOURCE_AAC:
+      [[fallthrough]];
+    case BTAV_A2DP_CODEC_INDEX_SINK_AAC: {
+      codec_config->codecType = CodecType::AAC;
+      codec_config->config.aacConfig({});
+      auto aac_config = codec_config->config.aacConfig();
+      uint8_t object_type = a2dp_offload.codec_info[0];
+      switch (object_type) {
+        case A2DP_AAC_OBJECT_TYPE_MPEG2_LC:
+          aac_config.objectType = AacObjectType::MPEG2_LC;
+          break;
+        case A2DP_AAC_OBJECT_TYPE_MPEG4_LC:
+          aac_config.objectType = AacObjectType::MPEG4_LC;
+          break;
+        case A2DP_AAC_OBJECT_TYPE_MPEG4_LTP:
+          aac_config.objectType = AacObjectType::MPEG4_LTP;
+          break;
+        case A2DP_AAC_OBJECT_TYPE_MPEG4_SCALABLE:
+          aac_config.objectType = AacObjectType::MPEG4_SCALABLE;
+          break;
+        default:
+          LOG(ERROR) << __func__
+                     << ": Unknown AAC object_type=" << +object_type;
+          return false;
+      }
+      aac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
+      if (aac_config.sampleRate == SampleRate::RATE_UNKNOWN) {
+        LOG(ERROR) << __func__
+                   << ": Unknown AAC sample_rate=" << current_codec.sample_rate;
+        return false;
+      }
+      aac_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec);
+      if (aac_config.channelMode == ChannelMode::UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown AAC channel_mode="
+                   << current_codec.channel_mode;
+        return false;
+      }
+      uint8_t vbr_enabled =
+          a2dp_offload.codec_info[1] & A2DP_AAC_VARIABLE_BIT_RATE_MASK;
+      switch (vbr_enabled) {
+        case A2DP_AAC_VARIABLE_BIT_RATE_ENABLED:
+          aac_config.variableBitRateEnabled = AacVariableBitRate::ENABLED;
+          break;
+        case A2DP_AAC_VARIABLE_BIT_RATE_DISABLED:
+          aac_config.variableBitRateEnabled = AacVariableBitRate::DISABLED;
+          break;
+        default:
+          LOG(ERROR) << __func__ << ": Unknown AAC VBR=" << +vbr_enabled;
+          return false;
+      }
+      aac_config.bitsPerSample =
+          a2dp_codec_to_hal_bits_per_sample(current_codec);
+      if (aac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown AAC bits_per_sample="
+                   << current_codec.bits_per_sample;
+        return false;
+      }
+      codec_config->config.aacConfig(aac_config);
+      break;
+    }
+    case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX:
+      [[fallthrough]];
+    case BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD: {
+      if (current_codec.codec_type == BTAV_A2DP_CODEC_INDEX_SOURCE_APTX) {
+        codec_config->codecType = CodecType::APTX;
+      } else {
+        codec_config->codecType = CodecType::APTX_HD;
+      }
+      codec_config->config.aptxConfig({});
+      auto aptx_config = codec_config->config.aptxConfig();
+      aptx_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
+      if (aptx_config.sampleRate == SampleRate::RATE_UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown aptX sample_rate="
+                   << current_codec.sample_rate;
+        return false;
+      }
+      aptx_config.channelMode = a2dp_codec_to_hal_channel_mode(current_codec);
+      if (aptx_config.channelMode == ChannelMode::UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown aptX channel_mode="
+                   << current_codec.channel_mode;
+        return false;
+      }
+      aptx_config.bitsPerSample =
+          a2dp_codec_to_hal_bits_per_sample(current_codec);
+      if (aptx_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown aptX bits_per_sample="
+                   << current_codec.bits_per_sample;
+        return false;
+      }
+      codec_config->config.aptxConfig(aptx_config);
+      break;
+    }
+    case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC: {
+      codec_config->codecType = CodecType::LDAC;
+      codec_config->config.ldacConfig({});
+      auto ldac_config = codec_config->config.ldacConfig();
+      ldac_config.sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
+      if (ldac_config.sampleRate == SampleRate::RATE_UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown LDAC sample_rate="
+                   << current_codec.sample_rate;
+        return false;
+      }
+      switch (a2dp_offload.codec_info[7]) {
+        case A2DP_LDAC_CHANNEL_MODE_STEREO:
+          ldac_config.channelMode = LdacChannelMode::STEREO;
+          break;
+        case A2DP_LDAC_CHANNEL_MODE_DUAL:
+          ldac_config.channelMode = LdacChannelMode::DUAL;
+          break;
+        case A2DP_LDAC_CHANNEL_MODE_MONO:
+          ldac_config.channelMode = LdacChannelMode::MONO;
+          break;
+        default:
+          LOG(ERROR) << __func__ << ": Unknown LDAC channel_mode="
+                     << a2dp_offload.codec_info[7];
+          ldac_config.channelMode = LdacChannelMode::UNKNOWN;
+          return false;
+      }
+      switch (a2dp_offload.codec_info[6]) {
+        case A2DP_LDAC_QUALITY_HIGH:
+          ldac_config.qualityIndex = LdacQualityIndex::QUALITY_HIGH;
+          break;
+        case A2DP_LDAC_QUALITY_MID:
+          ldac_config.qualityIndex = LdacQualityIndex::QUALITY_MID;
+          break;
+        case A2DP_LDAC_QUALITY_LOW:
+          ldac_config.qualityIndex = LdacQualityIndex::QUALITY_LOW;
+          break;
+        case A2DP_LDAC_QUALITY_ABR_OFFLOAD:
+          ldac_config.qualityIndex = LdacQualityIndex::QUALITY_ABR;
+          break;
+        default:
+          LOG(ERROR) << __func__ << ": Unknown LDAC QualityIndex="
+                     << a2dp_offload.codec_info[6];
+          return false;
+      }
+      ldac_config.bitsPerSample =
+          a2dp_codec_to_hal_bits_per_sample(current_codec);
+      if (ldac_config.bitsPerSample == BitsPerSample::BITS_UNKNOWN) {
+        LOG(ERROR) << __func__ << ": Unknown LDAC bits_per_sample="
+                   << current_codec.bits_per_sample;
+        return false;
+      }
+      codec_config->config.ldacConfig(ldac_config);
+      break;
+    }
+    case BTAV_A2DP_CODEC_INDEX_MAX:
+      [[fallthrough]];
+    default:
+      LOG(ERROR) << __func__
+                 << ": Unknown codec_type=" << current_codec.codec_type;
+      codec_config->codecType = CodecType::UNKNOWN;
+      codec_config->config = {};
+      return false;
+  }
+  codec_config->encodedAudioBitrate = a2dp_codec_configs->getTrackBitRate();
+  // Obtain the MTU
+  RawAddress peer_addr = btif_av_source_active_peer();
+  tA2DP_ENCODER_INIT_PEER_PARAMS peer_param;
+  bta_av_co_get_peer_params(peer_addr, &peer_param);
+  int effectiveMtu = a2dp_codec_configs->getEffectiveMtu();
+  if (effectiveMtu > 0 && effectiveMtu < peer_param.peer_mtu) {
+    codec_config->peerMtu = effectiveMtu;
+  } else {
+    codec_config->peerMtu = peer_param.peer_mtu;
+  }
+  LOG(INFO) << __func__ << ": CodecConfiguration=" << toString(*codec_config);
+  return true;
+}
+
+bool a2dp_get_selected_hal_pcm_config(PcmParameters* pcm_config) {
+  if (pcm_config == nullptr) return false;
+  A2dpCodecConfig* a2dp_codec_configs = bta_av_get_a2dp_current_codec();
+  if (a2dp_codec_configs == nullptr) {
+    LOG(WARNING) << __func__ << ": failure to get A2DP codec config";
+    *pcm_config = ::bluetooth::audio::BluetoothAudioClientInterface::
+        kInvalidPcmConfiguration;
+    return false;
+  }
+
+  btav_a2dp_codec_config_t current_codec = a2dp_codec_configs->getCodecConfig();
+  pcm_config->sampleRate = a2dp_codec_to_hal_sample_rate(current_codec);
+  pcm_config->bitsPerSample = a2dp_codec_to_hal_bits_per_sample(current_codec);
+  pcm_config->channelMode = a2dp_codec_to_hal_channel_mode(current_codec);
+  return (pcm_config->sampleRate != SampleRate::RATE_UNKNOWN &&
+          pcm_config->bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
+          pcm_config->channelMode != ChannelMode::UNKNOWN);
+}
+
+// Checking if new bluetooth_audio is supported
+bool is_hal_2_0_force_disabled() {
+  if (!is_configured) {
+    btaudio_a2dp_disabled = osi_property_get_bool(BLUETOOTH_AUDIO_HAL_PROP_DISABLED, false);
+    is_configured = true;
+  }
+  return btaudio_a2dp_disabled;
+}
+
+}  // namespace
+
+namespace bluetooth {
+namespace audio {
+namespace a2dp {
+
+// Checking if new bluetooth_audio is enabled
+bool is_hal_2_0_enabled() { return a2dp_hal_clientif != nullptr; }
+
+// Initialize BluetoothAudio HAL: openProvider
+bool init(bluetooth::common::MessageLoopThread* message_loop) {
+  LOG(INFO) << __func__;
+
+  if (is_hal_2_0_force_disabled()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudio HAL is disabled";
+    return false;
+  }
+
+  if (btif_av_is_a2dp_offload_enabled()) {
+    session_type = SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH;
+  } else {
+    session_type = SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH;
+  }
+  a2dp_sink = new A2dpTransport(session_type);
+  a2dp_hal_clientif = new bluetooth::audio::BluetoothAudioClientInterface(
+      a2dp_sink, message_loop);
+  if (!a2dp_hal_clientif->IsValid()) {
+    LOG(WARNING) << __func__ << ": BluetoothAudio HAL for A2DP session=" << toString(session_type) << " is invalid?!";
+    delete a2dp_hal_clientif;
+    a2dp_hal_clientif = nullptr;
+    delete a2dp_sink;
+    a2dp_sink = nullptr;
+    return false;
+  }
+
+  if (remote_delay != 0) {
+    LOG(INFO) << __func__ << ": restore DELAY "
+              << static_cast<float>(remote_delay / 10.0) << " ms";
+    a2dp_sink->SetRemoteDelay(remote_delay);
+    remote_delay = 0;
+  }
+  return true;
+}
+
+// Clean up BluetoothAudio HAL
+void cleanup() {
+  if (!is_hal_2_0_enabled()) return;
+  end_session();
+  delete a2dp_hal_clientif;
+  a2dp_hal_clientif = nullptr;
+  delete a2dp_sink;
+  a2dp_sink = nullptr;
+  session_type = SessionType::UNKNOWN;
+  remote_delay = 0;
+}
+
+// Set up the codec into BluetoothAudio HAL
+bool setup_codec() {
+  if (!is_hal_2_0_enabled()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled";
+    return false;
+  }
+  AudioConfiguration audio_config{};
+  if (session_type == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH) {
+    CodecConfiguration codec_config{};
+    if (!a2dp_get_selected_hal_codec_config(&codec_config)) {
+      LOG(ERROR) << __func__ << ": Failed to get CodecConfiguration";
+      return false;
+    }
+    audio_config.codecConfig(codec_config);
+  } else if (session_type == SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH) {
+    PcmParameters pcm_config{};
+    if (!a2dp_get_selected_hal_pcm_config(&pcm_config)) {
+      LOG(ERROR) << __func__ << ": Failed to get PcmConfiguration";
+      return false;
+    }
+    audio_config.pcmConfig(pcm_config);
+  }
+  return a2dp_hal_clientif->UpdateAudioConfig(audio_config);
+}
+
+void start_session() {
+  if (!is_hal_2_0_enabled()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled";
+    return;
+  }
+  a2dp_hal_clientif->StartSession();
+}
+
+void end_session() {
+  if (!is_hal_2_0_enabled()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled";
+    return;
+  }
+  a2dp_hal_clientif->EndSession();
+}
+
+void ack_stream_started(const tA2DP_CTRL_ACK& ack) {
+  auto ctrl_ack = a2dp_ack_to_bt_audio_ctrl_ack(ack);
+  LOG(INFO) << __func__ << ": result=" << ctrl_ack;
+  auto pending_cmd = a2dp_sink->GetPendingCmd();
+  if (pending_cmd == A2DP_CTRL_CMD_START) {
+    a2dp_hal_clientif->StreamStarted(ctrl_ack);
+  } else {
+    LOG(WARNING) << __func__ << ": pending=" << pending_cmd
+                 << " ignore result=" << ctrl_ack;
+    return;
+  }
+  if (ctrl_ack != bluetooth::audio::BluetoothAudioCtrlAck::PENDING) {
+    a2dp_sink->ResetPendingCmd();
+  }
+}
+
+void ack_stream_suspended(const tA2DP_CTRL_ACK& ack) {
+  auto ctrl_ack = a2dp_ack_to_bt_audio_ctrl_ack(ack);
+  LOG(INFO) << __func__ << ": result=" << ctrl_ack;
+  auto pending_cmd = a2dp_sink->GetPendingCmd();
+  if (pending_cmd == A2DP_CTRL_CMD_SUSPEND) {
+    a2dp_hal_clientif->StreamSuspended(ctrl_ack);
+  } else if (pending_cmd == A2DP_CTRL_CMD_STOP) {
+    LOG(INFO) << __func__ << ": A2DP_CTRL_CMD_STOP result=" << ctrl_ack;
+  } else {
+    LOG(WARNING) << __func__ << ": pending=" << pending_cmd
+                 << " ignore result=" << ctrl_ack;
+    return;
+  }
+  if (ctrl_ack != bluetooth::audio::BluetoothAudioCtrlAck::PENDING) {
+    a2dp_sink->ResetPendingCmd();
+  }
+}
+
+// Read from the FMQ of BluetoothAudio HAL
+size_t read(uint8_t* p_buf, uint32_t len) {
+  if (!is_hal_2_0_enabled()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudio HAL is not enabled";
+    return 0;
+  } else if (session_type != SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH) {
+    LOG(ERROR) << __func__ << ": session_type=" << toString(session_type)
+               << " is not A2DP_SOFTWARE_ENCODING_DATAPATH";
+    return 0;
+  }
+  return a2dp_hal_clientif->ReadAudioData(p_buf, len);
+}
+
+// Update A2DP delay report to BluetoothAudio HAL
+void set_remote_delay(uint16_t delay_report) {
+  if (!is_hal_2_0_enabled()) {
+    LOG(INFO) << __func__ << ":  not ready for DelayReport "
+              << static_cast<float>(delay_report / 10.0) << " ms";
+    remote_delay = delay_report;
+    return;
+  }
+  LOG(INFO) << __func__ << ": DELAY " << static_cast<float>(delay_report / 10.0)
+            << " ms";
+  a2dp_sink->SetRemoteDelay(delay_report);
+}
+
+}  // namespace a2dp
+}  // namespace audio
+}  // namespace bluetooth
diff --git a/audio_hal_interface/a2dp_encoding.h b/audio_hal_interface/a2dp_encoding.h
new file mode 100644
index 0000000..7b104ff
--- /dev/null
+++ b/audio_hal_interface/a2dp_encoding.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "audio_a2dp_hw/include/audio_a2dp_hw.h"
+#include "common/message_loop_thread.h"
+
+namespace bluetooth {
+namespace audio {
+namespace a2dp {
+
+// Check if new bluetooth_audio is enabled
+bool is_hal_2_0_enabled();
+
+// Initialize BluetoothAudio HAL: openProvider
+bool init(bluetooth::common::MessageLoopThread* message_loop);
+
+// Clean up BluetoothAudio HAL
+void cleanup();
+
+// Set up the codec into BluetoothAudio HAL
+bool setup_codec();
+
+// Send command to the BluetoothAudio HAL: StartSession, EndSession,
+// StreamStarted, StreamSuspended
+void start_session();
+void end_session();
+void ack_stream_started(const tA2DP_CTRL_ACK& status);
+void ack_stream_suspended(const tA2DP_CTRL_ACK& status);
+
+// Read from the FMQ of BluetoothAudio HAL
+size_t read(uint8_t* p_buf, uint32_t len);
+
+// Update A2DP delay report to BluetoothAudio HAL
+void set_remote_delay(uint16_t delay_report);
+
+}  // namespace a2dp
+}  // namespace audio
+}  // namespace bluetooth
diff --git a/audio_hal_interface/client_interface.cc b/audio_hal_interface/client_interface.cc
new file mode 100644
index 0000000..501e113
--- /dev/null
+++ b/audio_hal_interface/client_interface.cc
@@ -0,0 +1,499 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioClientIf"
+
+#include "client_interface.h"
+
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioPort.h>
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvidersFactory.h>
+#include <android/hidl/manager/1.2/IServiceManager.h>
+#include <base/logging.h>
+#include <hidl/MQDescriptor.h>
+#include <hidl/ServiceManagement.h>
+#include <future>
+
+#include "osi/include/log.h"
+
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::hidl_vec;
+using ::android::hardware::Return;
+using ::android::hardware::Void;
+using ::android::hardware::audio::common::V5_0::SourceMetadata;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioPort;
+using ::android::hardware::bluetooth::audio::V2_0::
+    IBluetoothAudioProvidersFactory;
+using DataMQ = ::android::hardware::MessageQueue<
+    uint8_t, ::android::hardware::kSynchronizedReadWrite>;
+
+static constexpr int kDefaultDataReadTimeoutMs = 10;      // 10 ms
+static constexpr int kDefaultDataReadPollIntervalMs = 1;  // non-blocking poll
+static constexpr char kFullyQualifiedInterfaceName[] =
+    "android.hardware.bluetooth.audio@2.0::IBluetoothAudioProvidersFactory";
+
+std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack) {
+  switch (ack) {
+    case BluetoothAudioCtrlAck::SUCCESS_FINISHED:
+      return os << "SUCCESS_FINISHED";
+    case BluetoothAudioCtrlAck::PENDING:
+      return os << "PENDING";
+    case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED:
+      return os << "FAILURE_UNSUPPORTED";
+    case BluetoothAudioCtrlAck::FAILURE_BUSY:
+      return os << "FAILURE_BUSY";
+    case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING:
+      return os << "FAILURE_DISCONNECTING";
+    case BluetoothAudioCtrlAck::FAILURE:
+      return os << "FAILURE";
+    default:
+      return os << "UNDEFINED " << static_cast<int8_t>(ack);
+  }
+}
+
+// Internal class within BluetoothAudioClientInterfaceace to implement
+// IBluetoothAudioPort (control interface used by Bluetooth Audio HAL)
+class BluetoothAudioPortImpl : public IBluetoothAudioPort {
+ public:
+  BluetoothAudioPortImpl(IBluetoothTransportInstance* sink,
+                         const android::sp<IBluetoothAudioProvider>& provider)
+      : sink_(sink), provider_(provider){};
+
+  Return<void> startStream() {
+    BluetoothAudioCtrlAck ack = sink_->StartRequest();
+    if (ack != BluetoothAudioCtrlAck::PENDING) {
+      auto hidl_retval =
+          provider_->streamStarted(BluetoothAudioCtrlAckToHalStatus(ack));
+      if (!hidl_retval.isOk()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
+      }
+    }
+    return Void();
+  }
+
+  Return<void> suspendStream() {
+    BluetoothAudioCtrlAck ack = sink_->SuspendRequest();
+    if (ack != BluetoothAudioCtrlAck::PENDING) {
+      auto hidl_retval =
+          provider_->streamSuspended(BluetoothAudioCtrlAckToHalStatus(ack));
+      if (!hidl_retval.isOk()) {
+        LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
+      }
+    }
+    return Void();
+  }
+
+  Return<void> stopStream() {
+    sink_->StopRequest();
+    return Void();
+  }
+
+  Return<void> getPresentationPosition(getPresentationPosition_cb _hidl_cb) {
+    uint64_t remote_delay_report_ns;
+    uint64_t total_bytes_read;
+    timespec data_position;
+    bool retval = sink_->GetPresentationPosition(
+        &remote_delay_report_ns, &total_bytes_read, &data_position);
+
+    TimeSpec transmittedOctetsTimeStamp;
+    if (retval) {
+      transmittedOctetsTimeStamp = timespec_convert_to_hal(data_position);
+    } else {
+      remote_delay_report_ns = 0;
+      total_bytes_read = 0;
+      transmittedOctetsTimeStamp = {};
+    }
+    VLOG(2) << __func__ << ": result=" << retval
+            << ", delay=" << remote_delay_report_ns
+            << ", data=" << total_bytes_read
+            << " byte(s), timestamp=" << toString(transmittedOctetsTimeStamp);
+    _hidl_cb((retval ? BluetoothAudioStatus::SUCCESS
+                     : BluetoothAudioStatus::FAILURE),
+             remote_delay_report_ns, total_bytes_read,
+             transmittedOctetsTimeStamp);
+    return Void();
+  }
+
+  Return<void> updateMetadata(const SourceMetadata& sourceMetadata) {
+    LOG(INFO) << __func__ << ": " << sourceMetadata.tracks.size()
+              << " track(s)";
+    // refer to StreamOut.impl.h within Audio HAL (AUDIO_HAL_VERSION_5_0)
+    std::vector<playback_track_metadata> metadata_vec;
+    metadata_vec.reserve(sourceMetadata.tracks.size());
+    for (const auto& metadata : sourceMetadata.tracks) {
+      metadata_vec.push_back({
+          .usage = static_cast<audio_usage_t>(metadata.usage),
+          .content_type =
+              static_cast<audio_content_type_t>(metadata.contentType),
+          .gain = metadata.gain,
+      });
+    }
+    const source_metadata_t source_metadata = {
+        .track_count = metadata_vec.size(), .tracks = metadata_vec.data()};
+    sink_->MetadataChanged(source_metadata);
+    return Void();
+  }
+
+ private:
+  IBluetoothTransportInstance* sink_;
+  const android::sp<IBluetoothAudioProvider> provider_;
+  TimeSpec timespec_convert_to_hal(const timespec& ts) {
+    return {.tvSec = static_cast<uint64_t>(ts.tv_sec),
+            .tvNSec = static_cast<uint64_t>(ts.tv_nsec)};
+  }
+};
+
+class BluetoothAudioDeathRecipient
+    : public ::android::hardware::hidl_death_recipient {
+ public:
+  BluetoothAudioDeathRecipient(
+      BluetoothAudioClientInterface* clientif,
+      bluetooth::common::MessageLoopThread* message_loop)
+      : bluetooth_audio_clientif_(clientif), message_loop_(message_loop) {}
+  void serviceDied(
+      uint64_t /*cookie*/,
+      const ::android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+    LOG(WARNING) << __func__ << ": restarting connection with new Audio Hal";
+    if (bluetooth_audio_clientif_ != nullptr && message_loop_ != nullptr) {
+      // restart the session on the correct thread
+      message_loop_->DoInThread(
+          FROM_HERE,
+          base::BindOnce(
+              &BluetoothAudioClientInterface::RenewAudioProviderAndSession,
+              base::Unretained(bluetooth_audio_clientif_)));
+    } else {
+      LOG(ERROR) << __func__ << ": BluetoothAudioClientInterface corrupted";
+    }
+  }
+
+ private:
+  BluetoothAudioClientInterface* bluetooth_audio_clientif_;
+  bluetooth::common::MessageLoopThread* message_loop_;
+};
+
+BluetoothAudioClientInterface::BluetoothAudioClientInterface(IBluetoothTransportInstance* sink,
+                                                             bluetooth::common::MessageLoopThread* message_loop)
+    : sink_(sink), provider_(nullptr), session_started_(false), mDataMQ(nullptr),
+      death_recipient_(new BluetoothAudioDeathRecipient(this, message_loop)) {
+  auto service_manager = android::hardware::defaultServiceManager1_2();
+  CHECK(service_manager != nullptr);
+  size_t instance_count = 0;
+  auto listManifestByInterface_cb = [&instance_count](const hidl_vec<android::hardware::hidl_string>& instanceNames) {
+    instance_count = instanceNames.size();
+    LOG(INFO) << "listManifestByInterface_cb returns " << instance_count << " instance(s)";
+  };
+  auto hidl_retval = service_manager->listManifestByInterface(kFullyQualifiedInterfaceName, listManifestByInterface_cb);
+  if (!hidl_retval.isOk()) {
+    LOG(FATAL) << __func__ << ": IServiceManager::listByInterface failure: " << hidl_retval.description();
+  }
+  if (instance_count > 0) {
+    fetch_audio_provider();
+  } else {
+    LOG(WARNING) << "IBluetoothAudioProvidersFactory not declared";
+  }
+}
+
+BluetoothAudioClientInterface::~BluetoothAudioClientInterface() {
+  if (provider_ != nullptr) {
+    auto hidl_retval = provider_->unlinkToDeath(death_recipient_);
+    if (!hidl_retval.isOk()) {
+      LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " << hidl_retval.description();
+    }
+  }
+}
+
+std::vector<AudioCapabilities>
+BluetoothAudioClientInterface::GetAudioCapabilities() const {
+  return capabilities_;
+}
+
+void BluetoothAudioClientInterface::fetch_audio_provider() {
+  if (provider_ != nullptr) {
+    LOG(WARNING) << __func__ << ": reflash";
+  }
+
+  android::sp<IBluetoothAudioProvidersFactory> providersFactory =
+      IBluetoothAudioProvidersFactory::getService();
+  CHECK(providersFactory != nullptr) << "IBluetoothAudioProvidersFactory::getService() failed";
+  LOG(INFO) << "IBluetoothAudioProvidersFactory::getService() returned "
+            << providersFactory.get()
+            << (providersFactory->isRemote() ? " (remote)" : " (local)");
+
+  std::promise<void> getProviderCapabilities_promise;
+  auto getProviderCapabilities_future =
+      getProviderCapabilities_promise.get_future();
+  auto getProviderCapabilities_cb =
+      [& capabilities = this->capabilities_, &getProviderCapabilities_promise](
+          const hidl_vec<AudioCapabilities>& audioCapabilities) {
+        for (auto capability : audioCapabilities) {
+          capabilities.push_back(capability);
+        }
+        getProviderCapabilities_promise.set_value();
+      };
+  auto hidl_retval = providersFactory->getProviderCapabilities(
+      sink_->GetSessionType(), getProviderCapabilities_cb);
+  getProviderCapabilities_future.get();
+  if (!hidl_retval.isOk()) {
+    LOG(FATAL) << __func__ << ": BluetoothAudioHal::getProviderCapabilities failure: " << hidl_retval.description();
+    return;
+  }
+  if (capabilities_.empty()) {
+    LOG(WARNING) << __func__
+                 << ": SessionType=" << toString(sink_->GetSessionType())
+                 << " Not supported by BluetoothAudioHal";
+    return;
+  }
+  LOG(INFO) << __func__ << ": BluetoothAudioHal SessionType="
+            << toString(sink_->GetSessionType()) << " has "
+            << capabilities_.size() << " AudioCapabilities";
+
+  std::promise<void> openProvider_promise;
+  auto openProvider_future = openProvider_promise.get_future();
+  auto openProvider_cb =
+      [& provider_ = this->provider_, &openProvider_promise](
+          BluetoothAudioStatus status,
+          const android::sp<IBluetoothAudioProvider>& provider) {
+        LOG(INFO) << "openProvider_cb(" << toString(status) << ")";
+        if (status == BluetoothAudioStatus::SUCCESS) {
+          provider_ = provider;
+        }
+        ALOGE_IF(!provider_, "Failed to open BluetoothAudio provider");
+        openProvider_promise.set_value();
+      };
+  hidl_retval =
+      providersFactory->openProvider(sink_->GetSessionType(), openProvider_cb);
+  openProvider_future.get();
+  if (!hidl_retval.isOk()) {
+    LOG(FATAL) << __func__ << ": BluetoothAudioHal::openProvider failure: " << hidl_retval.description();
+  }
+  CHECK(provider_ != nullptr);
+
+  if (!provider_->linkToDeath(death_recipient_, 0).isOk()) {
+    LOG(FATAL) << __func__ << ": BluetoothAudioDeathRecipient failure: " << hidl_retval.description();
+  }
+
+  LOG(INFO) << "IBluetoothAudioProvidersFactory::openProvider() returned "
+            << provider_.get()
+            << (provider_->isRemote() ? " (remote)" : " (local)");
+}
+
+bool BluetoothAudioClientInterface::UpdateAudioConfig(
+    const AudioConfiguration& audio_config) {
+  bool is_software_session =
+      (sink_->GetSessionType() ==
+           SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH ||
+       sink_->GetSessionType() ==
+           SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+  bool is_offload_session =
+      (sink_->GetSessionType() == SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  auto audio_config_discriminator = audio_config.getDiscriminator();
+  bool is_software_audio_config =
+      (is_software_session &&
+       audio_config_discriminator ==
+           AudioConfiguration::hidl_discriminator::pcmConfig);
+  bool is_offload_audio_config =
+      (is_offload_session &&
+       audio_config_discriminator ==
+           AudioConfiguration::hidl_discriminator::codecConfig);
+  if (!is_software_audio_config && !is_offload_audio_config) {
+    return false;
+  }
+  sink_->UpdateAudioConfiguration(audio_config);
+  return true;
+}
+
+int BluetoothAudioClientInterface::StartSession() {
+  std::lock_guard<std::mutex> guard(internal_mutex_);
+  if (provider_ == nullptr) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
+    session_started_ = false;
+    return -EINVAL;
+  }
+  if (session_started_) {
+    LOG(ERROR) << __func__ << ": session started already";
+    return -EBUSY;
+  }
+
+  android::sp<IBluetoothAudioPort> stack_if =
+      new BluetoothAudioPortImpl(sink_, provider_);
+  std::unique_ptr<DataMQ> tempDataMQ;
+  BluetoothAudioStatus session_status;
+
+  std::promise<void> hidl_startSession_promise;
+  auto hidl_startSession_future = hidl_startSession_promise.get_future();
+  auto hidl_cb = [&session_status, &tempDataMQ, &hidl_startSession_promise](
+                     BluetoothAudioStatus status,
+                     const DataMQ::Descriptor& dataMQ) {
+    LOG(INFO) << "startSession_cb(" << toString(status) << ")";
+    session_status = status;
+    if (status == BluetoothAudioStatus::SUCCESS && dataMQ.isHandleValid()) {
+      tempDataMQ.reset(new DataMQ(dataMQ));
+    }
+    hidl_startSession_promise.set_value();
+  };
+  auto hidl_retval = provider_->startSession(
+      stack_if, sink_->GetAudioConfiguration(), hidl_cb);
+  hidl_startSession_future.get();
+  if (!hidl_retval.isOk()) {
+    LOG(FATAL) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
+    return -EPROTO;
+  }
+
+  if (tempDataMQ && tempDataMQ->isValid()) {
+    mDataMQ = std::move(tempDataMQ);
+  } else if (sink_->GetSessionType() ==
+                 SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH &&
+             session_status == BluetoothAudioStatus::SUCCESS) {
+    sink_->ResetPresentationPosition();
+    session_started_ = true;
+    return 0;
+  }
+  if (mDataMQ && mDataMQ->isValid()) {
+    sink_->ResetPresentationPosition();
+    session_started_ = true;
+    return 0;
+  } else {
+    ALOGE_IF(!mDataMQ, "Failed to obtain audio data path");
+    ALOGE_IF(mDataMQ && !mDataMQ->isValid(), "Audio data path is invalid");
+    session_started_ = false;
+    return -EIO;
+  }
+}
+
+void BluetoothAudioClientInterface::StreamStarted(
+    const BluetoothAudioCtrlAck& ack) {
+  if (provider_ == nullptr) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
+    return;
+  }
+  if (ack == BluetoothAudioCtrlAck::PENDING) {
+    LOG(INFO) << __func__ << ": " << ack << " ignored";
+    return;
+  }
+  BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack);
+  auto hidl_retval = provider_->streamStarted(status);
+  if (!hidl_retval.isOk()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
+  }
+}
+
+void BluetoothAudioClientInterface::StreamSuspended(
+    const BluetoothAudioCtrlAck& ack) {
+  if (provider_ == nullptr) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
+    return;
+  }
+  if (ack == BluetoothAudioCtrlAck::PENDING) {
+    LOG(INFO) << __func__ << ": " << ack << " ignored";
+    return;
+  }
+  BluetoothAudioStatus status = BluetoothAudioCtrlAckToHalStatus(ack);
+  auto hidl_retval = provider_->streamSuspended(status);
+  if (!hidl_retval.isOk()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
+  }
+}
+
+int BluetoothAudioClientInterface::EndSession() {
+  std::lock_guard<std::mutex> guard(internal_mutex_);
+  if (!session_started_) {
+    LOG(INFO) << __func__ << ": sessoin ended already";
+    return 0;
+  }
+
+  session_started_ = false;
+  if (provider_ == nullptr) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
+    return -EINVAL;
+  }
+  mDataMQ = nullptr;
+  auto hidl_retval = provider_->endSession();
+  if (!hidl_retval.isOk()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal failure: " << hidl_retval.description();
+    return -EPROTO;
+  }
+  return 0;
+}
+
+size_t BluetoothAudioClientInterface::ReadAudioData(uint8_t* p_buf,
+                                                    uint32_t len) {
+  if (provider_ == nullptr) {
+    LOG(ERROR) << __func__ << ": BluetoothAudioHal nullptr";
+    return 0;
+  }
+  if (p_buf == nullptr || len == 0) return 0;
+
+  std::lock_guard<std::mutex> guard(internal_mutex_);
+
+  size_t total_read = 0;
+  int timeout_ms = kDefaultDataReadTimeoutMs;
+  do {
+    if (mDataMQ == nullptr || !mDataMQ->isValid()) break;
+
+    size_t avail_to_read = mDataMQ->availableToRead();
+    if (avail_to_read) {
+      if (avail_to_read > len - total_read) {
+        avail_to_read = len - total_read;
+      }
+      if (mDataMQ->read(p_buf + total_read, avail_to_read) == 0) {
+        LOG(WARNING) << __func__ << ": len=" << len
+                     << " total_read=" << total_read << " failed";
+        break;
+      }
+      total_read += avail_to_read;
+    } else if (timeout_ms >= kDefaultDataReadPollIntervalMs) {
+      std::this_thread::sleep_for(
+          std::chrono::milliseconds(kDefaultDataReadPollIntervalMs));
+      timeout_ms -= kDefaultDataReadPollIntervalMs;
+      continue;
+    } else {
+      LOG(WARNING) << __func__ << ": " << (len - total_read) << "/" << len
+                   << " no data " << (kDefaultDataReadTimeoutMs - timeout_ms)
+                   << " ms";
+      break;
+    }
+  } while (total_read < len);
+
+  if (timeout_ms <
+          (kDefaultDataReadTimeoutMs - kDefaultDataReadPollIntervalMs) &&
+      timeout_ms >= kDefaultDataReadPollIntervalMs) {
+    VLOG(1) << __func__ << ": underflow " << len << " -> " << total_read
+            << " read " << (kDefaultDataReadTimeoutMs - timeout_ms) << " ms";
+  } else {
+    VLOG(2) << __func__ << ": " << len << " -> " << total_read << " read";
+  }
+
+  sink_->LogBytesRead(total_read);
+  return total_read;
+}
+
+size_t BluetoothAudioClientInterface::WriteAudioData(uint8_t* p_buf,
+                                                     uint32_t len) {
+  // Not implemented!
+  return 0;
+}
+
+void BluetoothAudioClientInterface::RenewAudioProviderAndSession() {
+  // NOTE: must be invoked on the same thread where this
+  // BluetoothAudioClientInterface is running
+  fetch_audio_provider();
+  session_started_ = false;
+  StartSession();
+}
+
+}  // namespace audio
+}  // namespace bluetooth
diff --git a/audio_hal_interface/client_interface.h b/audio_hal_interface/client_interface.h
new file mode 100644
index 0000000..11984aa
--- /dev/null
+++ b/audio_hal_interface/client_interface.h
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <time.h>
+#include <mutex>
+
+#include <android/hardware/bluetooth/audio/2.0/IBluetoothAudioProvider.h>
+#include <android/hardware/bluetooth/audio/2.0/types.h>
+#include <fmq/MessageQueue.h>
+#include <hardware/audio.h>
+
+#include "common/message_loop_thread.h"
+
+#define BLUETOOTH_AUDIO_HAL_PROP_DISABLED "persist.bluetooth.bluetooth_audio_hal.disabled"
+
+namespace bluetooth {
+namespace audio {
+
+using ::android::hardware::bluetooth::audio::V2_0::AudioCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::AudioConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::BitsPerSample;
+using ::android::hardware::bluetooth::audio::V2_0::ChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::IBluetoothAudioProvider;
+using ::android::hardware::bluetooth::audio::V2_0::PcmParameters;
+using ::android::hardware::bluetooth::audio::V2_0::SampleRate;
+using ::android::hardware::bluetooth::audio::V2_0::SessionType;
+using ::android::hardware::bluetooth::audio::V2_0::TimeSpec;
+using BluetoothAudioStatus =
+    ::android::hardware::bluetooth::audio::V2_0::Status;
+
+enum class BluetoothAudioCtrlAck : uint8_t {
+  SUCCESS_FINISHED = 0,
+  PENDING,
+  FAILURE_UNSUPPORTED,
+  FAILURE_BUSY,
+  FAILURE_DISCONNECTING,
+  FAILURE
+};
+
+std::ostream& operator<<(std::ostream& os, const BluetoothAudioCtrlAck& ack);
+
+inline BluetoothAudioStatus BluetoothAudioCtrlAckToHalStatus(
+    const BluetoothAudioCtrlAck& ack) {
+  switch (ack) {
+    case BluetoothAudioCtrlAck::SUCCESS_FINISHED:
+      return BluetoothAudioStatus::SUCCESS;
+    case BluetoothAudioCtrlAck::FAILURE_UNSUPPORTED:
+      return BluetoothAudioStatus::UNSUPPORTED_CODEC_CONFIGURATION;
+    case BluetoothAudioCtrlAck::PENDING:
+      return BluetoothAudioStatus::FAILURE;
+    case BluetoothAudioCtrlAck::FAILURE_BUSY:
+      return BluetoothAudioStatus::FAILURE;
+    case BluetoothAudioCtrlAck::FAILURE_DISCONNECTING:
+      return BluetoothAudioStatus::FAILURE;
+    default:
+      return BluetoothAudioStatus::FAILURE;
+  }
+}
+
+// An IBluetoothTransportInstance needs to be implemented by a Bluetooth audio
+// transport, such as A2DP or Hearing Aid, to handle callbacks from Audio HAL.
+class IBluetoothTransportInstance {
+ public:
+  IBluetoothTransportInstance(SessionType sessionType,
+                              AudioConfiguration audioConfig)
+      : session_type_(sessionType), audio_config_(std::move(audioConfig)){};
+  virtual ~IBluetoothTransportInstance() = default;
+
+  SessionType GetSessionType() const { return session_type_; }
+
+  AudioConfiguration GetAudioConfiguration() const { return audio_config_; }
+
+  void UpdateAudioConfiguration(const AudioConfiguration& audio_config) {
+    audio_config_ = audio_config;
+  }
+
+  virtual BluetoothAudioCtrlAck StartRequest() = 0;
+
+  virtual BluetoothAudioCtrlAck SuspendRequest() = 0;
+
+  virtual void StopRequest() = 0;
+
+  virtual bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
+                                       uint64_t* total_bytes_readed,
+                                       timespec* data_position) = 0;
+
+  virtual void MetadataChanged(const source_metadata_t& source_metadata) = 0;
+
+  // Invoked when the transport is requested to reset presentation position
+  virtual void ResetPresentationPosition() = 0;
+
+  // Invoked when the transport is requested to log bytes read
+  virtual void LogBytesRead(size_t bytes_readed) = 0;
+
+ private:
+  const SessionType session_type_;
+  AudioConfiguration audio_config_;
+};
+
+// common object is shared between different kind of SessionType
+class BluetoothAudioDeathRecipient;
+
+// The client interface connects an IBluetoothTransportInstance to
+// IBluetoothAudioProvider and helps to route callbacks to
+// IBluetoothTransportInstance
+class BluetoothAudioClientInterface {
+ public:
+  // Constructs an BluetoothAudioClientInterface to communicate to
+  // BluetoothAudio HAL. |sink| is the implementation for the transport, and
+  // |message_loop| is the thread where callbacks are invoked.
+  BluetoothAudioClientInterface(
+      IBluetoothTransportInstance* sink,
+      bluetooth::common::MessageLoopThread* message_loop);
+
+  ~BluetoothAudioClientInterface();
+
+  bool IsValid() const {
+    return provider_ != nullptr;
+  }
+
+  std::vector<AudioCapabilities> GetAudioCapabilities() const;
+
+  bool UpdateAudioConfig(const AudioConfiguration& audioConfig);
+
+  int StartSession();
+
+  void StreamStarted(const BluetoothAudioCtrlAck& ack);
+
+  void StreamSuspended(const BluetoothAudioCtrlAck& ack);
+
+  int EndSession();
+
+  // Read data from audio  HAL through fmq
+  size_t ReadAudioData(uint8_t* p_buf, uint32_t len);
+
+  // Write data to audio HAL through fmq
+  size_t WriteAudioData(uint8_t* p_buf, uint32_t len);
+
+  // Renew the connection and usually is used when HIDL restarted
+  void RenewAudioProviderAndSession();
+
+  static constexpr PcmParameters kInvalidPcmConfiguration = {
+      .sampleRate = SampleRate::RATE_UNKNOWN,
+      .bitsPerSample = BitsPerSample::BITS_UNKNOWN,
+      .channelMode = ChannelMode::UNKNOWN};
+
+ private:
+  // Helper function to connect to an IBluetoothAudioProvider
+  void fetch_audio_provider();
+
+  mutable std::mutex internal_mutex_;
+  IBluetoothTransportInstance* sink_;
+  android::sp<IBluetoothAudioProvider> provider_;
+  std::vector<AudioCapabilities> capabilities_;
+  bool session_started_;
+  std::unique_ptr<::android::hardware::MessageQueue<
+      uint8_t, ::android::hardware::kSynchronizedReadWrite>>
+      mDataMQ;
+  android::sp<BluetoothAudioDeathRecipient> death_recipient_;
+};
+
+}  // namespace audio
+}  // namespace bluetooth
diff --git a/audio_hal_interface/client_interface_unittest.cc b/audio_hal_interface/client_interface_unittest.cc
new file mode 100644
index 0000000..de6ba52
--- /dev/null
+++ b/audio_hal_interface/client_interface_unittest.cc
@@ -0,0 +1,473 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include "client_interface.h"
+
+namespace {
+
+using ::android::hardware::bluetooth::audio::V2_0::AacObjectType;
+using ::android::hardware::bluetooth::audio::V2_0::AacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::AacVariableBitRate;
+using ::android::hardware::bluetooth::audio::V2_0::AptxParameters;
+using ::android::hardware::bluetooth::audio::V2_0::CodecCapabilities;
+using ::android::hardware::bluetooth::audio::V2_0::CodecConfiguration;
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::android::hardware::bluetooth::audio::V2_0::LdacChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::LdacParameters;
+using ::android::hardware::bluetooth::audio::V2_0::LdacQualityIndex;
+using ::android::hardware::bluetooth::audio::V2_0::SbcAllocMethod;
+using ::android::hardware::bluetooth::audio::V2_0::SbcBlockLength;
+using ::android::hardware::bluetooth::audio::V2_0::SbcChannelMode;
+using ::android::hardware::bluetooth::audio::V2_0::SbcNumSubbands;
+using ::android::hardware::bluetooth::audio::V2_0::SbcParameters;
+
+using ::bluetooth::audio::AudioCapabilities;
+using ::bluetooth::audio::AudioConfiguration;
+using ::bluetooth::audio::BitsPerSample;
+using ::bluetooth::audio::BluetoothAudioClientInterface;
+using ::bluetooth::audio::BluetoothAudioStatus;
+using ::bluetooth::audio::ChannelMode;
+using ::bluetooth::audio::PcmParameters;
+using ::bluetooth::audio::SampleRate;
+using ::bluetooth::audio::SessionType;
+using ::testing::Test;
+
+constexpr SampleRate kSampleRates[9] = {
+    SampleRate::RATE_UNKNOWN, SampleRate::RATE_44100, SampleRate::RATE_48000,
+    SampleRate::RATE_88200,   SampleRate::RATE_96000, SampleRate::RATE_176400,
+    SampleRate::RATE_192000,  SampleRate::RATE_16000, SampleRate::RATE_24000};
+constexpr BitsPerSample kBitsPerSamples[4] = {
+    BitsPerSample::BITS_UNKNOWN, BitsPerSample::BITS_16, BitsPerSample::BITS_24,
+    BitsPerSample::BITS_32};
+constexpr ChannelMode kChannelModes[3] = {
+    ChannelMode::UNKNOWN, ChannelMode::MONO, ChannelMode::STEREO};
+constexpr uint16_t kPeerMtus[5] = {660, 663, 883, 1005, 1500};
+
+class TestTransport : public bluetooth::audio::IBluetoothTransportInstance {
+ private:
+  static constexpr uint64_t kRemoteDelayReportMs = 200;
+
+ public:
+  TestTransport(SessionType session_type)
+      : bluetooth::audio::IBluetoothTransportInstance(session_type, {}){};
+  bluetooth::audio::BluetoothAudioCtrlAck StartRequest() {
+    return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
+  }
+  bluetooth::audio::BluetoothAudioCtrlAck SuspendRequest() {
+    return bluetooth::audio::BluetoothAudioCtrlAck::SUCCESS_FINISHED;
+  }
+  void StopRequest() {}
+  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
+                               uint64_t* total_bytes_readed,
+                               timespec* data_position) {
+    if (remote_delay_report_ns) {
+      *remote_delay_report_ns = kRemoteDelayReportMs * 1000000;
+    }
+    if (total_bytes_readed) {
+      *total_bytes_readed = 0;
+    }
+    if (data_position) {
+      clock_gettime(CLOCK_MONOTONIC, data_position);
+    }
+    return true;
+  }
+  void MetadataChanged(const source_metadata_t& source_metadata __unused) {}
+  void ResetPresentationPosition(){};
+  void LogBytesRead(size_t bytes_readed __unused){};
+};
+
+class BluetoothAudioClientInterfaceTest : public Test {
+ protected:
+  TestTransport* test_transport_;
+  BluetoothAudioClientInterface* clientif_;
+
+  static constexpr int kClientIfReturnSuccess = 0;
+
+  virtual void SetUp() override {}
+
+  virtual void TearDown() override {
+    clientif_ = nullptr;
+    test_transport_ = nullptr;
+  }
+
+  bool IsSoftwarePcmParametersSupported(const PcmParameters& pcm_config) {
+    const std::vector<AudioCapabilities>& capabilities =
+        clientif_->GetAudioCapabilities();
+    PcmParameters pcm_capabilities = capabilities[0].pcmCapabilities();
+    bool is_pcm_config_valid =
+        (pcm_config.sampleRate != SampleRate::RATE_UNKNOWN &&
+         pcm_config.bitsPerSample != BitsPerSample::BITS_UNKNOWN &&
+         pcm_config.channelMode != ChannelMode::UNKNOWN);
+    bool is_pcm_config_supported =
+        (pcm_config.sampleRate & pcm_capabilities.sampleRate &&
+         pcm_config.bitsPerSample & pcm_capabilities.bitsPerSample &&
+         pcm_config.channelMode & pcm_capabilities.channelMode);
+    return (is_pcm_config_valid && is_pcm_config_supported);
+  }
+
+  bool IsOffloadCodecConfigurationSupported(
+      const CodecConfiguration& codec_config) {
+    CodecCapabilities codec_capability = {};
+    for (auto audio_capability : clientif_->GetAudioCapabilities()) {
+      if (audio_capability.codecCapabilities().codecType ==
+          codec_config.codecType) {
+        codec_capability = audio_capability.codecCapabilities();
+      }
+    }
+    if (codec_capability.codecType != codec_config.codecType) {
+      // codec is unsupported
+      return false;
+    }
+    bool is_codec_config_supported = false;
+    switch (codec_config.codecType) {
+      case CodecType::SBC: {
+        SbcParameters sbc_config = codec_config.config.sbcConfig();
+        SbcParameters sbc_capability =
+            codec_capability.capabilities.sbcCapabilities();
+        is_codec_config_supported =
+            (sbc_config.sampleRate & sbc_capability.sampleRate &&
+             sbc_config.channelMode & sbc_capability.channelMode &&
+             sbc_config.blockLength & sbc_capability.blockLength &&
+             sbc_config.numSubbands & sbc_capability.numSubbands &&
+             sbc_config.allocMethod & sbc_capability.allocMethod &&
+             sbc_config.bitsPerSample & sbc_capability.bitsPerSample &&
+             (sbc_capability.minBitpool <= sbc_config.minBitpool &&
+              sbc_config.minBitpool <= sbc_config.maxBitpool &&
+              sbc_config.maxBitpool <= sbc_capability.maxBitpool));
+        return is_codec_config_supported;
+      }
+      case CodecType::AAC: {
+        AacParameters aac_config = codec_config.config.aacConfig();
+        AacParameters aac_capability =
+            codec_capability.capabilities.aacCapabilities();
+        is_codec_config_supported =
+            (aac_config.objectType & aac_capability.objectType &&
+             aac_config.sampleRate & aac_capability.sampleRate &&
+             aac_config.channelMode & aac_capability.channelMode &&
+             (aac_config.variableBitRateEnabled ==
+                  AacVariableBitRate::DISABLED ||
+              aac_capability.variableBitRateEnabled ==
+                  AacVariableBitRate::ENABLED) &&
+             aac_config.bitsPerSample & aac_capability.bitsPerSample);
+        return is_codec_config_supported;
+      }
+      case CodecType::LDAC: {
+        LdacParameters ldac_config = codec_config.config.ldacConfig();
+        LdacParameters ldac_capability =
+            codec_capability.capabilities.ldacCapabilities();
+        is_codec_config_supported =
+            (ldac_config.sampleRate & ldac_capability.sampleRate &&
+             ldac_config.channelMode & ldac_capability.channelMode &&
+             ldac_config.bitsPerSample & ldac_capability.bitsPerSample);
+        return is_codec_config_supported;
+      }
+      case CodecType::APTX:
+        [[fallthrough]];
+      case CodecType::APTX_HD: {
+        AptxParameters aptx_config = codec_config.config.aptxConfig();
+        AptxParameters aptx_capability =
+            codec_capability.capabilities.aptxCapabilities();
+        is_codec_config_supported =
+            (aptx_config.sampleRate & aptx_capability.sampleRate &&
+             aptx_config.channelMode & aptx_capability.channelMode &&
+             aptx_config.bitsPerSample & aptx_capability.bitsPerSample);
+        return is_codec_config_supported;
+      }
+      case CodecType::UNKNOWN:
+        return false;
+    }
+  }
+};
+
+}  // namespace
+
+TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpSoftwareSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_SOFTWARE_ENCODING_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  PcmParameters pcm_config = {};
+  for (auto sample_rate : kSampleRates) {
+    pcm_config.sampleRate = sample_rate;
+    for (auto bits_per_sample : kBitsPerSamples) {
+      pcm_config.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : kChannelModes) {
+        pcm_config.channelMode = channel_mode;
+        audio_config.pcmConfig(pcm_config);
+        clientif_->UpdateAudioConfig(audio_config);
+        if (IsSoftwarePcmParametersSupported(pcm_config)) {
+          EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+        } else {
+          EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+        }
+        EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+      }  // ChannelMode
+    }    // BitsPerSampple
+  }      // SampleRate
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadSbcSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  CodecConfiguration codec_config = {};
+  SbcBlockLength block_lengths[4] = {
+      SbcBlockLength::BLOCKS_4, SbcBlockLength::BLOCKS_8,
+      SbcBlockLength::BLOCKS_12, SbcBlockLength::BLOCKS_16};
+  SbcNumSubbands num_subbands[2] = {SbcNumSubbands::SUBBAND_4,
+                                    SbcNumSubbands::SUBBAND_8};
+  SbcAllocMethod alloc_methods[2] = {SbcAllocMethod::ALLOC_MD_S,
+                                     SbcAllocMethod::ALLOC_MD_L};
+  for (auto sample_rate : kSampleRates) {
+    for (auto bits_per_sample : kBitsPerSamples) {
+      for (auto channel_mode : kChannelModes) {
+        for (auto peer_mtu : kPeerMtus) {
+          for (auto block_length : block_lengths) {
+            for (auto num_subband : num_subbands) {
+              for (auto alloc_method : alloc_methods) {
+                codec_config.codecType = CodecType::SBC;
+                codec_config.peerMtu = peer_mtu;
+                codec_config.isScmstEnabled = false;
+                // A2DP_SBC_DEFAULT_BITRATE
+                codec_config.encodedAudioBitrate = 328000;
+                SbcParameters sbc = {
+                    .sampleRate = sample_rate,
+                    .channelMode = (channel_mode == ChannelMode::MONO
+                                        ? SbcChannelMode::MONO
+                                        : SbcChannelMode::JOINT_STEREO),
+                    .blockLength = block_length,
+                    .numSubbands = num_subband,
+                    .allocMethod = alloc_method,
+                    .bitsPerSample = bits_per_sample,
+                    .minBitpool = 2,
+                    .maxBitpool = 53};
+                codec_config.config.sbcConfig(sbc);
+                audio_config.codecConfig(codec_config);
+                clientif_->UpdateAudioConfig(audio_config);
+                if (IsOffloadCodecConfigurationSupported(codec_config)) {
+                  EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+                } else {
+                  EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+                }
+                EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+              }  // SbcAllocMethod
+            }    // SbcNumSubbands
+          }      // SbcBlockLength
+        }        // peerMtu
+      }          // ChannelMode
+    }            // BitsPerSampple
+  }              // SampleRate
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAacSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  CodecConfiguration codec_config = {};
+  AacObjectType object_types[4] = {
+      AacObjectType::MPEG2_LC, AacObjectType::MPEG4_LC,
+      AacObjectType::MPEG4_LTP, AacObjectType::MPEG4_SCALABLE};
+  AacVariableBitRate variable_bitrates[2] = {AacVariableBitRate::DISABLED,
+                                             AacVariableBitRate::ENABLED};
+  for (auto sample_rate : kSampleRates) {
+    for (auto bits_per_sample : kBitsPerSamples) {
+      for (auto channel_mode : kChannelModes) {
+        for (auto peer_mtu : kPeerMtus) {
+          for (auto object_type : object_types) {
+            for (auto variable_bitrate : variable_bitrates) {
+              codec_config.codecType = CodecType::AAC;
+              codec_config.peerMtu = peer_mtu;
+              codec_config.isScmstEnabled = false;
+              // A2DP_AAC_DEFAULT_BITRATE
+              codec_config.encodedAudioBitrate = 320000;
+              AacParameters aac = {.objectType = object_type,
+                                   .sampleRate = sample_rate,
+                                   .channelMode = channel_mode,
+                                   .variableBitRateEnabled = variable_bitrate,
+                                   .bitsPerSample = bits_per_sample};
+              codec_config.config.aacConfig(aac);
+              audio_config.codecConfig(codec_config);
+              clientif_->UpdateAudioConfig(audio_config);
+              if (IsOffloadCodecConfigurationSupported(codec_config)) {
+                EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+              } else {
+                EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+              }
+              EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+            }  // AacVariableBitRate
+          }    // AacObjectType
+        }      // peerMtu
+      }        // ChannelMode
+    }          // BitsPerSampple
+  }            // SampleRate
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadLdacSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  CodecConfiguration codec_config = {};
+  LdacQualityIndex quality_indexes[4] = {
+      LdacQualityIndex::QUALITY_HIGH, LdacQualityIndex::QUALITY_MID,
+      LdacQualityIndex::QUALITY_LOW, LdacQualityIndex::QUALITY_ABR};
+  for (auto sample_rate : kSampleRates) {
+    for (auto bits_per_sample : kBitsPerSamples) {
+      for (auto channel_mode : kChannelModes) {
+        for (auto peer_mtu : kPeerMtus) {
+          for (auto quality_index : quality_indexes) {
+            codec_config.codecType = CodecType::LDAC;
+            codec_config.peerMtu = peer_mtu;
+            codec_config.isScmstEnabled = false;
+            codec_config.encodedAudioBitrate = 990000;
+            LdacParameters ldac = {
+                .sampleRate = sample_rate,
+                .channelMode = (channel_mode == ChannelMode::MONO
+                                    ? LdacChannelMode::MONO
+                                    : LdacChannelMode::STEREO),
+                .qualityIndex = quality_index,
+                .bitsPerSample = bits_per_sample};
+            codec_config.config.ldacConfig(ldac);
+            audio_config.codecConfig(codec_config);
+            clientif_->UpdateAudioConfig(audio_config);
+            if (IsOffloadCodecConfigurationSupported(codec_config)) {
+              EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+            } else {
+              EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+            }
+            EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+          }  // LdacQualityIndex
+        }    // peerMtu
+      }      // ChannelMode
+    }        // BitsPerSampple
+  }          // SampleRate
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  CodecConfiguration codec_config = {};
+  for (auto sample_rate : kSampleRates) {
+    for (auto bits_per_sample : kBitsPerSamples) {
+      for (auto channel_mode : kChannelModes) {
+        for (auto peer_mtu : kPeerMtus) {
+          codec_config.codecType = CodecType::APTX;
+          codec_config.peerMtu = peer_mtu;
+          codec_config.isScmstEnabled = false;
+          codec_config.encodedAudioBitrate = 352000;
+          AptxParameters aptx = {.sampleRate = sample_rate,
+                                 .channelMode = channel_mode,
+                                 .bitsPerSample = bits_per_sample};
+          codec_config.config.aptxConfig(aptx);
+          audio_config.codecConfig(codec_config);
+          clientif_->UpdateAudioConfig(audio_config);
+          if (IsOffloadCodecConfigurationSupported(codec_config)) {
+            EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+          } else {
+            EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+          }
+          EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+        }  // peerMtu
+      }    // ChannelMode
+    }      // BitsPerSampple
+  }        // SampleRate
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest, StartAndEndA2dpOffloadAptxHdSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  CodecConfiguration codec_config = {};
+  for (auto sample_rate : kSampleRates) {
+    for (auto bits_per_sample : kBitsPerSamples) {
+      for (auto channel_mode : kChannelModes) {
+        for (auto peer_mtu : kPeerMtus) {
+          codec_config.codecType = CodecType::APTX_HD;
+          codec_config.peerMtu = peer_mtu;
+          codec_config.isScmstEnabled = false;
+          codec_config.encodedAudioBitrate = 576000;
+          AptxParameters aptx = {.sampleRate = sample_rate,
+                                 .channelMode = channel_mode,
+                                 .bitsPerSample = bits_per_sample};
+          codec_config.config.aptxConfig(aptx);
+          audio_config.codecConfig(codec_config);
+          clientif_->UpdateAudioConfig(audio_config);
+          if (IsOffloadCodecConfigurationSupported(codec_config)) {
+            EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+          } else {
+            EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+          }
+          EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+        }  // peerMtu
+      }    // ChannelMode
+    }      // BitsPerSampple
+  }        // SampleRate
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest,
+       StartAndEndA2dpOffloadUnknownSession) {
+  test_transport_ =
+      new TestTransport(SessionType::A2DP_HARDWARE_OFFLOAD_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  CodecConfiguration codec_config = {};
+  codec_config.codecType = CodecType::UNKNOWN;
+  codec_config.peerMtu = 1005;
+  codec_config.isScmstEnabled = false;
+  codec_config.encodedAudioBitrate = 328000;
+  codec_config.config = {};
+  audio_config.codecConfig(codec_config);
+  clientif_->UpdateAudioConfig(audio_config);
+  if (IsOffloadCodecConfigurationSupported(codec_config)) {
+    EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+  } else {
+    EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+  }
+  EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+}
+
+TEST_F(BluetoothAudioClientInterfaceTest,
+       StartAndEndHearingAidSoftwareSession) {
+  test_transport_ =
+      new TestTransport(SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH);
+  clientif_ = new BluetoothAudioClientInterface(test_transport_, nullptr);
+  AudioConfiguration audio_config = {};
+  PcmParameters pcm_config = {};
+  for (auto sample_rate : kSampleRates) {
+    pcm_config.sampleRate = sample_rate;
+    for (auto bits_per_sample : kBitsPerSamples) {
+      pcm_config.bitsPerSample = bits_per_sample;
+      for (auto channel_mode : kChannelModes) {
+        pcm_config.channelMode = channel_mode;
+        audio_config.pcmConfig(pcm_config);
+        clientif_->UpdateAudioConfig(audio_config);
+        if (IsSoftwarePcmParametersSupported(pcm_config)) {
+          EXPECT_EQ(clientif_->StartSession(), kClientIfReturnSuccess);
+        } else {
+          EXPECT_NE(clientif_->StartSession(), kClientIfReturnSuccess);
+        }
+        EXPECT_EQ(clientif_->EndSession(), kClientIfReturnSuccess);
+      }  // ChannelMode
+    }    // BitsPerSampple
+  }      // SampleRate
+}
diff --git a/audio_hal_interface/hearing_aid_software_encoding.cc b/audio_hal_interface/hearing_aid_software_encoding.cc
new file mode 100644
index 0000000..5107d46
--- /dev/null
+++ b/audio_hal_interface/hearing_aid_software_encoding.cc
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "BTAudioClientHearingAid"
+
+#include "hearing_aid_software_encoding.h"
+#include "client_interface.h"
+
+#include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
+#include "osi/include/log.h"
+#include "osi/include/properties.h"
+
+namespace {
+
+using ::android::hardware::bluetooth::audio::V2_0::CodecType;
+using ::bluetooth::audio::AudioConfiguration;
+using ::bluetooth::audio::BitsPerSample;
+using ::bluetooth::audio::BluetoothAudioCtrlAck;
+using ::bluetooth::audio::ChannelMode;
+using ::bluetooth::audio::PcmParameters;
+using ::bluetooth::audio::SampleRate;
+using ::bluetooth::audio::SessionType;
+using ::bluetooth::audio::hearing_aid::StreamCallbacks;
+
+// Transport implementation for Hearing Aids
+class HearingAidTransport
+    : public bluetooth::audio::IBluetoothTransportInstance {
+ public:
+  HearingAidTransport(StreamCallbacks stream_cb)
+      : IBluetoothTransportInstance(
+            SessionType::HEARING_AID_SOFTWARE_ENCODING_DATAPATH, {}),
+        stream_cb_(std::move(stream_cb)),
+        remote_delay_report_ms_(0),
+        total_bytes_read_(0),
+        data_position_({}){};
+
+  BluetoothAudioCtrlAck StartRequest() override {
+    LOG(INFO) << __func__;
+    if (stream_cb_.on_resume_(true)) {
+      return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
+    }
+    return BluetoothAudioCtrlAck::FAILURE;
+  }
+
+  BluetoothAudioCtrlAck SuspendRequest() override {
+    LOG(INFO) << __func__;
+    if (stream_cb_.on_suspend_()) {
+      uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2];
+      ::bluetooth::audio::hearing_aid::read(p_buf, sizeof(p_buf));
+      return BluetoothAudioCtrlAck::SUCCESS_FINISHED;
+    } else {
+      return BluetoothAudioCtrlAck::FAILURE;
+    }
+  }
+
+  void StopRequest() override {
+    LOG(INFO) << __func__;
+    if (stream_cb_.on_suspend_()) {
+      // flush
+      uint8_t p_buf[AUDIO_STREAM_OUTPUT_BUFFER_SZ * 2];
+      ::bluetooth::audio::hearing_aid::read(p_buf, sizeof(p_buf));
+    }
+  }
+
+  bool GetPresentationPosition(uint64_t* remote_delay_report_ns,
+                               uint64_t* total_bytes_read,
+                               timespec* data_position) override {
+    VLOG(2) << __func__ << ": data=" << total_bytes_read_
+            << " byte(s), timestamp=" << data_position_.tv_sec << "."
+            << data_position_.tv_nsec
+            << "s, delay report=" << remote_delay_report_ms_ << " msec.";
+    if (remote_delay_report_ns != nullptr) {
+      *remote_delay_report_ns = remote_delay_report_ms_ * 1000000u;
+    }
+    if (total_bytes_read != nullptr) *total_bytes_read = total_bytes_read_;
+    if (data_position != nullptr) *data_position = data_position_;
+
+    return true;
+  }
+
+  void MetadataChanged(const source_metadata_t& source_metadata) override {
+    auto track_count = source_metadata.track_count;
+    auto tracks = source_metadata.tracks;
+    LOG(INFO) << __func__ << ": " << track_count << " track(s) received";
+    while (track_count) {
+      VLOG(1) << __func__ << ": usage=" << tracks->usage
+              << ", content_type=" << tracks->content_type
+              << ", gain=" << tracks->gain;
+      --track_count;
+      ++tracks;
+    }
+  }
+
+  void ResetPresentationPosition() override {
+    VLOG(2) << __func__ << ": called.";
+    remote_delay_report_ms_ = 0;
+    total_bytes_read_ = 0;
+    data_position_ = {};
+  }
+
+  void LogBytesRead(size_t bytes_read) override {
+    if (bytes_read) {
+      total_bytes_read_ += bytes_read;
+      clock_gettime(CLOCK_MONOTONIC, &data_position_);
+    }
+  }
+
+  void SetRemoteDelay(uint16_t delay_report_ms) {
+    LOG(INFO) << __func__ << ": delay_report=" << delay_report_ms << " msec";
+    remote_delay_report_ms_ = delay_report_ms;
+  }
+
+ private:
+  StreamCallbacks stream_cb_;
+  uint16_t remote_delay_report_ms_;
+  uint64_t total_bytes_read_;
+  timespec data_position_;
+};
+
+bool HearingAidGetSelectedHalPcmConfig(PcmParameters* hal_pcm_config) {
+  if (hal_pcm_config == nullptr) return false;
+  // TODO: we only support one config for now!
+  hal_pcm_config->sampleRate = SampleRate::RATE_16000;
+  hal_pcm_config->bitsPerSample = BitsPerSample::BITS_16;
+  hal_pcm_config->channelMode = ChannelMode::STEREO;
+  return true;
+}
+
+// Sink instance of Hearing Aids to provide call-in APIs for Bluetooth Audio Hal
+HearingAidTransport* hearing_aid_sink = nullptr;
+// Common interface to call-out into Bluetooth Audio Hal
+bluetooth::audio::BluetoothAudioClientInterface*
+    hearing_aid_hal_clientinterface = nullptr;
+bool btaudio_hearing_aid_disabled = false;
+bool is_configured = false;
+
+// Save the value if the remote reports its delay before hearing_aid_sink is
+// initialized
+uint16_t remote_delay_ms = 0;
+
+bool is_hal_2_0_force_disabled() {
+  if (!is_configured) {
+    btaudio_hearing_aid_disabled = osi_property_get_bool(BLUETOOTH_AUDIO_HAL_PROP_DISABLED, false);
+    is_configured = true;
+  }
+  return btaudio_hearing_aid_disabled;
+}
+
+}  // namespace
+
+namespace bluetooth {
+namespace audio {
+namespace hearing_aid {
+
+bool is_hal_2_0_enabled() { return hearing_aid_hal_clientinterface != nullptr; }
+
+bool init(StreamCallbacks stream_cb,
+          bluetooth::common::MessageLoopThread* message_loop) {
+  LOG(INFO) << __func__;
+
+  if (is_hal_2_0_force_disabled()) {
+    LOG(ERROR) << __func__ << ": BluetoothAudio HAL is disabled";
+    return false;
+  }
+
+  hearing_aid_sink = new HearingAidTransport(std::move(stream_cb));
+  hearing_aid_hal_clientinterface =
+      new bluetooth::audio::BluetoothAudioClientInterface(hearing_aid_sink,
+                                                          message_loop);
+  if (!hearing_aid_hal_clientinterface->IsValid()) {
+    LOG(WARNING) << __func__ << ": BluetoothAudio HAL for Hearing Aid is invalid?!";
+    delete hearing_aid_hal_clientinterface;
+    hearing_aid_hal_clientinterface = nullptr;
+    delete hearing_aid_sink;
+    hearing_aid_sink = nullptr;
+    return false;
+  }
+
+  if (remote_delay_ms != 0) {
+    LOG(INFO) << __func__ << ": restore DELAY " << remote_delay_ms << " ms";
+    hearing_aid_sink->SetRemoteDelay(remote_delay_ms);
+    remote_delay_ms = 0;
+  }
+
+  return true;
+}
+
+void cleanup() {
+  LOG(INFO) << __func__;
+  if (!is_hal_2_0_enabled()) return;
+  end_session();
+  delete hearing_aid_hal_clientinterface;
+  hearing_aid_hal_clientinterface = nullptr;
+  delete hearing_aid_sink;
+  hearing_aid_sink = nullptr;
+  remote_delay_ms = 0;
+}
+
+void start_session() {
+  LOG(INFO) << __func__;
+  if (!is_hal_2_0_enabled()) return;
+  AudioConfiguration audio_config;
+  PcmParameters pcm_config{};
+  if (!HearingAidGetSelectedHalPcmConfig(&pcm_config)) {
+    LOG(ERROR) << __func__ << ": cannot get PCM config";
+    return;
+  }
+  audio_config.pcmConfig(pcm_config);
+  if (!hearing_aid_hal_clientinterface->UpdateAudioConfig(audio_config)) {
+    LOG(ERROR) << __func__ << ": cannot update audio config to HAL";
+    return;
+  }
+  hearing_aid_hal_clientinterface->StartSession();
+}
+
+void end_session() {
+  LOG(INFO) << __func__;
+  if (!is_hal_2_0_enabled()) return;
+  hearing_aid_hal_clientinterface->EndSession();
+}
+
+size_t read(uint8_t* p_buf, uint32_t len) {
+  if (!is_hal_2_0_enabled()) return 0;
+  return hearing_aid_hal_clientinterface->ReadAudioData(p_buf, len);
+}
+
+// Update Hearing Aids delay report to BluetoothAudio HAL
+void set_remote_delay(uint16_t delay_report_ms) {
+  if (!is_hal_2_0_enabled()) {
+    LOG(INFO) << __func__ << ":  not ready for DelayReport " << delay_report_ms
+              << " ms";
+    remote_delay_ms = delay_report_ms;
+    return;
+  }
+  LOG(INFO) << __func__ << ": delay_report_ms=" << delay_report_ms << " ms";
+  hearing_aid_sink->SetRemoteDelay(delay_report_ms);
+}
+
+}  // namespace hearing_aid
+}  // namespace audio
+}  // namespace bluetooth
diff --git a/audio_hal_interface/hearing_aid_software_encoding.h b/audio_hal_interface/hearing_aid_software_encoding.h
new file mode 100644
index 0000000..8a64fcd
--- /dev/null
+++ b/audio_hal_interface/hearing_aid_software_encoding.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include "common/message_loop_thread.h"
+
+namespace bluetooth {
+namespace audio {
+namespace hearing_aid {
+
+struct StreamCallbacks {
+  std::function<bool(bool start_media_task)> on_resume_;
+  std::function<bool(void)> on_suspend_;
+};
+
+// Check if new bluetooth_audio is enabled
+bool is_hal_2_0_enabled();
+
+// Initialize BluetoothAudio HAL: openProvider
+bool init(StreamCallbacks stream_cb,
+          bluetooth::common::MessageLoopThread* message_loop);
+
+// Clean up BluetoothAudio HAL
+void cleanup();
+
+// Send command to the BluetoothAudio HAL: StartSession, EndSession
+void start_session();
+void end_session();
+
+void set_remote_delay(uint16_t delay_report_ms);
+
+// Read from the FMQ of BluetoothAudio HAL
+size_t read(uint8_t* p_buf, uint32_t len);
+
+}  // namespace hearing_aid
+}  // namespace audio
+}  // namespace bluetooth
diff --git a/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc b/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc
index f3f535e..cac7302 100644
--- a/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc
+++ b/audio_hearing_aid_hw/src/audio_hearing_aid_hw.cc
@@ -693,8 +693,8 @@
       codec_config.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32;
       break;
     case AUDIO_FORMAT_PCM_8_24_BIT:
-    // FALLTHROUGH
-    // All 24-bit audio is expected in AUDIO_FORMAT_PCM_24_BIT_PACKED format
+      // All 24-bit audio is expected in AUDIO_FORMAT_PCM_24_BIT_PACKED format
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     default:
       ERROR("Invalid audio format: 0x%x", common->cfg.format);
       return -1;
diff --git a/binder/Android.bp b/binder/Android.bp
index 18428c2..650906c 100644
--- a/binder/Android.bp
+++ b/binder/Android.bp
@@ -8,7 +8,6 @@
     srcs: [
         "android/bluetooth/bluetooth_device.cc",
         "android/bluetooth/IBluetoothSocketManager.aidl",
-        "android/os/parcel_file_descriptor.cc",
         "android/os/parcel_uuid.cc",
 /* TODO: Uncomment this files as they get converted one-by-one into native implementation
         "android/bluetooth/IBluetooth.aidl",
@@ -20,8 +19,6 @@
         "android/bluetooth/IBluetoothProfileServiceConnection.aidl",
         "android/bluetooth/IBluetoothHeadset.aidl",
         "android/bluetooth/IBluetoothHeadsetPhone.aidl",
-        "android/bluetooth/IBluetoothHealth.aidl",
-        "android/bluetooth/IBluetoothHealthCallback.aidl",
         "android/bluetooth/IBluetoothHearingAid.aidl",
         "android/bluetooth/IBluetoothHidHost.aidl",
         "android/bluetooth/IBluetoothPan.aidl",
@@ -38,6 +35,7 @@
         "android/bluetooth/IBluetoothHidDeviceCallback.aidl",
         "android/bluetooth/IBluetoothGatt.aidl",
         "android/bluetooth/IBluetoothGattCallback.aidl",
+        "android/bluetooth/IBluetoothMetadataListener.aidl",
         "android/bluetooth/IBluetoothGattServerCallback.aidl",
         "android/bluetooth/le/IAdvertisingSetCallback.aidl",
         "android/bluetooth/le/IPeriodicAdvertisingCallback.aidl",
@@ -78,6 +76,9 @@
         "-Wextra",
         "-Wno-unused-parameter",
     ],
+    sanitize: {
+        scs: true,
+    },
 }
 
 // AIDL interface between libbluetooth-binder and framework.jar
@@ -93,8 +94,6 @@
         "android/bluetooth/IBluetoothProfileServiceConnection.aidl",
         "android/bluetooth/IBluetoothHeadset.aidl",
         "android/bluetooth/IBluetoothHeadsetPhone.aidl",
-        "android/bluetooth/IBluetoothHealth.aidl",
-        "android/bluetooth/IBluetoothHealthCallback.aidl",
         "android/bluetooth/IBluetoothHearingAid.aidl",
         "android/bluetooth/IBluetoothHidHost.aidl",
         "android/bluetooth/IBluetoothPan.aidl",
@@ -112,6 +111,7 @@
         "android/bluetooth/IBluetoothHidDeviceCallback.aidl",
         "android/bluetooth/IBluetoothGatt.aidl",
         "android/bluetooth/IBluetoothGattCallback.aidl",
+        "android/bluetooth/IBluetoothMetadataListener.aidl",
         "android/bluetooth/IBluetoothGattServerCallback.aidl",
         "android/bluetooth/le/IAdvertisingSetCallback.aidl",
         "android/bluetooth/le/IPeriodicAdvertisingCallback.aidl",
diff --git a/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl b/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl
deleted file mode 100644
index bc9e54f..0000000
--- a/binder/android/bluetooth/BluetoothHealthAppConfiguration.aidl
+++ /dev/null
@@ -1,19 +0,0 @@
-/*
-** Copyright 2011, The Android Open Source Project
-**
-** 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.
-*/
-
-package android.bluetooth;
-
-parcelable BluetoothHealthAppConfiguration;
diff --git a/binder/android/bluetooth/IBluetooth.aidl b/binder/android/bluetooth/IBluetooth.aidl
index 90c34b0..6bda14b 100644
--- a/binder/android/bluetooth/IBluetooth.aidl
+++ b/binder/android/bluetooth/IBluetooth.aidl
@@ -17,6 +17,7 @@
 package android.bluetooth;
 
 import android.bluetooth.IBluetoothCallback;
+import android.bluetooth.IBluetoothMetadataListener;
 import android.bluetooth.IBluetoothSocketManager;
 import android.bluetooth.IBluetoothStateChangeCallback;
 import android.bluetooth.BluetoothActivityEnergyInfo;
@@ -47,13 +48,18 @@
     BluetoothClass getBluetoothClass();
     boolean setBluetoothClass(in BluetoothClass bluetoothClass);
 
+    int getIoCapability();
+    boolean setIoCapability(int capability);
+    int getLeIoCapability();
+    boolean setLeIoCapability(int capability);
+
     int getScanMode();
     boolean setScanMode(int mode, int duration);
 
     int getDiscoverableTimeout();
     boolean setDiscoverableTimeout(int timeout);
 
-    boolean startDiscovery();
+    boolean startDiscovery(String callingPackage);
     boolean cancelDiscovery();
     boolean isDiscovering();
     long getDiscoveryEndMillis();
@@ -88,6 +94,8 @@
     boolean setPairingConfirmation(in BluetoothDevice device, boolean accept);
 
     int getPhonebookAccessPermission(in BluetoothDevice device);
+    boolean setSilenceMode(in BluetoothDevice device, boolean silence);
+    boolean getSilenceMode(in BluetoothDevice device);
     boolean setPhonebookAccessPermission(in BluetoothDevice device, int value);
     int getMessageAccessPermission(in BluetoothDevice device);
     boolean setMessageAccessPermission(in BluetoothDevice device, int value);
@@ -115,6 +123,13 @@
     int getLeMaximumAdvertisingDataLength();
     BluetoothActivityEnergyInfo reportActivityInfo();
 
+    // For Metadata
+    boolean registerMetadataListener(in IBluetoothMetadataListener listener, in BluetoothDevice device);
+    boolean unregisterMetadataListener(in BluetoothDevice device);
+    boolean setMetadata(in BluetoothDevice device, in int key, in byte[] value);
+    byte[] getMetadata(in BluetoothDevice device, in int key);
+
+
     /**
      * Requests the controller activity info asynchronously.
      * The implementor is expected to reply with the
diff --git a/binder/android/bluetooth/IBluetoothHeadset.aidl b/binder/android/bluetooth/IBluetoothHeadset.aidl
index f8dfb65..0f6954c 100644
--- a/binder/android/bluetooth/IBluetoothHeadset.aidl
+++ b/binder/android/bluetooth/IBluetoothHeadset.aidl
@@ -53,7 +53,7 @@
     void setForceScoAudio(boolean forced);
     boolean startScoUsingVirtualVoiceCall();
     boolean stopScoUsingVirtualVoiceCall();
-    oneway void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type);
+    oneway void phoneStateChanged(int numActive, int numHeld, int callState, String number, int type, String name);
     void clccResponse(int index, int direction, int status, int mode, boolean mpty,
                       String number, int type);
     boolean setActiveDevice(in BluetoothDevice device);
diff --git a/binder/android/bluetooth/IBluetoothHealth.aidl b/binder/android/bluetooth/IBluetoothHealth.aidl
deleted file mode 100644
index a3be367..0000000
--- a/binder/android/bluetooth/IBluetoothHealth.aidl
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2012 The Android Open Source Project
- *
- * 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.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.bluetooth.IBluetoothHealthCallback;
-import android.os.ParcelFileDescriptor;
-
-/**
- * API for Bluetooth Health service
- *
- * {@hide}
- */
-interface IBluetoothHealth
-{
-    boolean registerAppConfiguration(in BluetoothHealthAppConfiguration config,
-        in IBluetoothHealthCallback callback);
-    boolean unregisterAppConfiguration(in BluetoothHealthAppConfiguration config);
-    boolean connectChannelToSource(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
-    boolean connectChannelToSink(in BluetoothDevice device, in BluetoothHealthAppConfiguration config,
-        int channelType);
-    boolean disconnectChannel(in BluetoothDevice device, in BluetoothHealthAppConfiguration config, int id);
-    ParcelFileDescriptor getMainChannelFd(in BluetoothDevice device, in BluetoothHealthAppConfiguration config);
-    List<BluetoothDevice> getConnectedHealthDevices();
-    List<BluetoothDevice> getHealthDevicesMatchingConnectionStates(in int[] states);
-    int getHealthDeviceConnectionState(in BluetoothDevice device);
-}
diff --git a/binder/android/bluetooth/IBluetoothHealthCallback.aidl b/binder/android/bluetooth/IBluetoothHealthCallback.aidl
deleted file mode 100644
index ef7c191..0000000
--- a/binder/android/bluetooth/IBluetoothHealthCallback.aidl
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright 2011, The Android Open Source Project
- *
- * 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.
- */
-
-package android.bluetooth;
-
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHealthAppConfiguration;
-import android.os.ParcelFileDescriptor;
-
-/**
- *@hide
- */
-interface IBluetoothHealthCallback
-{
-    void onHealthAppConfigurationStatusChange(in BluetoothHealthAppConfiguration config, int status);
-    void onHealthChannelStateChange(in BluetoothHealthAppConfiguration config,
-        in BluetoothDevice device, int prevState, int newState, in
-        ParcelFileDescriptor fd, int id);
-}
diff --git a/binder/android/bluetooth/IBluetoothManager.aidl b/binder/android/bluetooth/IBluetoothManager.aidl
index a3ec1d8..2e12700 100644
--- a/binder/android/bluetooth/IBluetoothManager.aidl
+++ b/binder/android/bluetooth/IBluetoothManager.aidl
@@ -49,5 +49,6 @@
     boolean isBleScanAlwaysAvailable();
     int updateBleAppCount(IBinder b, boolean enable, String packageName);
     boolean isBleAppPresent();
+    boolean isHearingAidProfileSupported();
 }
 
diff --git a/binder/android/bluetooth/IBluetoothMapClient.aidl b/binder/android/bluetooth/IBluetoothMapClient.aidl
index 7ac91e9..54e2dd7 100644
--- a/binder/android/bluetooth/IBluetoothMapClient.aidl
+++ b/binder/android/bluetooth/IBluetoothMapClient.aidl
@@ -37,4 +37,5 @@
     boolean sendMessage(in BluetoothDevice device, in Uri[] contacts, in  String message,
         in PendingIntent sentIntent, in PendingIntent deliveryIntent);
     boolean getUnreadMessages(in BluetoothDevice device);
+    int getSupportedFeatures(in BluetoothDevice device);
 }
diff --git a/tools/Android.bp b/binder/android/bluetooth/IBluetoothMetadataListener.aidl
similarity index 60%
copy from tools/Android.bp
copy to binder/android/bluetooth/IBluetoothMetadataListener.aidl
index 9f75ba7..765b128 100644
--- a/tools/Android.bp
+++ b/binder/android/bluetooth/IBluetoothMetadataListener.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+import android.os.ParcelUuid;
+import android.bluetooth.BluetoothDevice;
+
+/**
+ * Callback definitions for interacting with database change
+ * @hide
+ */
+oneway interface IBluetoothMetadataListener {
+    void onMetadataChanged(in BluetoothDevice devices, in int key, in byte[] value);
+}
diff --git a/binder/android/os/parcel_file_descriptor.cc b/binder/android/os/parcel_file_descriptor.cc
deleted file mode 100644
index 37bef6d..0000000
--- a/binder/android/os/parcel_file_descriptor.cc
+++ /dev/null
@@ -1,43 +0,0 @@
-//
-//  Copyright 2017, The Android Open Source Project
-//
-//  Licensed under the Apache License, Version 2.0 (the "License");
-//  you may not use this file except in compliance with the License.
-//  You may obtain a copy of the License at:
-//
-//  http://www.apache.org/licenses/LICENSE-2.0
-//
-//  Unless required by applicable law or agreed to in writing, software
-//  distributed under the License is distributed on an "AS IS" BASIS,
-//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-//  See the License for the specific language governing permissions and
-//  limitations under the License.
-//
-
-#include "android/os/parcel_file_descriptor.h"
-#include <base/logging.h>
-
-using android::OK;
-using android::Parcel;
-using android::status_t;
-
-namespace android {
-namespace os {
-
-status_t ParcelFileDescriptor::writeToParcel(Parcel* parcel) const {
-  CHECK(fd_ >= 0);
-  return parcel->writeParcelFileDescriptor(fd_, takeOwnership_);
-}
-
-status_t ParcelFileDescriptor::readFromParcel(const Parcel* parcel) {
-  LOG(FATAL) << "Don't know how to read ParcelFileDescriptor";
-  return OK;
-}
-
-void ParcelFileDescriptor::setFileDescriptor(int fd, bool takeOwnership) {
-  fd_ = fd;
-  takeOwnership_ = takeOwnership;
-}
-
-}  // namespace os
-}  // namespace android
diff --git a/bta/Android.bp b/bta/Android.bp
index d6919de..0e7bfe8 100644
--- a/bta/Android.bp
+++ b/bta/Android.bp
@@ -34,6 +34,7 @@
 cc_library_static {
     name: "libbt-bta",
     defaults: ["fluoride_bta_defaults"],
+    cflags: ["-Wno-implicit-fallthrough"],
     srcs: [
         "ag/bta_ag_act.cc",
         "ag/bta_ag_api.cc",
@@ -68,6 +69,8 @@
         "gatt/bta_gatts_api.cc",
         "gatt/bta_gatts_main.cc",
         "gatt/bta_gatts_utils.cc",
+        "gatt/database.cc",
+        "gatt/database_builder.cc",
         "hearing_aid/hearing_aid.cc",
         "hearing_aid/hearing_aid_audio_source.cc",
         "hf_client/bta_hf_client_act.cc",
@@ -83,12 +86,6 @@
         "hh/bta_hh_le.cc",
         "hh/bta_hh_main.cc",
         "hh/bta_hh_utils.cc",
-        "hl/bta_hl_act.cc",
-        "hl/bta_hl_api.cc",
-        "hl/bta_hl_ci.cc",
-        "hl/bta_hl_main.cc",
-        "hl/bta_hl_sdp.cc",
-        "hl/bta_hl_utils.cc",
         "hd/bta_hd_act.cc",
         "hd/bta_hd_api.cc",
         "hd/bta_hd_main.cc",
@@ -127,17 +124,22 @@
     defaults: ["fluoride_bta_defaults"],
     srcs: [
         "test/bta_hf_client_test.cc",
-        "test/gatt_cache_file_test.cc",
+        "test/gatt/database_builder_test.cc",
+        "test/gatt/database_builder_sample_device_test.cc",
+        "test/gatt/database_test.cc",
     ],
     shared_libs: [
+        "libcrypto",
         "liblog",
         "libprotobuf-cpp-lite",
     ],
     static_libs: [
         "libbtcore",
         "libbt-bta",
+        "libbt-audio-hal-interface",
         "libbluetooth-types",
         "libbt-protos-lite",
         "libosi",
+        "libbt-common",
     ],
 }
diff --git a/bta/BUILD.gn b/bta/BUILD.gn
index fa85e40..0bf6544 100644
--- a/bta/BUILD.gn
+++ b/bta/BUILD.gn
@@ -20,7 +20,6 @@
     "ag/bta_ag_api.cc",
     "ag/bta_ag_at.cc",
     "ag/bta_ag_cfg.cc",
-    "ag/bta_ag_ci.cc",
     "ag/bta_ag_cmd.cc",
     "ag/bta_ag_main.cc",
     "ag/bta_ag_rfc.cc",
@@ -50,6 +49,10 @@
     "gatt/bta_gatts_api.cc",
     "gatt/bta_gatts_main.cc",
     "gatt/bta_gatts_utils.cc",
+    "gatt/database.cc",
+    "gatt/database_builder.cc",
+    "hearing_aid/hearing_aid.cc",
+    "hearing_aid/hearing_aid_audio_source.cc",
     "hf_client/bta_hf_client_act.cc",
     "hf_client/bta_hf_client_api.cc",
     "hf_client/bta_hf_client_at.cc",
@@ -66,12 +69,6 @@
     "hd/bta_hd_act.cc",
     "hd/bta_hd_api.cc",
     "hd/bta_hd_main.cc",
-    "hl/bta_hl_act.cc",
-    "hl/bta_hl_api.cc",
-    "hl/bta_hl_ci.cc",
-    "hl/bta_hl_main.cc",
-    "hl/bta_hl_sdp.cc",
-    "hl/bta_hl_utils.cc",
     "jv/bta_jv_act.cc",
     "jv/bta_jv_api.cc",
     "jv/bta_jv_cfg.cc",
@@ -100,6 +97,9 @@
     "include",
     "sys",
     "//",
+    "//linux_include",
+    "//bta",
+    "//internal_include",
     "//btcore/include",
     "//hci/include",
     "//internal_include",
@@ -108,10 +108,42 @@
     "//udrv/include",
     "//utils/include",
     "//vnd/include",
+    "//btif/include",
+    "//btif/avrcp",
+    "//include/hardware/avrcp",
+    "//profile/avrcp",
+    "//packet/avrcp",
+    "//packet/base",
   ]
 
   deps = [
     "//third_party/libchrome:base"
   ]
-
 }
+
+executable("net_test_bta") {
+  testonly = true
+  sources = [
+    "gatt/database_builder.cc",
+    "test/gatt/database_builder_test.cc",
+    "test/gatt/database_builder_sample_device_test.cc",
+    "test/gatt/database_test.cc",
+  ]
+
+  include_dirs = [
+    "include",
+    "//",
+    "//bta",
+    "//btcore/include",
+    "//hci/include",
+    "//internal_include",
+    "//stack/btm",
+  ]
+
+  deps = [
+    "//bta",
+    "//types",
+    "//third_party/googletest:gmock_main",
+    "//third_party/libchrome:base",
+  ]
+}
\ No newline at end of file
diff --git a/bta/ag/bta_ag_act.cc b/bta/ag/bta_ag_act.cc
index eb989eb..5a3697a 100644
--- a/bta/ag/bta_ag_act.cc
+++ b/bta/ag/bta_ag_act.cc
@@ -174,15 +174,13 @@
  *
  ******************************************************************************/
 void bta_ag_start_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
-  RawAddress pending_bd_addr = {};
-
-  /* store parameters */
   p_scb->peer_addr = data.api_open.bd_addr;
   p_scb->cli_sec_mask = data.api_open.sec_mask;
   p_scb->open_services = p_scb->reg_services;
 
   /* Check if RFCOMM has any incoming connection to avoid collision. */
-  if (PORT_IsOpening(pending_bd_addr)) {
+  RawAddress pending_bd_addr = RawAddress::kEmpty;
+  if (PORT_IsOpening(&pending_bd_addr)) {
     /* 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. */
@@ -516,16 +514,15 @@
  *
  ******************************************************************************/
 void bta_ag_rfc_acp_open(tBTA_AG_SCB* p_scb, const tBTA_AG_DATA& data) {
+  APPL_TRACE_DEBUG("%s: serv_handle0 = %d serv_handle = %d", __func__,
+                   p_scb->serv_handle[0], p_scb->serv_handle[1]);
   /* set role */
   p_scb->role = BTA_AG_ACP;
 
-  APPL_TRACE_DEBUG("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 */
   uint16_t lcid = 0;
   RawAddress dev_addr = RawAddress::kEmpty;
-  int status = PORT_CheckConnection(data.rfc.port_handle, dev_addr, &lcid);
+  int status = PORT_CheckConnection(data.rfc.port_handle, &dev_addr, &lcid);
   if (status != PORT_SUCCESS) {
     LOG(ERROR) << __func__ << ", PORT_CheckConnection returned " << status;
     return;
@@ -568,7 +565,7 @@
   p_scb->peer_addr = dev_addr;
 
   /* determine connected service from port handle */
-  for (int i = 0; i < BTA_AG_NUM_IDX; i++) {
+  for (uint8_t i = 0; i < BTA_AG_NUM_IDX; i++) {
     APPL_TRACE_DEBUG(
         "bta_ag_rfc_acp_open: i = %d serv_handle = %d port_handle = %d", i,
         p_scb->serv_handle[i], data.rfc.port_handle);
diff --git a/bta/ag/bta_ag_api.cc b/bta/ag/bta_ag_api.cc
index 7497fa7..727ad0f 100644
--- a/bta/ag/bta_ag_api.cc
+++ b/bta/ag/bta_ag_api.cc
@@ -31,6 +31,7 @@
 #include "bta_ag_int.h"
 #include "bta_api.h"
 #include "bta_sys.h"
+#include "stack/include/btu.h"
 
 /*****************************************************************************
  *  Constants
@@ -61,7 +62,7 @@
     }
   }
   bta_sys_register(BTA_ID_AG, &bta_ag_reg);
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_api_enable, p_cback));
+  do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_api_enable, p_cback));
   return BTA_SUCCESS;
 }
 
@@ -76,7 +77,7 @@
  *
  ******************************************************************************/
 void BTA_AgDisable() {
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_api_disable));
+  do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_api_disable));
 }
 
 /*******************************************************************************
@@ -93,7 +94,7 @@
                     tBTA_AG_FEAT features,
                     const std::vector<std::string>& service_names,
                     uint8_t app_id) {
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(&bta_ag_api_register, services, sec_mask, features,
                             service_names, app_id));
 }
@@ -109,9 +110,9 @@
  *
  ******************************************************************************/
 void BTA_AgDeregister(uint16_t handle) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                              BTA_AG_API_DEREGISTER_EVT, tBTA_AG_DATA::kEmpty));
+  do_in_main_thread(
+      FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                            BTA_AG_API_DEREGISTER_EVT, tBTA_AG_DATA::kEmpty));
 }
 
 /*******************************************************************************
@@ -131,8 +132,8 @@
   tBTA_AG_DATA data = {};
   data.api_open.bd_addr = bd_addr;
   data.api_open.sec_mask = sec_mask;
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                                         BTA_AG_API_OPEN_EVT, data));
+  do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                                          BTA_AG_API_OPEN_EVT, data));
 }
 
 /*******************************************************************************
@@ -147,9 +148,9 @@
  *
  ******************************************************************************/
 void BTA_AgClose(uint16_t handle) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                              BTA_AG_API_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                               BTA_AG_API_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
 }
 
 /*******************************************************************************
@@ -164,9 +165,9 @@
  *
  ******************************************************************************/
 void BTA_AgAudioOpen(uint16_t handle) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                              BTA_AG_API_AUDIO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
+  do_in_main_thread(
+      FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                            BTA_AG_API_AUDIO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
 }
 
 /*******************************************************************************
@@ -181,7 +182,7 @@
  *
  ******************************************************************************/
 void BTA_AgAudioClose(uint16_t handle) {
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
                             BTA_AG_API_AUDIO_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
 }
@@ -200,8 +201,8 @@
  ******************************************************************************/
 void BTA_AgResult(uint16_t handle, tBTA_AG_RES result,
                   const tBTA_AG_RES_DATA& data) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&bta_ag_api_result, handle, result, data));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&bta_ag_api_result, handle, result, data));
 }
 
 /*******************************************************************************
@@ -219,15 +220,15 @@
 void BTA_AgSetCodec(uint16_t handle, tBTA_AG_PEER_CODEC codec) {
   tBTA_AG_DATA data = {};
   data.api_setcodec.codec = codec;
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                                         BTA_AG_API_SETCODEC_EVT, data));
+  do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                                          BTA_AG_API_SETCODEC_EVT, data));
 }
 
 void BTA_AgSetScoAllowed(bool value) {
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_set_sco_allowed, value));
+  do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_set_sco_allowed, value));
 }
 
 void BTA_AgSetActiveDevice(const RawAddress& active_device_addr) {
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(&bta_ag_api_set_active_device, active_device_addr));
 }
diff --git a/bta/ag/bta_ag_cmd.cc b/bta/ag/bta_ag_cmd.cc
index 2489915..87b2a82 100644
--- a/bta/ag/bta_ag_cmd.cc
+++ b/bta/ag/bta_ag_cmd.cc
@@ -48,12 +48,6 @@
 /* Invalid Chld command */
 #define BTA_AG_INVALID_CHLD 255
 
-/* clip type constants */
-#define BTA_AG_CLIP_TYPE_MIN 128
-#define BTA_AG_CLIP_TYPE_MAX 175
-#define BTA_AG_CLIP_TYPE_DEFAULT 129
-#define BTA_AG_CLIP_TYPE_VOIP 255
-
 #define COLON_IDX_4_VGSVGM 4
 
 /* Local events which will not trigger a higher layer callback */
@@ -788,9 +782,11 @@
  ******************************************************************************/
 static bool bta_ag_parse_biev_response(tBTA_AG_SCB* p_scb, tBTA_AG_VAL* val) {
   char* p_token = strtok(val->str, ",");
+  if (p_token == nullptr) return false;
   uint16_t rcv_ind_id = atoi(p_token);
 
   p_token = strtok(nullptr, ",");
+  if (p_token == nullptr) return false;
   uint16_t rcv_ind_val = atoi(p_token);
 
   APPL_TRACE_DEBUG("%s BIEV indicator id %d, value %d", __func__, rcv_ind_id,
@@ -881,12 +877,22 @@
     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:
       /* send OK */
       bta_ag_send_ok(p_scb);
       break;
 
+    case BTA_AG_AT_CHUP_EVT:
+      if (!bta_ag_sco_is_active_device(p_scb->peer_addr)) {
+        LOG(WARNING) << __func__ << ": AT+CHUP rejected as " << p_scb->peer_addr
+                << " is not the active device";
+        event = 0;
+        bta_ag_send_error(p_scb, BTA_AG_ERR_OP_NOT_ALLOWED);
+      } else {
+        bta_ag_send_ok(p_scb);
+      }
+      break;
+
     case BTA_AG_AT_BLDN_EVT:
       /* Do not send OK, App will send error or OK depending on
       ** last dial number enabled or not */
@@ -1441,24 +1447,10 @@
       /* tell sys to stop av if any */
       bta_sys_sco_use(BTA_ID_AG, p_scb->app_id, p_scb->peer_addr);
 
-      /* Store caller id string.
-       * Append type info at the end.
-       * Make sure a valid type info is passed.
-       * Otherwise add 129 as default type */
-      uint16_t clip_type = result.data.num;
-      if ((clip_type < BTA_AG_CLIP_TYPE_MIN) ||
-          (clip_type > BTA_AG_CLIP_TYPE_MAX)) {
-        if (clip_type != BTA_AG_CLIP_TYPE_VOIP) {
-          clip_type = BTA_AG_CLIP_TYPE_DEFAULT;
-        }
-      }
-
-      APPL_TRACE_DEBUG("CLIP type :%d", clip_type);
       p_scb->clip[0] = 0;
-      if (result.data.str[0] != 0)
-        snprintf(p_scb->clip, sizeof(p_scb->clip), "%s,%d", result.data.str,
-                 clip_type);
-
+      if (result.data.str[0] != 0) {
+        snprintf(p_scb->clip, sizeof(p_scb->clip), "%s", result.data.str);
+      }
       /* send callsetup indicator */
       if (p_scb->post_sco == BTA_AG_POST_SCO_CALL_END) {
         /* Need to sent 2 callsetup IND's(Call End and Incoming call) after SCO
diff --git a/bta/ag/bta_ag_main.cc b/bta/ag/bta_ag_main.cc
index 996aa25..f70027f 100644
--- a/bta/ag/bta_ag_main.cc
+++ b/bta/ag/bta_ag_main.cc
@@ -537,13 +537,13 @@
 
   if (p_scb && (p_scb->state == BTA_AG_OPENING_ST)) {
     if (id == BTA_ID_SYS) {
-      LOG(WARNING) << __func__ << "AG found collision (ACL) for handle "
+      LOG(WARNING) << __func__ << ": AG found collision (ACL) for handle "
                    << unsigned(handle) << " device " << peer_addr;
     } else if (id == BTA_ID_AG) {
-      LOG(WARNING) << __func__ << "AG found collision (RFCOMM) for handle "
+      LOG(WARNING) << __func__ << ": AG found collision (RFCOMM) for handle "
                    << unsigned(handle) << " device " << peer_addr;
     } else {
-      LOG(WARNING) << __func__ << "AG found collision (UNKNOWN) for handle "
+      LOG(WARNING) << __func__ << ": AG found collision (UNKNOWN) for handle "
                    << unsigned(handle) << " device " << peer_addr;
     }
     bta_ag_sm_execute(p_scb, BTA_AG_COLLISION_EVT, tBTA_AG_DATA::kEmpty);
diff --git a/bta/ag/bta_ag_rfc.cc b/bta/ag/bta_ag_rfc.cc
index ba9bd7f..d878afe 100644
--- a/bta/ag/bta_ag_rfc.cc
+++ b/bta/ag/bta_ag_rfc.cc
@@ -34,6 +34,7 @@
 #include "osi/include/osi.h"
 #include "port_api.h"
 #include "rfcdefs.h"
+#include "stack/include/btu.h"
 #include "utl.h"
 
 /* Event mask for RfCOMM port callback */
@@ -89,9 +90,9 @@
                  << handle << " peer_addr " << p_scb->peer_addr << " state "
                  << std::to_string(p_scb->state);
     }
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                                BTA_AG_RFC_DATA_EVT, tBTA_AG_DATA::kEmpty));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                                 BTA_AG_RFC_DATA_EVT, tBTA_AG_DATA::kEmpty));
   }
 }
 
@@ -154,7 +155,7 @@
 
   tBTA_AG_DATA data = {};
   data.rfc.port_handle = port_handle;
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, handle, event, data));
 }
 
@@ -370,7 +371,7 @@
     /* Close API was called while AG is in Opening state.               */
     /* Need to trigger the state machine to send callback to the app    */
     /* and move back to INIT state.                                     */
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         base::Bind(&bta_ag_sm_execute_by_handle, bta_ag_scb_to_idx(p_scb),
                    BTA_AG_RFC_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
diff --git a/bta/ag/bta_ag_sco.cc b/bta/ag/bta_ag_sco.cc
index 94825ea..297d93d 100644
--- a/bta/ag/bta_ag_sco.cc
+++ b/bta/ag/bta_ag_sco.cc
@@ -32,6 +32,7 @@
 #include "device/include/controller.h"
 #include "device/include/esco_parameters.h"
 #include "osi/include/osi.h"
+#include "stack/include/btu.h"
 #include "utl.h"
 
 /* Codec negotiation timeout */
@@ -133,9 +134,9 @@
   }
 
   if (handle != 0) {
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                                BTA_AG_SCO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                                 BTA_AG_SCO_OPEN_EVT, tBTA_AG_DATA::kEmpty));
   } else {
     /* no match found; disconnect sco, init sco variables */
     bta_ag_cb.sco.p_curr_scb = nullptr;
@@ -216,9 +217,9 @@
 
     bta_ag_cb.sco.p_curr_scb->inuse_codec = BTA_AG_CODEC_NONE;
 
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&bta_ag_sm_execute_by_handle, handle,
-                                BTA_AG_SCO_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&bta_ag_sm_execute_by_handle, handle,
+                                 BTA_AG_SCO_CLOSE_EVT, tBTA_AG_DATA::kEmpty));
   } else {
     /* no match found */
     APPL_TRACE_DEBUG("no scb for ag_sco_disc_cback");
@@ -372,7 +373,7 @@
                  << " is not active, active_device=" << active_device_addr;
     if (bta_ag_cb.sco.p_curr_scb != nullptr &&
         bta_ag_cb.sco.p_curr_scb->in_use && p_scb == bta_ag_cb.sco.p_curr_scb) {
-      do_in_bta_thread(
+      do_in_main_thread(
           FROM_HERE, base::Bind(&bta_ag_sm_execute, p_scb, BTA_AG_SCO_CLOSE_EVT,
                                 tBTA_AG_DATA::kEmpty));
     }
@@ -385,8 +386,10 @@
     return;
   }
 
+#if (DISABLE_WBS == FALSE)
   if ((p_scb->sco_codec == BTA_AG_CODEC_MSBC) && !p_scb->codec_fallback)
     esco_codec = BTA_AG_CODEC_MSBC;
+#endif
 
   if (p_scb->codec_fallback) {
     p_scb->codec_fallback = false;
@@ -558,12 +561,27 @@
 void bta_ag_codec_negotiate(tBTA_AG_SCB* p_scb) {
   APPL_TRACE_DEBUG("%s", __func__);
   bta_ag_cb.sco.p_curr_scb = p_scb;
+  uint8_t* p_rem_feat = BTM_ReadRemoteFeatures(p_scb->peer_addr);
+  bool sdp_wbs_support = p_scb->peer_sdp_features & BTA_AG_FEAT_WBS_SUPPORT;
 
-  // Workaround for misbehaving HFs such as Sony XAV AX100 car kit and Sony
-  // MW600 Headset, which indicate WBS support in SDP, but no codec
-  // negotiation support in BRSF. In this case, using mSBC codec can result
-  // background noise or no audio. Thus, defaulting to CVSD instead.
-  if (!(p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
+  if (p_rem_feat == nullptr) {
+    LOG(WARNING) << __func__
+                 << ": Fail to read remote feature, skip codec negotiation";
+    bta_ag_sco_codec_nego(p_scb, false);
+    return;
+  }
+
+  // Workaround for misbehaving HFs, which indicate which one is not support on
+  // Transparent Synchronous Data in Remote Supported Features, WBS in SDP and
+  // and Codec Negotiation in BRSF. Fluoride will assume CVSD codec by default.
+  // In Sony XAV AX100 car kit and Sony MW600 Headset case, which indicate
+  // Transparent Synchronous Data and WBS support, but no codec negotiation
+  // support, using mSBC codec can result background noise or no audio.
+  // In Skullcandy JIB case, which indicate WBS and codec negotiation support,
+  // but no Transparent Synchronous Data support, using mSBC codec can result
+  // SCO setup fail by Firmware reject.
+  if (!HCI_LMP_TRANSPNT_SUPPORTED(p_rem_feat) || !sdp_wbs_support ||
+      !(p_scb->peer_features & BTA_AG_PEER_FEAT_CODEC)) {
     p_scb->sco_codec = UUID_CODEC_CVSD;
   }
 
@@ -635,9 +653,14 @@
           /* remove listening connection */
           bta_ag_remove_sco(p_scb, false);
 
+#if (DISABLE_WBS == FALSE)
           /* start codec negotiation */
           p_sco->state = BTA_AG_SCO_CODEC_ST;
           bta_ag_codec_negotiate(p_scb);
+#else
+          bta_ag_create_sco(p_scb, true);
+          p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
           break;
 
         case BTA_AG_SCO_SHUTDOWN_E:
@@ -732,11 +755,13 @@
           }
           break;
 
+#if (DISABLE_WBS == FALSE)
         case BTA_AG_SCO_REOPEN_E:
           /* start codec negotiation */
           p_sco->state = BTA_AG_SCO_CODEC_ST;
           bta_ag_codec_negotiate(p_scb);
           break;
+#endif
 
         case BTA_AG_SCO_XFER_E:
           /* save xfer scb */
@@ -1009,11 +1034,18 @@
           bta_ag_create_sco(p_scb, false);
           bta_ag_remove_sco(p_sco->p_xfer_scb, false);
 
+#if (DISABLE_WBS == FALSE)
           /* start codec negotiation */
           p_sco->state = BTA_AG_SCO_CODEC_ST;
           tBTA_AG_SCB* p_cn_scb = p_sco->p_xfer_scb;
           p_sco->p_xfer_scb = nullptr;
           bta_ag_codec_negotiate(p_cn_scb);
+#else
+          /* create sco connection to peer */
+          bta_ag_create_sco(p_sco->p_xfer_scb, true);
+          p_sco->p_xfer_scb = nullptr;
+          p_sco->state = BTA_AG_SCO_OPENING_ST;
+#endif
           break;
         }
 
diff --git a/bta/ag/bta_ag_sdp.cc b/bta/ag/bta_ag_sdp.cc
index 5ab1215..ba955d3 100644
--- a/bta/ag/bta_ag_sdp.cc
+++ b/bta/ag/bta_ag_sdp.cc
@@ -36,6 +36,7 @@
 #include "btm_api.h"
 #include "osi/include/osi.h"
 #include "sdp_api.h"
+#include "stack/include/btu.h"
 #include "utl.h"
 
 using bluetooth::Uuid;
@@ -87,8 +88,8 @@
       event = BTA_AG_DISC_INT_RES_EVT;
     }
     tBTA_AG_DATA disc_result = {.disc_result.status = status};
-    do_in_bta_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, idx,
-                                           event, disc_result));
+    do_in_main_thread(FROM_HERE, base::Bind(&bta_ag_sm_execute_by_handle, idx,
+                                            event, disc_result));
   }
 }
 
diff --git a/bta/av/bta_av_aact.cc b/bta/av/bta_av_aact.cc
index 3ecc1e6..b022b43 100644
--- a/bta/av/bta_av_aact.cc
+++ b/bta/av/bta_av_aact.cc
@@ -79,7 +79,6 @@
 /* ACL quota we are letting FW use for A2DP Offload Tx. */
 #define BTA_AV_A2DP_OFFLOAD_XMIT_QUOTA 4
 
-#define MAX_2MBPS_AVDTP_MTU 663
 #define BTIF_A2DP_MAX_BITPOOL_MQ 35
 
 static void bta_av_offload_codec_builder(tBTA_AV_SCB* p_scb,
@@ -966,7 +965,7 @@
  *
  ******************************************************************************/
 void bta_av_config_ind(tBTA_AV_SCB* p_scb, tBTA_AV_DATA* p_data) {
-  tBTA_AV_CI_SETCONFIG setconfig;
+  tBTA_AV_CI_SETCONFIG setconfig{};
   tAVDT_SEP_INFO* p_info;
   const AvdtpSepConfig* p_evt_cfg = &p_data->str_msg.cfg;
   uint8_t psc_mask = (p_evt_cfg->psc_mask | p_scb->cfg.psc_mask);
@@ -3247,7 +3246,7 @@
       APPL_TRACE_ERROR("%s: Unknown Codec type ", __func__);
       return;
   }
-  if (mtu > BTA_AV_MAX_A2DP_MTU) mtu = BTA_AV_MAX_A2DP_MTU;
+  if (mtu > MAX_3MBPS_AVDTP_MTU) mtu = MAX_3MBPS_AVDTP_MTU;
   p_a2dp_offload->codec_type = codec_type;
   p_a2dp_offload->max_latency = 0;
   p_a2dp_offload->mtu = mtu;
diff --git a/bta/av/bta_av_act.cc b/bta/av/bta_av_act.cc
index 5625f90..a727842 100644
--- a/bta/av/bta_av_act.cc
+++ b/bta/av/bta_av_act.cc
@@ -314,18 +314,26 @@
   tAVRC_CONN_CB ccb;
   RawAddress bda = RawAddress::kAny;
   uint8_t status = BTA_AV_RC_ROLE_ACP;
-  tBTA_AV_SCB* p_scb = p_cb->p_scb[shdl - 1];
   int i;
   uint8_t rc_handle;
   tBTA_AV_RCB* p_rcb;
 
   if (role == AVCT_INT) {
+    // Can't grab a stream control block that doesn't have a valid handle
+    if (!shdl) {
+      APPL_TRACE_ERROR(
+          "%s: Can't grab stream control block for shdl = %d -> index = %d",
+          __func__, shdl, shdl - 1);
+      return BTA_AV_RC_HANDLE_NONE;
+    }
+    tBTA_AV_SCB* p_scb = p_cb->p_scb[shdl - 1];
     bda = p_scb->PeerAddress();
     status = BTA_AV_RC_ROLE_INT;
   } else {
     p_rcb = bta_av_get_rcb_by_shdl(shdl);
     if (p_rcb != NULL) {
       APPL_TRACE_ERROR("%s: ACP handle exist for shdl:%d", __func__, shdl);
+      p_rcb->lidx = lidx;
       return p_rcb->handle;
     }
   }
@@ -1865,9 +1873,9 @@
       /*
        * In case scb is not created by the time we are done with SDP
        * we still need to send RC feature event. So we need to get BD
-       * from Message
+       * from Message.  Note that lidx is 1 based not 0 based
        */
-      rc_feat.peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx].addr;
+      rc_feat.peer_addr = p_cb->lcb[p_cb->rcb[rc_handle].lidx - 1].addr;
     } else {
       rc_feat.peer_addr = p_scb->PeerAddress();
     }
@@ -1939,11 +1947,6 @@
       } else {
         /* 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)) {
@@ -1964,6 +1967,9 @@
   tBTA_AV bta_av_data;
   bta_av_data.rc_close = rc_close;
   (*p_cb->p_cback)(BTA_AV_RC_CLOSE_EVT, &bta_av_data);
+  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_cfg.cc b/bta/av/bta_av_cfg.cc
index 76c9454..1da38b3 100644
--- a/bta/av/bta_av_cfg.cc
+++ b/bta/av/bta_av_cfg.cc
@@ -134,7 +134,7 @@
     BTA_AV_RC_SUPF_CT,     /* AVRCP controller categories */
     BTA_AV_RC_SUPF_TG,     /* AVRCP target categories */
     672,                   /* AVDTP signaling channel MTU at L2CAP */
-    BTA_AV_MAX_A2DP_MTU,   /* AVDTP audio transport channel MTU at L2CAP */
+    MAX_3MBPS_AVDTP_MTU,   /* AVDTP audio transport channel MTU at L2CAP */
     bta_av_audio_flush_to, /* AVDTP audio transport channel flush
                               timeout */
     6,                     /* AVDTP audio channel max data queue size */
@@ -161,7 +161,7 @@
     BTA_AVK_RC_SUPF_CT,    /* AVRCP controller categories */
     BTA_AVK_RC_SUPF_TG,    /* AVRCP target categories */
     672,                   /* AVDTP signaling channel MTU at L2CAP */
-    BTA_AV_MAX_A2DP_MTU,   /* AVDTP audio transport channel MTU at L2CAP */
+    MAX_3MBPS_AVDTP_MTU,   /* AVDTP audio transport channel MTU at L2CAP */
     bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
     6,                     /* AVDTP audio channel max data queue size */
     false, /* true, to accept AVRC 1.3 group nevigation command */
@@ -186,7 +186,7 @@
     BTA_AV_RC_SUPF_CT,     /* AVRCP controller categories */
     AVRC_SUPF_TG_CAT1,     /* Only support CAT1 for AVRCP1.3 */
     672,                   /* AVDTP signaling channel MTU at L2CAP */
-    BTA_AV_MAX_A2DP_MTU,   /* AVDTP audio transport channel MTU at L2CAP */
+    MAX_3MBPS_AVDTP_MTU,   /* AVDTP audio transport channel MTU at L2CAP */
     bta_av_audio_flush_to, /* AVDTP audio transport channel flush timeout */
     6,                     /* AVDTP audio channel max data queue size */
     false, /* true, to accept AVRC 1.3 group nevigation command */
diff --git a/bta/av/bta_av_main.cc b/bta/av/bta_av_main.cc
index 3679469..34516fc 100644
--- a/bta/av/bta_av_main.cc
+++ b/bta/av/bta_av_main.cc
@@ -635,6 +635,9 @@
     for (int i = codec_index_min; i < codec_index_max; i++) {
       btav_a2dp_codec_index_t codec_index =
           static_cast<btav_a2dp_codec_index_t>(i);
+      if (!bta_av_co_is_supported_codec(codec_index)) {
+        continue;
+      }
       if (!(*bta_av_a2dp_cos.init)(codec_index, &avdtp_stream_config.cfg)) {
         continue;
       }
@@ -1382,6 +1385,8 @@
 }
 
 void bta_debug_av_dump(int fd) {
+  if (appl_trace_level < BT_TRACE_LEVEL_DEBUG) return;
+
   dprintf(fd, "\nBTA AV State:\n");
   dprintf(fd, "  State Machine State: %s\n", bta_av_st_code(bta_av_cb.state));
   dprintf(fd, "  Link signalling timer: %s\n",
@@ -1410,6 +1415,9 @@
   for (size_t i = 0; i < sizeof(bta_av_cb.lcb) / sizeof(bta_av_cb.lcb[0]);
        i++) {
     const tBTA_AV_LCB& lcb = bta_av_cb.lcb[i];
+    if (lcb.addr.IsEmpty()) {
+      continue;
+    }
     dprintf(fd, "\n  Link control block: %zu peer: %s\n", i,
             lcb.addr.ToString().c_str());
     dprintf(fd, "    Connected stream handle mask: 0x%x\n", lcb.conn_msk);
@@ -1420,12 +1428,18 @@
     if (p_scb == nullptr) {
       continue;
     }
+    if (p_scb->PeerAddress().IsEmpty()) {
+      continue;
+    }
     dprintf(fd, "\n  BTA ID: %zu peer: %s\n", i,
             p_scb->PeerAddress().ToString().c_str());
     dprintf(fd, "    SDP discovery started: %s\n",
             p_scb->sdp_discovery_started ? "true" : "false");
     for (size_t j = 0; j < BTAV_A2DP_CODEC_INDEX_MAX; j++) {
       const tBTA_AV_SEP& sep = p_scb->seps[j];
+      if (sep.av_handle == 0) {
+        continue;
+      }
       dprintf(fd, "    SEP ID: %zu\n", j);
       dprintf(fd, "      SEP AVDTP handle: %d\n", sep.av_handle);
       dprintf(fd, "      Local SEP type: %d\n", sep.tsep);
diff --git a/bta/av/bta_av_ssm.cc b/bta/av/bta_av_ssm.cc
index 6c384e0..a1a94b0 100644
--- a/bta/av/bta_av_ssm.cc
+++ b/bta/av/bta_av_ssm.cc
@@ -131,7 +131,7 @@
     /* STR_START_FAIL_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
     /* STR_CLOSE_EVT */ {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
     /* STR_CONFIG_IND_EVT */
-    {BTA_AV_SETCONFIG_REJ, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
+    {BTA_AV_CONFIG_IND, BTA_AV_SIGNORE, BTA_AV_INCOMING_SST},
     /* STR_SECURITY_IND_EVT */
     {BTA_AV_SIGNORE, BTA_AV_SIGNORE, BTA_AV_INIT_SST},
     /* STR_SECURITY_CFM_EVT */
diff --git a/bta/dm/bta_dm_act.cc b/bta/dm/bta_dm_act.cc
index 5abda87..7ba3c74 100644
--- a/bta/dm/bta_dm_act.cc
+++ b/bta/dm/bta_dm_act.cc
@@ -38,6 +38,7 @@
 #include "bta_dm_co.h"
 #include "bta_dm_int.h"
 #include "bta_sys.h"
+#include "btif_storage.h"
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
@@ -46,6 +47,8 @@
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 #include "sdp_api.h"
+#include "stack/gatt/connection_manager.h"
+#include "stack/include/gatt_api.h"
 #include "utl.h"
 
 #if (GAP_INCLUDED == TRUE)
@@ -71,7 +74,7 @@
                                 BD_NAME bd_name, bool min_16_digit);
 static uint8_t bta_dm_new_link_key_cback(const RawAddress& bd_addr,
                                          DEV_CLASS dev_class, BD_NAME bd_name,
-                                         LINK_KEY key, uint8_t key_type);
+                                         const LinkKey& key, uint8_t key_type);
 static uint8_t bta_dm_authentication_complete_cback(const RawAddress& bd_addr,
                                                     DEV_CLASS dev_class,
                                                     BD_NAME bd_name,
@@ -189,12 +192,10 @@
 
 /*
  * NOTE : The number of element in bta_service_id_to_btm_srv_id_lkup_tbl should
- * be matching with
- *        the value BTA_MAX_SERVICE_ID in bta_api.h
+ * be matching with the value BTA_MAX_SERVICE_ID in bta_api.h
  *
- *        i.e., If you add new Service ID for BTA, the correct security ID of
- * the new service
- *              from Security service definitions (btm_api.h) should be added to
+ * i.e., If you add new Service ID for BTA, the correct security ID of the new
+ * service from Security service definitions (btm_api.h) should be added to
  * this lookup table.
  */
 const uint32_t bta_service_id_to_btm_srv_id_lkup_tbl[BTA_MAX_SERVICE_ID] = {
@@ -245,6 +246,9 @@
 
 extern DEV_CLASS local_device_default_class;
 
+// Stores the local Input/Output Capabilities of the Bluetooth device.
+static uint8_t btm_local_io_caps;
+
 /** Initialises the BT device manager */
 void bta_dm_enable(tBTA_DM_SEC_CBACK* p_sec_cback) {
   /* if already in use, return an error */
@@ -275,6 +279,8 @@
   sys_enable_event->hw_module = BTA_SYS_HW_BLUETOOTH;
 
   bta_sys_sendmsg(sys_enable_event);
+
+  btm_local_io_caps = btif_storage_get_local_io_caps();
 }
 
 /*******************************************************************************
@@ -337,7 +343,6 @@
   DEV_CLASS dev_class;
   tBTA_DM_SEC_CBACK* temp_cback;
   uint8_t key_mask = 0;
-  BT_OCTET16 er;
   tBTA_BLE_LOCAL_ID_KEYS id_key;
 
   APPL_TRACE_DEBUG("%s with event: %i", __func__, status);
@@ -400,7 +405,8 @@
     BTM_SetDeviceClass(dev_class);
 
     /* load BLE local information: ID keys, ER if available */
-    bta_dm_co_ble_load_local_keys(&key_mask, er, &id_key);
+    Octet16 er;
+    bta_dm_co_ble_load_local_keys(&key_mask, &er, &id_key);
 
     if (key_mask & BTA_BLE_LOCAL_KEY_TYPE_ER) {
       BTM_BleLoadLocalKeys(BTA_BLE_LOCAL_KEY_TYPE_ER,
@@ -471,7 +477,7 @@
   bta_dm_disable_search_and_disc();
   bta_dm_cb.disabling = true;
 
-  BTM_BleClearBgConnDev();
+  connection_manager::reset(false);
 
   if (BTM_GetNumAclLinks() == 0) {
 #if (BTA_DISABLE_DELAY > 0)
@@ -639,6 +645,10 @@
       auto& peer_device = bta_dm_cb.device_list.peer_device[i];
       if (peer_device.peer_bdaddr == bd_addr) {
         peer_device.conn_state = BTA_DM_UNPAIRING;
+
+        /* Make sure device is not in white list before we disconnect */
+        GATT_CancelConnect(0, bd_addr, false);
+
         btm_remove_acl(bd_addr, peer_device.transport);
         APPL_TRACE_DEBUG("%s: transport: %d", __func__, peer_device.transport);
 
@@ -675,6 +685,10 @@
       auto& peer_device = bta_dm_cb.device_list.peer_device[i];
       if (peer_device.peer_bdaddr == other_address) {
         peer_device.conn_state = BTA_DM_UNPAIRING;
+
+        /* Make sure device is not in white list before we disconnect */
+        GATT_CancelConnect(0, bd_addr, false);
+
         btm_remove_acl(other_address, peer_device.transport);
         break;
       }
@@ -699,11 +713,10 @@
  * Description      This function adds a Link Key to an security database entry.
  *                  It is normally called during host startup to restore all
  *                  required information stored in the NVRAM.
- ***
  ******************************************************************************/
 void bta_dm_add_device(std::unique_ptr<tBTA_DM_API_ADD_DEVICE> msg) {
   uint8_t* p_dc = NULL;
-  uint8_t* p_lc = NULL;
+  LinkKey* p_lc = NULL;
   uint32_t trusted_services_mask[BTM_SEC_SERVICE_ARRAY_SIZE];
   uint8_t index = 0;
   uint8_t btm_mask_index = 0;
@@ -713,7 +726,7 @@
   /* If not all zeros, the device class has been specified */
   if (msg->dc_known) p_dc = (uint8_t*)msg->dc;
 
-  if (msg->link_key_known) p_lc = (uint8_t*)msg->link_key;
+  if (msg->link_key_known) p_lc = &msg->link_key;
 
   if (msg->is_trusted) {
     /* covert BTA service mask to BTM mask */
@@ -757,6 +770,10 @@
     } else {
       APPL_TRACE_ERROR("unknown device, remove ACL failed");
     }
+
+    /* Make sure device is not in white list before we disconnect */
+    GATT_CancelConnect(0, bd_addr, false);
+
     /* Disconnect the ACL link */
     btm_remove_acl(bd_addr, transport);
   }
@@ -1968,12 +1985,13 @@
       /* 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 (bta_dm_search_cb.p_btm_inq_info) {
         APPL_TRACE_DEBUG(
             "%s p_btm_inq_info 0x%x results.device_type 0x%x "
@@ -2359,7 +2377,7 @@
  ******************************************************************************/
 static uint8_t bta_dm_new_link_key_cback(const RawAddress& bd_addr,
                                          UNUSED_ATTR DEV_CLASS dev_class,
-                                         BD_NAME bd_name, LINK_KEY key,
+                                         BD_NAME bd_name, const LinkKey& key,
                                          uint8_t key_type) {
   tBTA_DM_SEC sec_event;
   tBTA_DM_AUTH_CMPL* p_auth_cmpl;
@@ -2376,12 +2394,10 @@
 
     memcpy(p_auth_cmpl->bd_name, bd_name, (BD_NAME_LEN - 1));
     p_auth_cmpl->bd_name[BD_NAME_LEN - 1] = 0;
-
     p_auth_cmpl->key_present = true;
     p_auth_cmpl->key_type = key_type;
     p_auth_cmpl->success = true;
-
-    memcpy(p_auth_cmpl->key, key, LINK_KEY_LEN);
+    p_auth_cmpl->key = key;
     sec_event.auth_cmpl.fail_reason = HCI_SUCCESS;
 
     // Report the BR link key based on the BR/EDR address and type
@@ -2463,20 +2479,20 @@
   /* TODO_SP */
   switch (event) {
     case BTM_SP_IO_REQ_EVT:
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
-      /* translate auth_req */
-      bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
-                       &p_data->io_req.oob_data, &p_data->io_req.auth_req,
-                       p_data->io_req.is_orig);
-#endif
+      if (btm_local_io_caps != BTM_IO_CAP_NONE) {
+        /* translate auth_req */
+        bta_dm_co_io_req(p_data->io_req.bd_addr, &p_data->io_req.io_cap,
+                         &p_data->io_req.oob_data, &p_data->io_req.auth_req,
+                         p_data->io_req.is_orig);
+      }
       APPL_TRACE_EVENT("io mitm: %d oob_data:%d", p_data->io_req.auth_req,
                        p_data->io_req.oob_data);
       break;
     case BTM_SP_IO_RSP_EVT:
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
-      bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
-                       p_data->io_rsp.oob_data, p_data->io_rsp.auth_req);
-#endif
+      if (btm_local_io_caps != BTM_IO_CAP_NONE) {
+        bta_dm_co_io_rsp(p_data->io_rsp.bd_addr, p_data->io_rsp.io_cap,
+                         p_data->io_rsp.oob_data, p_data->io_rsp.auth_req);
+      }
       break;
 
     case BTM_SP_CFM_REQ_EVT:
@@ -2489,12 +2505,16 @@
       sec_event.cfm_req.rmt_io_caps = p_data->cfm_req.rmt_io_caps;
 
     /* continue to next case */
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
     /* Passkey entry mode, mobile device with output capability is very
         unlikely to receive key request, so skip this event */
     /*case BTM_SP_KEY_REQ_EVT: */
     case BTM_SP_KEY_NOTIF_EVT:
-#endif
+      if (btm_local_io_caps == BTM_IO_CAP_NONE &&
+          BTM_SP_KEY_NOTIF_EVT == event) {
+        status = BTM_NOT_AUTHORIZED;
+        break;
+      }
+
       bta_dm_cb.num_val = sec_event.key_notif.passkey =
           p_data->key_notif.passkey;
 
@@ -2774,7 +2794,9 @@
       bta_dm_cb.device_list.le_count--;
     conn.link_down.link_type = transport;
 
-    if (bta_dm_search_cb.wait_disc && bta_dm_search_cb.peer_bdaddr == bd_addr) {
+    if ((transport == BT_TRANSPORT_BR_EDR) &&
+        (bta_dm_search_cb.wait_disc &&
+         bta_dm_search_cb.peer_bdaddr == bd_addr)) {
       bta_dm_search_cb.wait_disc = false;
 
       if (bta_dm_search_cb.sdp_results) {
@@ -2820,34 +2842,34 @@
   switch (p_data->event) {
     case BTM_BL_CONN_EVT:
       /* connection up */
-      do_in_bta_thread(FROM_HERE,
-                       base::Bind(bta_dm_acl_change, true, *p_data->conn.p_bda,
-                                  p_data->conn.transport, p_data->conn.handle));
+      do_in_main_thread(
+          FROM_HERE, base::Bind(bta_dm_acl_change, true, *p_data->conn.p_bda,
+                                p_data->conn.transport, p_data->conn.handle));
       break;
     case BTM_BL_DISCN_EVT:
       /* connection down */
-      do_in_bta_thread(
+      do_in_main_thread(
           FROM_HERE, base::Bind(bta_dm_acl_change, false, *p_data->discn.p_bda,
                                 p_data->discn.transport, p_data->discn.handle));
       break;
 
     case BTM_BL_UPDATE_EVT: {
       /* busy level update */
-      do_in_bta_thread(FROM_HERE, base::Bind(send_busy_level_update,
-                                             p_data->update.busy_level,
-                                             p_data->update.busy_level_flags));
+      do_in_main_thread(FROM_HERE, base::Bind(send_busy_level_update,
+                                              p_data->update.busy_level,
+                                              p_data->update.busy_level_flags));
       return;
     }
     case BTM_BL_ROLE_CHG_EVT: {
       const auto& tmp = p_data->role_chg;
-      do_in_bta_thread(FROM_HERE, base::Bind(handle_role_change, *tmp.p_bda,
-                                             tmp.new_role, tmp.hci_status));
+      do_in_main_thread(FROM_HERE, base::Bind(handle_role_change, *tmp.p_bda,
+                                              tmp.new_role, tmp.hci_status));
       return;
     }
 
     case BTM_BL_COLLISION_EVT:
       /* Collision report from Stack: Notify profiles */
-      do_in_bta_thread(
+      do_in_main_thread(
           FROM_HERE, base::Bind(bta_sys_notify_collision, *p_data->conn.p_bda));
       return;
   }
@@ -3766,13 +3788,10 @@
   memset(&sec_event, 0, sizeof(tBTA_DM_SEC));
   switch (event) {
     case BTM_LE_IO_REQ_EVT:
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
-
       bta_dm_co_ble_io_req(
           bda, &p_data->io_req.io_cap, &p_data->io_req.oob_data,
           &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);
-#endif
       APPL_TRACE_EVENT("io mitm: %d oob_data:%d", p_data->io_req.auth_req,
                        p_data->io_req.oob_data);
 
@@ -3842,10 +3861,24 @@
       if (p_data->complt.reason != 0) {
         sec_event.auth_cmpl.fail_reason =
             BTA_DM_AUTH_CONVERT_SMP_CODE(((uint8_t)p_data->complt.reason));
-        /* delete this device entry from Sec Dev DB */
-        bta_dm_remove_sec_dev_entry(bda);
+
+        if (btm_sec_is_a_bonded_dev(bda) &&
+            p_data->complt.reason == SMP_CONN_TOUT) {
+          // Bonded device failed to encrypt - to test this remove battery from
+          // HID device right after connection, but before encryption is
+          // established
+          LOG(INFO) << __func__
+                    << ": bonded device disconnected when encrypting - no "
+                       "reason to unbond";
+        } else {
+          /* delete this device entry from Sec Dev DB */
+          bta_dm_remove_sec_dev_entry(bda);
+        }
+
       } else {
         sec_event.auth_cmpl.success = true;
+        if (!p_data->complt.smp_over_br)
+          GATT_ConfigServiceChangeCCC(bda, true, BT_TRANSPORT_LE);
       }
 
       if (bta_dm_cb.p_sec_cback) {
@@ -4018,20 +4051,6 @@
     }
   }
 }
-/*******************************************************************************
- *
- * Function         bta_dm_ble_set_adv_params
- *
- * Description      This function set the adv parameters.
- *
- * Parameters:
- *
- ******************************************************************************/
-void bta_dm_ble_set_adv_params(uint16_t adv_int_min, uint16_t adv_int_max,
-                               tBLE_BD_ADDR* p_dir_bda) {
-  BTM_BleSetAdvParams(adv_int_min, adv_int_max, p_dir_bda,
-                      BTA_DM_BLE_ADV_CHNL_MAP);
-}
 
 /** This function set the maximum transmission packet size */
 void bta_dm_ble_set_data_length(const RawAddress& bd_addr,
diff --git a/bta/dm/bta_dm_api.cc b/bta/dm/bta_dm_api.cc
index e968bd1..979d2f6 100644
--- a/bta/dm/bta_dm_api.cc
+++ b/bta/dm/bta_dm_api.cc
@@ -26,13 +26,13 @@
 
 #include "bt_common.h"
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bta_dm_int.h"
 #include "bta_sys.h"
 #include "bta_sys_int.h"
 #include "btm_api.h"
 #include "btm_int.h"
 #include "osi/include/osi.h"
+#include "stack/include/btu.h"
 #include "utl.h"
 
 using bluetooth::Uuid;
@@ -64,7 +64,7 @@
   /* if UUID list is not provided as static data */
   bta_sys_eir_register(bta_dm_eir_update_uuid);
 
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_enable, p_cback));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_enable, p_cback));
   return BTA_SUCCESS;
 }
 
@@ -79,19 +79,19 @@
  *
  ******************************************************************************/
 tBTA_STATUS BTA_DisableBluetooth(void) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_disable));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_disable));
   return BTA_SUCCESS;
 }
 
 /** Enables bluetooth device under test mode */
 void BTA_EnableTestMode(void) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(base::IgnoreResult(BTM_EnableTestMode)));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(base::IgnoreResult(BTM_EnableTestMode)));
 }
 
 /** Disable bluetooth device under test mode */
 void BTA_DisableTestMode(void) {
-  do_in_bta_thread(FROM_HERE, base::Bind(BTM_DeviceReset, nullptr));
+  do_in_main_thread(FROM_HERE, base::Bind(BTM_DeviceReset, nullptr));
 }
 
 /** This function sets the Bluetooth name of local device */
@@ -99,7 +99,7 @@
   std::vector<uint8_t> name(BD_NAME_LEN);
   strlcpy((char*)name.data(), p_name, BD_NAME_LEN);
 
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_set_dev_name, name));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_set_dev_name, name));
 }
 
 /** This function sets the Bluetooth connectable, discoverable, pairable and
@@ -107,9 +107,9 @@
  */
 void BTA_DmSetVisibility(tBTA_DM_DISC disc_mode, tBTA_DM_CONN conn_mode,
                          uint8_t pairable_mode, uint8_t conn_paired_only) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_set_visibility, disc_mode, conn_mode,
-                              pairable_mode, conn_paired_only));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_set_visibility, disc_mode, conn_mode,
+                               pairable_mode, conn_paired_only));
 }
 
 /*******************************************************************************
@@ -211,20 +211,20 @@
 
 /** This function initiates a bonding procedure with a peer device */
 void BTA_DmBond(const RawAddress& bd_addr) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_bond, bd_addr, BTA_TRANSPORT_UNKNOWN));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_bond, bd_addr, BTA_TRANSPORT_UNKNOWN));
 }
 
 /** This function initiates a bonding procedure with a peer device */
 void BTA_DmBondByTransport(const RawAddress& bd_addr,
                            tBTA_TRANSPORT transport) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_bond, bd_addr, transport));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_bond, bd_addr, transport));
 }
 
 /** This function cancels the bonding procedure with a peer device
  */
 void BTA_DmBondCancel(const RawAddress& bd_addr) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_bond_cancel, bd_addr));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_bond_cancel, bd_addr));
 }
 
 /*******************************************************************************
@@ -250,7 +250,8 @@
     memcpy(msg->p_pin, p_pin, pin_len);
   }
 
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_pin_reply, base::Passed(&msg)));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_pin_reply, base::Passed(&msg)));
 }
 
 /*******************************************************************************
@@ -267,7 +268,7 @@
  *
  ******************************************************************************/
 void BTA_DmLocalOob(void) {
-  do_in_bta_thread(FROM_HERE, base::Bind(BTM_ReadLocalOobData));
+  do_in_main_thread(FROM_HERE, base::Bind(BTM_ReadLocalOobData));
 }
 
 /*******************************************************************************
@@ -281,7 +282,7 @@
  *
  ******************************************************************************/
 void BTA_DmConfirm(const RawAddress& bd_addr, bool accept) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_confirm, bd_addr, accept));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_confirm, bd_addr, accept));
 }
 
 /*******************************************************************************
@@ -296,7 +297,7 @@
  *
  ******************************************************************************/
 void BTA_DmAddDevice(const RawAddress& bd_addr, DEV_CLASS dev_class,
-                     LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
+                     const LinkKey& link_key, tBTA_SERVICE_MASK trusted_mask,
                      bool is_trusted, uint8_t key_type, tBTA_IO_CAP io_cap,
                      uint8_t pin_length) {
   std::unique_ptr<tBTA_DM_API_ADD_DEVICE> msg =
@@ -306,12 +307,9 @@
   msg->tm = trusted_mask;
   msg->is_trusted = is_trusted;
   msg->io_cap = io_cap;
-
-  if (link_key) {
-    msg->link_key_known = true;
-    msg->key_type = key_type;
-    memcpy(msg->link_key, link_key, LINK_KEY_LEN);
-  }
+  msg->link_key_known = true;
+  msg->key_type = key_type;
+  msg->link_key = link_key;
 
   /* Load device class if specified */
   if (dev_class) {
@@ -323,14 +321,14 @@
   memset(msg->features, 0, sizeof(msg->features));
   msg->pin_length = pin_length;
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_add_device, base::Passed(&msg)));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_add_device, base::Passed(&msg)));
 }
 
 /** This function removes a device fromthe security database list of peer
  * device. It manages unpairing even while connected */
 tBTA_STATUS BTA_DmRemoveDevice(const RawAddress& bd_addr) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_remove_device, bd_addr));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_remove_device, bd_addr));
   return BTA_SUCCESS;
 }
 
@@ -443,8 +441,8 @@
  ******************************************************************************/
 void BTA_DmAddBleKey(const RawAddress& bd_addr, tBTA_LE_KEY_VALUE* p_le_key,
                      tBTA_LE_KEY_TYPE key_type) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_add_blekey, bd_addr, *p_le_key, key_type));
+  do_in_main_thread(
+      FROM_HERE, base::Bind(bta_dm_add_blekey, bd_addr, *p_le_key, key_type));
 }
 
 /*******************************************************************************
@@ -464,8 +462,8 @@
  ******************************************************************************/
 void BTA_DmAddBleDevice(const RawAddress& bd_addr, tBLE_ADDR_TYPE addr_type,
                         tBT_DEVICE_TYPE dev_type) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_add_ble_device, bd_addr,
-                                         addr_type, dev_type));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_add_ble_device, bd_addr,
+                                          addr_type, dev_type));
 }
 
 /*******************************************************************************
@@ -484,8 +482,8 @@
  ******************************************************************************/
 void BTA_DmBlePasskeyReply(const RawAddress& bd_addr, bool accept,
                            uint32_t passkey) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ble_passkey_reply, bd_addr,
-                                         accept, accept ? passkey : 0));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_ble_passkey_reply, bd_addr,
+                                          accept, accept ? passkey : 0));
 }
 
 /*******************************************************************************
@@ -502,8 +500,8 @@
  *
  ******************************************************************************/
 void BTA_DmBleConfirmReply(const RawAddress& bd_addr, bool accept) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_ble_confirm_reply, bd_addr, accept));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_ble_confirm_reply, bd_addr, accept));
 }
 
 /*******************************************************************************
@@ -520,7 +518,7 @@
  ******************************************************************************/
 void BTA_DmBleSecurityGrant(const RawAddress& bd_addr,
                             tBTA_DM_BLE_SEC_GRANT res) {
-  do_in_bta_thread(FROM_HERE, base::Bind(BTM_SecurityGrant, bd_addr, res));
+  do_in_main_thread(FROM_HERE, base::Bind(BTM_SecurityGrant, bd_addr, res));
 }
 
 /*******************************************************************************
@@ -546,9 +544,9 @@
                                 uint16_t min_conn_int, uint16_t max_conn_int,
                                 uint16_t slave_latency,
                                 uint16_t supervision_tout) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_ble_set_conn_params, bd_addr, min_conn_int,
-                              max_conn_int, slave_latency, supervision_tout));
+  do_in_main_thread(
+      FROM_HERE, base::Bind(bta_dm_ble_set_conn_params, bd_addr, min_conn_int,
+                            max_conn_int, slave_latency, supervision_tout));
 }
 
 /*******************************************************************************
@@ -565,13 +563,8 @@
  *
  ******************************************************************************/
 void BTA_DmSetBleConnScanParams(uint32_t scan_interval, uint32_t scan_window) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ble_set_conn_scan_params,
-                                         scan_interval, scan_window));
-}
-
-/** Set BLE connectable mode to auto connect */
-void BTA_DmBleStartAutoConn() {
-  do_in_bta_thread(FROM_HERE, base::Bind(BTM_BleStartAutoConn));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_ble_set_conn_scan_params,
+                                          scan_interval, scan_window));
 }
 
 /*******************************************************************************
@@ -729,7 +722,7 @@
                                      uint16_t min_int, uint16_t max_int,
                                      uint16_t latency, uint16_t timeout,
                                      uint16_t min_ce_len, uint16_t max_ce_len) {
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(bta_dm_ble_update_conn_params, bd_addr, min_int,
                             max_int, latency, timeout, min_ce_len, max_ce_len));
 }
@@ -747,8 +740,8 @@
  ******************************************************************************/
 void BTA_DmBleConfigLocalPrivacy(bool privacy_enable) {
 #if (BLE_PRIVACY_SPT == TRUE)
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_ble_config_local_privacy, privacy_enable));
+  do_in_main_thread(
+      FROM_HERE, base::Bind(bta_dm_ble_config_local_privacy, privacy_enable));
 #else
   UNUSED(privacy_enable);
 #endif
@@ -766,15 +759,15 @@
  *
  ******************************************************************************/
 void BTA_DmBleGetEnergyInfo(tBTA_BLE_ENERGY_INFO_CBACK* p_cmpl_cback) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_ble_get_energy_info, p_cmpl_cback));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_ble_get_energy_info, p_cmpl_cback));
 }
 
 /** This function is to set maximum LE data packet size */
 void BTA_DmBleSetDataLength(const RawAddress& remote_device,
                             uint16_t tx_data_length) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ble_set_data_length,
-                                         remote_device, tx_data_length));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_ble_set_data_length,
+                                          remote_device, tx_data_length));
 }
 
 /*******************************************************************************
@@ -803,8 +796,8 @@
                          tBTA_DM_ENCRYPT_CBACK* p_callback,
                          tBTA_DM_BLE_SEC_ACT sec_act) {
   APPL_TRACE_API("%s", __func__);
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_set_encryption, bd_addr,
-                                         transport, p_callback, sec_act));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_set_encryption, bd_addr,
+                                          transport, p_callback, sec_act));
 }
 
 /*******************************************************************************
@@ -822,7 +815,7 @@
  ******************************************************************************/
 void BTA_DmCloseACL(const RawAddress& bd_addr, bool remove_dev,
                     tBTA_TRANSPORT transport) {
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(bta_dm_close_acl, bd_addr, remove_dev, transport));
 }
 
@@ -844,7 +837,7 @@
 extern void BTA_DmBleObserve(bool start, uint8_t duration,
                              tBTA_DM_SEARCH_CBACK* p_results_cb) {
   APPL_TRACE_API("%s:start = %d ", __func__, start);
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(bta_dm_ble_observe, start, duration, p_results_cb));
 }
 
diff --git a/bta/dm/bta_dm_cfg.cc b/bta/dm/bta_dm_cfg.cc
index 91053a1..438f329 100644
--- a/bta/dm/bta_dm_cfg.cc
+++ b/bta/dm/bta_dm_cfg.cc
@@ -28,6 +28,7 @@
 #include "bt_target.h"
 #include "bta_api.h"
 #include "bta_dm_int.h"
+#include "bta_hh_api.h"
 #include "bta_jv_api.h"
 #include "bta_sys.h"
 
@@ -116,8 +117,8 @@
 const tBTA_DM_RM* p_bta_dm_rm_cfg = &bta_dm_rm_cfg[0];
 
 #define BTA_DM_NUM_PM_ENTRY \
-  23 /* number of entries in bta_dm_pm_cfg except the first */
-#define BTA_DM_NUM_PM_SPEC 15 /* number of entries in bta_dm_pm_spec */
+  25 /* number of entries in bta_dm_pm_cfg except the first */
+#define BTA_DM_NUM_PM_SPEC 16 /* number of entries in bta_dm_pm_spec */
 
 tBTA_DM_PM_TYPE_QUALIFIER tBTA_DM_PM_CFG
     bta_dm_pm_cfg[BTA_DM_NUM_PM_ENTRY + 1] = {
@@ -126,19 +127,23 @@
         {BTA_ID_AG, BTA_ALL_APP_ID,
          0},               /* ag uses first spec table for app id 0 */
         {BTA_ID_CT, 1, 1}, /* ct (BTA_ID_CT,APP ID=1) spec table */
-        {BTA_ID_CG, BTA_ALL_APP_ID, 1},   /* cg resue ct spec table */
-        {BTA_ID_DG, BTA_ALL_APP_ID, 2},   /* dg spec table */
-        {BTA_ID_AV, BTA_ALL_APP_ID, 4},   /* av spec table */
-        {BTA_ID_AVK, BTA_ALL_APP_ID, 12}, /* avk spec table */
-        {BTA_ID_FTC, BTA_ALL_APP_ID, 6},  /* ftc spec table */
-        {BTA_ID_FTS, BTA_ALL_APP_ID, 7},  /* fts spec table */
-        {BTA_ID_HD, BTA_ALL_APP_ID, 3},   /* hd spec table */
-        {BTA_ID_HH, BTA_ALL_APP_ID, 5},   /* hh spec table */
-        {BTA_ID_PBC, BTA_ALL_APP_ID, 2},  /* reuse dg spec table */
-        {BTA_ID_PBS, BTA_ALL_APP_ID, 7},  /* reuse fts spec table */
-        {BTA_ID_OPC, BTA_ALL_APP_ID, 6},  /* reuse ftc spec table */
-        {BTA_ID_OPS, BTA_ALL_APP_ID, 7},  /* reuse fts spec table */
-        {BTA_ID_MSE, BTA_ALL_APP_ID, 7},  /* reuse fts spec table */
+        {BTA_ID_CG, BTA_ALL_APP_ID, 1},     /* cg resue ct spec table */
+        {BTA_ID_DG, BTA_ALL_APP_ID, 2},     /* dg spec table */
+        {BTA_ID_AV, BTA_ALL_APP_ID, 4},     /* av spec table */
+        {BTA_ID_AVK, BTA_ALL_APP_ID, 12},   /* avk spec table */
+        {BTA_ID_FTC, BTA_ALL_APP_ID, 6},    /* ftc spec table */
+        {BTA_ID_FTS, BTA_ALL_APP_ID, 7},    /* fts spec table */
+        {BTA_ID_HD, BTA_ALL_APP_ID, 3},     /* hd spec table */
+        {BTA_ID_HH, BTA_HH_APP_ID_JOY, 5},  /* app BTA_HH_APP_ID_JOY,
+                                               similar to hh spec table */
+        {BTA_ID_HH, BTA_HH_APP_ID_GPAD, 5}, /* app BTA_HH_APP_ID_GPAD,
+                                               similar to hh spec table */
+        {BTA_ID_HH, BTA_ALL_APP_ID, 6},     /* hh spec table */
+        {BTA_ID_PBC, BTA_ALL_APP_ID, 2},    /* reuse dg spec table */
+        {BTA_ID_PBS, BTA_ALL_APP_ID, 7},    /* reuse fts spec table */
+        {BTA_ID_OPC, BTA_ALL_APP_ID, 6},    /* reuse ftc spec table */
+        {BTA_ID_OPS, BTA_ALL_APP_ID, 7},    /* reuse fts spec table */
+        {BTA_ID_MSE, BTA_ALL_APP_ID, 7},    /* reuse fts spec table */
         {BTA_ID_JV, BTA_JV_PM_ID_1,
          6}, /* app BTA_JV_PM_ID_1, reuse ftc spec table */
         {BTA_ID_JV, BTA_ALL_APP_ID, 7},     /* reuse fts spec table */
@@ -166,8 +171,9 @@
           {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_ACTIVE, 0}, {BTA_DM_PM_NO_ACTION, 0}},    /* busy */
+         {{BTA_DM_PM_SNIFF_A2DP_IDX, 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 */
      }},
@@ -236,7 +242,7 @@
     /* AV : 4 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
-     (BTA_DM_PM_SSR0), /* the SSR entry */
+     (BTA_DM_PM_SSR2), /* the SSR entry */
 #endif
      {
          {{BTA_DM_PM_SNIFF_A2DP_IDX, 7000},
@@ -253,7 +259,29 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* HH : 5 */
+    /* HH for joysticks and gamepad : 5 */
+    {(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
+#if (BTM_SSR_INCLUDED == TRUE)
+     (BTA_DM_PM_SSR1), /* the SSR entry */
+#endif
+     {
+         {{BTA_DM_PM_SNIFF6, BTA_DM_PM_HH_OPEN_DELAY},
+          {BTA_DM_PM_NO_ACTION, 0}}, /* conn open  sniff */
+         {{BTA_DM_PM_NO_PREF, 0}, {BTA_DM_PM_NO_ACTION, 0}},   /* conn close  */
+         {{BTA_DM_PM_NO_ACTION, 0}, {BTA_DM_PM_NO_ACTION, 0}}, /* app open */
+         {{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, used for HH suspend   */
+         {{BTA_DM_PM_SNIFF6, BTA_DM_PM_HH_IDLE_DELAY},
+          {BTA_DM_PM_NO_ACTION, 0}}, /* idle */
+         {{BTA_DM_PM_SNIFF6, BTA_DM_PM_HH_ACTIVE_DELAY},
+          {BTA_DM_PM_NO_ACTION, 0}}, /* busy */
+         {{BTA_DM_PM_NO_ACTION, 0},
+          {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
+     }},
+
+    /* HH : 6 */
     {(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR1), /* the SSR entry */
@@ -275,7 +303,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* FTC, OPC, JV : 6 */
+    /* FTC, OPC, JV : 7 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -295,7 +323,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* FTS, PBS, OPS, MSE, BTA_JV_PM_ID_1 : 7 */
+    /* FTS, PBS, OPS, MSE, BTA_JV_PM_ID_1 : 8 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -315,7 +343,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* HL : 8 */
+    /* HL : 9 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -336,7 +364,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* PANU : 9 */
+    /* PANU : 10 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -356,7 +384,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* NAP : 10 */
+    /* NAP : 11 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -377,7 +405,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* HS : 11 */
+    /* HS : 12 */
     {(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -398,7 +426,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }},
 
-    /* AVK : 12 */
+    /* AVK : 13 */
     {(BTA_DM_PM_SNIFF), /* allow sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
      (BTA_DM_PM_SSR2), /* the SSR entry */
@@ -417,7 +445,7 @@
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }}
 
-    /* GATTC : 13 */
+    /* GATTC : 14 */
     ,
     {(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
@@ -437,7 +465,7 @@
          {{BTA_DM_PM_RETRY, 5000},
           {BTA_DM_PM_NO_ACTION, 0}} /* mode change retry */
      }}
-    /* GATTS : 14 */
+    /* GATTS : 15 */
     ,
     {(BTA_DM_PM_SNIFF | BTA_DM_PM_PARK), /* allow park & sniff */
 #if (BTM_SSR_INCLUDED == TRUE)
@@ -474,7 +502,7 @@
 /* Please refer to the SNIFF table definitions in bta_api.h.
  *
  * Adding to or Modifying the Table
- * Additional sniff parameter entries can be added for BTA_DM_PM_SNIFF5 -
+ * Additional sniff parameter entries can be added for BTA_DM_PM_SNIFF6 -
  * BTA_DM_PM_SNIFF7.
  * Overrides of additional table entries can be specified in bdroid_buildcfg.h.
  * If additional
@@ -521,6 +549,9 @@
     {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- HD 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}
 
@@ -555,8 +586,9 @@
        default max latency and min remote timeout as 0, and always read
        individual device preference from HH module */
     {0, 0, 2},
-    {1200, 2, 2},    /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
-    {360, 160, 1600} /* BTA_DM_PM_SSR3 - HD */
+    {1200, 2, 2},     /* BTA_DM_PM_SSR2 - others (as long as sniff is allowed)*/
+    {360, 160, 1600}, /* BTA_DM_PM_SSR3 - HD */
+    {1200, 65534, 65534} /* BTA_DM_PM_SSR4 - A2DP streaming */
 };
 
 tBTA_DM_SSR_SPEC* p_bta_dm_ssr_spec = &bta_dm_ssr_spec[0];
diff --git a/bta/dm/bta_dm_ci.cc b/bta/dm/bta_dm_ci.cc
index 3d40480..45784c1 100644
--- a/bta/dm/bta_dm_ci.cc
+++ b/bta/dm/bta_dm_ci.cc
@@ -21,11 +21,12 @@
  *  This is the API implementation file for the BTA device manager.
  *
  ******************************************************************************/
+#include "bta_dm_ci.h"
 #include "bt_common.h"
 #include "bta_api.h"
-#include "bta_dm_ci.h"
 #include "bta_dm_int.h"
 #include "bta_sys.h"
+#include "stack/include/btu.h"
 
 #include <base/bind.h>
 #include <memory>
@@ -45,8 +46,8 @@
                       tBTA_OOB_DATA oob_data, tBTA_AUTH_REQ auth_req)
 
 {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_ci_io_req_act, bd_addr, io_cap,
-                                         oob_data, auth_req));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_ci_io_req_act, bd_addr, io_cap,
+                                          oob_data, auth_req));
 }
 
 /*******************************************************************************
@@ -60,17 +61,17 @@
  * Returns          void
  *
  ******************************************************************************/
-void bta_dm_ci_rmt_oob(bool accept, const RawAddress& bd_addr, BT_OCTET16 c,
-                       BT_OCTET16 r) {
+void bta_dm_ci_rmt_oob(bool accept, const RawAddress& bd_addr, const Octet16& c,
+                       const Octet16& r) {
   std::unique_ptr<tBTA_DM_CI_RMT_OOB> msg =
       std::make_unique<tBTA_DM_CI_RMT_OOB>();
 
   msg->bd_addr = bd_addr;
   msg->accept = accept;
-  memcpy(msg->c, c, BT_OCTET16_LEN);
-  memcpy(msg->r, r, BT_OCTET16_LEN);
+  msg->c = c;
+  msg->r = r;
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(bta_dm_ci_rmt_oob_act, base::Passed(&msg)));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(bta_dm_ci_rmt_oob_act, base::Passed(&msg)));
 }
 
diff --git a/bta/dm/bta_dm_int.h b/bta/dm/bta_dm_int.h
index 6aafd7d..97d7f80 100644
--- a/bta/dm/bta_dm_int.h
+++ b/bta/dm/bta_dm_int.h
@@ -118,8 +118,8 @@
 
 typedef struct {
   RawAddress bd_addr;
-  BT_OCTET16 c;
-  BT_OCTET16 r;
+  Octet16 c;
+  Octet16 r;
   bool accept;
 } tBTA_DM_CI_RMT_OOB;
 
@@ -150,7 +150,7 @@
 typedef struct {
   RawAddress bd_addr;
   DEV_CLASS dc;
-  LINK_KEY link_key;
+  LinkKey link_key;
   tBTA_SERVICE_MASK tm;
   bool is_trusted;
   uint8_t key_type;
@@ -250,7 +250,7 @@
 } tBTA_DM_SRVCS;
 
 #ifndef BTA_DM_NUM_CONN_SRVS
-#define BTA_DM_NUM_CONN_SRVS 10
+#define BTA_DM_NUM_CONN_SRVS 30
 #endif
 
 typedef struct {
@@ -510,9 +510,6 @@
                                           uint16_t, uint16_t, uint16_t,
                                           uint16_t);
 extern void bta_dm_ble_config_local_privacy(bool);
-extern void bta_dm_ble_set_adv_params(uint16_t adv_int_min,
-                                      uint16_t adv_int_max,
-                                      tBLE_BD_ADDR* p_dir_bda);
 
 extern void bta_dm_ble_set_data_length(const RawAddress&, uint16_t);
 
diff --git a/bta/dm/bta_dm_pm.cc b/bta/dm/bta_dm_pm.cc
index 731d253..51be1b6 100644
--- a/bta/dm/bta_dm_pm.cc
+++ b/bta/dm/bta_dm_pm.cc
@@ -35,6 +35,7 @@
 #include "bta_dm_int.h"
 #include "bta_sys.h"
 #include "btm_api.h"
+#include "stack/include/btu.h"
 
 static void bta_dm_pm_cback(tBTA_SYS_CONN_STATUS status, uint8_t id,
                             uint8_t app_id, const RawAddress& peer_addr);
@@ -64,7 +65,7 @@
  * can use it */
 #define BTA_DM_PM_SSR_HH BTA_DM_PM_SSR1
 #endif
-static void bta_dm_pm_ssr(const RawAddress& peer_addr);
+static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr);
 #endif
 
 tBTA_DM_CONNECTED_SRVCS bta_dm_conn_srvcs;
@@ -272,7 +273,7 @@
  *
  ******************************************************************************/
 static void bta_dm_pm_start_timer(tBTA_PM_TIMER* p_timer, uint8_t timer_idx,
-                                  period_ms_t timeout_ms, uint8_t srvc_id,
+                                  uint64_t timeout_ms, uint8_t srvc_id,
                                   uint8_t pm_action) {
   std::unique_lock<std::recursive_mutex> schedule_lock(pm_timer_schedule_mutex);
   std::unique_lock<std::recursive_mutex> state_lock(pm_timer_state_mutex);
@@ -362,6 +363,13 @@
   if ((BTA_SYS_CONN_OPEN == status) && p_dev &&
       (p_dev->info & BTA_DM_DI_USE_SSR)) {
     index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+  } else if (BTA_ID_AV == id) {
+    if (BTA_SYS_CONN_BUSY == status) {
+      /* set SSR4 for A2DP on SYS CONN BUSY */
+      index = BTA_DM_PM_SSR4;
+    } else if (BTA_SYS_CONN_IDLE == status) {
+      index = p_bta_dm_pm_spec[p_bta_dm_pm_cfg[i].spec_idx].ssr;
+    }
   }
 #endif
 
@@ -445,7 +453,7 @@
       || index == BTA_DM_PM_SSR_HH
 #endif
       ) {
-    bta_dm_pm_ssr(peer_addr);
+    bta_dm_pm_ssr(peer_addr, index);
   } else {
     uint8_t* p = NULL;
     if (((NULL != (p = BTM_ReadLocalFeatures())) &&
@@ -458,7 +466,7 @@
         BTM_SetSsrParams(peer_addr, 0, 0, 0);
       } else if (status == BTA_SYS_SCO_CLOSE) {
         APPL_TRACE_DEBUG("%s: SCO active, back to old SSR", __func__);
-        bta_dm_pm_ssr(peer_addr);
+        bta_dm_pm_ssr(peer_addr, BTA_DM_PM_SSR0);
       }
     }
   }
@@ -500,7 +508,7 @@
                                tBTA_DM_PM_ACTION pm_request,
                                tBTA_DM_PM_REQ pm_req) {
   tBTA_DM_PM_ACTION pm_action = BTA_DM_PM_NO_ACTION;
-  period_ms_t timeout_ms = 0;
+  uint64_t timeout_ms = 0;
   uint8_t i, j;
   tBTA_DM_PM_ACTION failed_pm = 0;
   tBTA_DM_PEER_DEVICE* p_peer_device = NULL;
@@ -513,7 +521,7 @@
   tBTA_DM_SRVCS* p_srvcs = NULL;
   bool timer_started = false;
   uint8_t timer_idx, available_timer = BTA_DM_PM_MODE_TIMER_MAX;
-  period_ms_t remaining_ms = 0;
+  uint64_t remaining_ms = 0;
 
   if (!bta_dm_cb.device_list.count) return;
 
@@ -750,9 +758,9 @@
  *
  ******************************************************************************/
 #if (BTM_SSR_INCLUDED == TRUE)
-static void bta_dm_pm_ssr(const RawAddress& peer_addr) {
+static void bta_dm_pm_ssr(const RawAddress& peer_addr, int ssr) {
   int current_ssr_index;
-  int ssr_index = BTA_DM_PM_SSR0;
+  int ssr_index = ssr;
   tBTA_DM_SSR_SPEC* p_spec = &p_bta_dm_ssr_spec[ssr_index];
 
   /* go through the connected services */
@@ -837,8 +845,8 @@
 static void bta_dm_pm_btm_cback(const RawAddress& bd_addr,
                                 tBTM_PM_STATUS status, uint16_t value,
                                 uint8_t hci_status) {
-  do_in_bta_thread(FROM_HERE, base::Bind(bta_dm_pm_btm_status, bd_addr, status,
-                                         value, hci_status));
+  do_in_main_thread(FROM_HERE, base::Bind(bta_dm_pm_btm_status, bd_addr, status,
+                                          value, hci_status));
 }
 
 /*******************************************************************************
@@ -878,7 +886,7 @@
   /* no more timers */
   if (i == BTA_DM_NUM_PM_TIMER) return;
 
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(bta_dm_pm_timer, bta_dm_cb.pm_timer[i].peer_bdaddr,
                             bta_dm_cb.pm_timer[i].pm_action[j]));
 }
@@ -912,7 +920,7 @@
 #if (BTM_SSR_INCLUDED == TRUE)
         if (p_dev->prev_low) {
           /* need to send the SSR paramaters to controller again */
-          bta_dm_pm_ssr(p_dev->peer_bdaddr);
+          bta_dm_pm_ssr(p_dev->peer_bdaddr, BTA_DM_PM_SSR0);
         }
         p_dev->prev_low = BTM_PM_STS_ACTIVE;
 #endif
diff --git a/bta/gatt/bta_gattc_act.cc b/bta/gatt/bta_gattc_act.cc
index 8a137dc..b009e5a 100644
--- a/bta/gatt/bta_gattc_act.cc
+++ b/bta/gatt/bta_gattc_act.cc
@@ -30,13 +30,13 @@
 #include <base/callback.h>
 #include "bt_common.h"
 #include "bt_target.h"
-#include "bta_closure_api.h"
 #include "bta_gattc_int.h"
 #include "bta_sys.h"
 #include "btif/include/btif_debug_conn.h"
 #include "l2c_api.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
+#include "stack/include/btu.h"
 #include "stack/l2cap/l2c_int.h"
 #include "utl.h"
 
@@ -192,7 +192,8 @@
         /* BTA use the same client interface as BTE GATT statck */
         client_if = bta_gattc_cb.cl_rcb[i].client_if;
 
-        do_in_bta_thread(FROM_HERE, base::Bind(&bta_gattc_start_if, client_if));
+        do_in_main_thread(FROM_HERE,
+                          base::Bind(&bta_gattc_start_if, client_if));
 
         status = GATT_SUCCESS;
         break;
@@ -337,8 +338,8 @@
 void bta_gattc_open_fail(tBTA_GATTC_CLCB* p_clcb,
                          UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
   LOG(WARNING) << __func__ << ": Cannot establish Connection. conn_id="
-               << +p_clcb->bta_conn_id << ". Return GATT_ERROR(" << +GATT_ERROR
-               << ")";
+               << loghex(p_clcb->bta_conn_id) << ". Return GATT_ERROR("
+               << +GATT_ERROR << ")";
 
   bta_gattc_send_open_cback(p_clcb->p_rcb, GATT_ERROR, p_clcb->bda,
                             p_clcb->bta_conn_id, p_clcb->transport, 0);
@@ -461,7 +462,7 @@
   VLOG(1) << __func__ << ": server cache state=" << +p_clcb->p_srcb->state;
 
   if (p_data != NULL) {
-    VLOG(1) << __func__ << ": conn_id=" << +p_data->hdr.layer_specific;
+    VLOG(1) << __func__ << ": conn_id=" << loghex(p_data->hdr.layer_specific);
     p_clcb->bta_conn_id = p_data->int_conn.hdr.layer_specific;
 
     GATT_GetConnectionInfor(p_data->hdr.layer_specific, &gatt_if, p_clcb->bda,
@@ -473,11 +474,11 @@
   if (p_clcb->p_srcb->mtu == 0) p_clcb->p_srcb->mtu = GATT_DEF_BLE_MTU_SIZE;
 
   /* start database cache if needed */
-  if (p_clcb->p_srcb->srvc_cache.empty() ||
+  if (p_clcb->p_srcb->gatt_database.IsEmpty() ||
       p_clcb->p_srcb->state != BTA_GATTC_SERV_IDLE) {
     if (p_clcb->p_srcb->state == BTA_GATTC_SERV_IDLE) {
       p_clcb->p_srcb->state = BTA_GATTC_SERV_LOAD;
-      if (bta_gattc_cache_load(p_clcb)) {
+      if (bta_gattc_cache_load(p_clcb->p_srcb)) {
         p_clcb->p_srcb->state = BTA_GATTC_SERV_IDLE;
         bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
       } else {
@@ -534,7 +535,7 @@
   tBTA_GATTC_RCB* p_clreg = p_clcb->p_rcb;
   tBTA_GATTC cb_data;
 
-  VLOG(1) << __func__ << ": conn_id=" << +p_clcb->bta_conn_id;
+  VLOG(1) << __func__ << ": conn_id=" << loghex(p_clcb->bta_conn_id);
 
   cb_data.close.client_if = p_clcb->p_rcb->client_if;
   cb_data.close.conn_id = p_clcb->bta_conn_id;
@@ -574,7 +575,8 @@
 
 /** close a GATTC connection while in discovery state */
 void bta_gattc_disc_close(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
-  VLOG(1) << __func__ << ": Discovery cancel conn_id=" << +p_clcb->bta_conn_id;
+  VLOG(1) << __func__
+          << ": Discovery cancel conn_id=" << loghex(p_clcb->bta_conn_id);
 
   if (p_clcb->disc_active)
     bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_ERROR);
@@ -594,7 +596,6 @@
 void bta_gattc_set_discover_st(tBTA_GATTC_SERV* p_srcb) {
   uint8_t i;
 
-  L2CA_EnableUpdateBleConnParams(p_srcb->server_bda, false);
   for (i = 0; i < BTA_GATTC_CLCB_MAX; i++) {
     if (bta_gattc_cb.clcb[i].p_srcb == p_srcb) {
       bta_gattc_cb.clcb[i].status = GATT_SUCCESS;
@@ -632,7 +633,7 @@
 /** Start a discovery on server */
 void bta_gattc_start_discover(tBTA_GATTC_CLCB* p_clcb,
                               UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
-  VLOG(1) << __func__ << ": conn_id:" << +p_clcb->bta_conn_id
+  VLOG(1) << __func__ << ": conn_id:" << loghex(p_clcb->bta_conn_id)
           << " p_clcb->p_srcb->state:" << +p_clcb->p_srcb->state;
 
   if (((p_clcb->p_q_cmd == NULL ||
@@ -655,11 +656,9 @@
       /* set all srcb related clcb into discovery ST */
       bta_gattc_set_discover_st(p_clcb->p_srcb);
 
-      p_clcb->status = bta_gattc_init_cache(p_clcb->p_srcb);
-      if (p_clcb->status == GATT_SUCCESS) {
-        p_clcb->status = bta_gattc_discover_pri_service(
-            p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL);
-      }
+      bta_gattc_init_cache(p_clcb->p_srcb);
+      p_clcb->status = bta_gattc_discover_pri_service(
+          p_clcb->bta_conn_id, p_clcb->p_srcb, GATT_DISC_SRVC_ALL);
       if (p_clcb->status != GATT_SUCCESS) {
         LOG(ERROR) << "discovery on server failed";
         bta_gattc_reset_discover_st(p_clcb->p_srcb, p_clcb->status);
@@ -683,7 +682,7 @@
                          UNUSED_ATTR tBTA_GATTC_DATA* p_data) {
   tBTA_GATTC_DATA* p_q_cmd = p_clcb->p_q_cmd;
 
-  VLOG(1) << __func__ << ": conn_id=" << +p_clcb->bta_conn_id;
+  VLOG(1) << __func__ << ": conn_id=" << loghex(p_clcb->bta_conn_id);
 
   if (p_clcb->transport == BTA_TRANSPORT_LE)
     L2CA_EnableUpdateBleConnParams(p_clcb->p_srcb->server_bda, true);
@@ -693,16 +692,15 @@
   if (p_clcb->status != GATT_SUCCESS) {
     /* clean up cache */
     if (p_clcb->p_srcb) {
-      // clear reallocating
-      std::vector<tBTA_GATTC_SERVICE>().swap(p_clcb->p_srcb->srvc_cache);
+      p_clcb->p_srcb->gatt_database.Clear();
     }
 
     /* used to reset cache in application */
     bta_gattc_cache_reset(p_clcb->p_srcb->server_bda);
   }
+
   if (p_clcb->p_srcb) {
-    /* release pending attribute list buffer */
-    p_clcb->p_srcb->pending_discovery.clear();
+    p_clcb->p_srcb->pending_discovery.Clear();
   }
 
   if (p_clcb->auto_update == BTA_GATTC_DISC_WAITING) {
@@ -724,6 +722,12 @@
      */
     if (p_q_cmd != p_clcb->p_q_cmd) osi_free_and_reset((void**)&p_q_cmd);
   }
+
+  if (p_clcb->p_rcb->p_cback) {
+    tBTA_GATTC bta_gattc;
+    bta_gattc.remote_bda = p_clcb->p_srcb->server_bda;
+    (*p_clcb->p_rcb->p_cback)(BTA_GATTC_SRVC_DISC_DONE_EVT, &bta_gattc);
+  }
 }
 
 /** Read an attribute */
@@ -981,8 +985,8 @@
 void bta_gattc_search(tBTA_GATTC_CLCB* p_clcb, tBTA_GATTC_DATA* p_data) {
   tGATT_STATUS status = GATT_INTERNAL_ERROR;
   tBTA_GATTC cb_data;
-  VLOG(1) << __func__ << ": conn_id=" << +p_clcb->bta_conn_id;
-  if (p_clcb->p_srcb && !p_clcb->p_srcb->srvc_cache.empty()) {
+  VLOG(1) << __func__ << ": conn_id=" << loghex(p_clcb->bta_conn_id);
+  if (p_clcb->p_srcb && !p_clcb->p_srcb->gatt_database.IsEmpty()) {
     status = GATT_SUCCESS;
     /* search the local cache of a server device */
     bta_gattc_search_service(p_clcb, p_data->api_search.p_srvc_uuid);
@@ -1080,8 +1084,8 @@
 
   VLOG(1) << __func__ << ": cif:" << +gattc_if;
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&bta_gattc_process_enc_cmpl, gattc_if, bda));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&bta_gattc_process_enc_cmpl, gattc_if, bda));
 }
 
 /** process refresh API to delete cache and start a new discovery if currently
@@ -1106,8 +1110,7 @@
     }
     /* in all other cases, mark it and delete the cache */
 
-    // clear reallocating
-    std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
+    p_srvc_cb->gatt_database.Clear();
   }
 
   /* used to reset cache in application */
@@ -1124,10 +1127,14 @@
   Uuid gattp_uuid = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
   Uuid srvc_chg_uuid = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
 
-  const tBTA_GATTC_CHARACTERISTIC* p_char =
+  if (p_srcb->gatt_database.IsEmpty() && p_srcb->state == BTA_GATTC_SERV_IDLE) {
+    bta_gattc_cache_load(p_srcb);
+  }
+
+  const gatt::Characteristic* p_char =
       bta_gattc_get_characteristic_srcb(p_srcb, p_notify->handle);
   if (!p_char) return false;
-  const tBTA_GATTC_SERVICE* p_svc =
+  const gatt::Service* p_svc =
       bta_gattc_get_service_for_handle_srcb(p_srcb, p_char->value_handle);
   if (!p_svc || p_svc->uuid != gattp_uuid || p_char->uuid != srvc_chg_uuid) {
     return false;
@@ -1189,7 +1196,7 @@
           << StringPrintf(
                  ": check p_data->att_value.handle=%d p_data->handle=%d",
                  p_data->att_value.handle, p_data->handle);
-  VLOG(1) << "is_notify", p_notify->is_notify;
+  VLOG(1) << "is_notify " << p_notify->is_notify;
 
   p_notify->is_notify = (op == GATTC_OPTYPE_INDICATION) ? false : true;
   p_notify->len = p_data->att_value.len;
diff --git a/bta/gatt/bta_gattc_api.cc b/bta/gatt/bta_gattc_api.cc
index bec0081..829084c 100644
--- a/bta/gatt/bta_gattc_api.cc
+++ b/bta/gatt/bta_gattc_api.cc
@@ -30,11 +30,11 @@
 #include <base/bind_helpers.h>
 #include <base/callback.h>
 #include "bt_common.h"
-#include "bta_closure_api.h"
 #include "bta_gatt_api.h"
 #include "bta_gattc_int.h"
 #include "bta_sys.h"
 #include "device/include/controller.h"
+#include "stack/include/btu.h"
 
 using bluetooth::Uuid;
 
@@ -62,7 +62,7 @@
     return;
   }
 
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_gattc_disable));
+  do_in_main_thread(FROM_HERE, base::Bind(&bta_gattc_disable));
   bta_sys_deregister(BTA_ID_GATTC);
 }
 
@@ -76,8 +76,9 @@
   if (!bta_sys_is_register(BTA_ID_GATTC))
     bta_sys_register(BTA_ID_GATTC, &bta_gattc_reg);
 
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_gattc_register, Uuid::GetRandom(),
-                                         p_client_cb, std::move(cb)));
+  do_in_main_thread(
+      FROM_HERE, base::Bind(&bta_gattc_register, Uuid::GetRandom(), p_client_cb,
+                            std::move(cb)));
 }
 
 static void app_deregister_impl(tGATT_IF client_if) {
@@ -96,7 +97,7 @@
  *
  ******************************************************************************/
 void BTA_GATTC_AppDeregister(tGATT_IF client_if) {
-  do_in_bta_thread(FROM_HERE, base::Bind(&app_deregister_impl, client_if));
+  do_in_main_thread(FROM_HERE, base::Bind(&app_deregister_impl, client_if));
 }
 
 /*******************************************************************************
@@ -246,15 +247,14 @@
   bta_sys_sendmsg(p_buf);
 }
 
-void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id,
-                                     const Uuid& p_srvc_uuid) {
-  tGATT_DISC_PARAM* param = new tGATT_DISC_PARAM;
-  param->s_handle = 0x0001;
-  param->e_handle = 0xFFFF;
-  param->service = p_srvc_uuid;
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(base::IgnoreResult(&GATTC_Discover), conn_id,
-                              GATT_DISC_SRVC_BY_UUID, base::Owned(param)));
+void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id, const Uuid& srvc_uuid) {
+  do_in_main_thread(
+      FROM_HERE,
+      base::Bind(
+          base::IgnoreResult<tGATT_STATUS (*)(uint16_t, tGATT_DISC_TYPE,
+                                              uint16_t, uint16_t, const Uuid&)>(
+              &GATTC_Discover),
+          conn_id, GATT_DISC_SRVC_BY_UUID, 0x0001, 0xFFFF, srvc_uuid));
 }
 
 /*******************************************************************************
@@ -266,10 +266,10 @@
  *
  * Parameters       conn_id: connection ID which identify the server.
  *
- * Returns          returns list of tBTA_GATTC_SERVICE or NULL.
+ * Returns          returns list of gatt::Service or NULL.
  *
  ******************************************************************************/
-const std::vector<tBTA_GATTC_SERVICE>* BTA_GATTC_GetServices(uint16_t conn_id) {
+const std::list<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id) {
   return bta_gattc_get_services(conn_id);
 }
 
@@ -283,11 +283,11 @@
  * Parameters       conn_id - connection ID which identify the server.
  *                  handle - characteristic handle
  *
- * Returns          returns pointer to tBTA_GATTC_CHARACTERISTIC or NULL.
+ * Returns          returns pointer to gatt::Characteristic or NULL.
  *
  ******************************************************************************/
-const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetCharacteristic(uint16_t conn_id,
-                                                             uint16_t handle) {
+const gatt::Characteristic* BTA_GATTC_GetCharacteristic(uint16_t conn_id,
+                                                        uint16_t handle) {
   return bta_gattc_get_characteristic(conn_id, handle);
 }
 
@@ -301,25 +301,25 @@
  * Parameters       conn_id - connection ID which identify the server.
  *                  handle - descriptor handle
  *
- * Returns          returns pointer to tBTA_GATTC_DESCRIPTOR or NULL.
+ * Returns          returns pointer to gatt::Descriptor or NULL.
  *
  ******************************************************************************/
-const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(uint16_t conn_id,
-                                                     uint16_t handle) {
+const gatt::Descriptor* BTA_GATTC_GetDescriptor(uint16_t conn_id,
+                                                uint16_t handle) {
   return bta_gattc_get_descriptor(conn_id, handle);
 }
 
 /* Return characteristic that owns descriptor with handle equal to |handle|, or
  * NULL */
-const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetOwningCharacteristic(
-    uint16_t conn_id, uint16_t handle) {
+const gatt::Characteristic* BTA_GATTC_GetOwningCharacteristic(uint16_t conn_id,
+                                                              uint16_t handle) {
   return bta_gattc_get_owning_characteristic(conn_id, handle);
 }
 
 /* Return service that owns descriptor or characteristic with handle equal to
  * |handle|, or NULL */
-const tBTA_GATTC_SERVICE* BTA_GATTC_GetOwningService(uint16_t conn_id,
-                                                     uint16_t handle) {
+const gatt::Service* BTA_GATTC_GetOwningService(uint16_t conn_id,
+                                                uint16_t handle) {
   return bta_gattc_get_service_for_handle(conn_id, handle);
 }
 
@@ -639,7 +639,7 @@
   uint8_t i;
 
   if (!handle) {
-    LOG(ERROR) << "deregistration failed, handle is 0";
+    LOG(ERROR) << __func__ << ": registration failed, handle is 0";
     return status;
   }
 
@@ -735,6 +735,6 @@
  *
  ******************************************************************************/
 void BTA_GATTC_Refresh(const RawAddress& remote_bda) {
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&bta_gattc_process_api_refresh, remote_bda));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&bta_gattc_process_api_refresh, remote_bda));
 }
diff --git a/bta/gatt/bta_gattc_cache.cc b/bta/gatt/bta_gattc_cache.cc
index 60224a3..eed1d67 100644
--- a/bta/gatt/bta_gattc_cache.cc
+++ b/bta/gatt/bta_gattc_cache.cc
@@ -31,6 +31,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <unistd.h>
+#include <sstream>
 
 #include "bt_common.h"
 #include "bta_gattc_int.h"
@@ -38,30 +39,39 @@
 #include "btm_api.h"
 #include "btm_ble_api.h"
 #include "btm_int.h"
+#include "database.h"
+#include "database_builder.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 #include "sdp_api.h"
 #include "sdpdefs.h"
 #include "utl.h"
 
-using bluetooth::Uuid;
 using base::StringPrintf;
+using bluetooth::Uuid;
+using gatt::Characteristic;
+using gatt::Database;
+using gatt::DatabaseBuilder;
+using gatt::Descriptor;
+using gatt::IncludedService;
+using gatt::Service;
+using gatt::StoredAttribute;
 
 static void bta_gattc_cache_write(const RawAddress& server_bda,
-                                  uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr);
-static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
-                                           tBTA_GATTC_SERV* p_srvc_cb);
+                                  const std::vector<StoredAttribute>& attr);
 static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id,
                                                tBTA_GATTC_SERV* p_server_cb);
-const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
-tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
+const Descriptor* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV* p_srcb,
+                                                uint16_t handle);
+const Characteristic* bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV* p_srcb,
+                                                        uint16_t handle);
+static void bta_gattc_explore_srvc_finished(uint16_t conn_id,
+                                            tBTA_GATTC_SERV* p_srvc_cb);
 
 #define BTA_GATT_SDP_DB_SIZE 4096
 
 #define GATT_CACHE_PREFIX "/data/misc/bluetooth/gatt_cache_"
-#define GATT_CACHE_VERSION 4
+#define GATT_CACHE_VERSION 5
 
 static void bta_gattc_generate_cache_file_name(char* buffer, size_t buffer_len,
                                                const RawAddress& bda) {
@@ -83,195 +93,42 @@
 /* utility functions */
 
 /* debug function to display the server cache */
-static void display_db(const std::vector<tBTA_GATTC_SERVICE>& cache) {
-  for (const tBTA_GATTC_SERVICE& service : cache) {
-    LOG(ERROR) << "Service: s_handle=" << loghex(service.s_handle)
-               << ", e_handle=" << loghex(service.e_handle)
-               << ", inst=" << loghex(service.handle)
-               << ", uuid=" << service.uuid;
-
-    if (service.characteristics.empty()) {
-      LOG(ERROR) << "\t No characteristics";
-      continue;
-    }
-
-    for (const tBTA_GATTC_CHARACTERISTIC& c : service.characteristics) {
-      LOG(ERROR) << "\t Characteristic value_handle=" << loghex(c.value_handle)
-                 << ", uuid=" << c.uuid << ", prop=" << loghex(c.properties);
-
-      if (c.descriptors.empty()) {
-        LOG(ERROR) << "\t\t No descriptors";
-        continue;
-      }
-
-      for (const tBTA_GATTC_DESCRIPTOR& d : c.descriptors) {
-        LOG(ERROR) << "\t\t Descriptor handle=" << loghex(d.handle)
-                   << ", uuid=" << d.uuid;
-      }
-    }
+static void bta_gattc_display_cache_server(const Database& database) {
+  LOG(INFO) << "<================Start Server Cache =============>";
+  std::istringstream iss(database.ToString());
+  for (std::string line; std::getline(iss, line);) {
+    LOG(INFO) << line;
   }
-}
-
-/* debug function to display the server cache */
-static void bta_gattc_display_cache_server(
-    const std::vector<tBTA_GATTC_SERVICE>& cache) {
-  LOG(ERROR) << "<================Start Server Cache =============>";
-  display_db(cache);
-  LOG(ERROR) << "<================End Server Cache =============>";
-  LOG(ERROR) << " ";
+  LOG(INFO) << "<================End Server Cache =============>";
 }
 
 /** debug function to display the exploration list */
-static void bta_gattc_display_explore_record(
-    const std::vector<tBTA_GATTC_SERVICE>& cache) {
-  LOG(ERROR) << "<================Start Explore Queue =============>";
-  display_db(cache);
-  LOG(ERROR) << "<================ End Explore Queue =============>";
-  LOG(ERROR) << " ";
+static void bta_gattc_display_explore_record(const DatabaseBuilder& database) {
+  LOG(INFO) << "<================Start Explore Queue =============>";
+  std::istringstream iss(database.ToString());
+  for (std::string line; std::getline(iss, line);) {
+    LOG(INFO) << line;
+  }
+  LOG(INFO) << "<================ End Explore Queue =============>";
 }
 #endif /* BTA_GATT_DEBUG == TRUE */
 
-/*******************************************************************************
- *
- * Function         bta_gattc_init_cache
- *
- * Description      Initialize the database cache and discovery related
- *                  resources.
- *
- * Returns          status
- *
- ******************************************************************************/
-tGATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
-  // clear reallocating
-  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
-  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
-  return GATT_SUCCESS;
+/** Initialize the database cache and discovery related resources */
+void bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb) {
+  p_srvc_cb->gatt_database = gatt::Database();
+  p_srvc_cb->pending_discovery.Clear();
 }
 
-tBTA_GATTC_SERVICE* bta_gattc_find_matching_service(
-    std::vector<tBTA_GATTC_SERVICE>& services, uint16_t handle) {
-  for (tBTA_GATTC_SERVICE& service : services) {
-    if (handle >= service.s_handle && handle <= service.e_handle)
+const Service* bta_gattc_find_matching_service(
+    const std::list<Service>& services, uint16_t handle) {
+  for (const Service& service : services) {
+    if (handle >= service.handle && handle <= service.end_handle)
       return &service;
   }
 
   return nullptr;
 }
 
-/** Add a service into GATT database */
-static void add_service_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
-                                   uint16_t s_handle, uint16_t e_handle,
-                                   const Uuid& uuid, bool is_primary) {
-#if (BTA_GATT_DEBUG == TRUE)
-  VLOG(1) << "Add a service into GATT DB";
-#endif
-
-  gatt_db.emplace_back(tBTA_GATTC_SERVICE{
-      .s_handle = s_handle,
-      .e_handle = e_handle,
-      .is_primary = is_primary,
-      .uuid = uuid,
-      .handle = s_handle,
-  });
-}
-
-/** Add a characteristic into GATT database */
-static void add_characteristic_to_gatt_db(
-    std::vector<tBTA_GATTC_SERVICE>& gatt_db, uint16_t attr_handle,
-    uint16_t value_handle, const Uuid& uuid, uint8_t property) {
-#if (BTA_GATT_DEBUG == TRUE)
-  VLOG(1) << __func__
-          << ": Add a characteristic into service. handle:" << +value_handle
-          << " uuid:" << uuid << " property=0x" << std::hex << +property;
-#endif
-
-  tBTA_GATTC_SERVICE* service =
-      bta_gattc_find_matching_service(gatt_db, attr_handle);
-  if (!service) {
-    LOG(ERROR) << "Illegal action to add char/descr/incl srvc for non-existing "
-                  "service!";
-    return;
-  }
-
-  /* TODO(jpawlowski): We should use attribute handle, not value handle to refer
-     to characteristic.
-     This is just a temporary workaround.
-  */
-  if (service->e_handle < value_handle) service->e_handle = value_handle;
-
-  service->characteristics.emplace_back(
-      tBTA_GATTC_CHARACTERISTIC{.declaration_handle = attr_handle,
-                                .value_handle = value_handle,
-                                .properties = property,
-                                .uuid = uuid});
-  return;
-}
-
-/* Add an descriptor into database cache buffer */
-static void add_descriptor_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
-                                      uint16_t handle, const Uuid& uuid) {
-#if (BTA_GATT_DEBUG == TRUE)
-  VLOG(1) << __func__ << ": add descriptor, handle=" << loghex(handle)
-          << ", uuid=" << uuid;
-#endif
-
-  tBTA_GATTC_SERVICE* service =
-      bta_gattc_find_matching_service(gatt_db, handle);
-  if (!service) {
-    LOG(ERROR) << "Illegal action to add descriptor for non-existing service!";
-    return;
-  }
-
-  if (service->characteristics.empty()) {
-    LOG(ERROR) << __func__
-               << ": Illegal action to add descriptor before adding a "
-                  "characteristic!";
-    return;
-  }
-
-  tBTA_GATTC_CHARACTERISTIC* char_node = &service->characteristics.front();
-  for (auto it = service->characteristics.begin();
-       it != service->characteristics.end(); it++) {
-    if (it->value_handle > handle) break;
-    char_node = &(*it);
-  }
-
-  char_node->descriptors.emplace_back(
-      tBTA_GATTC_DESCRIPTOR{.handle = handle, .uuid = uuid});
-}
-
-/* Add an attribute into database cache buffer */
-static void add_incl_srvc_to_gatt_db(std::vector<tBTA_GATTC_SERVICE>& gatt_db,
-                                     uint16_t handle, const Uuid& uuid,
-                                     uint16_t incl_srvc_s_handle) {
-#if (BTA_GATT_DEBUG == TRUE)
-  VLOG(1) << __func__ << ": add included service, handle=" << loghex(handle)
-          << ", uuid=" << uuid;
-#endif
-
-  tBTA_GATTC_SERVICE* service =
-      bta_gattc_find_matching_service(gatt_db, handle);
-  if (!service) {
-    LOG(ERROR) << "Illegal action to add incl srvc for non-existing service!";
-    return;
-  }
-
-  tBTA_GATTC_SERVICE* included_service =
-      bta_gattc_find_matching_service(gatt_db, incl_srvc_s_handle);
-  if (!included_service) {
-    LOG(ERROR) << __func__
-               << ": Illegal action to add non-existing included service!";
-    return;
-  }
-
-  service->included_svc.emplace_back(tBTA_GATTC_INCLUDED_SVC{
-      .handle = handle,
-      .uuid = uuid,
-      .owning_service = service,
-      .included_service = included_service,
-  });
-}
-
 /** Start primary service discovery */
 tGATT_STATUS bta_gattc_discover_pri_service(uint16_t conn_id,
                                             tBTA_GATTC_SERV* p_server_cb,
@@ -280,188 +137,154 @@
   if (!p_clcb) return GATT_ERROR;
 
   if (p_clcb->transport == BTA_TRANSPORT_LE) {
-    tGATT_DISC_PARAM param{.s_handle = 0x0001, .e_handle = 0xFFFF};
-    return GATTC_Discover(conn_id, disc_type, &param);
+    return GATTC_Discover(conn_id, disc_type, 0x0001, 0xFFFF);
   }
 
+  // only for Classic transport
   return bta_gattc_sdp_service_disc(conn_id, p_server_cb);
 }
 
+/** start exploring next service, or finish discovery if no more services left
+ */
+static void bta_gattc_explore_next_service(uint16_t conn_id,
+                                           tBTA_GATTC_SERV* p_srvc_cb) {
+  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+  if (!p_clcb) {
+    LOG(ERROR) << "unknown conn_id=" << loghex(conn_id);
+    return;
+  }
+
+  if (!p_srvc_cb->pending_discovery.StartNextServiceExploration()) {
+    bta_gattc_explore_srvc_finished(conn_id, p_srvc_cb);
+    return;
+  }
+
+  const auto& service = p_srvc_cb->pending_discovery.CurrentlyExploredService();
+  VLOG(1) << "Start service discovery";
+
+  /* start discovering included services */
+  GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, service.first, service.second);
+}
+
+static void bta_gattc_explore_srvc_finished(uint16_t conn_id,
+                                            tBTA_GATTC_SERV* p_srvc_cb) {
+  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
+  if (!p_clcb) {
+    LOG(ERROR) << "unknown conn_id=" << loghex(conn_id);
+    return;
+  }
+
+  /* no service found at all, the end of server discovery*/
+  LOG(INFO) << __func__ << ": service discovery finished";
+
+  p_srvc_cb->gatt_database = p_srvc_cb->pending_discovery.Build();
+
+#if (BTA_GATT_DEBUG == TRUE)
+  bta_gattc_display_cache_server(p_srvc_cb->gatt_database);
+#endif
+  /* save cache to NV */
+  p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
+
+  if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
+    bta_gattc_cache_write(p_clcb->p_srcb->server_bda,
+                          p_clcb->p_srcb->gatt_database.Serialize());
+  }
+
+  bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
+}
+
 /** Start discovery for characteristic descriptor */
 void bta_gattc_start_disc_char_dscp(uint16_t conn_id,
                                     tBTA_GATTC_SERV* p_srvc_cb) {
   VLOG(1) << "starting discover characteristics descriptor";
-  auto& characteristic = p_srvc_cb->pending_char;
 
-  uint16_t end_handle = 0xFFFF;
-  // if there are more characteristics in the service
-  if (std::next(p_srvc_cb->pending_char) !=
-      p_srvc_cb->pending_service->characteristics.end()) {
-    // end at beginning of next characteristic
-    end_handle = std::next(p_srvc_cb->pending_char)->declaration_handle - 1;
-  } else {
-    // end at the end of current service
-    end_handle = p_srvc_cb->pending_service->e_handle;
+  std::pair<uint16_t, uint16_t> range =
+      p_srvc_cb->pending_discovery.NextDescriptorRangeToExplore();
+  if (range == DatabaseBuilder::EXPLORE_END) {
+    goto descriptor_discovery_done;
   }
 
-  tGATT_DISC_PARAM param{
-      .s_handle = (uint16_t)(characteristic->value_handle + 1),
-      .e_handle = end_handle};
-  if (GATTC_Discover(conn_id, GATT_DISC_CHAR_DSCPT, &param) != 0) {
-    bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+  if (GATTC_Discover(conn_id, GATT_DISC_CHAR_DSCPT, range.first,
+                     range.second) != 0) {
+    goto descriptor_discovery_done;
   }
-}
+  return;
 
-/** process the service discovery complete event */
-static void bta_gattc_explore_srvc(uint16_t conn_id,
-                                   tBTA_GATTC_SERV* p_srvc_cb) {
-  tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
-  if (!p_clcb) {
-    LOG(ERROR) << "unknown conn_id=" << +conn_id;
-    return;
-  }
-
-  /* start expore a service if there is service not been explored */
-  if (p_srvc_cb->pending_service != p_srvc_cb->pending_discovery.end()) {
-    auto& service = *p_srvc_cb->pending_service;
-    VLOG(1) << "Start service discovery";
-
-    /* start discovering included services */
-    tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
-                              .e_handle = service.e_handle};
-    GATTC_Discover(conn_id, GATT_DISC_INC_SRVC, &param);
-    return;
-  }
-
-  /* no service found at all, the end of server discovery*/
-  LOG(INFO) << __func__ << ": no more services found";
-
-  p_srvc_cb->srvc_cache.swap(p_srvc_cb->pending_discovery);
-  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->pending_discovery);
-
-#if (BTA_GATT_DEBUG == TRUE)
-  bta_gattc_display_cache_server(p_srvc_cb->srvc_cache);
-#endif
-  /* save cache to NV */
-  p_clcb->p_srcb->state = BTA_GATTC_SERV_SAVE;
-
-  if (btm_sec_is_a_bonded_dev(p_srvc_cb->server_bda)) {
-    bta_gattc_cache_save(p_clcb->p_srcb, p_clcb->bta_conn_id);
-  }
-
-  bta_gattc_reset_discover_st(p_clcb->p_srcb, GATT_SUCCESS);
-}
-
-/** process the char descriptor discovery complete event */
-static void bta_gattc_char_dscpt_disc_cmpl(uint16_t conn_id,
-                                           tBTA_GATTC_SERV* p_srvc_cb) {
-  ++p_srvc_cb->pending_char;
-  if (p_srvc_cb->pending_char !=
-      p_srvc_cb->pending_service->characteristics.end()) {
-    /* start discoverying next characteristic for char descriptor */
-    bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
-    return;
-  }
-
+descriptor_discovery_done:
   /* all characteristic has been explored, start with next service if any */
-#if (BTA_GATT_DEBUG == TRUE)
-  LOG(ERROR) << "all char has been explored";
-#endif
-  p_srvc_cb->pending_service++;
-  bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+  DVLOG(3) << "all characteristics explored";
+
+  bta_gattc_explore_next_service(conn_id, p_srvc_cb);
+  return;
 }
 
-static bool bta_gattc_srvc_in_list(std::vector<tBTA_GATTC_SERVICE>& services,
-                                   uint16_t s_handle, uint16_t e_handle, Uuid) {
-  if (!GATT_HANDLE_IS_VALID(s_handle) || !GATT_HANDLE_IS_VALID(e_handle)) {
-    LOG(ERROR) << "invalid included service s_handle=" << loghex(s_handle)
-               << ", e_handle=" << loghex(e_handle);
-    return true;
-  }
-
-  for (tBTA_GATTC_SERVICE& service : services) {
-    if (service.s_handle == s_handle || service.e_handle == e_handle)
-      return true;
-  }
-
-  return false;
-}
-
-/*******************************************************************************
- *
- * Function         bta_gattc_sdp_callback
- *
- * Description      Process the discovery result from sdp
- *
- * Returns          void
- *
- ******************************************************************************/
+/* Process the discovery result from sdp */
 void bta_gattc_sdp_callback(uint16_t sdp_status, void* user_data) {
   tBTA_GATTC_CB_DATA* cb_data = (tBTA_GATTC_CB_DATA*)user_data;
   tBTA_GATTC_SERV* p_srvc_cb = bta_gattc_find_scb_by_cid(cb_data->sdp_conn_id);
 
   if (p_srvc_cb == nullptr) {
     LOG(ERROR) << "GATT service discovery is done on unknown connection";
-  } else {
-    bool no_pending_disc = p_srvc_cb->pending_discovery.empty();
-
-    if ((sdp_status == SDP_SUCCESS) || (sdp_status == SDP_DB_FULL)) {
-      tSDP_DISC_REC* p_sdp_rec = NULL;
-      do {
-        /* find a service record, report it */
-        p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
-        if (p_sdp_rec) {
-          Uuid service_uuid;
-          if (SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) {
-            tSDP_PROTOCOL_ELEM pe;
-            if (SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT,
-                                              &pe)) {
-              uint16_t start_handle = (uint16_t)pe.params[0];
-              uint16_t end_handle = (uint16_t)pe.params[1];
-
-#if (BTA_GATT_DEBUG == TRUE)
-              VLOG(1) << "Found ATT service uuid=" << service_uuid
-                      << ", s_handle=" << loghex(start_handle)
-                      << ", e_handle=" << loghex(end_handle);
-#endif
-
-              if (GATT_HANDLE_IS_VALID(start_handle) &&
-                  GATT_HANDLE_IS_VALID(end_handle) && p_srvc_cb != NULL) {
-                /* discover services result, add services into a service list */
-                add_service_to_gatt_db(p_srvc_cb->pending_discovery,
-                                       start_handle, end_handle, service_uuid,
-                                       true);
-              } else {
-                LOG(ERROR) << "invalid start_handle=" << loghex(start_handle)
-                           << ", end_handle=" << loghex(end_handle);
-              }
-            }
-          }
-        }
-      } while (p_sdp_rec);
-    }
-
-    if (no_pending_disc) {
-      p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
-    }
-
-    /* start discover primary service */
-    bta_gattc_explore_srvc(cb_data->sdp_conn_id, p_srvc_cb);
+    /* allocated in bta_gattc_sdp_service_disc */
+    osi_free(cb_data);
+    return;
   }
 
-  /* both were allocated in bta_gattc_sdp_service_disc */
-  osi_free(cb_data->p_sdp_db);
+  if ((sdp_status != SDP_SUCCESS) && (sdp_status != SDP_DB_FULL)) {
+    bta_gattc_explore_srvc_finished(cb_data->sdp_conn_id, p_srvc_cb);
+
+    /* allocated in bta_gattc_sdp_service_disc */
+    osi_free(cb_data);
+    return;
+  }
+
+  bool no_pending_disc = !p_srvc_cb->pending_discovery.InProgress();
+
+  tSDP_DISC_REC* p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, nullptr);
+  while (p_sdp_rec != nullptr) {
+    /* find a service record, report it */
+    Uuid service_uuid;
+    if (!SDP_FindServiceUUIDInRec(p_sdp_rec, &service_uuid)) continue;
+
+    tSDP_PROTOCOL_ELEM pe;
+    if (!SDP_FindProtocolListElemInRec(p_sdp_rec, UUID_PROTOCOL_ATT, &pe))
+      continue;
+
+    uint16_t start_handle = (uint16_t)pe.params[0];
+    uint16_t end_handle = (uint16_t)pe.params[1];
+
+#if (BTA_GATT_DEBUG == TRUE)
+    VLOG(1) << "Found ATT service uuid=" << service_uuid
+            << ", s_handle=" << loghex(start_handle)
+            << ", e_handle=" << loghex(end_handle);
+#endif
+
+    if (!GATT_HANDLE_IS_VALID(start_handle) ||
+        !GATT_HANDLE_IS_VALID(end_handle)) {
+      LOG(ERROR) << "invalid start_handle=" << loghex(start_handle)
+                 << ", end_handle=" << loghex(end_handle);
+      continue;
+    }
+
+    /* discover services result, add services into a service list */
+    p_srvc_cb->pending_discovery.AddService(start_handle, end_handle,
+                                            service_uuid, true);
+
+    p_sdp_rec = SDP_FindServiceInDb(cb_data->p_sdp_db, 0, p_sdp_rec);
+  }
+
+  // If discovery is already pending, no need to call
+  // bta_gattc_explore_next_service. Next service will be picked up to discovery
+  // once current one is discovered. If discovery is not pending, start one
+  if (no_pending_disc) {
+    bta_gattc_explore_next_service(cb_data->sdp_conn_id, p_srvc_cb);
+  }
+
+  /* allocated in bta_gattc_sdp_service_disc */
   osi_free(cb_data);
 }
-/*******************************************************************************
- *
- * Function         bta_gattc_sdp_service_disc
- *
- * Description      Start DSP Service Discovert
- *
- * Returns          void
- *
- ******************************************************************************/
+
+/* Start DSP Service Discovery */
 static tGATT_STATUS bta_gattc_sdp_service_disc(uint16_t conn_id,
                                                tBTA_GATTC_SERV* p_server_cb) {
   uint16_t num_attrs = 2;
@@ -471,10 +294,10 @@
    * On success, cb_data will be freed inside bta_gattc_sdp_callback,
    * otherwise it will be freed within this function.
    */
-  tBTA_GATTC_CB_DATA* cb_data =
-      (tBTA_GATTC_CB_DATA*)osi_malloc(sizeof(tBTA_GATTC_CB_DATA));
+  tBTA_GATTC_CB_DATA* cb_data = (tBTA_GATTC_CB_DATA*)osi_malloc(
+      sizeof(tBTA_GATTC_CB_DATA) + BTA_GATT_SDP_DB_SIZE);
 
-  cb_data->p_sdp_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_GATT_SDP_DB_SIZE);
+  cb_data->p_sdp_db = (tSDP_DISCOVERY_DB*)(cb_data + 1);
   attr_list[0] = ATTR_ID_SERVICE_CLASS_ID_LIST;
   attr_list[1] = ATTR_ID_PROTOCOL_DESC_LIST;
 
@@ -485,7 +308,6 @@
   if (!SDP_ServiceSearchAttributeRequest2(p_server_cb->server_bda,
                                           cb_data->p_sdp_db,
                                           &bta_gattc_sdp_callback, cb_data)) {
-    osi_free(cb_data->p_sdp_db);
     osi_free(cb_data);
     return GATT_ERROR;
   }
@@ -505,43 +327,27 @@
   switch (disc_type) {
     case GATT_DISC_SRVC_ALL:
     case GATT_DISC_SRVC_BY_UUID:
-      /* discover services result, add services into a service list */
-      add_service_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
-                             p_data->value.group_value.e_handle,
-                             p_data->value.group_value.service_type, true);
+      p_srvc_cb->pending_discovery.AddService(
+          p_data->handle, p_data->value.group_value.e_handle,
+          p_data->value.group_value.service_type, true);
       break;
 
     case GATT_DISC_INC_SRVC:
-      /* add included service into service list if it's secondary or it never
-         showed up in the primary service search */
-      if (!bta_gattc_srvc_in_list(p_srvc_cb->pending_discovery,
-                                  p_data->value.incl_service.s_handle,
-                                  p_data->value.incl_service.e_handle,
-                                  p_data->value.incl_service.service_type)) {
-        add_service_to_gatt_db(p_srvc_cb->pending_discovery,
-                               p_data->value.incl_service.s_handle,
-                               p_data->value.incl_service.e_handle,
-                               p_data->value.incl_service.service_type, false);
-      }
-
-      /* add into database */
-      add_incl_srvc_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
-                               p_data->value.incl_service.service_type,
-                               p_data->value.incl_service.s_handle);
+      p_srvc_cb->pending_discovery.AddIncludedService(
+          p_data->handle, p_data->value.incl_service.service_type,
+          p_data->value.incl_service.s_handle,
+          p_data->value.incl_service.e_handle);
       break;
 
     case GATT_DISC_CHAR:
-      /* add char value into database */
-      add_characteristic_to_gatt_db(p_srvc_cb->pending_discovery,
-                                    p_data->handle,
-                                    p_data->value.dclr_value.val_handle,
-                                    p_data->value.dclr_value.char_uuid,
-                                    p_data->value.dclr_value.char_prop);
+      p_srvc_cb->pending_discovery.AddCharacteristic(
+          p_data->handle, p_data->value.dclr_value.val_handle,
+          p_data->value.dclr_value.char_uuid,
+          p_data->value.dclr_value.char_prop);
       break;
 
     case GATT_DISC_CHAR_DSCPT:
-      add_descriptor_to_gatt_db(p_srvc_cb->pending_discovery, p_data->handle,
-                                p_data->type);
+      p_srvc_cb->pending_discovery.AddDescriptor(p_data->handle, p_data->type);
       break;
   }
 }
@@ -567,18 +373,13 @@
 #if (BTA_GATT_DEBUG == TRUE)
       bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
 #endif
-      p_srvc_cb->pending_service = p_srvc_cb->pending_discovery.begin();
-      bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+      bta_gattc_explore_next_service(conn_id, p_srvc_cb);
       break;
 
     case GATT_DISC_INC_SRVC: {
-      auto& service = *p_srvc_cb->pending_service;
-
-      /* start discoverying characteristic */
-
-      tGATT_DISC_PARAM param = {.s_handle = service.s_handle,
-                                .e_handle = service.e_handle};
-      GATTC_Discover(conn_id, GATT_DISC_CHAR, &param);
+      auto& service = p_srvc_cb->pending_discovery.CurrentlyExploredService();
+      /* start discovering characteristic */
+      GATTC_Discover(conn_id, GATT_DISC_CHAR, service.first, service.second);
       break;
     }
 
@@ -586,33 +387,25 @@
 #if (BTA_GATT_DEBUG == TRUE)
       bta_gattc_display_explore_record(p_srvc_cb->pending_discovery);
 #endif
-      auto& service = *p_srvc_cb->pending_service;
-      if (!service.characteristics.empty()) {
-        /* discover descriptors */
-        p_srvc_cb->pending_char = service.characteristics.begin();
-        bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
-        return;
-      }
-      /* start next service */
-      ++p_srvc_cb->pending_service;
-      bta_gattc_explore_srvc(conn_id, p_srvc_cb);
+      bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
       break;
     }
 
     case GATT_DISC_CHAR_DSCPT:
-      bta_gattc_char_dscpt_disc_cmpl(conn_id, p_srvc_cb);
+      /* start discovering next characteristic for char descriptor */
+      bta_gattc_start_disc_char_dscp(conn_id, p_srvc_cb);
       break;
   }
 }
 
 /** search local cache for matching service record */
 void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb, Uuid* p_uuid) {
-  for (const tBTA_GATTC_SERVICE& service : p_clcb->p_srcb->srvc_cache) {
+  for (const Service& service : p_clcb->p_srcb->gatt_database.Services()) {
     if (p_uuid && *p_uuid != service.uuid) continue;
 
 #if (BTA_GATT_DEBUG == TRUE)
     VLOG(1) << __func__ << "found service " << service.uuid
-            << ", inst:" << +service.handle << " handle:" << +service.s_handle;
+            << " handle:" << +service.handle;
 #endif
     if (!p_clcb->p_rcb->p_cback) continue;
 
@@ -626,14 +419,13 @@
   }
 }
 
-std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services_srcb(
-    tBTA_GATTC_SERV* p_srcb) {
-  if (!p_srcb || p_srcb->srvc_cache.empty()) return NULL;
+const std::list<Service>* bta_gattc_get_services_srcb(tBTA_GATTC_SERV* p_srcb) {
+  if (!p_srcb || p_srcb->gatt_database.IsEmpty()) return NULL;
 
-  return &p_srcb->srvc_cache;
+  return &p_srcb->gatt_database.Services();
 }
 
-std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services(uint16_t conn_id) {
+const std::list<Service>* bta_gattc_get_services(uint16_t conn_id) {
   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
   if (p_clcb == NULL) return NULL;
@@ -643,38 +435,37 @@
   return bta_gattc_get_services_srcb(p_srcb);
 }
 
-tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
-  std::vector<tBTA_GATTC_SERVICE>* services =
-      bta_gattc_get_services_srcb(p_srcb);
+const Service* bta_gattc_get_service_for_handle_srcb(tBTA_GATTC_SERV* p_srcb,
+                                                     uint16_t handle) {
+  const std::list<Service>* services = bta_gattc_get_services_srcb(p_srcb);
   if (services == NULL) return NULL;
   return bta_gattc_find_matching_service(*services, handle);
 }
 
-const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(uint16_t conn_id,
-                                                           uint16_t handle) {
-  std::vector<tBTA_GATTC_SERVICE>* services = bta_gattc_get_services(conn_id);
+const Service* bta_gattc_get_service_for_handle(uint16_t conn_id,
+                                                uint16_t handle) {
+  const std::list<Service>* services = bta_gattc_get_services(conn_id);
   if (services == NULL) return NULL;
 
   return bta_gattc_find_matching_service(*services, handle);
 }
 
-tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
-  tBTA_GATTC_SERVICE* service =
+const Characteristic* bta_gattc_get_characteristic_srcb(tBTA_GATTC_SERV* p_srcb,
+                                                        uint16_t handle) {
+  const Service* service =
       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
 
   if (!service) return NULL;
 
-  for (tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+  for (const Characteristic& charac : service->characteristics) {
     if (handle == charac.value_handle) return &charac;
   }
 
   return NULL;
 }
 
-tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(uint16_t conn_id,
-                                                        uint16_t handle) {
+const Characteristic* bta_gattc_get_characteristic(uint16_t conn_id,
+                                                   uint16_t handle) {
   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
   if (p_clcb == NULL) return NULL;
@@ -683,17 +474,17 @@
   return bta_gattc_get_characteristic_srcb(p_srcb, handle);
 }
 
-const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
-  const tBTA_GATTC_SERVICE* service =
+const Descriptor* bta_gattc_get_descriptor_srcb(tBTA_GATTC_SERV* p_srcb,
+                                                uint16_t handle) {
+  const Service* service =
       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
 
   if (!service) {
     return NULL;
   }
 
-  for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
-    for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+  for (const Characteristic& charac : service->characteristics) {
+    for (const Descriptor& desc : charac.descriptors) {
       if (handle == desc.handle) return &desc;
     }
   }
@@ -701,8 +492,7 @@
   return NULL;
 }
 
-const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
-                                                      uint16_t handle) {
+const Descriptor* bta_gattc_get_descriptor(uint16_t conn_id, uint16_t handle) {
   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
 
   if (p_clcb == NULL) return NULL;
@@ -711,15 +501,15 @@
   return bta_gattc_get_descriptor_srcb(p_srcb, handle);
 }
 
-tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic_srcb(
+const Characteristic* bta_gattc_get_owning_characteristic_srcb(
     tBTA_GATTC_SERV* p_srcb, uint16_t handle) {
-  tBTA_GATTC_SERVICE* service =
+  const Service* service =
       bta_gattc_get_service_for_handle_srcb(p_srcb, handle);
 
   if (!service) return NULL;
 
-  for (tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
-    for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+  for (const Characteristic& charac : service->characteristics) {
+    for (const Descriptor& desc : charac.descriptors) {
       if (handle == desc.handle) return &charac;
     }
   }
@@ -727,8 +517,8 @@
   return NULL;
 }
 
-const tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic(
-    uint16_t conn_id, uint16_t handle) {
+const Characteristic* bta_gattc_get_owning_characteristic(uint16_t conn_id,
+                                                          uint16_t handle) {
   tBTA_GATTC_CLCB* p_clcb = bta_gattc_find_clcb_by_conn_id(conn_id);
   if (!p_clcb) return NULL;
 
@@ -765,27 +555,27 @@
 /*******************************************************************************
  * Returns          number of elements inside db from start_handle to end_handle
  ******************************************************************************/
-static size_t bta_gattc_get_db_size(
-    const std::vector<tBTA_GATTC_SERVICE>& services, uint16_t start_handle,
-    uint16_t end_handle) {
+static size_t bta_gattc_get_db_size(const std::list<Service>& services,
+                                    uint16_t start_handle,
+                                    uint16_t end_handle) {
   if (services.empty()) return 0;
 
   size_t db_size = 0;
 
-  for (const tBTA_GATTC_SERVICE& service : services) {
-    if (service.s_handle < start_handle) continue;
+  for (const Service& service : services) {
+    if (service.handle < start_handle) continue;
 
-    if (service.e_handle > end_handle) break;
+    if (service.end_handle > end_handle) break;
 
     db_size++;
 
-    for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
+    for (const Characteristic& charac : service.characteristics) {
       db_size++;
 
       db_size += charac.descriptors.size();
     }
 
-    db_size += service.included_svc.size();
+    db_size += service.included_services.size();
   }
 
   return db_size;
@@ -814,39 +604,39 @@
           << StringPrintf(": start_handle 0x%04x, end_handle 0x%04x",
                           start_handle, end_handle);
 
-  if (p_srvc_cb->srvc_cache.empty()) {
+  if (p_srvc_cb->gatt_database.IsEmpty()) {
     *count = 0;
     *db = NULL;
     return;
   }
 
-  size_t db_size =
-      bta_gattc_get_db_size(p_srvc_cb->srvc_cache, start_handle, end_handle);
+  size_t db_size = bta_gattc_get_db_size(p_srvc_cb->gatt_database.Services(),
+                                         start_handle, end_handle);
 
   void* buffer = osi_malloc(db_size * sizeof(btgatt_db_element_t));
   btgatt_db_element_t* curr_db_attr = (btgatt_db_element_t*)buffer;
 
-  for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
-    if (service.s_handle < start_handle) continue;
+  for (const Service& service : p_srvc_cb->gatt_database.Services()) {
+    if (service.handle < start_handle) continue;
 
-    if (service.e_handle > end_handle) break;
+    if (service.end_handle > end_handle) break;
 
     bta_gattc_fill_gatt_db_el(curr_db_attr,
                               service.is_primary ? BTGATT_DB_PRIMARY_SERVICE
                                                  : BTGATT_DB_SECONDARY_SERVICE,
-                              0 /* att_handle */, service.s_handle,
-                              service.e_handle, service.s_handle, service.uuid,
+                              0 /* att_handle */, service.handle,
+                              service.end_handle, service.handle, service.uuid,
                               0 /* prop */);
     curr_db_attr++;
 
-    for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
+    for (const Characteristic& charac : service.characteristics) {
       bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_CHARACTERISTIC,
                                 charac.value_handle, 0 /* s_handle */,
                                 0 /* e_handle */, charac.value_handle,
                                 charac.uuid, charac.properties);
       curr_db_attr++;
 
-      for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
+      for (const Descriptor& desc : charac.descriptors) {
         bta_gattc_fill_gatt_db_el(
             curr_db_attr, BTGATT_DB_DESCRIPTOR, desc.handle, 0 /* s_handle */,
             0 /* e_handle */, desc.handle, desc.uuid, 0 /* property */);
@@ -854,11 +644,11 @@
       }
     }
 
-    for (const tBTA_GATTC_INCLUDED_SVC& p_isvc : service.included_svc) {
-      bta_gattc_fill_gatt_db_el(
-          curr_db_attr, BTGATT_DB_INCLUDED_SERVICE, p_isvc.handle,
-          p_isvc.included_service ? p_isvc.included_service->s_handle : 0,
-          0 /* e_handle */, p_isvc.handle, p_isvc.uuid, 0 /* property */);
+    for (const IncludedService& p_isvc : service.included_services) {
+      bta_gattc_fill_gatt_db_el(curr_db_attr, BTGATT_DB_INCLUDED_SERVICE,
+                                p_isvc.handle, p_isvc.start_handle,
+                                0 /* e_handle */, p_isvc.handle, p_isvc.uuid,
+                                0 /* property */);
       curr_db_attr++;
     }
   }
@@ -897,9 +687,8 @@
     return;
   }
 
-  if (!p_clcb->p_srcb ||
-      !p_clcb->p_srcb->pending_discovery.empty() || /* no active discovery */
-      p_clcb->p_srcb->srvc_cache.empty()) {
+  if (!p_clcb->p_srcb || p_clcb->p_srcb->pending_discovery.InProgress() ||
+      p_clcb->p_srcb->gatt_database.IsEmpty()) {
     LOG(ERROR) << "No server cache available";
     return;
   }
@@ -908,129 +697,20 @@
                              count);
 }
 
-/* rebuild server cache from NV cache */
-void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srvc_cb, uint16_t num_attr,
-                             tBTA_GATTC_NV_ATTR* p_attr) {
-  /* first attribute loading, initialize buffer */
-  LOG(INFO) << __func__ << " " << num_attr;
-
-  // clear reallocating
-  std::vector<tBTA_GATTC_SERVICE>().swap(p_srvc_cb->srvc_cache);
-
-  while (num_attr > 0 && p_attr != NULL) {
-    switch (p_attr->attr_type) {
-      case BTA_GATTC_ATTR_TYPE_SRVC:
-        add_service_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
-                               p_attr->e_handle, p_attr->uuid,
-                               p_attr->is_primary);
-        break;
-
-      case BTA_GATTC_ATTR_TYPE_CHAR:
-        add_characteristic_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
-                                      p_attr->s_handle, p_attr->uuid,
-                                      p_attr->prop);
-        break;
-
-      case BTA_GATTC_ATTR_TYPE_CHAR_DESCR:
-        add_descriptor_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
-                                  p_attr->uuid);
-        break;
-      case BTA_GATTC_ATTR_TYPE_INCL_SRVC:
-        add_incl_srvc_to_gatt_db(p_srvc_cb->srvc_cache, p_attr->s_handle,
-                                 p_attr->uuid, p_attr->incl_srvc_handle);
-        break;
-    }
-    p_attr++;
-    num_attr--;
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_gattc_fill_nv_attr
- *
- * Description      fill a NV attribute entry value
- *
- * Returns          None.
- *
- ******************************************************************************/
-void bta_gattc_fill_nv_attr(tBTA_GATTC_NV_ATTR* p_attr, uint8_t type,
-                            uint16_t s_handle, uint16_t e_handle, Uuid uuid,
-                            uint8_t prop, uint16_t incl_srvc_handle,
-                            bool is_primary) {
-  p_attr->s_handle = s_handle;
-  p_attr->e_handle = e_handle;
-  p_attr->attr_type = type;
-  p_attr->is_primary = is_primary;
-  p_attr->id = 0;
-  p_attr->prop = prop;
-  p_attr->incl_srvc_handle = incl_srvc_handle;
-  p_attr->uuid = uuid;
-}
-
-/*******************************************************************************
- *
- * Function         bta_gattc_cache_save
- *
- * Description      save the server cache into NV
- *
- * Returns          None.
- *
- ******************************************************************************/
-void bta_gattc_cache_save(tBTA_GATTC_SERV* p_srvc_cb, uint16_t conn_id) {
-  if (p_srvc_cb->srvc_cache.empty()) return;
-
-  int i = 0;
-  size_t db_size = bta_gattc_get_db_size(p_srvc_cb->srvc_cache, 0x0000, 0xFFFF);
-  tBTA_GATTC_NV_ATTR* nv_attr =
-      (tBTA_GATTC_NV_ATTR*)osi_malloc(db_size * sizeof(tBTA_GATTC_NV_ATTR));
-
-  for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
-    bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_SRVC,
-                           service.s_handle, service.e_handle, service.uuid,
-                           0 /* properties */, 0 /* incl_srvc_handle */,
-                           service.is_primary);
-  }
-
-  for (const tBTA_GATTC_SERVICE& service : p_srvc_cb->srvc_cache) {
-    for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
-      bta_gattc_fill_nv_attr(
-          &nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR, charac.value_handle, 0,
-          charac.uuid, charac.properties, 0 /* incl_srvc_handle */, false);
-
-      for (const tBTA_GATTC_DESCRIPTOR& desc : charac.descriptors) {
-        bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
-                               desc.handle, 0, desc.uuid, 0 /* properties */,
-                               0 /* incl_srvc_handle */, false);
-      }
-    }
-
-    for (const tBTA_GATTC_INCLUDED_SVC& p_isvc : service.included_svc) {
-      bta_gattc_fill_nv_attr(&nv_attr[i++], BTA_GATTC_ATTR_TYPE_INCL_SRVC,
-                             p_isvc.handle, 0, p_isvc.uuid, 0 /* properties */,
-                             p_isvc.included_service->s_handle, false);
-    }
-  }
-
-  bta_gattc_cache_write(p_srvc_cb->server_bda, db_size, nv_attr);
-  osi_free(nv_attr);
-}
-
 /*******************************************************************************
  *
  * Function         bta_gattc_cache_load
  *
  * Description      Load GATT cache from storage for server.
  *
- * Parameter        p_clcb: pointer to server clcb, that will
+ * Parameter        p_srcb: pointer to server cache, that will
  *                          be filled from storage
  * Returns          true on success, false otherwise
  *
  ******************************************************************************/
-bool bta_gattc_cache_load(tBTA_GATTC_CLCB* p_clcb) {
+bool bta_gattc_cache_load(tBTA_GATTC_SERV* p_srcb) {
   char fname[255] = {0};
-  bta_gattc_generate_cache_file_name(fname, sizeof(fname),
-                                     p_clcb->p_srcb->server_bda);
+  bta_gattc_generate_cache_file_name(fname, sizeof(fname), p_srcb->server_bda);
 
   FILE* fd = fopen(fname, "rb");
   if (!fd) {
@@ -1040,7 +720,6 @@
   }
 
   uint16_t cache_ver = 0;
-  tBTA_GATTC_NV_ATTR* attr = NULL;
   bool success = false;
   uint16_t num_attr = 0;
 
@@ -1060,19 +739,18 @@
     goto done;
   }
 
-  attr = (tBTA_GATTC_NV_ATTR*)osi_malloc(sizeof(tBTA_GATTC_NV_ATTR) * num_attr);
+  {
+    std::vector<StoredAttribute> attr(num_attr);
 
-  if (fread(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
-    LOG(ERROR) << __func__ << "s: can't read GATT attributes: " << fname;
-    goto done;
+    if (fread(attr.data(), sizeof(StoredAttribute), num_attr, fd) != num_attr) {
+      LOG(ERROR) << __func__ << "s: can't read GATT attributes: " << fname;
+      goto done;
+    }
+
+    p_srcb->gatt_database = gatt::Database::Deserialize(attr, &success);
   }
 
-  bta_gattc_rebuild_cache(p_clcb->p_srcb, num_attr, attr);
-
-  success = true;
-
 done:
-  osi_free(attr);
   fclose(fd);
   return success;
 }
@@ -1085,13 +763,12 @@
  *                  cache is available to save.
  *
  * Parameter        server_bda: server bd address of this cache belongs to
- *                  num_attr: number of attribute to be save.
- *                  attr: pointer to the list of attributes to save.
+ *                  attr: attributes to save.
  * Returns
  *
  ******************************************************************************/
 static void bta_gattc_cache_write(const RawAddress& server_bda,
-                                  uint16_t num_attr, tBTA_GATTC_NV_ATTR* attr) {
+                                  const std::vector<StoredAttribute>& attr) {
   char fname[255] = {0};
   bta_gattc_generate_cache_file_name(fname, sizeof(fname), server_bda);
 
@@ -1109,6 +786,7 @@
     return;
   }
 
+  uint16_t num_attr = attr.size();
   if (fwrite(&num_attr, sizeof(uint16_t), 1, fd) != 1) {
     LOG(ERROR) << __func__
                << ": can't write GATT cache attribute count: " << fname;
@@ -1116,7 +794,7 @@
     return;
   }
 
-  if (fwrite(attr, sizeof(tBTA_GATTC_NV_ATTR), num_attr, fd) != num_attr) {
+  if (fwrite(attr.data(), sizeof(StoredAttribute), num_attr, fd) != num_attr) {
     LOG(ERROR) << __func__ << ": can't write GATT cache attributes: " << fname;
     fclose(fd);
     return;
diff --git a/bta/gatt/bta_gattc_int.h b/bta/gatt/bta_gattc_int.h
index 5b33eae..f0ead49 100644
--- a/bta/gatt/bta_gattc_int.h
+++ b/bta/gatt/bta_gattc_int.h
@@ -28,6 +28,7 @@
 
 #include "bta_gatt_api.h"
 #include "bta_sys.h"
+#include "database_builder.h"
 #include "osi/include/fixed_queue.h"
 
 #include "bt_common.h"
@@ -206,13 +207,11 @@
 
   uint8_t state;
 
-  std::vector<tBTA_GATTC_SERVICE> srvc_cache;
+  gatt::Database gatt_database;
   uint8_t update_count; /* indication received */
   uint8_t num_clcb;     /* number of associated CLCB */
 
-  std::vector<tBTA_GATTC_SERVICE> pending_discovery;
-  std::vector<tBTA_GATTC_SERVICE>::iterator pending_service;
-  std::vector<tBTA_GATTC_CHARACTERISTIC>::iterator pending_char;
+  gatt::DatabaseBuilder pending_discovery;
 
   uint8_t srvc_hdl_chg; /* service handle change indication pending */
   uint16_t attr_index;  /* cahce NV saving/loading attribute index */
@@ -427,27 +426,23 @@
                                                    uint8_t disc_type);
 extern void bta_gattc_search_service(tBTA_GATTC_CLCB* p_clcb,
                                      bluetooth::Uuid* p_uuid);
-extern std::vector<tBTA_GATTC_SERVICE>* bta_gattc_get_services(
-    uint16_t conn_id);
-extern const tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle(
-    uint16_t conn_id, uint16_t handle);
-tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
-extern tBTA_GATTC_SERVICE* bta_gattc_get_service_for_handle_srcb(
-    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
-extern tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_characteristic(uint16_t conn_id,
-                                                               uint16_t handle);
-extern const tBTA_GATTC_DESCRIPTOR* bta_gattc_get_descriptor(uint16_t conn_id,
+extern const std::list<gatt::Service>* bta_gattc_get_services(uint16_t conn_id);
+extern const gatt::Service* bta_gattc_get_service_for_handle(uint16_t conn_id,
                                                              uint16_t handle);
-extern const tBTA_GATTC_CHARACTERISTIC* bta_gattc_get_owning_characteristic(
+const gatt::Characteristic* bta_gattc_get_characteristic_srcb(
+    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
+extern const gatt::Service* bta_gattc_get_service_for_handle_srcb(
+    tBTA_GATTC_SERV* p_srcb, uint16_t handle);
+extern const gatt::Characteristic* bta_gattc_get_characteristic(
+    uint16_t conn_id, uint16_t handle);
+extern const gatt::Descriptor* bta_gattc_get_descriptor(uint16_t conn_id,
+                                                        uint16_t handle);
+extern const gatt::Characteristic* bta_gattc_get_owning_characteristic(
     uint16_t conn_id, uint16_t handle);
 extern void bta_gattc_get_gatt_db(uint16_t conn_id, uint16_t start_handle,
                                   uint16_t end_handle, btgatt_db_element_t** db,
                                   int* count);
-extern tGATT_STATUS bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb);
-extern void bta_gattc_rebuild_cache(tBTA_GATTC_SERV* p_srcv, uint16_t num_attr,
-                                    tBTA_GATTC_NV_ATTR* attr);
-extern void bta_gattc_cache_save(tBTA_GATTC_SERV* p_srvc_cb, uint16_t conn_id);
+extern void bta_gattc_init_cache(tBTA_GATTC_SERV* p_srvc_cb);
 extern void bta_gattc_reset_discover_st(tBTA_GATTC_SERV* p_srcb,
                                         tGATT_STATUS status);
 
@@ -456,7 +451,7 @@
 extern tBTA_GATTC_CONN* bta_gattc_conn_find_alloc(const RawAddress& remote_bda);
 extern bool bta_gattc_conn_dealloc(const RawAddress& remote_bda);
 
-extern bool bta_gattc_cache_load(tBTA_GATTC_CLCB* p_clcb);
+extern bool bta_gattc_cache_load(tBTA_GATTC_SERV* p_srcb);
 extern void bta_gattc_cache_reset(const RawAddress& server_bda);
 
 #endif /* BTA_GATTC_INT_H */
diff --git a/bta/gatt/bta_gattc_queue.cc b/bta/gatt/bta_gattc_queue.cc
index c00a885..6d9fff3 100644
--- a/bta/gatt/bta_gattc_queue.cc
+++ b/bta/gatt/bta_gattc_queue.cc
@@ -81,7 +81,7 @@
 }
 
 void BtaGattQueue::gatt_execute_next_op(uint16_t conn_id) {
-  APPL_TRACE_DEBUG("%s:", __func__, conn_id);
+  APPL_TRACE_DEBUG("%s: conn_id=0x%x", __func__, conn_id);
   if (gatt_op_queue.empty()) {
     APPL_TRACE_DEBUG("%s: op queue is empty", __func__);
     return;
diff --git a/bta/gatt/bta_gattc_utils.cc b/bta/gatt/bta_gattc_utils.cc
index 21b63c0..2c8e5fd 100644
--- a/bta/gatt/bta_gattc_utils.cc
+++ b/bta/gatt/bta_gattc_utils.cc
@@ -204,7 +204,7 @@
     p_srcb->mtu = 0;
 
     // clear reallocating
-    std::vector<tBTA_GATTC_SERVICE>().swap(p_srcb->srvc_cache);
+    p_srcb->gatt_database.Clear();
   }
 
   osi_free_and_reset((void**)&p_clcb->p_q_cmd);
@@ -296,8 +296,8 @@
 
   if (p_tcb != NULL) {
     // clear reallocating
-    std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->srvc_cache);
-    std::vector<tBTA_GATTC_SERVICE>().swap(p_tcb->pending_discovery);
+    p_tcb->gatt_database.Clear();
+    p_tcb->pending_discovery.Clear();
     *p_tcb = tBTA_GATTC_SERV();
 
     p_tcb->in_use = true;
diff --git a/bta/gatt/bta_gatts_api.cc b/bta/gatt/bta_gatts_api.cc
index 9d7cda0..ef00269 100644
--- a/bta/gatt/bta_gatts_api.cc
+++ b/bta/gatt/bta_gatts_api.cc
@@ -28,10 +28,10 @@
 #include <string.h>
 
 #include "bt_common.h"
-#include "bta_closure_api.h"
 #include "bta_gatt_api.h"
 #include "bta_gatts_int.h"
 #include "bta_sys.h"
+#include "stack/include/btu.h"
 
 /*****************************************************************************
  *  Constants
@@ -168,8 +168,9 @@
 extern void BTA_GATTS_AddService(tGATT_IF server_if,
                                  std::vector<btgatt_db_element_t> service,
                                  BTA_GATTS_AddServiceCb cb) {
-  do_in_bta_thread(FROM_HERE, base::Bind(&bta_gatts_add_service_impl, server_if,
-                                         std::move(service), std::move(cb)));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&bta_gatts_add_service_impl, server_if,
+                               std::move(service), std::move(cb)));
 }
 
 /*******************************************************************************
diff --git a/bta/gatt/database.cc b/bta/gatt/database.cc
new file mode 100644
index 0000000..1486b08
--- /dev/null
+++ b/bta/gatt/database.cc
@@ -0,0 +1,186 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "database.h"
+#include "bt_trace.h"
+#include "stack/include/gattdefs.h"
+
+#include <base/logging.h>
+#include <list>
+#include <memory>
+#include <sstream>
+
+using bluetooth::Uuid;
+
+namespace gatt {
+
+namespace {
+const Uuid PRIMARY_SERVICE = Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
+const Uuid SECONDARY_SERVICE = Uuid::From16Bit(GATT_UUID_SEC_SERVICE);
+const Uuid INCLUDE = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE);
+const Uuid CHARACTERISTIC = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
+
+bool HandleInRange(const Service& svc, uint16_t handle) {
+  return handle >= svc.handle && handle <= svc.end_handle;
+}
+}  // namespace
+
+Service* FindService(std::list<Service>& services, uint16_t handle) {
+  for (Service& service : services) {
+    if (handle >= service.handle && handle <= service.end_handle)
+      return &service;
+  }
+
+  return nullptr;
+}
+
+std::string Database::ToString() const {
+  std::stringstream tmp;
+
+  for (const Service& service : services) {
+    tmp << "Service: handle=" << loghex(service.handle)
+        << ", end_handle=" << loghex(service.end_handle)
+        << ", uuid=" << service.uuid << "\n";
+
+    for (const auto& is : service.included_services) {
+      tmp << "\t Included service: handle=" << loghex(is.handle)
+          << ", start_handle=" << loghex(is.start_handle)
+          << ", end_handle=" << loghex(is.end_handle) << ", uuid=" << is.uuid
+          << "\n";
+    }
+
+    for (const Characteristic& c : service.characteristics) {
+      tmp << "\t Characteristic: declaration_handle="
+          << loghex(c.declaration_handle)
+          << ", value_handle=" << loghex(c.value_handle) << ", uuid=" << c.uuid
+          << ", prop=" << loghex(c.properties) << "\n";
+
+      for (const Descriptor& d : c.descriptors) {
+        tmp << "\t\t Descriptor: handle=" << loghex(d.handle)
+            << ", uuid=" << d.uuid << "\n";
+      }
+    }
+  }
+  return tmp.str();
+}
+
+std::vector<StoredAttribute> Database::Serialize() const {
+  std::vector<StoredAttribute> nv_attr;
+
+  if (services.empty()) return std::vector<StoredAttribute>();
+
+  for (const Service& service : services) {
+    // TODO: add constructor to NV_ATTR, use emplace_back
+    nv_attr.push_back({service.handle,
+                       service.is_primary ? PRIMARY_SERVICE : SECONDARY_SERVICE,
+                       {.service = {.uuid = service.uuid,
+                                    .end_handle = service.end_handle}}});
+  }
+
+  for (const Service& service : services) {
+    for (const IncludedService& p_isvc : service.included_services) {
+      nv_attr.push_back({p_isvc.handle,
+                         INCLUDE,
+                         {.included_service = {.handle = p_isvc.start_handle,
+                                               .end_handle = p_isvc.end_handle,
+                                               .uuid = p_isvc.uuid}}});
+    }
+
+    for (const Characteristic& charac : service.characteristics) {
+      nv_attr.push_back(
+          {charac.declaration_handle,
+           CHARACTERISTIC,
+           {.characteristic = {.properties = charac.properties,
+                               .value_handle = charac.value_handle,
+                               .uuid = charac.uuid}}});
+
+      for (const Descriptor& desc : charac.descriptors) {
+        nv_attr.push_back({desc.handle, desc.uuid, {}});
+      }
+    }
+  }
+
+  return nv_attr;
+}
+
+Database Database::Deserialize(const std::vector<StoredAttribute>& nv_attr,
+                               bool* success) {
+  // clear reallocating
+  Database result;
+  auto it = nv_attr.cbegin();
+
+  for (; it != nv_attr.cend(); ++it) {
+    const auto& attr = *it;
+    if (attr.type != PRIMARY_SERVICE && attr.type != SECONDARY_SERVICE) break;
+    result.services.emplace_back(
+        Service{.handle = attr.handle,
+                .end_handle = attr.value.service.end_handle,
+                .is_primary = (attr.type == PRIMARY_SERVICE),
+                .uuid = attr.value.service.uuid});
+  }
+
+  auto current_service_it = result.services.begin();
+  for (; it != nv_attr.cend(); it++) {
+    const auto& attr = *it;
+
+    // go to the service this attribute belongs to; attributes are stored in
+    // order, so iterating just forward is enough
+    while (current_service_it != result.services.end() &&
+           current_service_it->end_handle < attr.handle) {
+      current_service_it++;
+    }
+
+    if (current_service_it == result.services.end() ||
+        !HandleInRange(*current_service_it, attr.handle)) {
+      LOG(ERROR) << "Can't find service for attribute with handle: "
+                 << loghex(attr.handle);
+      *success = false;
+      return result;
+    }
+
+    if (attr.type == INCLUDE) {
+      Service* included_service =
+          FindService(result.services, attr.value.included_service.handle);
+      if (!included_service) {
+        LOG(ERROR) << __func__ << ": Non-existing included service!";
+        *success = false;
+        return result;
+      }
+      current_service_it->included_services.push_back(IncludedService{
+          .handle = attr.handle,
+          .uuid = attr.value.included_service.uuid,
+          .start_handle = attr.value.included_service.handle,
+          .end_handle = attr.value.included_service.end_handle,
+      });
+    } else if (attr.type == CHARACTERISTIC) {
+      current_service_it->characteristics.emplace_back(
+          Characteristic{.declaration_handle = attr.handle,
+                         .value_handle = attr.value.characteristic.value_handle,
+                         .properties = attr.value.characteristic.properties,
+                         .uuid = attr.value.characteristic.uuid});
+
+    } else {
+      current_service_it->characteristics.back().descriptors.emplace_back(
+          Descriptor{.handle = attr.handle, .uuid = attr.type});
+    }
+  }
+  *success = true;
+  return result;
+}
+
+}  // namespace gatt
diff --git a/bta/gatt/database.h b/bta/gatt/database.h
new file mode 100644
index 0000000..d1ba836
--- /dev/null
+++ b/bta/gatt/database.h
@@ -0,0 +1,127 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <list>
+#include <set>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "types/bluetooth/uuid.h"
+
+namespace gatt {
+constexpr uint16_t HANDLE_MIN = 0x0001;
+constexpr uint16_t HANDLE_MAX = 0xffff;
+
+/* Representation of GATT attribute for storage */
+struct StoredAttribute {
+  uint16_t handle;
+  bluetooth::Uuid type;
+
+  union {
+    /* primary or secondary service definition */
+    struct {
+      bluetooth::Uuid uuid;
+      uint16_t end_handle;
+    } service;
+
+    /* included service definition */
+    struct {
+      uint16_t handle;
+      uint16_t end_handle;
+      bluetooth::Uuid uuid;
+    } included_service;
+
+    /* characteristic deifnition */
+    struct {
+      uint8_t properties;
+      uint16_t value_handle;
+      bluetooth::Uuid uuid;
+    } characteristic;
+
+    /* for descriptor definition we don't store value*/
+  } value;
+};
+
+struct IncludedService;
+struct Characteristic;
+struct Descriptor;
+
+struct Service {
+  uint16_t handle;
+  bluetooth::Uuid uuid;
+  bool is_primary;
+  uint16_t end_handle;
+  std::vector<IncludedService> included_services;
+  std::vector<Characteristic> characteristics;
+};
+
+struct IncludedService {
+  uint16_t handle; /* definition handle */
+  bluetooth::Uuid uuid;
+  uint16_t start_handle; /* start handle of included service */
+  uint16_t end_handle;   /* end handle of included service */
+};
+
+struct Characteristic {
+  uint16_t declaration_handle;
+  bluetooth::Uuid uuid;
+  uint16_t value_handle;
+  uint8_t properties;
+  std::vector<Descriptor> descriptors;
+};
+
+struct Descriptor {
+  uint16_t handle;
+  bluetooth::Uuid uuid;
+};
+
+class DatabaseBuilder;
+
+class Database {
+ public:
+  /* Return true if there are no services in this database. */
+  bool IsEmpty() const { return services.empty(); }
+
+  /* Clear the GATT database. This method forces relocation to ensure no extra
+   * space is used unnecesarly */
+  void Clear() { std::list<Service>().swap(services); }
+
+  /* Return list of services available in this database */
+  const std::list<Service>& Services() const { return services; }
+
+  std::string ToString() const;
+
+  std::vector<gatt::StoredAttribute> Serialize() const;
+
+  static Database Deserialize(const std::vector<gatt::StoredAttribute>& nv_attr,
+                              bool* success);
+
+  friend class DatabaseBuilder;
+
+ private:
+  std::list<Service> services;
+};
+
+/* Find a service that should contain handle. Helper method for internal use
+ * inside gatt namespace.*/
+Service* FindService(std::list<Service>& services, uint16_t handle);
+
+}  // namespace gatt
diff --git a/bta/gatt/database_builder.cc b/bta/gatt/database_builder.cc
new file mode 100644
index 0000000..ed065ab
--- /dev/null
+++ b/bta/gatt/database_builder.cc
@@ -0,0 +1,190 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "database_builder.h"
+
+#include "bt_trace.h"
+
+#include <base/logging.h>
+#include <algorithm>
+
+using bluetooth::Uuid;
+
+namespace gatt {
+
+void DatabaseBuilder::AddService(uint16_t handle, uint16_t end_handle,
+                                 const Uuid& uuid, bool is_primary) {
+  // general case optimization - we add services in order
+  if (database.services.empty() ||
+      database.services.back().end_handle < handle) {
+    database.services.emplace_back(Service{.handle = handle,
+                                           .end_handle = end_handle,
+                                           .is_primary = is_primary,
+                                           .uuid = uuid});
+  } else {
+    auto& vec = database.services;
+
+    // Find first service whose start handle is bigger than new service handle
+    auto it = std::lower_bound(
+        vec.begin(), vec.end(), handle,
+        [](Service s, uint16_t handle) { return s.end_handle < handle; });
+
+    // Insert new service just before it
+    vec.emplace(it, Service{.handle = handle,
+                            .end_handle = end_handle,
+                            .is_primary = is_primary,
+                            .uuid = uuid});
+  }
+
+  services_to_discover.insert({handle, end_handle});
+}
+
+void DatabaseBuilder::AddIncludedService(uint16_t handle, const Uuid& uuid,
+                                         uint16_t start_handle,
+                                         uint16_t end_handle) {
+  Service* service = FindService(database.services, handle);
+  if (!service) {
+    LOG(ERROR) << "Illegal action to add to non-existing service!";
+    return;
+  }
+
+  /* We discover all Primary Services first. If included service was not seen
+   * before, it must be a Secondary Service */
+  if (!FindService(database.services, start_handle)) {
+    AddService(start_handle, end_handle, uuid, false /* not primary */);
+  }
+
+  service->included_services.push_back(IncludedService{
+      .handle = handle,
+      .uuid = uuid,
+      .start_handle = start_handle,
+      .end_handle = end_handle,
+  });
+}
+
+void DatabaseBuilder::AddCharacteristic(uint16_t handle, uint16_t value_handle,
+                                        const Uuid& uuid, uint8_t properties) {
+  Service* service = FindService(database.services, handle);
+  if (!service) {
+    LOG(ERROR) << "Illegal action to add to non-existing service!";
+    return;
+  }
+
+  if (service->end_handle < value_handle)
+    LOG(WARNING) << "Remote device violates spec: value_handle="
+                 << loghex(value_handle) << " is after service end_handle="
+                 << loghex(service->end_handle);
+
+  service->characteristics.emplace_back(
+      Characteristic{.declaration_handle = handle,
+                     .value_handle = value_handle,
+                     .properties = properties,
+                     .uuid = uuid});
+  return;
+}
+
+void DatabaseBuilder::AddDescriptor(uint16_t handle, const Uuid& uuid) {
+  Service* service = FindService(database.services, handle);
+  if (!service) {
+    LOG(ERROR) << "Illegal action to add to non-existing service!";
+    return;
+  }
+
+  if (service->characteristics.empty()) {
+    LOG(ERROR) << __func__
+               << ": Illegal action to add to non-existing characteristic!";
+    return;
+  }
+
+  Characteristic* char_node = &service->characteristics.front();
+  for (auto it = service->characteristics.begin();
+       it != service->characteristics.end(); it++) {
+    if (it->declaration_handle > handle) break;
+    char_node = &(*it);
+  }
+
+  char_node->descriptors.emplace_back(
+      gatt::Descriptor{.handle = handle, .uuid = uuid});
+}
+
+bool DatabaseBuilder::StartNextServiceExploration() {
+  while (!services_to_discover.empty()) {
+    auto handle_range = services_to_discover.begin();
+    pending_service = *handle_range;
+    services_to_discover.erase(handle_range);
+
+    // Empty service declaration, nothing to explore, skip to next.
+    if (pending_service.first == pending_service.second) continue;
+
+    pending_characteristic = HANDLE_MIN;
+    return true;
+  }
+  return false;
+}
+
+const std::pair<uint16_t, uint16_t>&
+DatabaseBuilder::CurrentlyExploredService() {
+  return pending_service;
+}
+
+std::pair<uint16_t, uint16_t> DatabaseBuilder::NextDescriptorRangeToExplore() {
+  Service* service = FindService(database.services, pending_service.first);
+  if (!service || service->characteristics.empty()) {
+    return {HANDLE_MAX, HANDLE_MAX};
+  }
+
+  for (auto it = service->characteristics.cbegin();
+       it != service->characteristics.cend(); it++) {
+    if (it->declaration_handle > pending_characteristic) {
+      auto next = std::next(it);
+
+      /* Characteristic Declaration is followed by Characteristic Value
+       * Declaration, first descriptor is after that, see BT Spect 5.0 Vol 3,
+       * Part G 3.3.2 and 3.3.3 */
+      uint16_t start = it->declaration_handle + 2;
+      uint16_t end;
+      if (next != service->characteristics.end())
+        end = next->declaration_handle - 1;
+      else
+        end = service->end_handle;
+
+      // No place for descriptor - skip to next characteristic
+      if (start > end) continue;
+
+      pending_characteristic = start;
+      return {start, end};
+    }
+  }
+
+  pending_characteristic = HANDLE_MAX;
+  return {HANDLE_MAX, HANDLE_MAX};
+}
+
+bool DatabaseBuilder::InProgress() const { return !database.services.empty(); }
+
+Database DatabaseBuilder::Build() {
+  Database tmp = database;
+  database.Clear();
+  return tmp;
+}
+
+void DatabaseBuilder::Clear() { database.Clear(); }
+
+std::string DatabaseBuilder::ToString() const { return database.ToString(); }
+
+}  // namespace gatt
diff --git a/bta/gatt/database_builder.h b/bta/gatt/database_builder.h
new file mode 100644
index 0000000..d2cc720
--- /dev/null
+++ b/bta/gatt/database_builder.h
@@ -0,0 +1,83 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include "gatt/database.h"
+
+#include <utility>
+
+namespace gatt {
+
+class DatabaseBuilder {
+ public:
+  constexpr static std::pair<uint16_t, uint16_t> EXPLORE_END =
+      std::make_pair(0xFFFF, 0xFFFF);
+
+  void AddService(uint16_t handle, uint16_t end_handle,
+                  const bluetooth::Uuid& uuid, bool is_primary);
+  void AddIncludedService(uint16_t handle, const bluetooth::Uuid& uuid,
+                          uint16_t start_handle, uint16_t end_handle);
+  void AddCharacteristic(uint16_t handle, uint16_t value_handle,
+                         const bluetooth::Uuid& uuid, uint8_t properties);
+  void AddDescriptor(uint16_t handle, const bluetooth::Uuid& uuid);
+
+  /* Returns true if next service exploration started, false if there are no
+   * more services to explore. */
+  bool StartNextServiceExploration();
+
+  /* Return pair with start and end handle of the currently explored service.
+   */
+  const std::pair<uint16_t, uint16_t>& CurrentlyExploredService();
+
+  /* Return pair with start and end handle of the descriptor range to discover,
+   * or DatabaseBuilder::EXPLORE_END if no more descriptors left.
+   */
+  std::pair<uint16_t, uint16_t> NextDescriptorRangeToExplore();
+
+  /* Returns true, if GATT discovery is in progress, false if discovery was not
+   * started, or is already finished.
+   */
+  // TODO(jpawlowski): in the future, we might create this object only for the
+  // time of discovery, in such case InProgress won't be needed, because object
+  // existence will mean discovery is pending
+  bool InProgress() const;
+
+  /* Call this method at end of GATT discovery, to obtain object representing
+   * the database of remote device */
+  Database Build();
+
+  void Clear();
+
+  /* Return text representation of internal state for debugging purposes */
+  std::string ToString() const;
+
+ private:
+  Database database;
+  /* Start and end handle of service that is currently being discovered on the
+   * remote device */
+  std::pair<uint16_t, uint16_t> pending_service;
+  /* Characteristic inside pending_service that is currently being explored */
+  uint16_t pending_characteristic;
+
+  /* sorted, unique set of start_handle, end_handle pair of all services that
+   * have not yet been discovered */
+  std::set<std::pair<uint16_t, uint16_t>> services_to_discover;
+};
+
+}  // namespace gatt
diff --git a/bta/hearing_aid/hearing_aid.cc b/bta/hearing_aid/hearing_aid.cc
index 3643184..fb7cab7 100644
--- a/bta/hearing_aid/hearing_aid.cc
+++ b/bta/hearing_aid/hearing_aid.cc
@@ -44,24 +44,22 @@
 constexpr uint16_t CONNECTION_INTERVAL_10MS_PARAM = 0x0008;
 constexpr uint16_t CONNECTION_INTERVAL_20MS_PARAM = 0x0010;
 
-void btif_storage_add_hearing_aid(const RawAddress& address, uint16_t psm,
-                                  uint8_t capabilities, uint16_t codecs,
-                                  uint16_t audio_control_point_handle,
-                                  uint16_t volume_handle, uint64_t hiSyncId,
-                                  uint16_t render_delay,
-                                  uint16_t preparation_delay);
+void btif_storage_add_hearing_aid(const HearingDevice& dev_info);
+bool btif_storage_get_hearing_aid_prop(
+    const RawAddress& address, uint8_t* capabilities, uint64_t* hi_sync_id,
+    uint16_t* render_delay, uint16_t* preparation_delay, uint16_t* codecs);
 
 constexpr uint8_t CODEC_G722_16KHZ = 0x01;
 constexpr uint8_t CODEC_G722_24KHZ = 0x02;
 
-// Masks for checking capability support
-constexpr uint8_t CAPABILITY_SIDE = 0x01;
-constexpr uint8_t CAPABILITY_BINAURAL = 0x02;
-constexpr uint8_t CAPABILITY_RESERVED = 0xFC;
-
 // audio control point opcodes
 constexpr uint8_t CONTROL_POINT_OP_START = 0x01;
 constexpr uint8_t CONTROL_POINT_OP_STOP = 0x02;
+constexpr uint8_t CONTROL_POINT_OP_STATE_CHANGE = 0x03;
+
+constexpr uint8_t STATE_CHANGE_OTHER_SIDE_DISCONNECTED = 0x00;
+constexpr uint8_t STATE_CHANGE_OTHER_SIDE_CONNECTED = 0x01;
+constexpr uint8_t STATE_CHANGE_CONN_UPDATE = 0x02;
 
 // used to mark current_volume as not yet known, or possibly old
 constexpr int8_t VOLUME_UNKNOWN = 127;
@@ -70,6 +68,17 @@
 // audio type
 constexpr uint8_t AUDIOTYPE_UNKNOWN = 0x00;
 
+// Status of the other side Hearing Aids device
+constexpr uint8_t OTHER_SIDE_NOT_STREAMING = 0x00;
+constexpr uint8_t OTHER_SIDE_IS_STREAMING = 0x01;
+
+// This ADD_RENDER_DELAY_INTERVALS is the number of connection intervals when
+// the audio data packet is send by Audio Engine to when the Hearing Aids device
+// received it from the air. We assumed that there is 2 data buffer queued from
+// audio subsystem to bluetooth chip. Then the estimated OTA delay is two
+// connnection intervals.
+constexpr uint16_t ADD_RENDER_DELAY_INTERVALS = 4;
+
 namespace {
 
 // clang-format off
@@ -84,6 +93,7 @@
 void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data);
 void encryption_callback(const RawAddress*, tGATT_TRANSPORT, void*,
                          tBTM_STATUS);
+void read_rssi_cb(void* p_void);
 
 inline BT_HDR* malloc_l2cap_buf(uint16_t len) {
   BT_HDR* msg = (BT_HDR*)osi_malloc(BT_HDR_SIZE + L2CAP_MIN_OFFSET +
@@ -97,116 +107,10 @@
   return (uint8_t*)(msg) + BT_HDR_SIZE + L2CAP_MIN_OFFSET;
 }
 
-struct AudioStats {
-  size_t packet_flush_count;
-  size_t packet_send_count;
-  size_t frame_flush_count;
-  size_t frame_send_count;
-
-  AudioStats() { Reset(); }
-
-  void Reset() {
-    packet_flush_count = 0;
-    packet_send_count = 0;
-    frame_flush_count = 0;
-    frame_send_count = 0;
-  }
-};
-
 class HearingAidImpl;
 HearingAidImpl* instance;
 HearingAidAudioReceiver* audioReceiver;
 
-/** Possible states for the Connection Update status */
-typedef enum {
-  NONE,      // Connection Update not pending or has completed
-  AWAITING,  // Waiting for start the Connection Update operation
-  STARTED    // Connection Update has started
-} connection_update_status_t;
-
-struct HearingDevice {
-  RawAddress address;
-  /* This is true only during first connection to profile, until we store the
-   * device */
-  bool first_connection;
-
-  /* we are making active attempt to connect to this device, 'direct connect'.
-   * This is true only during initial phase of first connection. */
-  bool connecting_actively;
-
-  /* For two hearing aids, you must update their parameters one after another,
-   * not simulteanously, to ensure start of connection events for both devices
-   * are far from each other. This status tracks whether this device is waiting
-   * for update of parameters, that should happen after "LE Connection Update
-   * Complete" event
-   */
-  connection_update_status_t connection_update_status;
-  uint16_t requested_connection_interval;
-
-  /* if true, we are connected, L2CAP socket is open, we can stream audio.
-     However, the actual audio stream also depends on whether the
-     Audio Service has resumed.
-   */
-  bool accepting_audio;
-
-  uint16_t conn_id;
-  uint16_t gap_handle;
-  uint16_t audio_control_point_handle;
-  uint16_t volume_handle;
-  uint16_t psm;
-
-  uint8_t capabilities;
-  uint64_t hi_sync_id;
-  uint16_t render_delay;
-  uint16_t preparation_delay;
-  uint16_t codecs;
-
-  AudioStats audio_stats;
-  /* Keep tracks of whether the "Start Cmd" has been send to this device. When
-     the "Stop Cmd" is send or when this device disconnects, then this flag is
-     cleared. Please note that the "Start Cmd" is not send during device
-     connection in the case when the audio is suspended. */
-  bool playback_started;
-
-  HearingDevice(const RawAddress& address, uint16_t psm, uint8_t capabilities,
-                uint16_t codecs, uint16_t audio_control_point_handle,
-                uint16_t volume_handle, uint64_t hiSyncId,
-                uint16_t render_delay, uint16_t preparation_delay)
-      : address(address),
-        first_connection(false),
-        connecting_actively(false),
-        connection_update_status(NONE),
-        accepting_audio(false),
-        conn_id(0),
-        gap_handle(0),
-        audio_control_point_handle(audio_control_point_handle),
-        volume_handle(volume_handle),
-        psm(psm),
-        capabilities(capabilities),
-        hi_sync_id(hiSyncId),
-        render_delay(render_delay),
-        preparation_delay(preparation_delay),
-        codecs(codecs),
-        playback_started(false) {}
-
-  HearingDevice(const RawAddress& address, bool first_connection)
-      : address(address),
-        first_connection(first_connection),
-        connecting_actively(first_connection),
-        connection_update_status(NONE),
-        accepting_audio(false),
-        conn_id(0),
-        gap_handle(0),
-        psm(0),
-        playback_started(false) {}
-
-  HearingDevice() { HearingDevice(RawAddress::kEmpty, false); }
-
-  /* return true if this device represents left Hearing Aid. Returned value is
-   * valid only after capabilities are discovered */
-  bool isLeft() const { return !(capabilities & CAPABILITY_SIDE); }
-};
-
 class HearingDevices {
  public:
   void Add(HearingDevice device) {
@@ -262,18 +166,70 @@
     return false;
   }
 
+  void StartRssiLog() {
+    int read_rssi_start_interval_count = 0;
+
+    for (auto& d : devices) {
+      VLOG(1) << __func__ << ": device=" << d.address << ", read_rssi_count=" << d.read_rssi_count;
+
+      // Reset the count
+      if (d.read_rssi_count <= 0) {
+        d.read_rssi_count = READ_RSSI_NUM_TRIES;
+        d.num_intervals_since_last_rssi_read = read_rssi_start_interval_count;
+
+        // Spaced apart the Read RSSI commands to the BT controller.
+        read_rssi_start_interval_count += PERIOD_TO_READ_RSSI_IN_INTERVALS / 2;
+        read_rssi_start_interval_count %= PERIOD_TO_READ_RSSI_IN_INTERVALS;
+
+        std::deque<rssi_log>& rssi_logs = d.audio_stats.rssi_history;
+        if (rssi_logs.size() >= MAX_RSSI_HISTORY) {
+          rssi_logs.pop_front();
+        }
+        rssi_logs.emplace_back();
+      }
+    }
+  }
+
   size_t size() { return (devices.size()); }
 
   std::vector<HearingDevice> devices;
 };
 
+static void write_rpt_ctl_cfg_cb(uint16_t conn_id, tGATT_STATUS status,
+                                 uint16_t handle, void* data) {
+  if (status != GATT_SUCCESS) {
+    LOG(ERROR) << __func__ << ": handle=" << handle << ", conn_id=" << conn_id
+               << ", status=" << loghex(status);
+  }
+}
+
 g722_encode_state_t* encoder_state_left = nullptr;
 g722_encode_state_t* encoder_state_right = nullptr;
 
+inline void encoder_state_init() {
+  if (encoder_state_left != nullptr) {
+    LOG(WARNING) << __func__ << ": encoder already initialized";
+    return;
+  }
+  encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
+  encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
+}
+
+inline void encoder_state_release() {
+  if (encoder_state_left != nullptr) {
+    g722_encode_release(encoder_state_left);
+    encoder_state_left = nullptr;
+    g722_encode_release(encoder_state_right);
+    encoder_state_right = nullptr;
+  }
+}
+
 class HearingAidImpl : public HearingAid {
  private:
   // Keep track of whether the Audio Service has resumed audio playback
   bool audio_running;
+  // For Testing: overwrite the MIN_CE_LEN during connection parameter updates
+  uint16_t overwrite_min_ce_len;
 
  public:
   virtual ~HearingAidImpl() = default;
@@ -281,6 +237,7 @@
   HearingAidImpl(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
                  Closure initCb)
       : audio_running(false),
+        overwrite_min_ce_len(0),
         gatt_if(0),
         seq_counter(0),
         current_volume(VOLUME_UNKNOWN),
@@ -298,6 +255,13 @@
     VLOG(2) << __func__
             << ", default_data_interval_ms=" << default_data_interval_ms;
 
+    overwrite_min_ce_len = (uint16_t)osi_property_get_int32(
+        "persist.bluetooth.hearingaidmincelen", 0);
+    if (overwrite_min_ce_len) {
+      LOG(INFO) << __func__
+                << ": Overwrites MIN_CE_LEN=" << overwrite_min_ce_len;
+    }
+
     BTA_GATTC_AppRegister(
         hearingaid_gattc_callback,
         base::Bind(
@@ -334,6 +298,12 @@
         connection_interval = CONNECTION_INTERVAL_10MS_PARAM;
     }
 
+    if (overwrite_min_ce_len != 0) {
+      VLOG(2) << __func__ << ": min_ce_len=" << min_ce_len
+              << " is overwritten to " << overwrite_min_ce_len;
+      min_ce_len = overwrite_min_ce_len;
+    }
+
     L2CA_UpdateBleConnParams(address, connection_interval, connection_interval,
                              0x000A, 0x0064 /*1s*/, min_ce_len, min_ce_len);
     return connection_interval;
@@ -349,37 +319,26 @@
     VLOG(2) << __func__ << " address: " << address;
     hearingDevices.Add(HearingDevice(address, true));
     BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
-    BTA_DmBleStartAutoConn();
   }
 
-  void RemoveFromWhiteList(const RawAddress& address) override {
-    VLOG(2) << __func__ << " address: " << address;
-    BTA_GATTC_CancelOpen(gatt_if, address, false);
-  }
-
-  void AddFromStorage(const RawAddress& address, uint16_t psm,
-                      uint8_t capabilities, uint16_t codecs,
-                      uint16_t audio_control_point_handle,
-                      uint16_t volume_handle, uint64_t hiSyncId,
-                      uint16_t render_delay, uint16_t preparation_delay,
-                      uint16_t is_white_listed) {
-    DVLOG(2) << __func__ << " " << address << ", hiSyncId=" << loghex(hiSyncId)
+  void AddFromStorage(const HearingDevice& dev_info, uint16_t is_white_listed) {
+    DVLOG(2) << __func__ << " " << dev_info.address
+             << ", hiSyncId=" << loghex(dev_info.hi_sync_id)
              << ", isWhiteListed=" << is_white_listed;
     if (is_white_listed) {
-      hearingDevices.Add(HearingDevice(
-          address, psm, capabilities, codecs, audio_control_point_handle,
-          volume_handle, hiSyncId, render_delay, preparation_delay));
+      hearingDevices.Add(dev_info);
 
       // TODO: we should increase the scanning window for few seconds, to get
       // faster initial connection, same after hearing aid disconnects, i.e.
       // BTM_BleSetConnScanParams(2048, 1024);
 
       /* add device into BG connection to accept remote initiated connection */
-      BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
-      BTA_DmBleStartAutoConn();
+      BTA_GATTC_Open(gatt_if, dev_info.address, false, GATT_TRANSPORT_LE,
+                     false);
     }
 
-    callbacks->OnDeviceAvailable(capabilities, hiSyncId, address);
+    callbacks->OnDeviceAvailable(dev_info.capabilities, dev_info.hi_sync_id,
+                                 dev_info.address);
   }
 
   int GetDeviceCount() { return (hearingDevices.size()); }
@@ -391,7 +350,11 @@
 
     HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
     if (!hearingDevice) {
-      DVLOG(2) << "Skipping unknown device, address=" << address;
+      /* When Hearing Aid is quickly disabled and enabled in settings, this case
+       * might happen */
+      LOG(WARNING) << "Closing connection to non hearing-aid device, address="
+                   << address;
+      BTA_GATTC_Close(conn_id);
       return;
     }
 
@@ -471,31 +434,72 @@
     }
 
     if (p_data) {
-      if ((p_data->conn_update.status == 0) &&
-          (hearingDevice->requested_connection_interval !=
-           p_data->conn_update.interval)) {
-        LOG(WARNING) << __func__ << ": Ignored. Different connection interval="
-                     << p_data->conn_update.interval << ", expected="
-                     << hearingDevice->requested_connection_interval
-                     << ", conn_id=" << conn_id;
-        return;
-      }
-      LOG(INFO) << __func__ << ": interval=" << p_data->conn_update.interval
-                << ": status=" << loghex(p_data->conn_update.status)
-                << ", conn_id=" << conn_id;
-    }
+      if (p_data->conn_update.status == 0) {
+        bool same_conn_interval =
+            (hearingDevice->requested_connection_interval ==
+             p_data->conn_update.interval);
 
-    if (hearingDevice->connection_update_status != STARTED) {
-      // TODO: We may get extra connection updates during service discovery and
-      // these updates are not accounted for.
-      LOG(INFO) << __func__
-                << ": Unexpected connection update complete. Expecting "
-                   "state=STARTED but current="
-                << hearingDevice->connection_update_status
-                << ", conn_id=" << conn_id
-                << ", device=" << hearingDevice->address;
+        switch (hearingDevice->connection_update_status) {
+          case COMPLETED:
+            if (!same_conn_interval) {
+              LOG(WARNING) << __func__
+                           << ": Unexpected change. Redo. connection interval="
+                           << p_data->conn_update.interval << ", expected="
+                           << hearingDevice->requested_connection_interval
+                           << ", conn_id=" << conn_id
+                           << ", connection_update_status="
+                           << hearingDevice->connection_update_status;
+              // Redo this connection interval change.
+              hearingDevice->connection_update_status = AWAITING;
+            }
+            break;
+          case STARTED:
+            if (same_conn_interval) {
+              LOG(INFO) << __func__
+                        << ": Connection update completed. conn_id=" << conn_id
+                        << ", device=" << hearingDevice->address;
+              hearingDevice->connection_update_status = COMPLETED;
+            } else {
+              LOG(WARNING) << __func__
+                           << ": Ignored. Different connection interval="
+                           << p_data->conn_update.interval << ", expected="
+                           << hearingDevice->requested_connection_interval
+                           << ", conn_id=" << conn_id
+                           << ", connection_update_status="
+                           << hearingDevice->connection_update_status;
+              // Wait for the right Connection Update Completion.
+              return;
+            }
+            break;
+          case AWAITING:
+          case NONE:
+            break;
+        }
+
+        // Inform this side and other side device (if any) of Connection
+        // Updates.
+        std::vector<uint8_t> conn_update(
+            {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_CONN_UPDATE,
+             (uint8_t)p_data->conn_update.interval});
+        send_state_change_to_other_side(hearingDevice, conn_update);
+        send_state_change(hearingDevice, conn_update);
+      } else {
+        LOG(INFO) << __func__
+                  << ": error status=" << loghex(p_data->conn_update.status)
+                  << ", conn_id=" << conn_id
+                  << ", device=" << hearingDevice->address
+                  << ", connection_update_status="
+                  << hearingDevice->connection_update_status;
+
+        if (hearingDevice->connection_update_status == STARTED) {
+          // Redo this connection interval change.
+          LOG(ERROR) << __func__ << ": Redo Connection Interval change";
+          hearingDevice->connection_update_status = AWAITING;
+        }
+      }
+    } else {
+      hearingDevice->connection_update_status = NONE;
     }
-    hearingDevice->connection_update_status = NONE;
 
     for (auto& device : hearingDevices.devices) {
       if (device.conn_id && (device.connection_update_status == AWAITING)) {
@@ -507,6 +511,34 @@
     }
   }
 
+  // Completion Callback for the RSSI read operation.
+  void OnReadRssiComplete(const RawAddress& address, int8_t rssi_value) {
+    HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+    if (!hearingDevice) {
+      LOG(INFO) << "Skipping unknown device" << address;
+      return;
+    }
+
+    VLOG(1) << __func__ << ": device=" << address << ", rssi=" << (int)rssi_value;
+
+    if (hearingDevice->read_rssi_count <= 0) {
+      LOG(ERROR) << __func__ << ": device=" << address
+                 << ", invalid read_rssi_count=" << hearingDevice->read_rssi_count;
+      return;
+    }
+
+    rssi_log& last_log_set = hearingDevice->audio_stats.rssi_history.back();
+
+    if (hearingDevice->read_rssi_count == READ_RSSI_NUM_TRIES) {
+      // Store the timestamp only for the first one after packet flush
+      clock_gettime(CLOCK_REALTIME, &last_log_set.timestamp);
+      LOG(INFO) << __func__ << ": store time. device=" << address << ", rssi=" << (int)rssi_value;
+    }
+
+    last_log_set.rssi.emplace_back(rssi_value);
+    hearingDevice->read_rssi_count--;
+  }
+
   void OnEncryptionComplete(const RawAddress& address, bool success) {
     HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
     if (!hearingDevice) {
@@ -525,13 +557,43 @@
 
     DVLOG(2) << __func__ << " " << address;
 
-    if (!hearingDevice->first_connection) {
-      // Use cached data, jump to connecting socket
-      ConnectSocket(hearingDevice);
+    if (hearingDevice->audio_control_point_handle &&
+        hearingDevice->audio_status_handle &&
+        hearingDevice->audio_status_ccc_handle &&
+        hearingDevice->volume_handle && hearingDevice->read_psm_handle) {
+      // Use cached data, jump to read PSM
+      ReadPSM(hearingDevice);
+    } else {
+      hearingDevice->first_connection = true;
+      BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
+    }
+  }
+
+  void OnServiceChangeEvent(const RawAddress& address) {
+    HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+    if (!hearingDevice) {
+      VLOG(2) << "Skipping unknown device" << address;
       return;
     }
+    LOG(INFO) << __func__ << ": address=" << address;
+    hearingDevice->first_connection = true;
+    hearingDevice->service_changed_rcvd = true;
+    BtaGattQueue::Clean(hearingDevice->conn_id);
+    if (hearingDevice->gap_handle) {
+      GAP_ConnClose(hearingDevice->gap_handle);
+      hearingDevice->gap_handle = 0;
+    }
+  }
 
-    BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
+  void OnServiceDiscDoneEvent(const RawAddress& address) {
+    HearingDevice* hearingDevice = hearingDevices.FindByAddress(address);
+    if (!hearingDevice) {
+      VLOG(2) << "Skipping unknown device" << address;
+      return;
+    }
+    if (hearingDevice->service_changed_rcvd) {
+      BTA_GATTC_ServiceSearchRequest(hearingDevice->conn_id, &HEARING_AID_UUID);
+    }
   }
 
   void OnServiceSearchComplete(uint16_t conn_id, tGATT_STATUS status) {
@@ -554,15 +616,19 @@
       return;
     }
 
-    const std::vector<tBTA_GATTC_SERVICE>* services =
-        BTA_GATTC_GetServices(conn_id);
+    const std::list<gatt::Service>* services = BTA_GATTC_GetServices(conn_id);
 
-    const tBTA_GATTC_SERVICE* service = nullptr;
-    for (const tBTA_GATTC_SERVICE& tmp : *services) {
-      if (tmp.uuid != HEARING_AID_UUID) continue;
-      LOG(INFO) << "Found Hearing Aid service, handle=" << loghex(tmp.handle);
-      service = &tmp;
-      break;
+    const gatt::Service* service = nullptr;
+    for (const gatt::Service& tmp : *services) {
+      if (tmp.uuid == Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER)) {
+        LOG(INFO) << "Found UUID_SERVCLASS_GATT_SERVER, handle="
+                  << loghex(tmp.handle);
+        const gatt::Service* service_changed_service = &tmp;
+        find_server_changed_ccc_handle(conn_id, service_changed_service);
+      } else if (tmp.uuid == HEARING_AID_UUID) {
+        LOG(INFO) << "Found Hearing Aid service, handle=" << loghex(tmp.handle);
+        service = &tmp;
+      }
     }
 
     if (!service) {
@@ -572,36 +638,92 @@
       return;
     }
 
-    uint16_t psm_handle = 0x0000;
-    for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+    for (const gatt::Characteristic& charac : service->characteristics) {
       if (charac.uuid == READ_ONLY_PROPERTIES_UUID) {
-        DVLOG(2) << "Reading read only properties "
-                 << loghex(charac.value_handle);
-        BtaGattQueue::ReadCharacteristic(
-            conn_id, charac.value_handle,
-            HearingAidImpl::OnReadOnlyPropertiesReadStatic, nullptr);
+        if (!btif_storage_get_hearing_aid_prop(
+                hearingDevice->address, &hearingDevice->capabilities,
+                &hearingDevice->hi_sync_id, &hearingDevice->render_delay,
+                &hearingDevice->preparation_delay, &hearingDevice->codecs)) {
+          VLOG(2) << "Reading read only properties "
+                  << loghex(charac.value_handle);
+          BtaGattQueue::ReadCharacteristic(
+              conn_id, charac.value_handle,
+              HearingAidImpl::OnReadOnlyPropertiesReadStatic, nullptr);
+        }
       } else if (charac.uuid == AUDIO_CONTROL_POINT_UUID) {
         hearingDevice->audio_control_point_handle = charac.value_handle;
         // store audio control point!
       } else if (charac.uuid == AUDIO_STATUS_UUID) {
-        DVLOG(2) << "Reading Audio status " << loghex(charac.value_handle);
-        BtaGattQueue::ReadCharacteristic(conn_id, charac.value_handle,
-                                         HearingAidImpl::OnAudioStatusStatic,
-                                         nullptr);
+        hearingDevice->audio_status_handle = charac.value_handle;
+
+        hearingDevice->audio_status_ccc_handle =
+            find_ccc_handle(conn_id, charac.value_handle);
+        if (!hearingDevice->audio_status_ccc_handle) {
+          LOG(ERROR) << __func__ << ": cannot find Audio Status CCC descriptor";
+          continue;
+        }
+
+        LOG(INFO) << __func__
+                  << ": audio_status_handle=" << loghex(charac.value_handle)
+                  << ", ccc=" << loghex(hearingDevice->audio_status_ccc_handle);
       } else if (charac.uuid == VOLUME_UUID) {
         hearingDevice->volume_handle = charac.value_handle;
       } else if (charac.uuid == LE_PSM_UUID) {
-        psm_handle = charac.value_handle;
+        hearingDevice->read_psm_handle = charac.value_handle;
       } else {
         LOG(WARNING) << "Unknown characteristic found:" << charac.uuid;
       }
     }
 
-    if (psm_handle) {
-      DVLOG(2) << "Reading PSM " << loghex(psm_handle);
-      BtaGattQueue::ReadCharacteristic(
-          conn_id, psm_handle, HearingAidImpl::OnPsmReadStatic, nullptr);
+    if (hearingDevice->service_changed_rcvd) {
+      hearingDevice->service_changed_rcvd = false;
     }
+
+    ReadPSM(hearingDevice);
+  }
+
+  void ReadPSM(HearingDevice* hearingDevice) {
+    if (hearingDevice->read_psm_handle) {
+      LOG(INFO) << "Reading PSM " << loghex(hearingDevice->read_psm_handle)
+                << ", device=" << hearingDevice->address;
+      BtaGattQueue::ReadCharacteristic(
+          hearingDevice->conn_id, hearingDevice->read_psm_handle,
+          HearingAidImpl::OnPsmReadStatic, nullptr);
+    }
+  }
+
+  void OnNotificationEvent(uint16_t conn_id, uint16_t handle, uint16_t len,
+                           uint8_t* value) {
+    HearingDevice* device = hearingDevices.FindByConnId(conn_id);
+    if (!device) {
+      LOG(INFO) << __func__
+                << ": Skipping unknown device, conn_id=" << loghex(conn_id);
+      return;
+    }
+
+    if (device->audio_status_handle != handle) {
+      LOG(INFO) << __func__ << ": Mismatched handle, "
+                << loghex(device->audio_status_handle)
+                << "!=" << loghex(handle);
+      return;
+    }
+
+    if (len < 1) {
+      LOG(ERROR) << __func__ << ": Data Length too small, len=" << len
+                 << ", expecting at least 1";
+      return;
+    }
+
+    if (value[0] != 0) {
+      LOG(INFO) << __func__
+                << ": Invalid returned status. data=" << loghex(value[0]);
+      return;
+    }
+
+    LOG(INFO) << __func__
+              << ": audio status success notification. command_acked="
+              << device->command_acked;
+    device->command_acked = true;
   }
 
   void OnReadOnlyPropertiesRead(uint16_t conn_id, tGATT_STATUS status,
@@ -712,7 +834,7 @@
 
   void OnAudioStatus(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
                      uint16_t len, uint8_t* value, void* data) {
-    DVLOG(2) << __func__ << " " << base::HexEncode(value, len);
+    LOG(INFO) << __func__ << " " << base::HexEncode(value, len);
   }
 
   void OnPsmRead(uint16_t conn_id, tGATT_STATUS status, uint16_t handle,
@@ -733,24 +855,25 @@
       return;
     }
 
-    uint16_t psm_val = *((uint16_t*)value);
-    hearingDevice->psm = psm_val;
-    VLOG(2) << "read psm:" << loghex(hearingDevice->psm);
+    uint16_t psm = *((uint16_t*)value);
+    VLOG(2) << "read psm:" << loghex(psm);
 
-    ConnectSocket(hearingDevice);
+    ConnectSocket(hearingDevice, psm);
   }
 
-  void ConnectSocket(HearingDevice* hearingDevice) {
+  void ConnectSocket(HearingDevice* hearingDevice, uint16_t psm) {
     tL2CAP_CFG_INFO cfg_info = tL2CAP_CFG_INFO{.mtu = 512};
 
+    SendEnableServiceChangedInd(hearingDevice);
+
     uint8_t service_id = hearingDevice->isLeft()
                              ? BTM_SEC_SERVICE_HEARING_AID_LEFT
                              : BTM_SEC_SERVICE_HEARING_AID_RIGHT;
     uint16_t gap_handle = GAP_ConnOpen(
-        "", service_id, false, &hearingDevice->address, hearingDevice->psm,
-        514 /* MPS */, &cfg_info, nullptr,
-        BTM_SEC_NONE /* TODO: request security ? */, L2CAP_FCR_LE_COC_MODE,
-        HearingAidImpl::GapCallbackStatic, BT_TRANSPORT_LE);
+        "", service_id, false, &hearingDevice->address, psm, 514 /* MPS */,
+        &cfg_info, nullptr, BTM_SEC_NONE /* TODO: request security ? */,
+        L2CAP_FCR_LE_COC_MODE, HearingAidImpl::GapCallbackStatic,
+        BT_TRANSPORT_LE);
     if (gap_handle == GAP_INVALID_HANDLE) {
       LOG(ERROR) << "UNABLE TO GET gap_handle";
       return;
@@ -793,25 +916,50 @@
     if (hearingDevice->first_connection) {
       /* add device into BG connection to accept remote initiated connection */
       BTA_GATTC_Open(gatt_if, address, false, GATT_TRANSPORT_LE, false);
-      BTA_DmBleStartAutoConn();
 
-      btif_storage_add_hearing_aid(
-          address, hearingDevice->psm, hearingDevice->capabilities,
-          hearingDevice->codecs, hearingDevice->audio_control_point_handle,
-          hearingDevice->volume_handle, hearingDevice->hi_sync_id,
-          hearingDevice->render_delay, hearingDevice->preparation_delay);
+      btif_storage_add_hearing_aid(*hearingDevice);
 
       hearingDevice->first_connection = false;
     }
 
+    LOG(INFO) << __func__ << ": audio_status_handle="
+              << loghex(hearingDevice->audio_status_handle)
+              << ", audio_status_ccc_handle="
+              << loghex(hearingDevice->audio_status_ccc_handle);
+
+    /* Register and enable the Audio Status Notification */
+    tGATT_STATUS register_status;
+    register_status = BTA_GATTC_RegisterForNotifications(
+        gatt_if, address, hearingDevice->audio_status_handle);
+    if (register_status != GATT_SUCCESS) {
+      LOG(ERROR) << __func__
+                 << ": BTA_GATTC_RegisterForNotifications failed, status="
+                 << loghex(register_status);
+      return;
+    }
+    std::vector<uint8_t> value(2);
+    uint8_t* ptr = value.data();
+    UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_NOTIFICATION);
+    BtaGattQueue::WriteDescriptor(
+        hearingDevice->conn_id, hearingDevice->audio_status_ccc_handle,
+        std::move(value), GATT_WRITE, write_rpt_ctl_cfg_cb, nullptr);
+
     ChooseCodec(*hearingDevice);
 
     SendStart(hearingDevice);
 
+    if (audio_running) {
+      // Inform the other side (if any) of this connection
+      std::vector<uint8_t> inform_conn_state(
+          {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_OTHER_SIDE_CONNECTED});
+      send_state_change_to_other_side(hearingDevice, inform_conn_state);
+    }
+
     hearingDevice->accepting_audio = true;
     LOG(INFO) << __func__ << ": address=" << address
               << ", hi_sync_id=" << loghex(hearingDevice->hi_sync_id)
-              << ", codec_in_use=" << loghex(codec_in_use);
+              << ", codec_in_use=" << loghex(codec_in_use)
+              << ", audio_running=" << audio_running;
 
     StartSendingAudio(*hearingDevice);
 
@@ -821,11 +969,10 @@
   }
 
   void StartSendingAudio(const HearingDevice& hearingDevice) {
-    VLOG(0) << __func__ << hearingDevice.address;
+    VLOG(0) << __func__ << ": device=" << hearingDevice.address;
 
     if (encoder_state_left == nullptr) {
-      encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
-      encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
+      encoder_state_init();
       seq_counter = 0;
 
       // use the best codec avaliable for this pair of devices.
@@ -847,7 +994,14 @@
       codec.bit_rate = 16;
       codec.data_interval_ms = default_data_interval_ms;
 
-      HearingAidAudioSource::Start(codec, audioReceiver);
+      uint16_t delay_report_ms = 0;
+      if (hearingDevice.render_delay != 0) {
+        delay_report_ms =
+            hearingDevice.render_delay +
+            (ADD_RENDER_DELAY_INTERVALS * default_data_interval_ms);
+      }
+
+      HearingAidAudioSource::Start(codec, audioReceiver, delay_report_ms);
     }
   }
 
@@ -870,6 +1024,7 @@
       } else {
         LOG(INFO) << __func__ << ": send Stop cmd, device=" << device.address;
         device.playback_started = false;
+        device.command_acked = false;
         BtaGattQueue::WriteCharacteristic(device.conn_id,
                                           device.audio_control_point_handle,
                                           stop, GATT_WRITE, nullptr, nullptr);
@@ -886,12 +1041,8 @@
     audio_running = true;
 
     // TODO: shall we also reset the encoder ?
-    if (encoder_state_left != nullptr) {
-      g722_encode_release(encoder_state_left);
-      g722_encode_release(encoder_state_right);
-      encoder_state_left = g722_encode_init(nullptr, 64000, G722_PACKED);
-      encoder_state_right = g722_encode_init(nullptr, 64000, G722_PACKED);
-    }
+    encoder_state_release();
+    encoder_state_init();
     seq_counter = 0;
 
     for (auto& device : hearingDevices.devices) {
@@ -900,9 +1051,36 @@
     }
   }
 
+  uint8_t GetOtherSideStreamStatus(HearingDevice* this_side_device) {
+    for (auto& device : hearingDevices.devices) {
+      if ((device.address == this_side_device->address) ||
+          (device.hi_sync_id != this_side_device->hi_sync_id)) {
+        continue;
+      }
+      if (audio_running && (device.conn_id != 0)) {
+        return (OTHER_SIDE_IS_STREAMING);
+      } else {
+        return (OTHER_SIDE_NOT_STREAMING);
+      }
+    }
+    return (OTHER_SIDE_NOT_STREAMING);
+  }
+
+  void SendEnableServiceChangedInd(HearingDevice* device) {
+    VLOG(2) << __func__ << " Enable " << device->address
+            << "service changed ind.";
+    std::vector<uint8_t> value(2);
+    uint8_t* ptr = value.data();
+    UINT16_TO_STREAM(ptr, GATT_CHAR_CLIENT_CONFIG_INDICTION);
+    BtaGattQueue::WriteDescriptor(
+        device->conn_id, device->service_changed_ccc_handle, std::move(value),
+        GATT_WRITE, nullptr, nullptr);
+  }
+
   void SendStart(HearingDevice* device) {
     std::vector<uint8_t> start({CONTROL_POINT_OP_START, codec_in_use,
-                                AUDIOTYPE_UNKNOWN, (uint8_t)current_volume});
+                                AUDIOTYPE_UNKNOWN, (uint8_t)current_volume,
+                                OTHER_SIDE_NOT_STREAMING});
 
     if (!audio_running) {
       if (!device->playback_started) {
@@ -924,10 +1102,13 @@
                  << ": Playback already started, skip send Start cmd, device="
                  << device->address;
     } else {
+      start[4] = GetOtherSideStreamStatus(device);
       LOG(INFO) << __func__ << ": send Start cmd, volume=" << loghex(start[3])
                 << ", audio type=" << loghex(start[2])
-                << ", device=" << device->address;
+                << ", device=" << device->address
+                << ", other side streaming=" << loghex(start[4]);
       device->playback_started = true;
+      device->command_acked = false;
       BtaGattQueue::WriteCharacteristic(device->conn_id,
                                         device->audio_control_point_handle,
                                         start, GATT_WRITE, nullptr, nullptr);
@@ -960,6 +1141,8 @@
 
     if (left == nullptr && right == nullptr) {
       HearingAidAudioSource::Stop();
+      audio_running = false;
+      encoder_state_release();
       current_volume = VOLUME_UNKNOWN;
       return;
     }
@@ -1016,9 +1199,11 @@
                 << " packets";
         left->audio_stats.packet_flush_count += packets_to_flush;
         left->audio_stats.frame_flush_count++;
+        hearingDevices.StartRssiLog();
       }
       // flush all packets stuck in queue
       L2CA_FlushChannel(cid, 0xffff);
+      check_and_do_rssi_read(left);
     }
 
     std::vector<uint8_t> encoded_data_right;
@@ -1038,9 +1223,11 @@
                 << " packets";
         right->audio_stats.packet_flush_count += packets_to_flush;
         right->audio_stats.frame_flush_count++;
+        hearingDevices.StartRssiLog();
       }
       // flush all packets stuck in queue
       L2CA_FlushChannel(cid, 0xffff);
+      check_and_do_rssi_read(right);
     }
 
     size_t encoded_data_size =
@@ -1066,9 +1253,11 @@
 
   void SendAudio(uint8_t* encoded_data, uint16_t packet_size,
                  HearingDevice* hearingAid) {
-    if (!hearingAid->playback_started) {
-      LOG(INFO) << __func__
-                << ": Playback not started, device=" << hearingAid->address;
+    if (!hearingAid->playback_started || !hearingAid->command_acked) {
+      VLOG(2) << __func__
+              << ": Playback stalled, device=" << hearingAid->address
+              << ", cmd send=" << hearingAid->playback_started
+              << ", cmd acked=" << hearingAid->command_acked;
       return;
     }
 
@@ -1112,6 +1301,7 @@
         hearingDevice->accepting_audio = false;
         hearingDevice->gap_handle = 0;
         hearingDevice->playback_started = false;
+        hearingDevice->command_acked = false;
         break;
       case GAP_EVT_CONN_DATA_AVAIL: {
         DVLOG(2) << "GAP_EVT_CONN_DATA_AVAIL";
@@ -1176,6 +1366,40 @@
     if (instance) instance->GapCallback(gap_handle, event, data);
   }
 
+  void DumpRssi(int fd, const HearingDevice& device) {
+    const struct AudioStats* stats = &device.audio_stats;
+
+    if (stats->rssi_history.size() <= 0) {
+      dprintf(fd, "  No RSSI history for %s:\n", device.address.ToString().c_str());
+      return;
+    }
+    dprintf(fd, "  RSSI history for %s:\n", device.address.ToString().c_str());
+
+    dprintf(fd, "    Time of RSSI    0.0  0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9\n");
+    for (auto& rssi_logs : stats->rssi_history) {
+      if (rssi_logs.rssi.size() <= 0) {
+        break;
+      }
+
+      char eventtime[20];
+      char temptime[20];
+      struct tm* tstamp = localtime(&rssi_logs.timestamp.tv_sec);
+      if (!strftime(temptime, sizeof(temptime), "%H:%M:%S", tstamp)) {
+        LOG(ERROR) << __func__ << ": strftime fails. tm_sec=" << tstamp->tm_sec << ", tm_min=" << tstamp->tm_min
+                   << ", tm_hour=" << tstamp->tm_hour;
+        strlcpy(temptime, "UNKNOWN TIME", sizeof(temptime));
+      }
+      snprintf(eventtime, sizeof(eventtime), "%s.%03ld", temptime, rssi_logs.timestamp.tv_nsec / 1000000);
+
+      dprintf(fd, "    %s: ", eventtime);
+
+      for (auto rssi_value : rssi_logs.rssi) {
+        dprintf(fd, " %04d", rssi_value);
+      }
+      dprintf(fd, "\n");
+    }
+  }
+
   void Dump(int fd) {
     std::stringstream stream;
     for (const auto& device : hearingDevices.devices) {
@@ -1193,6 +1417,8 @@
           << "\n    Frame counts (enqueued/flushed)                         : "
           << device.audio_stats.frame_send_count << " / "
           << device.audio_stats.frame_flush_count << std::endl;
+
+      DumpRssi(fd, device);
     }
     dprintf(fd, "%s", stream.str().c_str());
   }
@@ -1208,28 +1434,23 @@
     VLOG(2) << __func__ << ": " << address;
 
     bool connected = hearingDevice->accepting_audio;
-    hearingDevice->accepting_audio = false;
 
     LOG(INFO) << "GAP_EVT_CONN_CLOSED: " << hearingDevice->address
-              << ", playback_started=" << hearingDevice->playback_started;
-    hearingDevice->playback_started = false;
+              << ", playback_started=" << hearingDevice->playback_started
+              << ", accepting_audio=" << hearingDevice->accepting_audio;
 
     if (hearingDevice->connecting_actively) {
       // cancel pending direct connect
       BTA_GATTC_CancelOpen(gatt_if, address, true);
     }
 
-    if (hearingDevice->conn_id) {
-      BTA_GATTC_Close(hearingDevice->conn_id);
-    }
+    // Removes all registrations for connection.
+    BTA_GATTC_CancelOpen(0, address, false);
 
-    if (hearingDevice->gap_handle) {
-      GAP_ConnClose(hearingDevice->gap_handle);
-      hearingDevice->gap_handle = 0;
-    }
-
-    // cancel autoconnect
-    BTA_GATTC_CancelOpen(gatt_if, address, false);
+    // Inform the other side (if any) of this disconnection
+    std::vector<uint8_t> inform_disconn_state(
+        {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_OTHER_SIDE_DISCONNECTED});
+    send_state_change_to_other_side(hearingDevice, inform_disconn_state);
 
     DoDisconnectCleanUp(hearingDevice);
 
@@ -1244,9 +1465,17 @@
                           tBTA_GATT_REASON reason) {
     HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
     if (!hearingDevice) {
-      VLOG(2) << "Skipping unknown device disconnect, conn_id=" << conn_id;
+      VLOG(2) << "Skipping unknown device disconnect, conn_id="
+              << loghex(conn_id);
       return;
     }
+    VLOG(2) << __func__ << ": conn_id=" << loghex(conn_id)
+            << ", reason=" << loghex(reason) << ", remote_bda=" << remote_bda;
+
+    // Inform the other side (if any) of this disconnection
+    std::vector<uint8_t> inform_disconn_state(
+        {CONTROL_POINT_OP_STATE_CHANGE, STATE_CHANGE_OTHER_SIDE_DISCONNECTED});
+    send_state_change_to_other_side(hearingDevice, inform_disconn_state);
 
     DoDisconnectCleanUp(hearingDevice);
 
@@ -1254,7 +1483,7 @@
   }
 
   void DoDisconnectCleanUp(HearingDevice* hearingDevice) {
-    if (hearingDevice->connection_update_status != NONE) {
+    if (hearingDevice->connection_update_status != COMPLETED) {
       LOG(INFO) << __func__ << ": connection update not completed. Current="
                 << hearingDevice->connection_update_status
                 << ", device=" << hearingDevice->address;
@@ -1262,16 +1491,25 @@
       if (hearingDevice->connection_update_status == STARTED) {
         OnConnectionUpdateComplete(hearingDevice->conn_id, NULL);
       }
-      hearingDevice->connection_update_status = NONE;
+    }
+    hearingDevice->connection_update_status = NONE;
+
+    if (hearingDevice->conn_id) {
+      BtaGattQueue::Clean(hearingDevice->conn_id);
+      BTA_GATTC_Close(hearingDevice->conn_id);
+      hearingDevice->conn_id = 0;
     }
 
-    BtaGattQueue::Clean(hearingDevice->conn_id);
+    if (hearingDevice->gap_handle) {
+      GAP_ConnClose(hearingDevice->gap_handle);
+      hearingDevice->gap_handle = 0;
+    }
 
     hearingDevice->accepting_audio = false;
-    hearingDevice->conn_id = 0;
     LOG(INFO) << __func__ << ": device=" << hearingDevice->address
               << ", playback_started=" << hearingDevice->playback_started;
     hearingDevice->playback_started = false;
+    hearingDevice->command_acked = false;
   }
 
   void SetVolume(int8_t volume) override {
@@ -1290,14 +1528,12 @@
   void CleanUp() {
     BTA_GATTC_AppDeregister(gatt_if);
     for (HearingDevice& device : hearingDevices.devices) {
-      if (!device.gap_handle) continue;
-
-      GAP_ConnClose(device.gap_handle);
-      device.gap_handle = 0;
+      DoDisconnectCleanUp(&device);
     }
 
     hearingDevices.devices.clear();
-    HearingAidAudioSource::Stop();
+
+    encoder_state_release();
   }
 
  private:
@@ -1313,8 +1549,99 @@
   uint16_t default_data_interval_ms;
 
   HearingDevices hearingDevices;
+
+  void find_server_changed_ccc_handle(uint16_t conn_id,
+                                      const gatt::Service* service) {
+    HearingDevice* hearingDevice = hearingDevices.FindByConnId(conn_id);
+    if (!hearingDevice) {
+      DVLOG(2) << "Skipping unknown device, conn_id=" << loghex(conn_id);
+      return;
+    }
+    for (const gatt::Characteristic& charac : service->characteristics) {
+      if (charac.uuid == Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD)) {
+        hearingDevice->service_changed_ccc_handle =
+            find_ccc_handle(conn_id, charac.value_handle);
+        if (!hearingDevice->service_changed_ccc_handle) {
+          LOG(ERROR) << __func__
+                     << ": cannot find service changed CCC descriptor";
+          continue;
+        }
+        LOG(INFO) << __func__ << " service_changed_ccc="
+                  << loghex(hearingDevice->service_changed_ccc_handle);
+        break;
+      }
+    }
+  }
+
+  // Find the handle for the client characteristics configuration of a given
+  // characteristics
+  uint16_t find_ccc_handle(uint16_t conn_id, uint16_t char_handle) {
+    const gatt::Characteristic* p_char =
+        BTA_GATTC_GetCharacteristic(conn_id, char_handle);
+
+    if (!p_char) {
+      LOG(WARNING) << __func__ << ": No such characteristic: " << char_handle;
+      return 0;
+    }
+
+    for (const gatt::Descriptor& desc : p_char->descriptors) {
+      if (desc.uuid == Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG))
+        return desc.handle;
+    }
+
+    return 0;
+  }
+
+  void send_state_change(HearingDevice* device, std::vector<uint8_t> payload) {
+    if (device->conn_id != 0) {
+      if (device->service_changed_rcvd) {
+        LOG(INFO)
+            << __func__
+            << ": service discover is in progress, skip send State Change cmd.";
+        return;
+      }
+      // Send the data packet
+      LOG(INFO) << __func__ << ": Send State Change. device=" << device->address
+                << ", status=" << loghex(payload[1]);
+      BtaGattQueue::WriteCharacteristic(
+          device->conn_id, device->audio_control_point_handle, payload,
+          GATT_WRITE_NO_RSP, nullptr, nullptr);
+    }
+  }
+
+  void send_state_change_to_other_side(HearingDevice* this_side_device,
+                                       std::vector<uint8_t> payload) {
+    for (auto& device : hearingDevices.devices) {
+      if ((device.address == this_side_device->address) ||
+          (device.hi_sync_id != this_side_device->hi_sync_id)) {
+        continue;
+      }
+      send_state_change(&device, payload);
+    }
+  }
+
+  void check_and_do_rssi_read(HearingDevice* device) {
+    if (device->read_rssi_count > 0) {
+      device->num_intervals_since_last_rssi_read++;
+      if (device->num_intervals_since_last_rssi_read >= PERIOD_TO_READ_RSSI_IN_INTERVALS) {
+        device->num_intervals_since_last_rssi_read = 0;
+        VLOG(1) << __func__ << ": device=" << device->address;
+        BTM_ReadRSSI(device->address, read_rssi_cb);
+      }
+    }
+  }
 };
 
+void read_rssi_cb(void* p_void) {
+  tBTM_RSSI_RESULT* p_result = (tBTM_RSSI_RESULT*)p_void;
+
+  if (!p_result) return;
+
+  if ((instance) && (p_result->status == BTM_SUCCESS)) {
+    instance->OnReadRssiComplete(p_result->rem_bda, p_result->rssi);
+  }
+}
+
 void hearingaid_gattc_callback(tBTA_GATTC_EVT event, tBTA_GATTC* p_data) {
   VLOG(2) << __func__ << " event = " << +event;
 
@@ -1346,6 +1673,16 @@
       break;
 
     case BTA_GATTC_NOTIF_EVT:
+      if (!instance) return;
+      if (!p_data->notify.is_notify || p_data->notify.len > GATT_MAX_ATTR_LEN) {
+        LOG(ERROR) << __func__ << ": rejected BTA_GATTC_NOTIF_EVT. is_notify="
+                   << p_data->notify.is_notify
+                   << ", len=" << p_data->notify.len;
+        break;
+      }
+      instance->OnNotificationEvent(p_data->notify.conn_id,
+                                    p_data->notify.handle, p_data->notify.len,
+                                    p_data->notify.value);
       break;
 
     case BTA_GATTC_ENC_CMPL_CB_EVT:
@@ -1358,6 +1695,16 @@
       instance->OnConnectionUpdateComplete(p_data->conn_update.conn_id, p_data);
       break;
 
+    case BTA_GATTC_SRVC_CHG_EVT:
+      if (!instance) return;
+      instance->OnServiceChangeEvent(p_data->remote_bda);
+      break;
+
+    case BTA_GATTC_SRVC_DISC_DONE_EVT:
+      if (!instance) return;
+      instance->OnServiceDiscDoneEvent(p_data->remote_bda);
+      break;
+
     default:
       break;
   }
@@ -1402,27 +1749,20 @@
   HearingAidAudioSource::Initialize();
 }
 
-bool HearingAid::IsInitialized() { return instance; }
+bool HearingAid::IsHearingAidRunning() { return instance; }
 
 HearingAid* HearingAid::Get() {
   CHECK(instance);
   return instance;
 };
 
-void HearingAid::AddFromStorage(const RawAddress& address, uint16_t psm,
-                                uint8_t capabilities, uint16_t codecs,
-                                uint16_t audio_control_point_handle,
-                                uint16_t volume_handle, uint64_t hiSyncId,
-                                uint16_t render_delay,
-                                uint16_t preparation_delay,
+void HearingAid::AddFromStorage(const HearingDevice& dev_info,
                                 uint16_t is_white_listed) {
   if (!instance) {
     LOG(ERROR) << "Not initialized yet";
   }
 
-  instance->AddFromStorage(address, psm, capabilities, codecs,
-                           audio_control_point_handle, volume_handle, hiSyncId,
-                           render_delay, preparation_delay, is_white_listed);
+  instance->AddFromStorage(dev_info, is_white_listed);
 };
 
 int HearingAid::GetDeviceCount() {
@@ -1438,16 +1778,19 @@
   // Must stop audio source to make sure it doesn't call any of callbacks on our
   // soon to be  null instance
   HearingAidAudioSource::Stop();
-  HearingAidAudioSource::CleanUp();
 
-  instance->CleanUp();
   HearingAidImpl* ptr = instance;
   instance = nullptr;
+  HearingAidAudioSource::CleanUp();
+
+  ptr->CleanUp();
+
   delete ptr;
 };
 
 void HearingAid::DebugDump(int fd) {
-  dprintf(fd, "\nHearing Aid Manager:\n");
+  dprintf(fd, "Hearing Aid Manager:\n");
   if (instance) instance->Dump(fd);
   HearingAidAudioSource::DebugDump(fd);
-}
\ No newline at end of file
+  dprintf(fd, "\n");
+}
diff --git a/bta/hearing_aid/hearing_aid_audio_source.cc b/bta/hearing_aid/hearing_aid_audio_source.cc
index 48eaea3..3b92d41 100644
--- a/bta/hearing_aid/hearing_aid_audio_source.cc
+++ b/bta/hearing_aid/hearing_aid_audio_source.cc
@@ -16,15 +16,19 @@
  *
  ******************************************************************************/
 
+#include "audio_hal_interface/hearing_aid_software_encoding.h"
 #include "audio_hearing_aid_hw/include/audio_hearing_aid_hw.h"
-#include "bta_closure_api.h"
 #include "bta_hearing_aid_api.h"
-#include "osi/include/alarm.h"
+#include "btu.h"
+#include "osi/include/wakelock.h"
 #include "uipc.h"
 
 #include <base/files/file_util.h>
 #include <include/hardware/bt_av.h>
 
+#include "common/repeating_timer.h"
+#include "common/time_util.h"
+
 using base::FilePath;
 extern const char* audio_ha_hw_dump_ctrl_event(tHEARING_AID_CTRL_CMD event);
 
@@ -33,10 +37,9 @@
 int sample_rate = -1;
 int data_interval_ms = -1;
 int num_channels = 2;
-alarm_t* audio_timer = nullptr;
-
-HearingAidAudioReceiver* localAudioReceiver;
-std::unique_ptr<tUIPC_STATE> uipc_hearing_aid;
+bluetooth::common::RepeatingTimer audio_timer;
+HearingAidAudioReceiver* localAudioReceiver = nullptr;
+std::unique_ptr<tUIPC_STATE> uipc_hearing_aid = nullptr;
 
 struct AudioHalStats {
   size_t media_read_total_underflow_bytes;
@@ -54,26 +57,37 @@
 
 AudioHalStats stats;
 
-void send_audio_data(void*) {
+bool hearing_aid_on_resume_req(bool start_media_task);
+bool hearing_aid_on_suspend_req();
+
+void send_audio_data() {
   uint32_t bytes_per_tick =
       (num_channels * sample_rate * data_interval_ms * (bit_rate / 8)) / 1000;
 
   uint16_t event;
   uint8_t p_buf[bytes_per_tick];
 
-  uint32_t bytes_read = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO,
-                                  &event, p_buf, bytes_per_tick);
+  uint32_t bytes_read;
+  if (bluetooth::audio::hearing_aid::is_hal_2_0_enabled()) {
+    bytes_read = bluetooth::audio::hearing_aid::read(p_buf, bytes_per_tick);
+  } else {
+    bytes_read = UIPC_Read(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, &event,
+                           p_buf, bytes_per_tick);
+  }
 
   VLOG(2) << "bytes_read: " << bytes_read;
   if (bytes_read < bytes_per_tick) {
     stats.media_read_total_underflow_bytes += bytes_per_tick - bytes_read;
     stats.media_read_total_underflow_count++;
-    stats.media_read_last_underflow_us = time_get_os_boottime_us();
+    stats.media_read_last_underflow_us =
+        bluetooth::common::time_get_os_boottime_us();
   }
 
   std::vector<uint8_t> data(p_buf, p_buf + bytes_read);
 
-  localAudioReceiver->OnAudioDataReady(data);
+  if (localAudioReceiver != nullptr) {
+    localAudioReceiver->OnAudioDataReady(data);
+  }
 }
 
 void hearing_aid_send_ack(tHEARING_AID_CTRL_ACK status) {
@@ -82,10 +96,22 @@
   UIPC_Send(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
 }
 
+void start_audio_ticks() {
+  wakelock_acquire();
+  audio_timer.SchedulePeriodic(get_main_thread()->GetWeakPtr(), FROM_HERE, base::Bind(&send_audio_data),
+                               base::TimeDelta::FromMilliseconds(data_interval_ms));
+}
+
+void stop_audio_ticks() {
+  audio_timer.CancelAndWait();
+  wakelock_release();
+}
+
 void hearing_aid_data_cb(tUIPC_CH_ID, tUIPC_EVENT event) {
   DVLOG(2) << "Hearing Aid audio data event: " << event;
   switch (event) {
     case UIPC_OPEN_EVT:
+      LOG(INFO) << __func__ << ": UIPC_OPEN_EVT";
       /*
        * Read directly from media task from here on (keep callback for
        * connection events.
@@ -100,15 +126,12 @@
         LOG(FATAL) << " Unsupported data interval: " << data_interval_ms;
       }
 
-      audio_timer = alarm_new_periodic("hearing_aid_data_timer");
-      alarm_set_on_mloop(audio_timer, data_interval_ms, send_audio_data,
-                         nullptr);
+      start_audio_ticks();
       break;
     case UIPC_CLOSE_EVT:
+      LOG(INFO) << __func__ << ": UIPC_CLOSE_EVT";
       hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
-      if (audio_timer) {
-        alarm_cancel(audio_timer);
-      }
+      stop_audio_ticks();
       break;
     default:
       LOG(ERROR) << "Hearing Aid audio data event not recognized:" << event;
@@ -133,46 +156,38 @@
   LOG(INFO) << __func__ << " " << audio_ha_hw_dump_ctrl_event(cmd);
   //  a2dp_cmd_pending = cmd;
 
+  tHEARING_AID_CTRL_ACK ctrl_ack_status;
+
   switch (cmd) {
     case HEARING_AID_CTRL_CMD_CHECK_READY:
       hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
       break;
 
     case HEARING_AID_CTRL_CMD_START:
-      if (localAudioReceiver) {
-        // Call OnAudioResume and block till it returns.
-        std::promise<void> do_resume_promise;
-        std::future<void> do_resume_future = do_resume_promise.get_future();
-        do_in_bta_thread_once(
-            FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
-                                      base::Unretained(localAudioReceiver),
-                                      std::move(do_resume_promise)));
-        do_resume_future.wait();
-      }
-
+      ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
       // timer is restarted in UIPC_Open
-      UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
-                HEARING_AID_DATA_PATH);
-      hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+      if (!hearing_aid_on_resume_req(false)) {
+        ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
+      } else {
+        UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_AUDIO, hearing_aid_data_cb,
+                  HEARING_AID_DATA_PATH);
+      }
+      hearing_aid_send_ack(ctrl_ack_status);
       break;
 
     case HEARING_AID_CTRL_CMD_STOP:
+      if (!hearing_aid_on_suspend_req()) {
+        LOG(INFO) << __func__ << ":HEARING_AID_CTRL_CMD_STOP: hearing_aid_on_suspend_req() errs, but ignored.";
+      }
       hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
       break;
 
     case HEARING_AID_CTRL_CMD_SUSPEND:
-      if (audio_timer) alarm_cancel(audio_timer);
-      if (localAudioReceiver) {
-        // Call OnAudioSuspend and block till it returns.
-        std::promise<void> do_suspend_promise;
-        std::future<void> do_suspend_future = do_suspend_promise.get_future();
-        do_in_bta_thread_once(
-            FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
-                                      base::Unretained(localAudioReceiver),
-                                      std::move(do_suspend_promise)));
-        do_suspend_future.wait();
+      ctrl_ack_status = HEARING_AID_CTRL_ACK_SUCCESS;
+      if (!hearing_aid_on_suspend_req()) {
+        ctrl_ack_status = HEARING_AID_CTRL_ACK_FAILURE;
       }
-      hearing_aid_send_ack(HEARING_AID_CTRL_ACK_SUCCESS);
+      hearing_aid_send_ack(ctrl_ack_status);
       break;
 
     case HEARING_AID_CTRL_GET_OUTPUT_AUDIO_CONFIG: {
@@ -276,8 +291,11 @@
     case UIPC_OPEN_EVT:
       break;
     case UIPC_CLOSE_EVT:
-      UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
-                HEARING_AID_CTRL_PATH);
+      /* restart ctrl server unless we are shutting down */
+      if (HearingAid::IsHearingAidRunning()) {
+        UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
+                  HEARING_AID_CTRL_PATH);
+      }
       break;
     case UIPC_RX_DATA_READY_EVT:
       hearing_aid_recv_ctrl_data();
@@ -286,38 +304,122 @@
       LOG(ERROR) << "Hearing Aid audio ctrl unrecognized event: " << event;
   }
 }
+
+bool hearing_aid_on_resume_req(bool start_media_task) {
+  // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_START)
+  if (localAudioReceiver != nullptr) {
+    // Call OnAudioResume and block till it returns.
+    std::promise<void> do_resume_promise;
+    std::future<void> do_resume_future = do_resume_promise.get_future();
+    bt_status_t status = do_in_main_thread(
+        FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioResume,
+                                  base::Unretained(localAudioReceiver),
+                                  std::move(do_resume_promise)));
+    if (status == BT_STATUS_SUCCESS) {
+      do_resume_future.wait();
+    } else {
+      LOG(ERROR) << __func__
+                 << ": HEARING_AID_CTRL_CMD_START: do_in_main_thread err="
+                 << status;
+      return false;
+    }
+  } else {
+    LOG(ERROR) << __func__
+               << ": HEARING_AID_CTRL_CMD_START: audio receiver not started";
+    return false;
+  }
+
+  // hearing_aid_data_cb(UIPC_OPEN_EVT): start_media_task
+  if (start_media_task) {
+    if (data_interval_ms != HA_INTERVAL_10_MS &&
+        data_interval_ms != HA_INTERVAL_20_MS) {
+      LOG(FATAL) << " Unsupported data interval: " << data_interval_ms;
+      data_interval_ms = HA_INTERVAL_10_MS;
+    }
+    start_audio_ticks();
+  }
+  return true;
+}
+
+bool hearing_aid_on_suspend_req() {
+  // hearing_aid_recv_ctrl_data(HEARING_AID_CTRL_CMD_SUSPEND): stop_media_task
+  stop_audio_ticks();
+  if (localAudioReceiver != nullptr) {
+    // Call OnAudioSuspend and block till it returns.
+    std::promise<void> do_suspend_promise;
+    std::future<void> do_suspend_future = do_suspend_promise.get_future();
+    bt_status_t status = do_in_main_thread(
+        FROM_HERE, base::BindOnce(&HearingAidAudioReceiver::OnAudioSuspend,
+                                  base::Unretained(localAudioReceiver),
+                                  std::move(do_suspend_promise)));
+    if (status == BT_STATUS_SUCCESS) {
+      do_suspend_future.wait();
+      return true;
+    } else {
+      LOG(ERROR) << __func__
+                 << ": HEARING_AID_CTRL_CMD_SUSPEND: do_in_main_thread err="
+                 << status;
+    }
+  } else {
+    LOG(ERROR) << __func__
+               << ": HEARING_AID_CTRL_CMD_SUSPEND: audio receiver not started";
+  }
+  return false;
+}
 }  // namespace
 
 void HearingAidAudioSource::Start(const CodecConfiguration& codecConfiguration,
-                                  HearingAidAudioReceiver* audioReceiver) {
-  localAudioReceiver = audioReceiver;
-  VLOG(2) << "Hearing Aid UIPC Open";
+                                  HearingAidAudioReceiver* audioReceiver,
+                                  uint16_t remote_delay_ms) {
+  LOG(INFO) << __func__ << ": Hearing Aid Source Open";
 
   bit_rate = codecConfiguration.bit_rate;
   sample_rate = codecConfiguration.sample_rate;
   data_interval_ms = codecConfiguration.data_interval_ms;
 
   stats.Reset();
+
+  if (bluetooth::audio::hearing_aid::is_hal_2_0_enabled()) {
+    bluetooth::audio::hearing_aid::start_session();
+    bluetooth::audio::hearing_aid::set_remote_delay(remote_delay_ms);
+  }
+  localAudioReceiver = audioReceiver;
 }
 
 void HearingAidAudioSource::Stop() {
-  if (audio_timer) {
-    alarm_cancel(audio_timer);
+  LOG(INFO) << __func__ << ": Hearing Aid Source Close";
+
+  localAudioReceiver = nullptr;
+  if (bluetooth::audio::hearing_aid::is_hal_2_0_enabled()) {
+    bluetooth::audio::hearing_aid::end_session();
   }
+
+  stop_audio_ticks();
 }
 
 void HearingAidAudioSource::Initialize() {
-  uipc_hearing_aid = UIPC_Init();
-  UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb,
-            HEARING_AID_CTRL_PATH);
+  auto stream_cb = bluetooth::audio::hearing_aid::StreamCallbacks{
+      .on_resume_ = hearing_aid_on_resume_req,
+      .on_suspend_ = hearing_aid_on_suspend_req,
+  };
+  if (!bluetooth::audio::hearing_aid::init(stream_cb, get_main_thread())) {
+    LOG(WARNING) << __func__ << ": Using legacy HAL";
+    uipc_hearing_aid = UIPC_Init();
+    UIPC_Open(*uipc_hearing_aid, UIPC_CH_ID_AV_CTRL, hearing_aid_ctrl_cb, HEARING_AID_CTRL_PATH);
+  }
 }
 
 void HearingAidAudioSource::CleanUp() {
-  UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_ALL);
+  if (bluetooth::audio::hearing_aid::is_hal_2_0_enabled()) {
+    bluetooth::audio::hearing_aid::cleanup();
+  } else {
+    UIPC_Close(*uipc_hearing_aid, UIPC_CH_ID_ALL);
+    uipc_hearing_aid = nullptr;
+  }
 }
 
 void HearingAidAudioSource::DebugDump(int fd) {
-  uint64_t now_us = time_get_os_boottime_us();
+  uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
   std::stringstream stream;
   stream << "  Hearing Aid Audio HAL:"
          << "\n    Counts (underflow)                                      : "
diff --git a/bta/hf_client/bta_hf_client_act.cc b/bta/hf_client/bta_hf_client_act.cc
index 3e6c22d..e3f25f6 100644
--- a/bta/hf_client/bta_hf_client_act.cc
+++ b/bta/hf_client/bta_hf_client_act.cc
@@ -103,8 +103,8 @@
   }
 
   /* Check if RFCOMM has any incoming connection to avoid collision. */
-  RawAddress pending_bd_addr;
-  if (PORT_IsOpening(pending_bd_addr)) {
+  RawAddress pending_bd_addr = RawAddress::kEmpty;
+  if (PORT_IsOpening(&pending_bd_addr)) {
     /* Let the incoming connection goes through.                        */
     /* Issue collision for now.                                         */
     /* We will decide what to do when we find incoming connection later.*/
@@ -164,21 +164,17 @@
                      p_data->hdr.layer_specific);
     return;
   }
-
-  uint16_t lcid;
-  RawAddress dev_addr;
-  int status;
-
   /* set role */
   client_cb->role = BTA_HF_CLIENT_ACP;
 
   APPL_TRACE_DEBUG("%s: conn_handle %d", __func__, client_cb->conn_handle);
 
   /* get bd addr of peer */
-  if (PORT_SUCCESS != (status = PORT_CheckConnection(client_cb->conn_handle,
-                                                     dev_addr, &lcid))) {
-    APPL_TRACE_DEBUG("%s: error PORT_CheckConnection returned status %d",
-                     __func__, status);
+  uint16_t lcid = 0;
+  RawAddress dev_addr = RawAddress::kEmpty;
+  int status = PORT_CheckConnection(client_cb->conn_handle, &dev_addr, &lcid);
+  if (status != PORT_SUCCESS) {
+    LOG(ERROR) << __func__ << ": PORT_CheckConnection returned " << status;
   }
 
   /* Collision Handling */
diff --git a/bta/hf_client/bta_hf_client_main.cc b/bta/hf_client/bta_hf_client_main.cc
index 4f717ae..fac61c7 100644
--- a/bta/hf_client/bta_hf_client_main.cc
+++ b/bta/hf_client/bta_hf_client_main.cc
@@ -329,6 +329,8 @@
     client_cb->state = BTA_HF_CLIENT_OPENING_ST;
     tBTA_HF_CLIENT_DATA msg;
     msg.hdr.layer_specific = client_cb->handle;
+    msg.api_open.bd_addr = client_cb->peer_addr;
+    msg.api_open.sec_mask = client_cb->cli_sec_mask;
     bta_hf_client_start_open(&msg);
   }
 }
@@ -386,7 +388,7 @@
 
     /* reopen registered server */
     /* Collision may be detected before or after we close servers. */
-    // bta_hf_client_start_server();
+    bta_hf_client_start_server();
 
     /* Start timer to handle connection opening restart */
     alarm_set_on_mloop(client_cb->collision_timer,
@@ -749,19 +751,14 @@
     evt.bd_addr = client_cb->peer_addr;
     if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
       bta_hf_client_app_callback(BTA_HF_CLIENT_CLOSE_EVT, &evt);
+      APPL_TRACE_DEBUG("%s: marking CB handle %d to false", __func__, client_cb->handle);
+      client_cb->is_allocated = false;
     } else if (client_cb->state == BTA_HF_CLIENT_OPEN_ST) {
       evt.open.handle = client_cb->handle;
       bta_hf_client_app_callback(BTA_HF_CLIENT_OPEN_EVT, &evt);
     }
   }
 
-  /* if the next state is INIT then release the cb for future use */
-  if (client_cb->state == BTA_HF_CLIENT_INIT_ST) {
-    APPL_TRACE_DEBUG("%s: marking CB handle %d to false", __func__,
-                     client_cb->handle);
-    client_cb->is_allocated = false;
-  }
-
   VLOG(2) << __func__ << ": device " << client_cb->peer_addr
           << "state change: [" << bta_hf_client_state_str(in_state) << "] -> ["
           << bta_hf_client_state_str(client_cb->state) << "] after Event ["
diff --git a/bta/hf_client/bta_hf_client_rfc.cc b/bta/hf_client/bta_hf_client_rfc.cc
index e261c16..f3e0947 100644
--- a/bta/hf_client/bta_hf_client_rfc.cc
+++ b/bta/hf_client/bta_hf_client_rfc.cc
@@ -98,9 +98,12 @@
       APPL_TRACE_DEBUG("%s: allocating a new CB for incoming connection",
                        __func__);
       // Find the BDADDR of the peer device
-      RawAddress peer_addr;
-      uint16_t lcid;
-      PORT_CheckConnection(port_handle, peer_addr, &lcid);
+      RawAddress peer_addr = RawAddress::kEmpty;
+      uint16_t lcid = 0;
+      int status = PORT_CheckConnection(port_handle, &peer_addr, &lcid);
+      if (status != PORT_SUCCESS) {
+        LOG(ERROR) << __func__ << ": PORT_CheckConnection returned " << status;
+      }
 
       // Since we accepted a remote request we should allocate a handle first.
       uint16_t tmp_handle = -1;
diff --git a/bta/hf_client/bta_hf_client_sco.cc b/bta/hf_client/bta_hf_client_sco.cc
index e03de4f..50820bd 100644
--- a/bta/hf_client/bta_hf_client_sco.cc
+++ b/bta/hf_client/bta_hf_client_sco.cc
@@ -112,7 +112,7 @@
       resp = esco_parameters_for_codec(ESCO_CODEC_CVSD);
     } else {
       if (client_cb->negotiated_codec == BTA_AG_CODEC_MSBC) {
-        resp = esco_parameters_for_codec(ESCO_CODEC_MSBC_T1);
+        resp = esco_parameters_for_codec(ESCO_CODEC_MSBC_T2);
       } else {
         // default codec
         resp = esco_parameters_for_codec(ESCO_CODEC_CVSD);
diff --git a/bta/hh/bta_hh_act.cc b/bta/hh/bta_hh_act.cc
index a7bdc9c..f64fbf0 100644
--- a/bta/hh/bta_hh_act.cc
+++ b/bta/hh/bta_hh_act.cc
@@ -633,7 +633,7 @@
  *
  * Function         bta_hh_handsk_act
  *
- * Description      HID Host process a handshake acknoledgement.
+ * Description      HID Host process a handshake acknowledgement.
  *
  *
  * Returns          void
@@ -652,7 +652,7 @@
     /* GET_ transsaction, handshake indicate unsupported request */
     case BTA_HH_GET_PROTO_EVT:
       bta_hh.hs_data.rsp_data.proto_mode = BTA_HH_PROTO_UNKNOWN;
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case BTA_HH_GET_RPT_EVT:
     case BTA_HH_GET_IDLE_EVT:
       bta_hh.hs_data.handle = p_cb->hid_handle;
@@ -660,7 +660,9 @@
       bta_hh.hs_data.status = bta_hh_get_trans_status(p_data->hid_cback.data);
       if (bta_hh.hs_data.status == BTA_HH_OK)
         bta_hh.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(bta_hh.dev_status.handle, bta_hh.hs_data.status,
+                              NULL, 0);
       (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
       p_cb->w4_evt = 0;
       break;
@@ -672,6 +674,9 @@
       bta_hh.dev_status.handle = p_cb->hid_handle;
       bta_hh.dev_status.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(bta_hh.dev_status.handle,
+                              bta_hh.dev_status.status);
       (*bta_hh_cb.p_cback)(p_cb->w4_evt, &bta_hh);
       p_cb->w4_evt = 0;
       break;
@@ -733,6 +738,8 @@
       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*/
@@ -748,11 +755,11 @@
       break;
     /* should not expect control DATA for SET_ transaction */
     case BTA_HH_SET_PROTO_EVT:
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case BTA_HH_SET_RPT_EVT:
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case BTA_HH_SET_IDLE_EVT:
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     default:
 #if (BTA_HH_DEBUG == TRUE)
       APPL_TRACE_DEBUG("invalid  transaction type for DATA payload: 4_evt[%s]",
@@ -1054,21 +1061,21 @@
     } else {
       switch (p_data->api_sndcmd.t_type) {
         case HID_TRANS_SET_PROTOCOL:
-        /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case HID_TRANS_GET_REPORT:
-        /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case HID_TRANS_SET_REPORT:
-        /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case HID_TRANS_GET_PROTOCOL:
-        /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case HID_TRANS_GET_IDLE:
-        /* fall through */
+          FALLTHROUGH_INTENDED;  /* FALLTHROUGH */
         case HID_TRANS_SET_IDLE: /* set w4_handsk event name for callback
                                     function use */
           p_cb->w4_evt = event;
           break;
         case HID_TRANS_DATA: /* output report */
-                             /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case HID_TRANS_CONTROL:
           /* no handshake event will be generated */
           /* if VC_UNPLUG is issued, set flag */
diff --git a/bta/hh/bta_hh_api.cc b/bta/hh/bta_hh_api.cc
index e9b3f64..cd32ede 100644
--- a/bta/hh/bta_hh_api.cc
+++ b/bta/hh/bta_hh_api.cc
@@ -172,7 +172,13 @@
  ******************************************************************************/
 void BTA_HhSetReport(uint8_t dev_handle, tBTA_HH_RPT_TYPE r_type,
                      BT_HDR* p_data) {
-  bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0, p_data);
+  /* send feature report on control channel */
+  if (r_type == BTA_HH_RPTT_FEATURE)
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_SET_REPORT, r_type, 0, 0,
+                         p_data);
+  /* send output data report on interrupt channel */
+  else
+    bta_hh_snd_write_dev(dev_handle, HID_TRANS_DATA, r_type, 0, 0, p_data);
 }
 /*******************************************************************************
  *
diff --git a/bta/hh/bta_hh_le.cc b/bta/hh/bta_hh_le.cc
index adeb957..510e3a4 100644
--- a/bta/hh/bta_hh_le.cc
+++ b/bta/hh/bta_hh_le.cc
@@ -457,9 +457,9 @@
   return NULL;
 }
 
-static const tBTA_GATTC_DESCRIPTOR* find_descriptor_by_short_uuid(
+static const gatt::Descriptor* find_descriptor_by_short_uuid(
     uint16_t conn_id, uint16_t char_handle, uint16_t short_uuid) {
-  const tBTA_GATTC_CHARACTERISTIC* p_char =
+  const gatt::Characteristic* p_char =
       BTA_GATTC_GetCharacteristic(conn_id, char_handle);
 
   if (!p_char) {
@@ -467,7 +467,7 @@
     return NULL;
   }
 
-  for (const tBTA_GATTC_DESCRIPTOR& desc : p_char->descriptors) {
+  for (const gatt::Descriptor& desc : p_char->descriptors) {
     if (desc.uuid == Uuid::From16Bit(short_uuid)) return &desc;
   }
 
@@ -486,7 +486,7 @@
                                                      uint16_t short_uuid,
                                                      GATT_READ_OP_CB cb,
                                                      void* cb_data) {
-  const tBTA_GATTC_DESCRIPTOR* p_desc =
+  const gatt::Descriptor* p_desc =
       find_descriptor_by_short_uuid(p_cb->conn_id, char_handle, short_uuid);
   if (!p_desc) return BTA_HH_ERR;
 
@@ -671,7 +671,7 @@
 bool bta_hh_le_write_ccc(tBTA_HH_DEV_CB* p_cb, uint8_t char_handle,
                          uint16_t clt_cfg_value, GATT_WRITE_OP_CB cb,
                          void* cb_data) {
-  const tBTA_GATTC_DESCRIPTOR* p_desc = find_descriptor_by_short_uuid(
+  const gatt::Descriptor* p_desc = find_descriptor_by_short_uuid(
       p_cb->conn_id, char_handle, GATT_UUID_CHAR_CLIENT_CONFIG);
   if (!p_desc) return false;
 
@@ -691,7 +691,7 @@
   uint8_t srvc_inst_id, hid_inst_id;
 
   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
-  const tBTA_GATTC_CHARACTERISTIC* characteristic =
+  const gatt::Characteristic* characteristic =
       BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
   uint16_t char_uuid = characteristic->uuid.As16Bit();
 
@@ -701,7 +701,7 @@
     case GATT_UUID_BATTERY_LEVEL: /* battery level clt cfg registered */
       hid_inst_id = bta_hh_le_find_service_inst_by_battery_inst_id(
           p_dev_cb, srvc_inst_id);
-    /* FALLTHROUGH */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case GATT_UUID_HID_BT_KB_INPUT:
     case GATT_UUID_HID_BT_MOUSE_INPUT:
     case GATT_UUID_HID_REPORT:
@@ -1310,17 +1310,16 @@
   }
 
   tBTA_HH_DEV_CB* p_dev_cb = (tBTA_HH_DEV_CB*)data;
-  const tBTA_GATTC_DESCRIPTOR* p_desc =
-      BTA_GATTC_GetDescriptor(conn_id, handle);
+  const gatt::Descriptor* p_desc = BTA_GATTC_GetDescriptor(conn_id, handle);
 
   if (!p_desc) {
     APPL_TRACE_ERROR("%s: error: descriptor is null!", __func__);
     return;
   }
 
-  const tBTA_GATTC_CHARACTERISTIC* characteristic =
+  const gatt::Characteristic* characteristic =
       BTA_GATTC_GetOwningCharacteristic(conn_id, handle);
-  const tBTA_GATTC_SERVICE* service =
+  const gatt::Service* service =
       BTA_GATTC_GetOwningService(conn_id, characteristic->value_handle);
 
   tBTA_HH_LE_RPT* p_rpt;
@@ -1398,10 +1397,10 @@
  *
  ******************************************************************************/
 static void bta_hh_le_search_hid_chars(tBTA_HH_DEV_CB* p_dev_cb,
-                                       const tBTA_GATTC_SERVICE* service) {
+                                       const gatt::Service* service) {
   tBTA_HH_LE_RPT* p_rpt;
 
-  for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+  for (const gatt::Characteristic& charac : service->characteristics) {
     if (!charac.uuid.Is16Bit()) continue;
 
     uint16_t uuid16 = charac.uuid.As16Bit();
@@ -1460,7 +1459,7 @@
   }
 
   /* Make sure PROTO_MODE is processed as last */
-  for (const tBTA_GATTC_CHARACTERISTIC& charac : service->characteristics) {
+  for (const gatt::Characteristic& charac : service->characteristics) {
     if (charac.uuid == Uuid::From16Bit(GATT_UUID_HID_PROTO_MODE)) {
       p_dev_cb->hid_srvc.proto_mode_handle = charac.value_handle;
       bta_hh_le_set_protocol_mode(p_dev_cb, p_dev_cb->mode);
@@ -1491,11 +1490,11 @@
     return;
   }
 
-  const std::vector<tBTA_GATTC_SERVICE>* services =
+  const std::list<gatt::Service>* services =
       BTA_GATTC_GetServices(p_data->conn_id);
 
   bool have_hid = false;
-  for (const tBTA_GATTC_SERVICE& service : *services) {
+  for (const gatt::Service& service : *services) {
     if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_LE_HID) &&
         service.is_primary && !have_hid) {
       have_hid = true;
@@ -1513,7 +1512,7 @@
     } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_SCAN_PARAM)) {
       p_dev_cb->scan_refresh_char_handle = 0;
 
-      for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
+      for (const gatt::Characteristic& charac : service.characteristics) {
         if (charac.uuid == Uuid::From16Bit(GATT_UUID_SCAN_REFRESH)) {
           p_dev_cb->scan_refresh_char_handle = charac.value_handle;
 
@@ -1528,7 +1527,7 @@
     } else if (service.uuid == Uuid::From16Bit(UUID_SERVCLASS_GAP_SERVER)) {
       // TODO(jpawlowski): this should be done by GAP profile, remove when GAP
       // is fixed.
-      for (const tBTA_GATTC_CHARACTERISTIC& charac : service.characteristics) {
+      for (const gatt::Characteristic& charac : service.characteristics) {
         if (charac.uuid == Uuid::From16Bit(GATT_UUID_GAP_PREF_CONN_PARAM)) {
           /* read the char value */
           BtaGattQueue::ReadCharacteristic(p_dev_cb->conn_id,
@@ -1565,7 +1564,7 @@
     return;
   }
 
-  const tBTA_GATTC_CHARACTERISTIC* p_char =
+  const gatt::Characteristic* p_char =
       BTA_GATTC_GetCharacteristic(p_dev_cb->conn_id, p_data->handle);
   if (p_char == NULL) {
     APPL_TRACE_ERROR(
@@ -1719,7 +1718,7 @@
 static void read_report_cb(uint16_t conn_id, tGATT_STATUS status,
                            uint16_t handle, uint16_t len, uint8_t* value,
                            void* data) {
-  const tBTA_GATTC_CHARACTERISTIC* p_char =
+  const gatt::Characteristic* p_char =
       BTA_GATTC_GetCharacteristic(conn_id, handle);
 
   if (p_char == NULL) return;
@@ -1752,7 +1751,7 @@
   hs_data.handle = p_dev_cb->hid_handle;
 
   if (status == GATT_SUCCESS) {
-    const tBTA_GATTC_SERVICE* p_svc =
+    const gatt::Service* p_svc =
         BTA_GATTC_GetOwningService(conn_id, p_char->value_handle);
 
     p_rpt = bta_hh_le_find_report_entry(p_dev_cb, p_svc->handle, char_uuid,
@@ -1818,7 +1817,7 @@
   APPL_TRACE_DEBUG("bta_hh_le_write_cmpl w4_evt: %d", p_dev_cb->w4_evt);
 #endif
 
-  const tBTA_GATTC_CHARACTERISTIC* p_char =
+  const gatt::Characteristic* p_char =
       BTA_GATTC_GetCharacteristic(conn_id, handle);
   uint16_t uuid = p_char->uuid.As16Bit();
   if (uuid != GATT_UUID_HID_REPORT && uuid != GATT_UUID_HID_BT_KB_INPUT &&
@@ -1867,7 +1866,7 @@
 
   p_cb->w4_evt = w4_evt;
 
-  const tBTA_GATTC_CHARACTERISTIC* p_char =
+  const gatt::Characteristic* p_char =
       BTA_GATTC_GetCharacteristic(p_cb->conn_id, p_rpt->char_inst_id);
 
   tGATT_WRITE_TYPE write_type = GATT_WRITE;
@@ -1996,8 +1995,6 @@
     BTA_GATTC_Open(bta_hh_cb.gatt_if, p_cb->addr, false, GATT_TRANSPORT_LE,
                    false);
     p_cb->in_bg_conn = true;
-
-    BTA_DmBleStartAutoConn();
   }
   return;
 }
diff --git a/bta/hh/bta_hh_utils.cc b/bta/hh/bta_hh_utils.cc
index c4c6061..f3cb1b3 100644
--- a/bta/hh/bta_hh_utils.cc
+++ b/bta/hh/bta_hh_utils.cc
@@ -21,6 +21,8 @@
 #if (BTA_HH_INCLUDED == TRUE)
 
 #include "bta_hh_int.h"
+#include "btif/include/btif_storage.h"
+#include "device/include/interop.h"
 #include "osi/include/osi.h"
 
 /* if SSR max latency is not defined by remote device, set the default value
@@ -393,6 +395,16 @@
         if (ssr_max_latency > BTA_HH_SSR_MAX_LATENCY_DEF)
           ssr_max_latency = BTA_HH_SSR_MAX_LATENCY_DEF;
 
+        char remote_name[BTM_MAX_REM_BD_NAME_LEN] = "";
+        if (btif_storage_get_stored_remote_name(bd_addr, remote_name)) {
+          if (interop_match_name(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL,
+                                 remote_name)) {
+            if (ssr_max_latency > 18 /* slots * 0.625ms */) {
+              ssr_max_latency = 18;
+            }
+          }
+        }
+
         *p_max_ssr_lat = ssr_max_latency;
       } else
         *p_max_ssr_lat = p_cb->kdev[i].dscp_info.ssr_max_latency;
diff --git a/bta/hl/bta_hl_act.cc b/bta/hl/bta_hl_act.cc
deleted file mode 100644
index 6d37bdf..0000000
--- a/bta/hl/bta_hl_act.cc
+++ /dev/null
@@ -1,2377 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2003-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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This file contains the HeaLth device profile (HL) action functions for
- *  the state machine.
- *
- ******************************************************************************/
-
-#include <string.h>
-
-#include "bt_target.h"
-#if (HL_INCLUDED == TRUE)
-
-#include "bt_common.h"
-#include "bta_hl_api.h"
-#include "bta_hl_int.h"
-#include "bta_sys.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "osi/include/osi.h"
-#include "port_api.h"
-#include "sdp_api.h"
-#include "utl.h"
-
-using bluetooth::Uuid;
-
-/*****************************************************************************
- *  Local Function prototypes
- ****************************************************************************/
-#if (BTA_HL_DEBUG == TRUE)
-static const char* bta_hl_mcap_evt_code(uint8_t evt_code);
-static const char* bta_hl_dch_oper_code(tBTA_HL_DCH_OPER oper_code);
-static const char* bta_hl_cback_evt_code(uint8_t evt_code);
-#endif
-static void bta_hl_sdp_cback(uint8_t sdp_op, uint8_t app_idx, uint8_t mcl_idx,
-                             uint8_t mdl_idx, uint16_t status);
-static void bta_hl_sdp_cback0(uint16_t status);
-static void bta_hl_sdp_cback1(uint16_t status);
-static void bta_hl_sdp_cback2(uint16_t status);
-static void bta_hl_sdp_cback3(uint16_t status);
-static void bta_hl_sdp_cback4(uint16_t status);
-static void bta_hl_sdp_cback5(uint16_t status);
-static void bta_hl_sdp_cback6(uint16_t status);
-
-static tSDP_DISC_CMPL_CB* const bta_hl_sdp_cback_arr[] = {
-    bta_hl_sdp_cback0, bta_hl_sdp_cback1, bta_hl_sdp_cback2, bta_hl_sdp_cback3,
-    bta_hl_sdp_cback4, bta_hl_sdp_cback5, bta_hl_sdp_cback6};
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_cong_change
- *
- * Description      Action routine for processing congestion change notification
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_cong_change(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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_CONG_CHG* p_cong_chg = &p_data->mca_evt.mca_data.cong_chg;
-  tBTA_HL evt_data;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_cong_change mdl_id=%d cong=%d",
-                   p_cong_chg->mdl_id, p_cong_chg->cong);
-#endif
-  evt_data.dch_cong_ind.cong = p_dcb->cong = p_cong_chg->cong;
-  evt_data.dch_cong_ind.mdl_handle = p_dcb->mdl_handle;
-  evt_data.dch_cong_ind.mcl_handle = p_mcb->mcl_handle;
-  evt_data.dch_cong_ind.app_handle = p_acb->app_handle;
-
-  p_acb->p_cback(BTA_HL_CONG_CHG_IND_EVT, (tBTA_HL*)&evt_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_echo_test
- *
- * Description      Action routine for processing echo test request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_echo_test(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                          UNUSED_ATTR tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_echo_test");
-#endif
-
-  p_dcb->echo_oper = BTA_HL_ECHO_OP_CI_GET_ECHO_DATA;
-  p_dcb->cout_oper |= BTA_HL_CO_GET_ECHO_DATA_MASK;
-
-  bta_hl_co_get_echo_data(
-      p_acb->app_id, p_mcb->mcl_handle, p_dcb->p_echo_tx_pkt->len,
-      BTA_HL_GET_BUF_PTR(p_dcb->p_echo_tx_pkt), BTA_HL_CI_GET_ECHO_DATA_EVT);
-}
-/*******************************************************************************
- *
- * Function         bta_hl_dch_sdp_init
- *
- * Description      Action routine for processing DCH SDP initiation
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_sdp_init(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                         tBTA_HL_DATA* p_data) {
-  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);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_sdp_init");
-#endif
-  if (p_mcb->sdp_oper == BTA_HL_SDP_OP_NONE) {
-    p_mcb->sdp_mdl_idx = mdl_idx;
-    if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN) {
-      p_mcb->sdp_oper = BTA_HL_SDP_OP_DCH_OPEN_INIT;
-
-    } else {
-      p_mcb->sdp_oper = BTA_HL_SDP_OP_DCH_RECONNECT_INIT;
-    }
-
-    if (bta_hl_init_sdp(p_mcb->sdp_oper, app_idx, mcl_idx, mdl_idx) !=
-        BTA_HL_STATUS_OK) {
-      APPL_TRACE_ERROR("SDP INIT failed");
-      p_mcb->sdp_oper = BTA_HL_SDP_OP_NONE;
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_FAIL_EVT,
-                            p_data);
-    }
-  } else {
-    APPL_TRACE_ERROR("SDP in use");
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_SDP_FAIL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_close_echo_test
- *
- * Description      Action routine for processing the closing of echo test
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_close_echo_test(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_close_echo_test");
-#endif
-
-  switch (p_dcb->echo_oper) {
-    case BTA_HL_ECHO_OP_DCH_CLOSE_CFM:
-    case BTA_HL_ECHO_OP_OPEN_IND:
-    case BTA_HL_ECHO_OP_ECHO_PKT:
-      p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST;
-      break;
-    case BTA_HL_ECHO_OP_MDL_CREATE_CFM:
-    case BTA_HL_ECHO_OP_DCH_OPEN_CFM:
-    case BTA_HL_ECHO_OP_LOOP_BACK:
-    default:
-      break;
-  }
-
-  if (MCA_CloseReq((tMCA_DL)p_dcb->mdl_handle) != MCA_SUCCESS) {
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_rcv_data
- *
- * Description      Action routine for processing the received data
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_rcv_data(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                             tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_rcv_data");
-#endif
-
-  if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-    switch (p_dcb->echo_oper) {
-      case BTA_HL_ECHO_OP_ECHO_PKT:
-
-        if (MCA_WriteReq((tMCA_DL)p_dcb->mdl_handle,
-                         p_data->mca_rcv_data_evt.p_pkt) != MCA_SUCCESS) {
-          osi_free_and_reset((void**)&p_data->mca_rcv_data_evt.p_pkt);
-          bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                                BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
-        }
-        break;
-      case BTA_HL_ECHO_OP_LOOP_BACK:
-
-        p_dcb->p_echo_rx_pkt = p_data->mca_rcv_data_evt.p_pkt;
-        p_dcb->echo_oper = BTA_HL_ECHO_OP_CI_PUT_ECHO_DATA;
-        p_dcb->cout_oper |= BTA_HL_CO_PUT_ECHO_DATA_MASK;
-        p_dcb->ci_put_echo_data_status = BTA_HL_STATUS_FAIL;
-
-        bta_hl_co_put_echo_data(p_acb->app_id, p_mcb->mcl_handle,
-                                p_dcb->p_echo_rx_pkt->len,
-                                BTA_HL_GET_BUF_PTR(p_dcb->p_echo_rx_pkt),
-                                BTA_HL_CI_PUT_ECHO_DATA_EVT);
-        break;
-      default:
-        APPL_TRACE_ERROR("Unknonw echo_oper=%d", p_dcb->echo_oper);
-        break;
-    }
-
-  } else {
-    p_dcb->cout_oper |= BTA_HL_CO_PUT_RX_DATA_MASK;
-    p_dcb->p_rx_pkt = p_data->mca_rcv_data_evt.p_pkt;
-
-    bta_hl_co_put_rx_data(
-        p_acb->app_id, p_dcb->mdl_handle, p_dcb->p_rx_pkt->len,
-        BTA_HL_GET_BUF_PTR(p_dcb->p_rx_pkt), BTA_HL_CI_PUT_RX_DATA_EVT);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_ci_put_echo_data
- *
- * Description      Action routine for processing the call-in of the
- *                  put echo data event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_ci_put_echo_data(uint8_t app_idx, uint8_t mcl_idx,
-                                 uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_ci_put_echo_data");
-#endif
-
-  p_dcb->cout_oper &= ~BTA_HL_CO_PUT_ECHO_DATA_MASK;
-  osi_free_and_reset((void**)&p_dcb->p_echo_rx_pkt);
-  p_dcb->ci_put_echo_data_status = p_data->ci_get_put_echo_data.status;
-
-  p_dcb->echo_oper = BTA_HL_ECHO_OP_DCH_CLOSE_CFM;
-  bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                        BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_ci_get_echo_data
- *
- * Description      Action routine for processing the call-in of the
- *                  get echo data event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_ci_get_echo_data(uint8_t app_idx, uint8_t mcl_idx,
-                                 uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-  tBTA_HL_STATUS status;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_ci_get_echo_data");
-#endif
-
-  p_dcb->cout_oper &= ~BTA_HL_CO_GET_ECHO_DATA_MASK;
-
-  if (!p_dcb->abort_oper) {
-    status = p_data->ci_get_put_echo_data.status;
-    if (status == BTA_HL_STATUS_OK) {
-      p_dcb->echo_oper = BTA_HL_ECHO_OP_MDL_CREATE_CFM;
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_OPEN_EVT,
-                            p_data);
-    } else {
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    }
-  } else {
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_ci_put_rx_data
- *
- * Description      Action routine for processing the call-in of the
- *                  put rx data event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_ci_put_rx_data(uint8_t app_idx, uint8_t mcl_idx,
-                               uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-  tBTA_HL evt_data;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_ci_put_rx_data");
-#endif
-
-  p_dcb->cout_oper &= ~BTA_HL_CO_PUT_RX_DATA_MASK;
-  osi_free_and_reset((void**)&p_dcb->p_rx_pkt);
-  bta_hl_build_rcv_data_ind(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                            p_dcb->mdl_handle);
-  p_acb->p_cback(BTA_HL_DCH_RCV_DATA_IND_EVT, (tBTA_HL*)&evt_data);
-  if (p_dcb->close_pending) {
-    if (!p_dcb->cout_oper) {
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT,
-                            p_data);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_ci_get_tx_data
- *
- * Description      Action routine for processing the call-in of the
- *                  get tx data event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_ci_get_tx_data(uint8_t app_idx, uint8_t mcl_idx,
-                               uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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;
-  bool free_buf = false;
-  bool close_dch = false;
-  tBTA_HL evt_data;
-
-#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("%s: status=%d", __func__, status);
-  }
-
-  p_dcb->cout_oper &= ~BTA_HL_CO_GET_TX_DATA_MASK;
-
-  if (p_dcb->close_pending) {
-    status = BTA_HL_STATUS_FAIL;
-    free_buf = true;
-
-    if (!p_dcb->cout_oper) {
-      close_dch = true;
-    }
-  } else if (status == BTA_HL_STATUS_FAIL) {
-    free_buf = TRUE;
-  } else {
-    result = MCA_WriteReq((tMCA_DL)p_dcb->mdl_handle, p_dcb->p_tx_pkt);
-    if (result != MCA_SUCCESS) {
-      if (result == MCA_BUSY) {
-        status = BTA_HL_STATUS_DCH_BUSY;
-      } else {
-        status = BTA_HL_STATUS_FAIL;
-      }
-      free_buf = true;
-    } else {
-      p_dcb->p_tx_pkt = NULL;
-    }
-  }
-
-  if (free_buf) osi_free_and_reset((void**)&p_dcb->p_tx_pkt);
-
-  bta_hl_build_send_data_cfm(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                             p_dcb->mdl_handle, status);
-  p_acb->p_cback(BTA_HL_DCH_SEND_DATA_CFM_EVT, (tBTA_HL*)&evt_data);
-
-  if (close_dch) {
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_send_data
- *
- * Description      Action routine for processing api send data request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_send_data(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                          tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-  tBTA_HL evt_data;
-  bool success = true;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_send_data");
-#endif
-
-  if (!(p_dcb->cout_oper & BTA_HL_CO_GET_TX_DATA_MASK)) {
-    // p_dcb->chnl_cfg.fcs may be BTA_HL_MCA_USE_FCS (0x11) or BTA_HL_MCA_NO_FCS
-    // (0x10) or BTA_HL_DEFAULT_SOURCE_FCS (1)
-    bool fcs_use = (bool)(p_dcb->chnl_cfg.fcs & BTA_HL_MCA_FCS_USE_MASK);
-    p_dcb->p_tx_pkt = bta_hl_get_buf(p_data->api_send_data.pkt_size, fcs_use);
-    if (p_dcb->p_tx_pkt != NULL) {
-      bta_hl_co_get_tx_data(
-          p_acb->app_id, p_dcb->mdl_handle, p_data->api_send_data.pkt_size,
-          BTA_HL_GET_BUF_PTR(p_dcb->p_tx_pkt), BTA_HL_CI_GET_TX_DATA_EVT);
-      p_dcb->cout_oper |= BTA_HL_CO_GET_TX_DATA_MASK;
-    } else {
-      success = false;
-    }
-  } else {
-    success = false;
-  }
-
-  if (!success) {
-    bta_hl_build_send_data_cfm(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                               p_dcb->mdl_handle, BTA_HL_STATUS_FAIL);
-    p_acb->p_cback(BTA_HL_DCH_SEND_DATA_CFM_EVT, (tBTA_HL*)&evt_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_close_cmpl
- *
- * Description      Action routine for processing the close complete event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_close_cmpl(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                           tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-  tBTA_HL evt_data;
-  tBTA_HL_EVT event = 0;
-  bool send_evt = true;
-  tBTA_HL_STATUS status;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_close_cmpl dch oper=%s",
-                   bta_hl_dch_oper_code(p_dcb->dch_oper));
-#endif
-
-  switch (p_dcb->dch_oper) {
-    case BTA_HL_DCH_OP_LOCAL_OPEN:
-    case BTA_HL_DCH_OP_LOCAL_RECONNECT:
-
-      if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK) {
-        bta_hl_build_abort_cfm(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                               BTA_HL_STATUS_OK);
-        event = BTA_HL_DCH_ABORT_CFM_EVT;
-      } else if (p_dcb->abort_oper & BTA_HL_ABORT_REMOTE_MASK) {
-        bta_hl_build_abort_ind(&evt_data, p_acb->app_handle, p_mcb->mcl_handle);
-        event = BTA_HL_DCH_ABORT_IND_EVT;
-      } else {
-        bta_hl_build_dch_open_cfm(&evt_data, p_acb->app_handle,
-                                  p_mcb->mcl_handle, BTA_HL_INVALID_MDL_HANDLE,
-                                  0, 0, 0, 0, 0, BTA_HL_STATUS_FAIL);
-        event = BTA_HL_DCH_OPEN_CFM_EVT;
-        if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT) {
-          event = BTA_HL_DCH_RECONNECT_CFM_EVT;
-        }
-      }
-      break;
-
-    case BTA_HL_DCH_OP_LOCAL_CLOSE:
-    case BTA_HL_DCH_OP_REMOTE_DELETE:
-    case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
-    case BTA_HL_DCH_OP_NONE:
-
-      bta_hl_build_dch_close_cfm(&evt_data, p_acb->app_handle,
-                                 p_mcb->mcl_handle, p_dcb->mdl_handle,
-                                 BTA_HL_STATUS_OK);
-      event = BTA_HL_DCH_CLOSE_CFM_EVT;
-      break;
-
-    case BTA_HL_DCH_OP_REMOTE_CLOSE:
-      bta_hl_build_dch_close_ind(&evt_data, p_acb->app_handle,
-                                 p_mcb->mcl_handle, p_dcb->mdl_handle,
-                                 p_dcb->intentional_close);
-      event = BTA_HL_DCH_CLOSE_IND_EVT;
-      break;
-
-    case BTA_HL_DCH_OP_REMOTE_OPEN:
-
-      if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK) {
-        bta_hl_build_abort_cfm(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                               BTA_HL_STATUS_OK);
-        event = BTA_HL_DCH_ABORT_CFM_EVT;
-      } else if (p_dcb->abort_oper & BTA_HL_ABORT_REMOTE_MASK) {
-        bta_hl_build_abort_ind(&evt_data, p_acb->app_handle, p_mcb->mcl_handle);
-        event = BTA_HL_DCH_ABORT_IND_EVT;
-      } else {
-        bta_hl_build_dch_close_ind(&evt_data, p_acb->app_handle,
-                                   p_mcb->mcl_handle, p_dcb->mdl_handle,
-                                   p_dcb->intentional_close);
-        event = BTA_HL_DCH_CLOSE_IND_EVT;
-      }
-      break;
-
-    case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
-    /* this is normal echo test close */
-    case BTA_HL_DCH_OP_REMOTE_CREATE:
-    case BTA_HL_DCH_OP_REMOTE_RECONNECT:
-      send_evt = false;
-      break;
-
-    default:
-#if (BTA_HL_DEBUG == TRUE)
-      APPL_TRACE_ERROR("DCH operation not found oper=%s",
-                       bta_hl_dch_oper_code(p_dcb->dch_oper));
-#endif
-      send_evt = false;
-      break;
-  }
-
-  if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-    p_mcb->echo_test = false;
-    send_evt = false;
-
-    if (p_dcb->dch_oper != BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST) {
-      switch (p_dcb->echo_oper) {
-        case BTA_HL_ECHO_OP_CI_GET_ECHO_DATA:
-        case BTA_HL_ECHO_OP_SDP_INIT:
-        case BTA_HL_ECHO_OP_MDL_CREATE_CFM:
-        case BTA_HL_ECHO_OP_DCH_OPEN_CFM:
-        case BTA_HL_ECHO_OP_LOOP_BACK:
-
-          status = BTA_HL_STATUS_FAIL;
-          send_evt = true;
-          break;
-        case BTA_HL_ECHO_OP_OPEN_IND:
-        case BTA_HL_ECHO_OP_ECHO_PKT:
-          break;
-        default:
-          APPL_TRACE_ERROR("Invalid echo_oper=%d", p_dcb->echo_oper);
-          break;
-      }
-    } else {
-      status = p_dcb->ci_put_echo_data_status;
-      send_evt = true;
-    }
-
-    if (send_evt) {
-      bta_hl_build_echo_test_cfm(&evt_data, p_acb->app_handle,
-                                 p_mcb->mcl_handle, status);
-      event = BTA_HL_DCH_ECHO_TEST_CFM_EVT;
-    }
-  }
-
-  bta_hl_clean_mdl_cb(app_idx, mcl_idx, mdl_idx);
-
-  if (send_evt) {
-    if (p_acb->p_cback) {
-#if (BTA_HL_DEBUG == TRUE)
-      APPL_TRACE_DEBUG("Send Event: %s", bta_hl_cback_evt_code(event));
-#endif
-      p_acb->p_cback(event, (tBTA_HL*)&evt_data);
-    }
-  }
-  /* check cch close is in progress or not */
-  bta_hl_check_cch_close(app_idx, mcl_idx, p_data, false);
-}
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_close_ind
- *
- * Description      Action routine for processing the close indication
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_close_ind(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                              tBTA_HL_DATA* p_data) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_close_ind dch oper=%s",
-                   bta_hl_dch_oper_code(p_dcb->dch_oper));
-#endif
-
-  p_dcb->intentional_close = false;
-  if (p_data->mca_evt.mca_data.close_ind.reason == L2CAP_DISC_OK) {
-    p_dcb->intentional_close = true;
-  }
-
-  if (!p_dcb->cout_oper) {
-    if ((p_dcb->dch_oper != BTA_HL_DCH_OP_REMOTE_OPEN) &&
-        (p_dcb->dch_oper != BTA_HL_DCH_OP_REMOTE_RECONNECT)) {
-      p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_CLOSE;
-    }
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  } else {
-    p_dcb->close_pending = true;
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_close_cfm
- *
- * Description      Action routine for processing the close confirmation
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_close_cfm(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                              tBTA_HL_DATA* p_data) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_close_cfm dch_oper=%s",
-                   bta_hl_dch_oper_code(p_dcb->dch_oper));
-#endif
-
-  switch (p_dcb->dch_oper) {
-    case BTA_HL_DCH_OP_LOCAL_CLOSE:
-    case BTA_HL_DCH_OP_LOCAL_OPEN:
-    case BTA_HL_DCH_OP_LOCAL_RECONNECT:
-    case BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST:
-    case BTA_HL_DCH_OP_REMOTE_DELETE:
-    case BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT:
-    case BTA_HL_DCH_OP_NONE:
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-      break;
-    default:
-#if (BTA_HL_DEBUG == TRUE)
-      APPL_TRACE_ERROR("Invalid dch_oper=%s for close cfm",
-                       bta_hl_dch_oper_code(p_dcb->dch_oper));
-#endif
-      break;
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_close
- *
- * Description      Action routine for processing the DCH close request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_close(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                          tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-  tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
-  tBTA_HL evt_data;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_close");
-#endif
-  if (!p_dcb->cout_oper) {
-    p_dcb->close_pending = false;
-    if (MCA_CloseReq((tMCA_DL)p_dcb->mdl_handle) == MCA_SUCCESS) {
-      p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE;
-    } else {
-      status = BTA_HL_STATUS_FAIL;
-    }
-
-    if ((status != BTA_HL_STATUS_OK) &&
-        (p_mcb->cch_close_dch_oper != BTA_HL_CCH_CLOSE_OP_DCH_CLOSE)) {
-      bta_hl_build_dch_close_cfm(&evt_data, p_acb->app_handle,
-                                 p_mcb->mcl_handle,
-                                 p_data->api_dch_close.mdl_handle, status);
-      p_acb->p_cback(BTA_HL_DCH_CLOSE_CFM_EVT, (tBTA_HL*)&evt_data);
-    }
-  } else {
-    p_dcb->close_pending = true;
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_open_ind
- *
- * Description      Action routine for processing the open indication
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_open_ind(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                             tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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_DL_OPEN* p_open_ind = &p_data->mca_evt.mca_data.open_ind;
-  tBTA_HL evt_data;
-  tBTA_HL_EVT event;
-  uint8_t old_dch_oper = BTA_HL_DCH_OP_NONE;
-  bool send_event = false;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_open_ind");
-#endif
-  if ((p_dcb->dch_oper == BTA_HL_DCH_OP_REMOTE_OPEN) ||
-      (p_dcb->dch_oper == BTA_HL_DCH_OP_REMOTE_RECONNECT)) {
-    p_dcb->mdl_handle = (tBTA_HL_MDL_HANDLE)p_open_ind->mdl;
-    p_dcb->mtu = p_open_ind->mtu;
-
-    evt_data.dch_open_ind.mdl_handle = p_dcb->mdl_handle;
-    evt_data.dch_open_ind.mcl_handle = p_mcb->mcl_handle;
-    evt_data.dch_open_ind.app_handle = p_acb->app_handle;
-
-    evt_data.dch_open_ind.local_mdep_id = p_dcb->local_mdep_id;
-    evt_data.dch_open_ind.mdl_id = p_dcb->mdl_id;
-    evt_data.dch_open_ind.mtu = p_dcb->mtu;
-
-    if (p_dcb->chnl_cfg.fcr_opt.mode == L2CAP_FCR_ERTM_MODE) {
-      evt_data.dch_open_ind.dch_mode = BTA_HL_DCH_MODE_RELIABLE;
-      if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx)) {
-        p_dcb->is_the_first_reliable = true;
-      }
-    } else {
-      evt_data.dch_open_ind.dch_mode = BTA_HL_DCH_MODE_STREAMING;
-    }
-    evt_data.dch_open_ind.first_reliable = p_dcb->is_the_first_reliable;
-
-    old_dch_oper = p_dcb->dch_oper;
-    p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
-  }
-
-  switch (old_dch_oper) {
-    case BTA_HL_DCH_OP_REMOTE_OPEN:
-
-      p_dcb->dch_mode = evt_data.dch_open_ind.dch_mode;
-      if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID) {
-        bta_hl_save_mdl_cfg(app_idx, mcl_idx, mdl_idx);
-        event = BTA_HL_DCH_OPEN_IND_EVT;
-        send_event = true;
-      } else {
-        p_dcb->echo_oper = BTA_HL_ECHO_OP_ECHO_PKT;
-      }
-
-      break;
-
-    case BTA_HL_DCH_OP_REMOTE_RECONNECT:
-
-      if (bta_hl_validate_chan_cfg(app_idx, mcl_idx, mdl_idx)) {
-        bta_hl_save_mdl_cfg(app_idx, mcl_idx, mdl_idx);
-        event = BTA_HL_DCH_RECONNECT_IND_EVT;
-        send_event = true;
-      } else {
-        if (MCA_CloseReq((tMCA_DL)p_dcb->mdl_handle) == MCA_SUCCESS) {
-          p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT;
-        } else {
-          APPL_TRACE_ERROR("Unabel to close DCH for reconnect cfg mismatch");
-        }
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (send_event) {
-    p_acb->p_cback(event, (tBTA_HL*)&evt_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_open_cfm
- *
- * Description      Action routine for processing the open confirmation
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_open_cfm(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                             tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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_DL_OPEN* p_open_cfm = &p_data->mca_evt.mca_data.open_cfm;
-  tBTA_HL evt_data;
-  tBTA_HL_EVT event;
-  uint8_t old_dch_oper = BTA_HL_DCH_OP_NONE;
-  tBTA_HL_DCH_MODE dch_mode = BTA_HL_DCH_MODE_STREAMING;
-  bool send_event = false;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_open_cfm");
-#endif
-  if ((p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN) ||
-      (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT)) {
-    p_dcb->mdl_handle = (tBTA_HL_MDL_HANDLE)p_open_cfm->mdl;
-    p_dcb->mtu = p_open_cfm->mtu;
-
-    /*todo verify dch_mode, mtu and fcs for reconnect */
-    if (p_dcb->chnl_cfg.fcr_opt.mode == L2CAP_FCR_ERTM_MODE) {
-      dch_mode = BTA_HL_DCH_MODE_RELIABLE;
-    }
-
-    if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID) {
-      if (dch_mode == BTA_HL_DCH_MODE_RELIABLE) {
-        if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx)) {
-          p_dcb->is_the_first_reliable = true;
-        }
-      }
-    }
-
-    bta_hl_build_dch_open_cfm(
-        &evt_data, p_acb->app_handle, p_mcb->mcl_handle, p_dcb->mdl_handle,
-        p_dcb->local_mdep_id, p_dcb->mdl_id, dch_mode,
-        p_dcb->is_the_first_reliable, p_dcb->mtu, BTA_HL_STATUS_OK);
-
-    old_dch_oper = p_dcb->dch_oper;
-    p_dcb->dch_oper = BTA_HL_DCH_OP_NONE;
-  } else {
-    APPL_TRACE_ERROR("Error dch oper =%d", p_dcb->dch_oper);
-    return;
-  }
-
-  switch (old_dch_oper) {
-    case BTA_HL_DCH_OP_LOCAL_OPEN:
-
-      p_dcb->dch_mode = dch_mode;
-      if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID) {
-        bta_hl_save_mdl_cfg(app_idx, mcl_idx, mdl_idx);
-        event = BTA_HL_DCH_OPEN_CFM_EVT;
-        send_event = true;
-      } else {
-        p_dcb->echo_oper = BTA_HL_ECHO_OP_LOOP_BACK;
-        if (MCA_WriteReq((tMCA_DL)p_dcb->mdl_handle, p_dcb->p_echo_tx_pkt) !=
-            MCA_SUCCESS) {
-          bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                                BTA_HL_DCH_CLOSE_ECHO_TEST_EVT, p_data);
-        } else {
-          p_dcb->p_echo_tx_pkt = NULL;
-        }
-      }
-      break;
-
-    case BTA_HL_DCH_OP_LOCAL_RECONNECT:
-
-      if (bta_hl_validate_chan_cfg(app_idx, mcl_idx, mdl_idx)) {
-        bta_hl_save_mdl_cfg(app_idx, mcl_idx, mdl_idx);
-        event = BTA_HL_DCH_RECONNECT_CFM_EVT;
-        send_event = true;
-      } else {
-        if (MCA_CloseReq((tMCA_DL)p_dcb->mdl_handle) == MCA_SUCCESS) {
-          p_dcb->dch_oper = BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT;
-        } else {
-          APPL_TRACE_ERROR("Unabel to close DCH for reconnect cfg mismatch");
-        }
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (send_event) p_acb->p_cback(event, (tBTA_HL*)&evt_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_abort_ind
- *
- * Description      Action routine for processing the abort indication
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_abort_ind(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                              tBTA_HL_DATA* p_data) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_abort_ind");
-#endif
-
-  p_dcb->abort_oper |= BTA_HL_ABORT_REMOTE_MASK;
-  bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                        p_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_abort_cfm
- *
- * Description      Action routine for processing the abort confirmation
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_abort_cfm(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                              tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-  tBTA_HL evt_data;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_abort_cfm");
-#endif
-
-  if (p_dcb->abort_oper) {
-    if (p_data->mca_evt.mca_data.abort_cfm.rsp_code != MCA_RSP_SUCCESS) {
-      if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK) {
-        bta_hl_build_abort_cfm(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                               BTA_HL_STATUS_FAIL);
-        p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT, (tBTA_HL*)&evt_data);
-      }
-    } else {
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    }
-  } else {
-    APPL_TRACE_ERROR("Not expecting Abort CFM ");
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_abort
- *
- * Description      Action routine for processing the abort request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_abort(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                          tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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 mca_result;
-  tBTA_HL evt_data;
-
-  if (((p_mcb->sdp_oper == BTA_HL_SDP_OP_DCH_OPEN_INIT) ||
-       (p_mcb->sdp_oper == BTA_HL_SDP_OP_DCH_RECONNECT_INIT)) &&
-      (p_mcb->sdp_mdl_idx == mdl_idx)) {
-    p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
-    return;
-  } else if (p_dcb->echo_oper == BTA_HL_ECHO_OP_CI_GET_ECHO_DATA) {
-    p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
-    return;
-  }
-
-  p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
-
-  mca_result = MCA_Abort((tMCA_CL)p_mcb->mcl_handle);
-  if (mca_result != MCA_SUCCESS) {
-    if (mca_result == MCA_NO_RESOURCES) {
-      p_dcb->abort_oper |= BTA_HL_ABORT_PENDING_MASK;
-    } else {
-      if (p_dcb->abort_oper & BTA_HL_ABORT_LOCAL_MASK) {
-        bta_hl_build_abort_cfm(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                               BTA_HL_STATUS_FAIL);
-        p_acb->p_cback(BTA_HL_DCH_ABORT_CFM_EVT, (tBTA_HL*)&evt_data);
-      }
-      bta_hl_check_cch_close(app_idx, mcl_idx, p_data, false);
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_abort abort_oper=0x%x", p_dcb->abort_oper);
-#endif
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_reconnect_ind
- *
- * Description      Action routine for processing the reconnect indication
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_reconnect_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  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);
-  tBTA_HL_MDL_CFG* p_mdl_cfg;
-  tMCA_EVT_HDR* p_reconnect_ind = &p_data->mca_evt.mca_data.reconnect_ind;
-  uint8_t mdl_cfg_idx, in_use_mdl_idx, mdep_cfg_idx;
-  uint8_t rsp_code = MCA_RSP_SUCCESS;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_reconnect_ind mdl_id=%d",
-                   p_reconnect_ind->mdl_id);
-#endif
-
-  if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect_ind->mdl_id,
-                              &mdl_cfg_idx)) {
-    if (!bta_hl_find_mdl_idx(app_idx, mcl_idx, p_reconnect_ind->mdl_id,
-                             &in_use_mdl_idx)) {
-      p_mdl_cfg = BTA_HL_GET_MDL_CFG_PTR(app_idx, mdl_cfg_idx);
-
-      if (bta_hl_find_mdep_cfg_idx(app_idx, p_mdl_cfg->local_mdep_id,
-                                   &mdep_cfg_idx)) {
-        p_dcb->in_use = true;
-        p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_RECONNECT;
-        p_dcb->sec_mask = (BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
-        p_dcb->peer_mdep_id = 0xFF;
-        p_dcb->local_mdep_id = p_mdl_cfg->local_mdep_id;
-        p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
-        p_dcb->local_cfg = BTA_HL_DCH_CFG_UNKNOWN;
-        p_dcb->mdl_id = p_reconnect_ind->mdl_id;
-        p_dcb->mdl_cfg_idx_included = true;
-        p_dcb->mdl_cfg_idx = mdl_cfg_idx;
-        p_dcb->dch_mode = p_mdl_cfg->dch_mode;
-        bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
-                                   &p_dcb->max_rx_apdu_size,
-                                   &p_dcb->max_tx_apdu_size);
-        bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
-      } else {
-        rsp_code = MCA_RSP_BAD_MDL;
-      }
-    } else {
-      rsp_code = MCA_RSP_BAD_MDL;
-    }
-  } else {
-    rsp_code = MCA_RSP_BAD_MDL;
-  }
-
-  if (MCA_ReconnectMdlRsp((tMCA_CL)p_mcb->mcl_handle, p_dcb->local_mdep_id,
-                          p_dcb->mdl_id, rsp_code,
-                          &p_dcb->chnl_cfg) != MCA_SUCCESS) {
-    MCA_Abort((tMCA_CL)p_mcb->mcl_handle);
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_reconnect_cfm
- *
- * Description      Action routine for processing the reconenct confirmation
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_reconnect_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  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_RSP_EVT* p_reconnect_cfm = &p_data->mca_evt.mca_data.reconnect_cfm;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_reconnect_cfm");
-#endif
-  if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK) {
-    p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT,
-                          p_data);
-    return;
-  }
-
-  if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_RECONNECT) {
-    if (p_reconnect_cfm->rsp_code == MCA_RSP_SUCCESS) {
-      bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
-
-      if (MCA_DataChnlCfg((tMCA_CL)p_mcb->mcl_handle, &p_dcb->chnl_cfg) !=
-          MCA_SUCCESS) {
-        /* should be able to abort so no checking of the return code */
-        MCA_Abort((tMCA_CL)p_mcb->mcl_handle);
-        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                              BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-      }
-    } else {
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_reconnect
- *
- * Description      Action routine for processing the reconnect request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_reconnect(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                              tBTA_HL_DATA* p_data) {
-  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_CHNL_CFG* p_chnl_cfg = NULL;
-  uint8_t sdp_idx;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_reconnect");
-#endif
-  if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->ctrl_psm,
-                                         &sdp_idx)) {
-    p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
-    if (MCA_ReconnectMdl((tMCA_CL)p_mcb->mcl_handle, p_dcb->local_mdep_id,
-                         p_mcb->data_psm, p_dcb->mdl_id,
-                         p_chnl_cfg) != MCA_SUCCESS) {
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    }
-  } else {
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_create_rsp
- *
- * Description      Action routine for processing BTA_HL_API_DCH_CREATE_RSP_EVT
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_create_rsp(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                           tBTA_HL_DATA* p_data) {
-  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);
-  tBTA_HL_API_DCH_CREATE_RSP* p_create_rsp = &p_data->api_dch_create_rsp;
-  uint8_t mca_rsp_code = MCA_RSP_SUCCESS;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_create_rsp");
-#endif
-  if (p_create_rsp->rsp_code == BTA_HL_DCH_CREATE_RSP_SUCCESS) {
-    p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_OPEN;
-    p_dcb->local_cfg = p_create_rsp->cfg_rsp;
-
-    bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
-  } else {
-    mca_rsp_code = MCA_RSP_CFG_REJ;
-  }
-
-  if (MCA_CreateMdlRsp((tMCA_CL)p_mcb->mcl_handle, p_dcb->local_mdep_id,
-                       p_dcb->mdl_id, p_dcb->local_cfg, mca_rsp_code,
-                       &p_dcb->chnl_cfg) != MCA_SUCCESS) {
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_create_ind
- *
- * Description      Action routine for processing
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_create_ind(uint8_t app_idx, uint8_t mcl_idx,
-                               uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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_CREATE_IND* p_create_ind = &p_data->mca_evt.mca_data.create_ind;
-  uint8_t mdep_cfg_idx;
-  uint8_t cfg_rsp;
-  uint8_t rsp_code = MCA_RSP_SUCCESS;
-  bool send_create_ind_evt = false;
-  tBTA_HL evt_data;
-  tBTA_HL_ECHO_CFG* p_echo_cfg;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_create_ind");
-#endif
-
-  if (bta_hl_find_mdep_cfg_idx(app_idx, p_create_ind->dep_id, &mdep_cfg_idx)) {
-    if (p_create_ind->dep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-      if (bta_hl_find_echo_cfg_rsp(app_idx, mcl_idx, mdep_cfg_idx,
-                                   p_create_ind->cfg, &cfg_rsp)) {
-        p_dcb->in_use = true;
-        p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_OPEN;
-        p_dcb->local_mdep_id = p_create_ind->dep_id;
-        p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
-        p_dcb->local_cfg = cfg_rsp;
-        p_dcb->remote_cfg = p_create_ind->cfg;
-        p_dcb->mdl_id = p_create_ind->mdl_id;
-        p_dcb->mdl_cfg_idx_included = false;
-        p_echo_cfg = BTA_HL_GET_ECHO_CFG_PTR(app_idx);
-        p_dcb->max_rx_apdu_size = p_echo_cfg->max_rx_apdu_size;
-        p_dcb->max_tx_apdu_size = p_echo_cfg->max_tx_apdu_size;
-
-        bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
-      } else {
-        rsp_code = MCA_RSP_CFG_REJ;
-      }
-    } else
-
-    {
-      p_dcb->in_use = true;
-      p_dcb->dch_oper = BTA_HL_DCH_OP_REMOTE_CREATE;
-      p_dcb->local_mdep_id = p_create_ind->dep_id;
-      p_dcb->local_mdep_cfg_idx = mdep_cfg_idx;
-      p_dcb->local_cfg = BTA_HL_DCH_CFG_UNKNOWN;
-      p_dcb->remote_cfg = p_create_ind->cfg;
-      p_dcb->mdl_id = p_create_ind->mdl_id;
-      p_dcb->mdl_cfg_idx_included = false;
-      bta_hl_find_rxtx_apdu_size(app_idx, mdep_cfg_idx,
-                                 &p_dcb->max_rx_apdu_size,
-                                 &p_dcb->max_tx_apdu_size);
-      send_create_ind_evt = true;
-    }
-  } else {
-    rsp_code = MCA_RSP_BAD_MDEP;
-  }
-
-  if (send_create_ind_evt) {
-    evt_data.dch_create_ind.mcl_handle = p_mcb->mcl_handle;
-    evt_data.dch_create_ind.app_handle = p_acb->app_handle;
-    evt_data.dch_create_ind.local_mdep_id = p_dcb->local_mdep_id;
-    evt_data.dch_create_ind.mdl_id = p_dcb->mdl_id;
-    evt_data.dch_create_ind.cfg = p_dcb->remote_cfg;
-    evt_data.dch_create_ind.bd_addr = p_mcb->bd_addr;
-    p_acb->p_cback(BTA_HL_DCH_CREATE_IND_EVT, (tBTA_HL*)&evt_data);
-  } else {
-    if (MCA_CreateMdlRsp((tMCA_CL)p_mcb->mcl_handle, p_dcb->local_mdep_id,
-                         p_dcb->mdl_id, p_dcb->local_cfg, rsp_code,
-                         &p_dcb->chnl_cfg) != MCA_SUCCESS) {
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    } else {
-      if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-        p_mcb->echo_test = true;
-        p_dcb->echo_oper = BTA_HL_ECHO_OP_OPEN_IND;
-      }
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_create_cfm
- *
- * Description      Action routine for processing
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_create_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                               uint8_t mdl_idx, tBTA_HL_DATA* p_data) {
-  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_CREATE_CFM* p_create_cfm = &p_data->mca_evt.mca_data.create_cfm;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_create_cfm");
-#endif
-
-  if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK) {
-    p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT,
-                          p_data);
-    return;
-  }
-
-  if (p_dcb->dch_oper == BTA_HL_DCH_OP_LOCAL_OPEN) {
-    if (p_create_cfm->rsp_code == MCA_RSP_SUCCESS) {
-      if (bta_hl_validate_cfg(app_idx, mcl_idx, mdl_idx, p_create_cfm->cfg)) {
-        bta_hl_set_dch_chan_cfg(app_idx, mcl_idx, mdl_idx, p_data);
-
-        if (MCA_DataChnlCfg((tMCA_CL)p_mcb->mcl_handle, &p_dcb->chnl_cfg) !=
-            MCA_SUCCESS) {
-          /* this should not happen */
-          APPL_TRACE_ERROR("Unable to create data channel");
-          MCA_Abort((tMCA_CL)p_mcb->mcl_handle);
-          bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                                BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-        } else {
-          if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-            p_dcb->echo_oper = BTA_HL_ECHO_OP_DCH_OPEN_CFM;
-          }
-        }
-      } else {
-        MCA_Abort((tMCA_CL)p_mcb->mcl_handle);
-        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                              BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-      }
-    } else {
-      APPL_TRACE_ERROR("MCA Create- failed");
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_mca_create
- *
- * Description      Action routine for processing the MDL create request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_mca_create(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                           tBTA_HL_DATA* p_data) {
-  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;
-  uint8_t sdp_idx;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_mca_create");
-#endif
-
-  if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->ctrl_psm,
-                                         &sdp_idx) &&
-      bta_hl_validate_peer_cfg(app_idx, mcl_idx, mdl_idx, p_dcb->peer_mdep_id,
-                               p_dcb->peer_mdep_role, sdp_idx)) {
-    p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
-    result = MCA_CreateMdl((tMCA_CL)p_mcb->mcl_handle, p_dcb->local_mdep_id,
-                           p_mcb->data_psm, p_dcb->mdl_id, p_dcb->peer_mdep_id,
-                           p_dcb->local_cfg, NULL);
-    if (result != MCA_SUCCESS) {
-      APPL_TRACE_ERROR("MCA_CreateMdl FAIL mca_result=%d", result);
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                            BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-    }
-  } else {
-    APPL_TRACE_ERROR("MCA Create- SDP idx or peer MDEP cfg not found");
-    bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                          p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_sdp_fail
- *
- * Description      Action routine for processing the SDP failed event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_dch_sdp_fail(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                         tBTA_HL_DATA* p_data) {
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_dch_sdp_fail");
-#endif
-  bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                        p_data);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback
- *
- * Description      This is the SDP callback function used by HL.
- *                  This function will be executed by SDP when the service
- *                  search is completed.  If the search is successful, it
- *                  finds the first record in the database that matches the
- *                  UUID of the search.  Then retrieves the scn from the
- *                  record.
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback(uint8_t sdp_oper, uint8_t app_idx, uint8_t mcl_idx,
-                             uint8_t mdl_idx, uint16_t status) {
-  tBTA_HL_MCL_CB* p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  tBTA_HL_SDP_REC* p_hdp_rec;
-  tBTA_HL_CCH_SDP* p_cch_buf;
-  tBTA_HL_DCH_SDP* p_dch_buf;
-  tSDP_DISC_REC* p_rec = NULL;
-  tSDP_PROTOCOL_ELEM pe;
-  tSDP_DISC_ATTR* p_attr;
-  uint8_t i, rec_cnt;
-  tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature;
-  bool sdp_parsing_ok = false, result = false;
-  uint16_t event;
-  tBTA_HL_MDL_CB* p_dcb;
-  uint16_t service_uuid;
-  uint16_t name_len;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG(
-      "bta_hl_sdp_cback status:%d sdp_oper=%d app_idx=%d, mcl_idx=%d,   "
-      "mdl_idx=%d",
-      status, sdp_oper, app_idx, mcl_idx, mdl_idx);
-#endif
-
-  rec_cnt = 0;
-  service_uuid = bta_hl_get_service_uuids(sdp_oper, app_idx, mcl_idx, mdl_idx);
-
-  if (status == SDP_SUCCESS || status == SDP_DB_FULL) {
-    memset(&p_cb->sdp, 0, sizeof(tBTA_HL_SDP));
-    do {
-      if (bta_hl_find_service_in_db(app_idx, mcl_idx, service_uuid, &p_rec)) {
-        p_hdp_rec = &p_cb->sdp.sdp_rec[rec_cnt];
-        p_cb->sdp.num_recs = rec_cnt + 1;
-      } else {
-        break;
-      }
-
-      if (SDP_FindProtocolListElemInRec(p_rec, UUID_PROTOCOL_L2CAP, &pe)) {
-        p_hdp_rec->ctrl_psm = (uint16_t)pe.params[0];
-      } else {
-        APPL_TRACE_WARNING("Control PSM not found");
-        break;
-      }
-      if (SDP_FindAddProtoListsElemInRec(p_rec, UUID_PROTOCOL_L2CAP, &pe)) {
-        p_hdp_rec->data_psm = (uint16_t)pe.params[0];
-      } else {
-        APPL_TRACE_WARNING("Data PSM not found");
-        break;
-      }
-
-      p_hdp_rec->srv_name[0] = '\0';
-      p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_NAME);
-      if (p_attr != NULL) {
-        if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
-          name_len = (uint16_t)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
-        else
-          name_len = BT_MAX_SERVICE_NAME_LEN;
-        memcpy(p_hdp_rec->srv_name, p_attr->attr_value.v.array, name_len);
-      }
-
-      p_hdp_rec->srv_desp[0] = '\0';
-      p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_SERVICE_DESCRIPTION);
-      if (p_attr != NULL) {
-        if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
-          name_len = (uint16_t)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
-        else
-          name_len = BT_MAX_SERVICE_NAME_LEN;
-        memcpy(p_hdp_rec->srv_desp, p_attr->attr_value.v.array, name_len);
-      }
-
-      p_hdp_rec->provider_name[0] = '\0';
-      p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_PROVIDER_NAME);
-      if (p_attr != NULL) {
-        if (SDP_DISC_ATTR_LEN(p_attr->attr_len_type) < BT_MAX_SERVICE_NAME_LEN)
-          name_len = (uint16_t)SDP_DISC_ATTR_LEN(p_attr->attr_len_type);
-        else
-          name_len = BT_MAX_SERVICE_NAME_LEN;
-        memcpy(p_hdp_rec->provider_name, p_attr->attr_value.v.array, name_len);
-      }
-
-      p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HDP_MCAP_SUP_PROC);
-      if (p_attr != NULL) {
-        p_hdp_rec->mcap_sup_proc = p_attr->attr_value.v.u8;
-      } else {
-        APPL_TRACE_WARNING("MCAP SUP PROC not found");
-        break;
-      }
-
-      p_attr = SDP_FindAttributeInRec(p_rec, ATTR_ID_HDP_SUP_FEAT_LIST);
-      if (p_attr != NULL) {
-        if (bta_hl_fill_sup_feature_list(p_attr, &sup_feature)) {
-          p_hdp_rec->num_mdeps = (uint8_t)sup_feature.num_elems;
-          APPL_TRACE_WARNING("bta_hl_sdp_cback num_mdeps %d",
-                             sup_feature.num_elems);
-          for (i = 0; i < sup_feature.num_elems; i++) {
-            p_hdp_rec->mdep_cfg[i].data_type =
-                sup_feature.list_elem[i].data_type;
-            p_hdp_rec->mdep_cfg[i].mdep_id = sup_feature.list_elem[i].mdep_id;
-            p_hdp_rec->mdep_cfg[i].mdep_role =
-                sup_feature.list_elem[i].mdep_role;
-            /* Check MDEP Description pointer to prevent crash due to null
-             * pointer */
-            if (sup_feature.list_elem[i].p_mdep_desp != NULL) {
-              strlcpy(p_hdp_rec->mdep_cfg[i].mdep_desp,
-                      sup_feature.list_elem[i].p_mdep_desp,
-                      BTA_HL_MDEP_DESP_LEN);
-            } else {
-              APPL_TRACE_ERROR(
-                  "bta_hl_sdp_cback Incorrect Mdep[%d] Description (Null ptr)",
-                  i);
-            }
-          }
-
-          sdp_parsing_ok = true;
-        } else {
-          APPL_TRACE_WARNING("HDP supported feature list fill failed");
-          break;
-        }
-      } else {
-        APPL_TRACE_WARNING("HDP supported feature list not found");
-        break;
-      }
-#if (BTA_HL_DEBUG == TRUE)
-      APPL_TRACE_DEBUG("record=%d ctrl_psm=%0x data_psm=%x", rec_cnt + 1,
-                       p_hdp_rec->ctrl_psm, p_hdp_rec->data_psm);
-      APPL_TRACE_DEBUG("srv_name=[%s]", (p_hdp_rec->srv_name[0] != '\0')
-                                            ? p_hdp_rec->srv_name
-                                            : "NULL");
-      APPL_TRACE_DEBUG("srv_desp=[%s]", (p_hdp_rec->srv_desp[0] != '\0')
-                                            ? p_hdp_rec->srv_desp
-                                            : "NULL");
-      for (i = 0; i < sup_feature.num_elems; i++) {
-        APPL_TRACE_DEBUG(
-            "index=0x%02x mdep_id=0x%04x data type=0x%04x mdep role=%s(0x%02x)",
-            (i + 1), p_hdp_rec->mdep_cfg[i].mdep_id,
-            p_hdp_rec->mdep_cfg[i].data_type,
-            (p_hdp_rec->mdep_cfg[i].mdep_role == BTA_HL_MDEP_ROLE_SOURCE)
-                ? "Src"
-                : "Snk",
-            p_hdp_rec->mdep_cfg[i].mdep_role);
-      }
-      APPL_TRACE_DEBUG("provider_name=[%s]",
-                       (p_hdp_rec->provider_name[0] != '\0')
-                           ? p_hdp_rec->provider_name
-                           : "NULL");
-      APPL_TRACE_DEBUG("found MCAP sup procedure=%d",
-                       p_cb->sdp.sdp_rec[rec_cnt].mcap_sup_proc);
-#endif
-      rec_cnt++;
-      if (rec_cnt >= BTA_HL_NUM_SDP_RECS) {
-        APPL_TRACE_WARNING("No more spaces for SDP recs max_rec_cnt=%d",
-                           BTA_HL_NUM_SDP_RECS);
-        break;
-      }
-
-    } while (true);
-  }
-
-  osi_free_and_reset((void**)&p_cb->p_db);
-
-  if ((status == SDP_SUCCESS || status == SDP_DB_FULL) && p_cb->sdp.num_recs &&
-      sdp_parsing_ok) {
-    result = true;
-  } else {
-    APPL_TRACE_WARNING(
-        "SDP Failed sdp_status=%d num_recs=%d sdp_parsing_ok=%d ", status,
-        p_cb->sdp.num_recs, sdp_parsing_ok);
-  }
-
-  p_cb->sdp_oper = BTA_HL_SDP_OP_NONE;
-
-  switch (sdp_oper) {
-    case BTA_HL_SDP_OP_CCH_INIT:
-    case BTA_HL_SDP_OP_SDP_QUERY_NEW:
-    case BTA_HL_SDP_OP_SDP_QUERY_CURRENT:
-
-      /* send result in event back to BTA */
-      p_cch_buf = (tBTA_HL_CCH_SDP*)osi_malloc(sizeof(tBTA_HL_CCH_SDP));
-      if (result) {
-        if (sdp_oper == BTA_HL_SDP_OP_CCH_INIT) {
-          event = BTA_HL_CCH_SDP_OK_EVT;
-          if (p_cb->close_pending) event = BTA_HL_CCH_SDP_FAIL_EVT;
-        } else {
-          event = BTA_HL_SDP_QUERY_OK_EVT;
-        }
-      } else {
-        if (sdp_oper == BTA_HL_SDP_OP_CCH_INIT)
-          event = BTA_HL_CCH_SDP_FAIL_EVT;
-        else
-          event = BTA_HL_SDP_QUERY_FAIL_EVT;
-      }
-      p_cch_buf->hdr.event = event;
-
-      p_cch_buf->app_idx = app_idx;
-      p_cch_buf->mcl_idx = mcl_idx;
-      p_cch_buf->release_mcl_cb = false;
-      if (sdp_oper == BTA_HL_SDP_OP_SDP_QUERY_NEW)
-        p_cch_buf->release_mcl_cb = true;
-
-      bta_sys_sendmsg(p_cch_buf);
-      break;
-    case BTA_HL_SDP_OP_DCH_OPEN_INIT:
-    case BTA_HL_SDP_OP_DCH_RECONNECT_INIT:
-      p_dch_buf = (tBTA_HL_DCH_SDP*)osi_malloc(sizeof(tBTA_HL_DCH_SDP));
-      p_dch_buf->hdr.event = BTA_HL_DCH_SDP_FAIL_EVT;
-      p_dch_buf->app_idx = app_idx;
-      p_dch_buf->mcl_idx = mcl_idx;
-      p_dch_buf->mdl_idx = mdl_idx;
-      p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-      if (p_dcb->abort_oper & BTA_HL_ABORT_PENDING_MASK) {
-        p_dcb->abort_oper &= ~BTA_HL_ABORT_PENDING_MASK;
-        result = false;
-      }
-      if (result) {
-        if (sdp_oper == BTA_HL_SDP_OP_DCH_OPEN_INIT) {
-          if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-            p_dch_buf->hdr.event = BTA_HL_DCH_ECHO_TEST_EVT;
-          } else {
-            p_dch_buf->hdr.event = BTA_HL_DCH_OPEN_EVT;
-          }
-        } else {
-          p_dch_buf->hdr.event = BTA_HL_DCH_RECONNECT_EVT;
-        }
-      }
-      bta_sys_sendmsg(p_dch_buf);
-      break;
-    default:
-      break;
-  }
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback0
- *
- * Description      This is the SDP callback function used by index = 0
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback0(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[0].sdp_oper, bta_hl_cb.scb[0].app_idx,
-                   bta_hl_cb.scb[0].mcl_idx, bta_hl_cb.scb[0].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(0);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback1
- *
- * Description      This is the SDP callback function used by index = 1
- *
- * Parameters       status  - status of the SDP callabck
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback1(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[1].sdp_oper, bta_hl_cb.scb[1].app_idx,
-                   bta_hl_cb.scb[1].mcl_idx, bta_hl_cb.scb[1].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(1);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback2
- *
- * Description      This is the SDP callback function used by index = 2
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback2(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[2].sdp_oper, bta_hl_cb.scb[2].app_idx,
-                   bta_hl_cb.scb[2].mcl_idx, bta_hl_cb.scb[2].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(2);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback3
- *
- * Description      This is the SDP callback function used by index = 3
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback3(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[3].sdp_oper, bta_hl_cb.scb[3].app_idx,
-                   bta_hl_cb.scb[3].mcl_idx, bta_hl_cb.scb[3].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(3);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback4
- *
- * Description      This is the SDP callback function used by index = 4
- *
- * Parameters       status  - status of the SDP callabck
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback4(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[4].sdp_oper, bta_hl_cb.scb[4].app_idx,
-                   bta_hl_cb.scb[4].mcl_idx, bta_hl_cb.scb[4].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(4);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback5
- *
- * Description      This is the SDP callback function used by index = 5
- *
- * Parameters       status  - status of the SDP callabck
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback5(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[5].sdp_oper, bta_hl_cb.scb[5].app_idx,
-                   bta_hl_cb.scb[5].mcl_idx, bta_hl_cb.scb[5].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(5);
-}
-
-/******************************************************************************
- *
- * Function         bta_hl_sdp_cback6
- *
- * Description      This is the SDP callback function used by index = 6
- *
- * Returns          void.
- *
- *****************************************************************************/
-static void bta_hl_sdp_cback6(uint16_t status) {
-  bta_hl_sdp_cback(bta_hl_cb.scb[6].sdp_oper, bta_hl_cb.scb[6].app_idx,
-                   bta_hl_cb.scb[6].mcl_idx, bta_hl_cb.scb[6].mdl_idx, status);
-  bta_hl_deallocate_spd_cback(6);
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_deallocate_spd_cback
- *
- * Description   Deallocate a SDP control block
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-void bta_hl_deallocate_spd_cback(uint8_t sdp_cback_idx) {
-  tBTA_HL_SDP_CB* p_spd_cb = &bta_hl_cb.scb[sdp_cback_idx];
-
-  memset(p_spd_cb, 0, sizeof(tBTA_HL_SDP_CB));
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_deallocate_spd_cback index=%d", sdp_cback_idx);
-#endif
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_allocate_spd_cback
- *
- * Description   Finds a not in used SDP control block index
- *
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-tSDP_DISC_CMPL_CB* bta_hl_allocate_spd_cback(tBTA_HL_SDP_OPER sdp_oper,
-                                             uint8_t app_idx, uint8_t mcl_idx,
-                                             uint8_t mdl_idx,
-                                             uint8_t* p_sdp_cback_idx) {
-  uint8_t i;
-  tSDP_DISC_CMPL_CB* p_cbcak = NULL;
-
-  for (i = 0; i < BTA_HL_NUM_SDP_CBACKS; i++) {
-    if (!bta_hl_cb.scb[i].in_use) {
-      p_cbcak = bta_hl_sdp_cback_arr[i];
-      bta_hl_cb.scb[i].in_use = true;
-      bta_hl_cb.scb[i].sdp_oper = sdp_oper;
-      bta_hl_cb.scb[i].app_idx = app_idx;
-      bta_hl_cb.scb[i].mcl_idx = mcl_idx;
-      bta_hl_cb.scb[i].mdl_idx = mdl_idx;
-      *p_sdp_cback_idx = i;
-      break;
-    }
-  }
-
-  if (i == BTA_HL_NUM_SDP_CBACKS) {
-    APPL_TRACE_WARNING("No scb is available to allocate")
-  } else {
-#if (BTA_HL_DEBUG == TRUE)
-    APPL_TRACE_DEBUG("bta_hl_allocate_spd_cback cback_idx=%d ", i);
-    APPL_TRACE_DEBUG("sdp_oper=%d, app_idx=%d, mcl_idx=%d,  mdl_idx=%d",
-                     bta_hl_cb.scb[i].sdp_oper, bta_hl_cb.scb[i].app_idx,
-                     bta_hl_cb.scb[i].mcl_idx, bta_hl_cb.scb[i].mdl_idx);
-#endif
-  }
-  return p_cbcak;
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_init_sdp
- *
- * Description      Action routine for processing the SDP initiattion request
- *
- * Returns          void
- *
- ******************************************************************************/
-tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper, uint8_t app_idx,
-                               uint8_t mcl_idx, uint8_t mdl_idx) {
-  tBTA_HL_MCL_CB* p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  uint16_t attr_list[BTA_HL_NUM_SRCH_ATTR];
-  uint16_t num_attrs = BTA_HL_NUM_SRCH_ATTR;
-  tBTA_HL_STATUS status;
-  uint8_t sdp_cback_idx;
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG(
-      "bta_hl_init_sdp sdp_oper=%d app_idx=%d mcl_idx=%d, mdl_idx=%d", sdp_oper,
-      app_idx, mcl_idx, mdl_idx);
-#endif
-  p_cb->sdp_cback = bta_hl_allocate_spd_cback(sdp_oper, app_idx, mcl_idx,
-                                              mdl_idx, &sdp_cback_idx);
-  if (p_cb->sdp_cback != NULL) {
-    if (p_cb->p_db == NULL)
-      (p_cb->p_db = (tSDP_DISCOVERY_DB*)osi_malloc(BTA_HL_DISC_SIZE));
-    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_ADDITION_PROTO_DESC_LISTS;
-    attr_list[4] = ATTR_ID_SERVICE_NAME;
-    attr_list[5] = ATTR_ID_SERVICE_DESCRIPTION;
-    attr_list[6] = ATTR_ID_PROVIDER_NAME;
-    attr_list[7] = ATTR_ID_HDP_SUP_FEAT_LIST;
-    attr_list[8] = ATTR_ID_HDP_DATA_EXCH_SPEC;
-    attr_list[9] = ATTR_ID_HDP_MCAP_SUP_PROC;
-
-    Uuid uuid_list = Uuid::From16Bit(UUID_SERVCLASS_HDP_PROFILE);
-    SDP_InitDiscoveryDb(p_cb->p_db, BTA_HL_DISC_SIZE, 1, &uuid_list, num_attrs,
-                        attr_list);
-
-    if (!SDP_ServiceSearchAttributeRequest(p_cb->bd_addr, p_cb->p_db,
-                                           p_cb->sdp_cback)) {
-      status = BTA_HL_STATUS_FAIL;
-    } else {
-      status = BTA_HL_STATUS_OK;
-    }
-  } else {
-    status = BTA_HL_STATUS_SDP_NO_RESOURCE;
-  }
-
-  if (status != BTA_HL_STATUS_OK) {
-    osi_free_and_reset((void**)&p_cb->p_db);
-    if (status != BTA_HL_STATUS_SDP_NO_RESOURCE)
-      bta_hl_deallocate_spd_cback(sdp_cback_idx);
-  }
-
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_sdp_init
- *
- * Description      Action routine for processing the CCH SDP init event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_sdp_init(uint8_t app_idx, uint8_t mcl_idx,
-                         tBTA_HL_DATA* p_data) {
-  tBTA_HL_MCL_CB* p_cb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_init_sdp");
-#endif
-  if (p_cb->sdp_oper == BTA_HL_SDP_OP_NONE) {
-    p_cb->app_id = p_data->api_cch_open.app_id;
-    p_cb->sdp_oper = BTA_HL_SDP_OP_CCH_INIT;
-
-    if (bta_hl_init_sdp(p_cb->sdp_oper, app_idx, mcl_idx, 0xFF) !=
-        BTA_HL_STATUS_OK) {
-      p_cb->sdp_oper = BTA_HL_SDP_OP_NONE;
-      bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_SDP_FAIL_EVT, p_data);
-    }
-  } else {
-    APPL_TRACE_ERROR("SDP in use");
-    bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_SDP_FAIL_EVT, p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_mca_open
- *
- * Description      Action routine for processing the CCH open request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_mca_open(uint8_t app_idx, uint8_t mcl_idx,
-                         tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  uint8_t sdp_idx;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_mca_open");
-#endif
-
-  if (bta_hl_find_sdp_idx_using_ctrl_psm(&p_mcb->sdp, p_mcb->req_ctrl_psm,
-                                         &sdp_idx)) {
-    p_mcb->ctrl_psm = p_mcb->sdp.sdp_rec[sdp_idx].ctrl_psm;
-    p_mcb->data_psm = p_mcb->sdp.sdp_rec[sdp_idx].data_psm;
-    if (MCA_ConnectReq((tMCA_HANDLE)p_acb->app_handle, p_mcb->bd_addr,
-                       p_mcb->ctrl_psm, p_mcb->sec_mask) != MCA_SUCCESS) {
-      bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT,
-                            p_data);
-    }
-  } else {
-    bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_mca_close
- *
- * Description      Action routine for processing the CCH close request
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_mca_close(uint8_t app_idx, uint8_t mcl_idx,
-                          tBTA_HL_DATA* p_data) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_mca_close mcl_handle=%d", p_mcb->mcl_handle);
-#endif
-  if (p_mcb->sdp_oper != BTA_HL_SDP_OP_CCH_INIT) {
-    if (p_mcb->mcl_handle) {
-      if (MCA_DisconnectReq((tMCA_HANDLE)p_mcb->mcl_handle) != MCA_SUCCESS) {
-        bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT,
-                              p_data);
-      }
-    } else {
-      p_mcb->close_pending = true;
-      APPL_TRACE_DEBUG(
-          "No valid mcl_handle to stop the CCH setup now so wait until CCH is "
-          "up then close it");
-    }
-  } else {
-    p_mcb->close_pending = true;
-    APPL_TRACE_DEBUG(
-        "can not stop the CCH setup becasue SDP is in progress so wait until "
-        "it is done");
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_close_cmpl
- *
- * Description      Action routine for processing the CCH close complete event
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_close_cmpl(uint8_t app_idx, uint8_t mcl_idx,
-                           tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-
-  tBTA_HL evt_data;
-  tBTA_HL_EVT event;
-  bool send_evt = true;
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_close_cmpl");
-#endif
-  bta_sys_conn_close(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
-
-  if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE &&
-      p_mcb->force_close_local_cch_opening) {
-    p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_OPEN;
-    APPL_TRACE_DEBUG(
-        "change cch_oper from BTA_HL_CCH_OP_LOCAL_CLOSE to "
-        "BTA_HL_CCH_OP_LOCAL_OPEN");
-  }
-
-  switch (p_mcb->cch_oper) {
-    case BTA_HL_CCH_OP_LOCAL_OPEN:
-      bta_hl_build_cch_open_cfm(&evt_data, p_mcb->app_id, p_acb->app_handle,
-                                p_mcb->mcl_handle, p_mcb->bd_addr,
-                                BTA_HL_STATUS_FAIL);
-      event = BTA_HL_CCH_OPEN_CFM_EVT;
-      break;
-    case BTA_HL_CCH_OP_LOCAL_CLOSE:
-      bta_hl_build_cch_close_cfm(&evt_data, p_acb->app_handle,
-                                 p_mcb->mcl_handle, BTA_HL_STATUS_OK);
-      event = BTA_HL_CCH_CLOSE_CFM_EVT;
-      break;
-    case BTA_HL_CCH_OP_REMOTE_CLOSE:
-      bta_hl_build_cch_close_ind(&evt_data, p_acb->app_handle,
-                                 p_mcb->mcl_handle, p_mcb->intentional_close);
-      event = BTA_HL_CCH_CLOSE_IND_EVT;
-      break;
-    default:
-      send_evt = false;
-      break;
-  }
-
-  memset(p_mcb, 0, sizeof(tBTA_HL_MCL_CB));
-
-  if (send_evt) p_acb->p_cback(event, (tBTA_HL*)&evt_data);
-
-  bta_hl_check_deregistration(app_idx, p_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_mca_disconnect
- *
- * Description      Action routine for processing the CCH disconnect indication
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_mca_disconnect(uint8_t app_idx, uint8_t mcl_idx,
-                               tBTA_HL_DATA* p_data) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  tBTA_HL_MDL_CB* p_dcb;
-  uint8_t i;
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_mca_disconnect");
-#endif
-
-  p_mcb->intentional_close = false;
-  if (p_data->mca_evt.mca_data.disconnect_ind.reason == L2CAP_DISC_OK) {
-    p_mcb->intentional_close = true;
-  }
-
-  for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-    p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, i);
-    if (p_dcb->in_use && (p_dcb->dch_state != BTA_HL_DCH_IDLE_ST)) {
-      if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE) {
-        bta_hl_dch_sm_execute(app_idx, mcl_idx, i, BTA_HL_DCH_CLOSE_CMPL_EVT,
-                              p_data);
-      } else {
-        bta_hl_dch_sm_execute(app_idx, mcl_idx, i, BTA_HL_MCA_CLOSE_IND_EVT,
-                              p_data);
-      }
-    }
-  }
-  bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_CMPL_EVT, p_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_mca_disc_open
- *
- * Description      Action routine for disconnect the just opened Control
- *                  channel
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_mca_disc_open(uint8_t app_idx, uint8_t mcl_idx,
-                              tBTA_HL_DATA* p_data) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_mca_disc_open mcl_handle=0x%x close_pending=%d",
-                   p_data->mca_evt.mcl_handle, p_mcb->close_pending);
-#endif
-
-  p_mcb->close_pending = false;
-  p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
-  bta_hl_cch_mca_close(app_idx, mcl_idx, p_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_mca_rsp_tout
- *
- * Description      Action routine for processing the MCAP response timeout
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_mca_rsp_tout(uint8_t app_idx, uint8_t mcl_idx,
-                             tBTA_HL_DATA* p_data) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_mca_rsp_tout");
-#endif
-
-  p_mcb->rsp_tout = true;
-
-  bta_hl_check_cch_close(app_idx, mcl_idx, p_data, true);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cch_mca_connect
- *
- * Description      Action routine for processing the CCH connect indication
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_cch_mca_connect(uint8_t app_idx, uint8_t mcl_idx,
-                            tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  tBTA_HL evt_data;
-  tBTA_HL_EVT event;
-  bool send_event = true;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_cch_mca_connect mcl_handle=%d ",
-                   p_data->mca_evt.mcl_handle);
-#endif
-
-  p_mcb->mcl_handle = p_data->mca_evt.mcl_handle;
-  p_mcb->bd_addr = p_data->mca_evt.mca_data.connect_ind.bd_addr;
-  p_mcb->cch_mtu = p_data->mca_evt.mca_data.connect_ind.mtu;
-
-  bta_sys_conn_open(BTA_ID_HL, p_acb->app_id, p_mcb->bd_addr);
-  switch (p_mcb->cch_oper) {
-    case BTA_HL_CCH_OP_LOCAL_OPEN:
-      bta_hl_build_cch_open_cfm(&evt_data, p_mcb->app_id, p_acb->app_handle,
-                                p_mcb->mcl_handle, p_mcb->bd_addr,
-                                BTA_HL_STATUS_OK);
-      event = BTA_HL_CCH_OPEN_CFM_EVT;
-      break;
-    case BTA_HL_CCH_OP_REMOTE_OPEN:
-      bta_hl_build_cch_open_ind(&evt_data, p_acb->app_handle, p_mcb->mcl_handle,
-                                p_mcb->bd_addr);
-      event = BTA_HL_CCH_OPEN_IND_EVT;
-      break;
-    default:
-      send_event = false;
-      break;
-  }
-
-  p_mcb->cch_oper = BTA_HL_CCH_OP_NONE;
-  if (send_event) p_acb->p_cback(event, (tBTA_HL*)&evt_data);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_mcap_ctrl_cback
- *
- * Description      MCAP control callback function for HL.
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_mcap_ctrl_cback(tMCA_HANDLE handle, tMCA_CL mcl, uint8_t event,
-                            tMCA_CTRL* p_data) {
-  bool send_event = true;
-  uint16_t mca_event;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_EVENT("bta_hl_mcap_ctrl_cback event[%s]",
-                   bta_hl_mcap_evt_code(event));
-#endif
-
-  switch (event) {
-    case MCA_CREATE_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_CREATE_IND_EVT;
-      break;
-    case MCA_CREATE_CFM_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_CREATE_CFM_EVT;
-      break;
-    case MCA_RECONNECT_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_RECONNECT_IND_EVT;
-      break;
-    case MCA_RECONNECT_CFM_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_RECONNECT_CFM_EVT;
-      break;
-    case MCA_ABORT_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_ABORT_IND_EVT;
-      break;
-    case MCA_ABORT_CFM_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_ABORT_CFM_EVT;
-      break;
-    case MCA_DELETE_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_DELETE_IND_EVT;
-      break;
-    case MCA_DELETE_CFM_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_DELETE_CFM_EVT;
-      break;
-    case MCA_CONNECT_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_CONNECT_IND_EVT;
-      break;
-    case MCA_DISCONNECT_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_DISCONNECT_IND_EVT;
-      break;
-    case MCA_OPEN_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_OPEN_IND_EVT;
-      break;
-    case MCA_OPEN_CFM_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_OPEN_CFM_EVT;
-      break;
-    case MCA_CLOSE_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_CLOSE_IND_EVT;
-      break;
-    case MCA_CLOSE_CFM_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_CLOSE_CFM_EVT;
-      break;
-    case MCA_CONG_CHG_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_CONG_CHG_EVT;
-      break;
-    case MCA_RSP_TOUT_IND_EVT:
-      mca_event = (uint16_t)BTA_HL_MCA_RSP_TOUT_IND_EVT;
-      break;
-    case MCA_ERROR_RSP_EVT:
-
-    default:
-      send_event = false;
-      break;
-  }
-
-  if (send_event) {
-    tBTA_HL_MCA_EVT* p_msg =
-        (tBTA_HL_MCA_EVT*)osi_malloc(sizeof(tBTA_HL_MCA_EVT));
-    p_msg->hdr.event = mca_event;
-    p_msg->app_handle = (tBTA_HL_APP_HANDLE)handle;
-    p_msg->mcl_handle = (tBTA_HL_MCL_HANDLE)mcl;
-    memcpy(&p_msg->mca_data, p_data, sizeof(tMCA_CTRL));
-    bta_sys_sendmsg(p_msg);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_mcap_data_cback
- *
- * Description      MCAP data callback function for HL.
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_mcap_data_cback(tMCA_DL mdl, BT_HDR* p_pkt) {
-  uint8_t app_idx, mcl_idx, mdl_idx;
-  if (bta_hl_find_mdl_idx_using_handle((tBTA_HL_MDL_HANDLE)mdl, &app_idx,
-                                       &mcl_idx, &mdl_idx)) {
-    tBTA_HL_MCA_RCV_DATA_EVT* p_msg =
-        (tBTA_HL_MCA_RCV_DATA_EVT*)osi_malloc(sizeof(tBTA_HL_MCA_RCV_DATA_EVT));
-    p_msg->hdr.event = BTA_HL_MCA_RCV_DATA_EVT;
-    p_msg->app_idx = app_idx;
-    p_msg->mcl_idx = mcl_idx;
-    p_msg->mdl_idx = mdl_idx;
-    p_msg->p_pkt = p_pkt;
-    bta_sys_sendmsg(p_msg);
-  }
-}
-
-/*****************************************************************************
- *  Debug Functions
- ****************************************************************************/
-#if (BTA_HL_DEBUG == TRUE)
-
-#define CASE_RETURN_STR(const) \
-  case const:                  \
-    return #const;
-
-/*******************************************************************************
- *
- * Function         bta_hl_mcap_evt_code
- *
- * Description      get the MCAP event string pointer
- *
- * Returns          char * - event string pointer
- *
- ******************************************************************************/
-static const char* bta_hl_mcap_evt_code(uint8_t evt_code) {
-  switch (evt_code) {
-    CASE_RETURN_STR(MCA_ERROR_RSP_EVT)
-    CASE_RETURN_STR(MCA_CREATE_IND_EVT)
-    CASE_RETURN_STR(MCA_CREATE_CFM_EVT)
-    CASE_RETURN_STR(MCA_RECONNECT_IND_EVT)
-    CASE_RETURN_STR(MCA_RECONNECT_CFM_EVT)
-    CASE_RETURN_STR(MCA_ABORT_IND_EVT)
-    CASE_RETURN_STR(MCA_ABORT_CFM_EVT)
-    CASE_RETURN_STR(MCA_DELETE_IND_EVT)
-    CASE_RETURN_STR(MCA_DELETE_CFM_EVT)
-    CASE_RETURN_STR(MCA_CONNECT_IND_EVT)
-    CASE_RETURN_STR(MCA_DISCONNECT_IND_EVT)
-    CASE_RETURN_STR(MCA_OPEN_IND_EVT)
-    CASE_RETURN_STR(MCA_OPEN_CFM_EVT)
-    CASE_RETURN_STR(MCA_CLOSE_IND_EVT)
-    CASE_RETURN_STR(MCA_CLOSE_CFM_EVT)
-    CASE_RETURN_STR(MCA_CONG_CHG_EVT)
-    CASE_RETURN_STR(MCA_RSP_TOUT_IND_EVT)
-    default:
-      return "Unknown MCAP event code";
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_cback_evt_code
- *
- * Description      get the HDP event string pointer
- *
- * Returns          char * - event string pointer
- *
- ******************************************************************************/
-static const char* bta_hl_cback_evt_code(uint8_t evt_code) {
-  switch (evt_code) {
-    CASE_RETURN_STR(BTA_HL_CCH_OPEN_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_CCH_OPEN_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_CCH_CLOSE_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_CCH_CLOSE_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_OPEN_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_OPEN_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_CLOSE_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_CLOSE_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_RCV_DATA_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_REGISTER_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DEREGISTER_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_RECONNECT_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_RECONNECT_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_ECHO_TEST_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_SDP_QUERY_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_CONG_CHG_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_CREATE_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DELETE_MDL_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DELETE_MDL_CFM_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_ABORT_IND_EVT)
-    CASE_RETURN_STR(BTA_HL_DCH_ABORT_CFM_EVT)
-    default:
-      return "Unknown HDP event code";
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_dch_oper_code
- *
- * Description      Get the DCH operation string
- *
- * Returns          char * - DCH operation string pointer
- *
- ******************************************************************************/
-static const char* bta_hl_dch_oper_code(tBTA_HL_DCH_OPER oper_code) {
-  switch (oper_code) {
-    CASE_RETURN_STR(BTA_HL_DCH_OP_NONE)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_REMOTE_CREATE)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_LOCAL_OPEN)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_REMOTE_OPEN)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_LOCAL_CLOSE)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_REMOTE_CLOSE)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_LOCAL_DELETE)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_REMOTE_DELETE)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_LOCAL_RECONNECT)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_REMOTE_RECONNECT)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST)
-    CASE_RETURN_STR(BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT)
-    default:
-      return "Unknown DCH oper code";
-  }
-}
-
-#endif /* Debug Functions */
-#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_api.cc b/bta/hl/bta_hl_api.cc
deleted file mode 100644
index fa82245..0000000
--- a/bta/hl/bta_hl_api.cc
+++ /dev/null
@@ -1,489 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation of the API for the HeaLth device profile (HL)
- *  subsystem of BTA, Broadcom Corp's Bluetooth application layer for mobile
- *  phones.
- *
- ******************************************************************************/
-
-#include <string.h>
-
-#include "bt_target.h"
-#if (HL_INCLUDED == TRUE)
-
-#include "bt_common.h"
-#include "bta_hl_api.h"
-#include "bta_hl_int.h"
-
-/*****************************************************************************
- *  Constants
- ****************************************************************************/
-
-static const tBTA_SYS_REG bta_hl_reg = {bta_hl_hdl_event, BTA_HlDisable};
-
-/*******************************************************************************
- *
- * Function         BTA_HlEnable
- *
- * Description      Enable the HL subsystems.  This function must be
- *                  called before any other functions in the HL API are called.
- *                  When the enable operation is completed the callback function
- *                  will be called with an BTA_HL_CTRL_ENABLE_CFM_EVT event.
- *
- * Parameters       p_cback - HL event call back function
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlEnable(tBTA_HL_CTRL_CBACK* p_ctrl_cback) {
-  tBTA_HL_API_ENABLE* p_buf =
-      (tBTA_HL_API_ENABLE*)osi_malloc(sizeof(tBTA_HL_API_ENABLE));
-
-  /* register with BTA system manager */
-  bta_sys_register(BTA_ID_HL, &bta_hl_reg);
-
-  p_buf->hdr.event = BTA_HL_API_ENABLE_EVT;
-  p_buf->p_cback = p_ctrl_cback;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDisable
- *
- * Description     Disable the HL subsystem.
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDisable(void) {
-  BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
-
-  bta_sys_deregister(BTA_ID_HL);
-  p_buf->event = BTA_HL_API_DISABLE_EVT;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlUpdate
- *
- * Description      Register an HDP application
- *
- * Parameters       app_id        - Application ID
- *                  p_reg_param   - non-platform related parameters for the
- *                                  HDP application
- *                  p_cback       - HL event callback fucntion
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlUpdate(uint8_t app_id, tBTA_HL_REG_PARAM* p_reg_param,
-                  bool is_register, tBTA_HL_CBACK* p_cback) {
-  tBTA_HL_API_UPDATE* p_buf =
-      (tBTA_HL_API_UPDATE*)osi_malloc(sizeof(tBTA_HL_API_UPDATE));
-
-  APPL_TRACE_DEBUG("%s", __func__);
-
-  p_buf->hdr.event = BTA_HL_API_UPDATE_EVT;
-  p_buf->app_id = app_id;
-  p_buf->is_register = is_register;
-
-  if (is_register) {
-    p_buf->sec_mask =
-        (p_reg_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
-    p_buf->p_cback = p_cback;
-    if (p_reg_param->p_srv_name)
-      strlcpy(p_buf->srv_name, p_reg_param->p_srv_name, BTA_SERVICE_NAME_LEN);
-    else
-      p_buf->srv_name[0] = 0;
-
-    if (p_reg_param->p_srv_desp)
-      strlcpy(p_buf->srv_desp, p_reg_param->p_srv_desp, BTA_SERVICE_DESP_LEN);
-    else
-      p_buf->srv_desp[0] = 0;
-
-    if (p_reg_param->p_provider_name)
-      strlcpy(p_buf->provider_name, p_reg_param->p_provider_name,
-              BTA_PROVIDER_NAME_LEN);
-    else
-      p_buf->provider_name[0] = 0;
-  }
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlRegister
- *
- * Description      Register an HDP application
- *
- * Parameters       app_id        - Application ID
- *                  p_reg_param   - non-platform related parameters for the
- *                                  HDP application
- *                  p_cback       - HL event callback fucntion
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlRegister(uint8_t app_id, tBTA_HL_REG_PARAM* p_reg_param,
-                    tBTA_HL_CBACK* p_cback) {
-  tBTA_HL_API_REGISTER* p_buf =
-      (tBTA_HL_API_REGISTER*)osi_malloc(sizeof(tBTA_HL_API_REGISTER));
-
-  p_buf->hdr.event = BTA_HL_API_REGISTER_EVT;
-  p_buf->app_id = app_id;
-  p_buf->sec_mask =
-      (p_reg_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
-  p_buf->p_cback = p_cback;
-
-  if (p_reg_param->p_srv_name)
-    strlcpy(p_buf->srv_name, p_reg_param->p_srv_name, BTA_SERVICE_NAME_LEN);
-  else
-    p_buf->srv_name[0] = 0;
-
-  if (p_reg_param->p_srv_desp)
-    strlcpy(p_buf->srv_desp, p_reg_param->p_srv_desp, BTA_SERVICE_DESP_LEN);
-  else
-    p_buf->srv_desp[0] = 0;
-
-  if (p_reg_param->p_provider_name)
-    strlcpy(p_buf->provider_name, p_reg_param->p_provider_name,
-            BTA_PROVIDER_NAME_LEN);
-  else
-    p_buf->provider_name[0] = 0;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDeregister
- *
- * Description      Deregister an HDP application
- *
- * Parameters       app_handle - Application handle
- *
- * Returns           void
- *
- ******************************************************************************/
-void BTA_HlDeregister(uint8_t app_id, tBTA_HL_APP_HANDLE app_handle) {
-  tBTA_HL_API_DEREGISTER* p_buf =
-      (tBTA_HL_API_DEREGISTER*)osi_malloc(sizeof(tBTA_HL_API_DEREGISTER));
-
-  p_buf->hdr.event = BTA_HL_API_DEREGISTER_EVT;
-  p_buf->app_id = app_id;
-  p_buf->app_handle = app_handle;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlCchOpen
- *
- * Description      Open a Control channel connection with the specified BD
- *                  address
- *
- * Parameters       app_handle - Application Handle
- *                  p_open_param - parameters for opening a control channel
- *
- * Returns          void
- *
- *                  Note: The control PSM value is used to select which
- *                  HDP insatnce should be used in case the peer device support
- *                  multiple HDP instances. Also, if the control PSM value is
- *                  zero then the first HDP instance is used for the control
- *                  channel setup
- ******************************************************************************/
-void BTA_HlCchOpen(uint8_t app_id, tBTA_HL_APP_HANDLE app_handle,
-                   tBTA_HL_CCH_OPEN_PARAM* p_open_param) {
-  tBTA_HL_API_CCH_OPEN* p_buf =
-      (tBTA_HL_API_CCH_OPEN*)osi_malloc(sizeof(tBTA_HL_API_CCH_OPEN));
-
-  p_buf->hdr.event = BTA_HL_API_CCH_OPEN_EVT;
-  p_buf->app_id = app_id;
-  p_buf->app_handle = app_handle;
-  p_buf->sec_mask =
-      (p_open_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
-  p_buf->bd_addr = p_open_param->bd_addr;
-  p_buf->ctrl_psm = p_open_param->ctrl_psm;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlCchClose
- *
- * Description      Close a Control channel connection with the specified MCL
- *                  handle
- *
- * Parameters       mcl_handle - MCL handle
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlCchClose(tBTA_HL_MCL_HANDLE mcl_handle) {
-  tBTA_HL_API_CCH_CLOSE* p_buf =
-      (tBTA_HL_API_CCH_CLOSE*)osi_malloc(sizeof(tBTA_HL_API_CCH_CLOSE));
-
-  p_buf->hdr.event = BTA_HL_API_CCH_CLOSE_EVT;
-  p_buf->mcl_handle = mcl_handle;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchOpen
- *
- * Description      Open a data channel connection with the specified DCH
- *                  parameters
- *
- * Parameters       mcl_handle - MCL handle
- *                  p_open_param - parameters for opening a data channel
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDchOpen(tBTA_HL_MCL_HANDLE mcl_handle,
-                   tBTA_HL_DCH_OPEN_PARAM* p_open_param) {
-  tBTA_HL_API_DCH_OPEN* p_buf =
-      (tBTA_HL_API_DCH_OPEN*)osi_malloc(sizeof(tBTA_HL_API_DCH_OPEN));
-
-  p_buf->hdr.event = BTA_HL_API_DCH_OPEN_EVT;
-  p_buf->mcl_handle = mcl_handle;
-  p_buf->ctrl_psm = p_open_param->ctrl_psm;
-  p_buf->local_mdep_id = p_open_param->local_mdep_id;
-  p_buf->peer_mdep_id = p_open_param->peer_mdep_id;
-  p_buf->local_cfg = p_open_param->local_cfg;
-  p_buf->sec_mask =
-      (p_open_param->sec_mask | BTA_SEC_AUTHENTICATE | BTA_SEC_ENCRYPT);
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchReconnect
- *
- * Description      Reconnect a data channel with the specified MDL_ID
- *
- * Parameters       mcl_handle      - MCL handle
-*8                  p_recon_param   - parameters for reconnecting a data channel
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDchReconnect(tBTA_HL_MCL_HANDLE mcl_handle,
-                        tBTA_HL_DCH_RECONNECT_PARAM* p_recon_param) {
-  tBTA_HL_API_DCH_RECONNECT* p_buf =
-      (tBTA_HL_API_DCH_RECONNECT*)osi_malloc(sizeof(tBTA_HL_API_DCH_RECONNECT));
-
-  p_buf->hdr.event = BTA_HL_API_DCH_RECONNECT_EVT;
-  p_buf->mcl_handle = mcl_handle;
-  p_buf->ctrl_psm = p_recon_param->ctrl_psm;
-  p_buf->mdl_id = p_recon_param->mdl_id;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchClose
- *
- * Description      Close a data channel with the specified MDL handle
- *
- * Parameters       mdl_handle  - MDL handle
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDchClose(tBTA_HL_MDL_HANDLE mdl_handle) {
-  tBTA_HL_API_DCH_CLOSE* p_buf =
-      (tBTA_HL_API_DCH_CLOSE*)osi_malloc(sizeof(tBTA_HL_API_DCH_CLOSE));
-
-  p_buf->hdr.event = BTA_HL_API_DCH_CLOSE_EVT;
-  p_buf->mdl_handle = mdl_handle;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchAbort
- *
- * Description      Abort the current data channel setup with the specified MCL
- *                  handle
- *
- * Parameters       mcl_handle  - MCL handle
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDchAbort(tBTA_HL_MCL_HANDLE mcl_handle) {
-  tBTA_HL_API_DCH_ABORT* p_buf =
-      (tBTA_HL_API_DCH_ABORT*)osi_malloc(sizeof(tBTA_HL_API_DCH_ABORT));
-
-  p_buf->hdr.event = BTA_HL_API_DCH_ABORT_EVT;
-  p_buf->mcl_handle = mcl_handle;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlSendData
- *
- * Description      Send an APDU to the peer device
- *
- * Parameters       mdl_handle  - MDL handle
- *                  pkt_size    - size of the data packet to be sent
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlSendData(tBTA_HL_MDL_HANDLE mdl_handle, uint16_t pkt_size) {
-  tBTA_HL_API_SEND_DATA* p_buf =
-      (tBTA_HL_API_SEND_DATA*)osi_malloc(sizeof(tBTA_HL_API_SEND_DATA));
-
-  p_buf->hdr.event = BTA_HL_API_SEND_DATA_EVT;
-  p_buf->mdl_handle = mdl_handle;
-  p_buf->pkt_size = pkt_size;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDeleteMdl
- *
- * Description      Delete the specified MDL_ID within the specified MCL handle
- *
- * Parameters       mcl_handle  - MCL handle
- *                  mdl_id      - MDL ID
- *
- * Returns          void
- *
- *                  note: If mdl_id = 0xFFFF then this means to delete all MDLs
- *                        and this value can only be used with DeleteMdl request
- *                        only not other requests
- *
- ******************************************************************************/
-void BTA_HlDeleteMdl(tBTA_HL_MCL_HANDLE mcl_handle, tBTA_HL_MDL_ID mdl_id) {
-  tBTA_HL_API_DELETE_MDL* p_buf =
-      (tBTA_HL_API_DELETE_MDL*)osi_malloc(sizeof(tBTA_HL_API_DELETE_MDL));
-
-  p_buf->hdr.event = BTA_HL_API_DELETE_MDL_EVT;
-  p_buf->mcl_handle = mcl_handle;
-  p_buf->mdl_id = mdl_id;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchEchoTest
- *
- * Description      Initiate an echo test with the specified MCL handle
- *
- * Parameters       mcl_handle           - MCL handle
-*8                  p_echo_test_param   -  parameters for echo testing
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDchEchoTest(tBTA_HL_MCL_HANDLE mcl_handle,
-                       tBTA_HL_DCH_ECHO_TEST_PARAM* p_echo_test_param) {
-  tBTA_HL_API_DCH_ECHO_TEST* p_buf =
-      (tBTA_HL_API_DCH_ECHO_TEST*)osi_malloc(sizeof(tBTA_HL_API_DCH_ECHO_TEST));
-
-  p_buf->hdr.event = BTA_HL_API_DCH_ECHO_TEST_EVT;
-  p_buf->mcl_handle = mcl_handle;
-  p_buf->ctrl_psm = p_echo_test_param->ctrl_psm;
-  p_buf->local_cfg = p_echo_test_param->local_cfg;
-  p_buf->pkt_size = p_echo_test_param->pkt_size;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlSdpQuery
- *
- * Description      SDP query request for the specified BD address
- *
- * Parameters       app_handle      - application handle
- *                  bd_addr         - BD address
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlSdpQuery(uint8_t app_id, tBTA_HL_APP_HANDLE app_handle,
-                    const RawAddress& bd_addr) {
-  tBTA_HL_API_SDP_QUERY* p_buf =
-      (tBTA_HL_API_SDP_QUERY*)osi_malloc(sizeof(tBTA_HL_API_SDP_QUERY));
-
-  p_buf->hdr.event = BTA_HL_API_SDP_QUERY_EVT;
-  p_buf->app_id = app_id;
-  p_buf->app_handle = app_handle;
-  p_buf->bd_addr = bd_addr;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchCreateMdlRsp
- *
- * Description      Set the Response and configuration values for the Create MDL
- *                  request
- *
- * Parameters       mcl_handle  - MCL handle
- *                  p_rsp_param - parameters specified whether the request
- *                                should be accepted or not and if it should be
- *                                accepted, then it also specified the
- *                                configuration response value
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTA_HlDchCreateRsp(tBTA_HL_MCL_HANDLE mcl_handle,
-                        tBTA_HL_DCH_CREATE_RSP_PARAM* p_rsp_param) {
-  tBTA_HL_API_DCH_CREATE_RSP* p_buf = (tBTA_HL_API_DCH_CREATE_RSP*)osi_malloc(
-      sizeof(tBTA_HL_API_DCH_CREATE_RSP));
-
-  p_buf->hdr.event = BTA_HL_API_DCH_CREATE_RSP_EVT;
-  p_buf->mcl_handle = mcl_handle;
-  p_buf->mdl_id = p_rsp_param->mdl_id;
-  p_buf->local_mdep_id = p_rsp_param->local_mdep_id;
-  p_buf->rsp_code = p_rsp_param->rsp_code;
-  p_buf->cfg_rsp = p_rsp_param->cfg_rsp;
-
-  bta_sys_sendmsg(p_buf);
-}
-
-#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_ci.cc b/bta/hl/bta_hl_ci.cc
deleted file mode 100644
index e48c74b..0000000
--- a/bta/hl/bta_hl_ci.cc
+++ /dev/null
@@ -1,162 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the HeaLth device profile (HL)
- *  subsystem call-in functions.
- *
- ******************************************************************************/
-
-#include <stddef.h>
-
-#include "bta_api.h"
-#include "bta_hl_api.h"
-#include "bta_hl_ci.h"
-#include "bta_hl_co.h"
-#include "bta_hl_int.h"
-#include "bta_sys.h"
-#include "btm_api.h"
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_get_tx_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_get_tx_data call-out function.
- *
- * Parameters       mdl_handle -MDL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_ci_get_tx_data(tBTA_HL_MDL_HANDLE mdl_handle, tBTA_HL_STATUS status,
-                           uint16_t evt) {
-  tBTA_HL_CI_GET_PUT_DATA* p_evt =
-      (tBTA_HL_CI_GET_PUT_DATA*)osi_malloc(sizeof(tBTA_HL_CI_GET_PUT_DATA));
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("%s mdl_handle=%d status=%d evt=%d\n", __func__, mdl_handle,
-                   status, evt);
-#endif
-
-  p_evt->hdr.event = evt;
-  p_evt->mdl_handle = mdl_handle;
-  p_evt->status = status;
-
-  bta_sys_sendmsg(p_evt);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_put_rx_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_put_rx_data call-out function.
- *
- * Parameters       mdl_handle -MDL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_put_rx_data(tBTA_HL_MDL_HANDLE mdl_handle,
-                                  tBTA_HL_STATUS status, uint16_t evt) {
-  tBTA_HL_CI_GET_PUT_DATA* p_evt =
-      (tBTA_HL_CI_GET_PUT_DATA*)osi_malloc(sizeof(tBTA_HL_CI_GET_PUT_DATA));
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("%s mdl_handle=%d status=%d evt=%d\n", __func__, mdl_handle,
-                   status, evt);
-#endif
-
-  p_evt->hdr.event = evt;
-  p_evt->mdl_handle = mdl_handle;
-  p_evt->status = status;
-
-  bta_sys_sendmsg(p_evt);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_get_echo_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_get_echo_data call-out function.
- *
- * Parameters       mcl_handle -MCL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_get_echo_data(tBTA_HL_MCL_HANDLE mcl_handle,
-                                    tBTA_HL_STATUS status, uint16_t evt) {
-  tBTA_HL_CI_ECHO_DATA* p_evt =
-      (tBTA_HL_CI_ECHO_DATA*)osi_malloc(sizeof(tBTA_HL_CI_ECHO_DATA));
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("%s mcl_handle=%d status=%d evt=%d\n", __func__, mcl_handle,
-                   status, evt);
-#endif
-
-  p_evt->hdr.event = evt;
-  p_evt->mcl_handle = mcl_handle;
-  p_evt->status = status;
-
-  bta_sys_sendmsg(p_evt);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_put_echo_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_put_echo_data call-out function.
- *
- * Parameters       mcl_handle -MCL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_put_echo_data(tBTA_HL_MCL_HANDLE mcl_handle,
-                                    tBTA_HL_STATUS status, uint16_t evt) {
-  tBTA_HL_CI_ECHO_DATA* p_evt =
-      (tBTA_HL_CI_ECHO_DATA*)osi_malloc(sizeof(tBTA_HL_CI_ECHO_DATA));
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("%s mcl_handle=%d status=%d evt=%d\n", __func__, mcl_handle,
-                   status, evt);
-#endif
-
-  p_evt->hdr.event = evt;
-  p_evt->mcl_handle = mcl_handle;
-  p_evt->status = status;
-
-  bta_sys_sendmsg(p_evt);
-}
diff --git a/bta/hl/bta_hl_int.h b/bta/hl/bta_hl_int.h
deleted file mode 100644
index c6dce11..0000000
--- a/bta/hl/bta_hl_int.h
+++ /dev/null
@@ -1,856 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 1998-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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the private file for the message access equipment (MSE)
- *  subsystem.
- *
- ******************************************************************************/
-#ifndef BTA_HL_INT_H
-#define BTA_HL_INT_H
-
-#include "bt_target.h"
-#include "bta_hl_api.h"
-#include "bta_hl_co.h"
-#include "bta_sys.h"
-#include "l2cdefs.h"
-
-typedef uint16_t(tBTA_HL_ALLOCATE_PSM)(void);
-
-/*****************************************************************************
- *  Constants and data types
- ****************************************************************************/
-
-#ifndef BTA_HL_DISC_SIZE
-#define BTA_HL_DISC_SIZE 1600
-#endif
-#define BTA_HL_NUM_SRCH_ATTR 10
-#define BTA_HL_MIN_SDP_MDEP_LEN 7
-
-/* L2CAP defualt parameters */
-#define BTA_HL_L2C_TX_WIN_SIZE 10
-#define BTA_HL_L2C_MAX_TRANSMIT 32
-#define BTA_HL_L2C_RTRANS_TOUT 2000
-#define BTA_HL_L2C_MON_TOUT 12000
-#define BTA_HL_L2C_MPS 1017
-
-/* L2CAP FCS setting*/
-#define BTA_HL_MCA_USE_FCS MCA_FCS_USE
-#define BTA_HL_MCA_NO_FCS MCA_FCS_BYPASS
-#define BTA_HL_L2C_USE_FCS 1
-#define BTA_HL_L2C_NO_FCS 0
-#define BTA_HL_DEFAULT_SOURCE_FCS BTA_HL_L2C_USE_FCS
-#define BTA_HL_MCA_FCS_USE_MASK MCA_FCS_USE_MASK
-
-/* SDP Operations */
-#define BTA_HL_SDP_OP_NONE 0
-#define BTA_HL_SDP_OP_CCH_INIT 1
-#define BTA_HL_SDP_OP_DCH_OPEN_INIT 2
-#define BTA_HL_SDP_OP_DCH_RECONNECT_INIT 3
-#define BTA_HL_SDP_OP_SDP_QUERY_NEW 4
-#define BTA_HL_SDP_OP_SDP_QUERY_CURRENT 5
-
-typedef uint8_t tBTA_HL_SDP_OPER;
-
-/* CCH Operations */
-#define BTA_HL_CCH_OP_NONE 0
-#define BTA_HL_CCH_OP_LOCAL_OPEN 1
-#define BTA_HL_CCH_OP_REMOTE_OPEN 2
-#define BTA_HL_CCH_OP_LOCAL_CLOSE 3
-#define BTA_HL_CCH_OP_REMOTE_CLOSE 4
-
-typedef uint8_t tBTA_HL_CCH_OPER;
-
-/* Pending DCH close operations when closing a CCH */
-#define BTA_HL_CCH_CLOSE_OP_DCH_NONE 0
-#define BTA_HL_CCH_CLOSE_OP_DCH_ABORT 1
-#define BTA_HL_CCH_CLOSE_OP_DCH_CLOSE 2
-typedef uint8_t tBTA_HL_CCH_CLOSE_DCH_OPER;
-
-/* DCH Operations */
-#define BTA_HL_DCH_OP_NONE 0
-#define BTA_HL_DCH_OP_REMOTE_CREATE 1
-#define BTA_HL_DCH_OP_LOCAL_OPEN 2
-#define BTA_HL_DCH_OP_REMOTE_OPEN 3
-#define BTA_HL_DCH_OP_LOCAL_CLOSE 4
-#define BTA_HL_DCH_OP_REMOTE_CLOSE 5
-#define BTA_HL_DCH_OP_LOCAL_DELETE 6
-#define BTA_HL_DCH_OP_REMOTE_DELETE 7
-#define BTA_HL_DCH_OP_LOCAL_RECONNECT 8
-#define BTA_HL_DCH_OP_REMOTE_RECONNECT 9
-#define BTA_HL_DCH_OP_LOCAL_CLOSE_ECHO_TEST 10
-#define BTA_HL_DCH_OP_LOCAL_CLOSE_RECONNECT 11
-
-typedef uint8_t tBTA_HL_DCH_OPER;
-
-/* Echo test Operations */
-#define BTA_HL_ECHO_OP_NONE 0
-#define BTA_HL_ECHO_OP_CI_GET_ECHO_DATA 1
-#define BTA_HL_ECHO_OP_SDP_INIT 2
-#define BTA_HL_ECHO_OP_MDL_CREATE_CFM 3
-#define BTA_HL_ECHO_OP_DCH_OPEN_CFM 4
-#define BTA_HL_ECHO_OP_LOOP_BACK 5
-#define BTA_HL_ECHO_OP_CI_PUT_ECHO_DATA 6
-#define BTA_HL_ECHO_OP_DCH_CLOSE_CFM 7
-#define BTA_HL_ECHO_OP_OPEN_IND 8
-#define BTA_HL_ECHO_OP_ECHO_PKT 9
-
-typedef uint8_t tBTA_HL_ECHO_OPER;
-
-/* abort status mask for abort_oper */
-
-#define BTA_HL_ABORT_NONE_MASK 0x00
-#define BTA_HL_ABORT_PENDING_MASK 0x01
-#define BTA_HL_ABORT_LOCAL_MASK 0x10
-#define BTA_HL_ABORT_REMOTE_MASK 0x20
-#define BTA_HL_ABORT_CCH_CLOSE_MASK 0x40
-
-/* call out mask for cout_oper */
-#define BTA_HL_CO_NONE_MASK 0x00
-#define BTA_HL_CO_GET_TX_DATA_MASK 0x01
-#define BTA_HL_CO_PUT_RX_DATA_MASK 0x02
-#define BTA_HL_CO_GET_ECHO_DATA_MASK 0x04
-#define BTA_HL_CO_PUT_ECHO_DATA_MASK 0x08
-
-typedef struct {
-  uint16_t mtu;
-  uint8_t fcs; /* '0' No FCS, otherwise '1' */
-} tBTA_HL_L2CAP_CFG_INFO;
-
-/* State Machine Events */
-enum {
-  /* these events are handled by the state machine */
-  BTA_HL_CCH_OPEN_EVT = BTA_SYS_EVT_START(BTA_ID_HL),
-  BTA_HL_CCH_SDP_OK_EVT,
-  BTA_HL_CCH_SDP_FAIL_EVT,
-  BTA_HL_MCA_CONNECT_IND_EVT,
-  BTA_HL_MCA_DISCONNECT_IND_EVT,
-  BTA_HL_CCH_CLOSE_EVT,
-  BTA_HL_CCH_CLOSE_CMPL_EVT,
-  BTA_HL_MCA_RSP_TOUT_IND_EVT,
-  /* DCH EVENT */
-  BTA_HL_DCH_SDP_INIT_EVT,
-  BTA_HL_DCH_OPEN_EVT,
-  BTA_HL_MCA_CREATE_IND_EVT,
-  BTA_HL_MCA_CREATE_CFM_EVT,
-  BTA_HL_MCA_OPEN_IND_EVT,
-
-  BTA_HL_MCA_OPEN_CFM_EVT,
-  BTA_HL_DCH_CLOSE_EVT,
-  BTA_HL_MCA_CLOSE_IND_EVT,
-  BTA_HL_MCA_CLOSE_CFM_EVT,
-  BTA_HL_API_SEND_DATA_EVT,
-
-  BTA_HL_MCA_RCV_DATA_EVT,
-  BTA_HL_DCH_CLOSE_CMPL_EVT,
-  BTA_HL_DCH_RECONNECT_EVT,
-  BTA_HL_DCH_SDP_FAIL_EVT,
-  BTA_HL_MCA_RECONNECT_IND_EVT,
-
-  BTA_HL_MCA_RECONNECT_CFM_EVT,
-  BTA_HL_DCH_CLOSE_ECHO_TEST_EVT,
-  BTA_HL_API_DCH_CREATE_RSP_EVT,
-  BTA_HL_DCH_ABORT_EVT,
-  BTA_HL_MCA_ABORT_IND_EVT,
-
-  BTA_HL_MCA_ABORT_CFM_EVT,
-  BTA_HL_MCA_CONG_CHG_EVT,
-  BTA_HL_CI_GET_TX_DATA_EVT,
-  BTA_HL_CI_PUT_RX_DATA_EVT,
-  BTA_HL_CI_GET_ECHO_DATA_EVT,
-  BTA_HL_DCH_ECHO_TEST_EVT,
-  BTA_HL_CI_PUT_ECHO_DATA_EVT,
-
-  /* these events are handled outside the state machine */
-  BTA_HL_API_ENABLE_EVT,
-  BTA_HL_API_DISABLE_EVT,
-  BTA_HL_API_UPDATE_EVT,
-  BTA_HL_API_REGISTER_EVT,
-  BTA_HL_API_DEREGISTER_EVT,
-  BTA_HL_API_CCH_OPEN_EVT,
-  BTA_HL_API_CCH_CLOSE_EVT,
-  BTA_HL_API_DCH_OPEN_EVT,
-  BTA_HL_API_DCH_RECONNECT_EVT,
-  BTA_HL_API_DCH_CLOSE_EVT,
-  BTA_HL_API_DELETE_MDL_EVT,
-  BTA_HL_API_DCH_ABORT_EVT,
-
-  BTA_HL_API_DCH_ECHO_TEST_EVT,
-  BTA_HL_API_SDP_QUERY_EVT,
-  BTA_HL_SDP_QUERY_OK_EVT,
-  BTA_HL_SDP_QUERY_FAIL_EVT,
-  BTA_HL_MCA_DELETE_IND_EVT,
-  BTA_HL_MCA_DELETE_CFM_EVT
-};
-typedef uint16_t tBTA_HL_INT_EVT;
-
-#define BTA_HL_DCH_EVT_MIN BTA_HL_DCH_SDP_INIT_EVT
-#define BTA_HL_DCH_EVT_MAX 0xFFFF
-
-/* state machine states */
-enum {
-  BTA_HL_CCH_IDLE_ST = 0, /* Idle  */
-  BTA_HL_CCH_OPENING_ST,  /* Opening a connection*/
-  BTA_HL_CCH_OPEN_ST,     /* Connection is open */
-  BTA_HL_CCH_CLOSING_ST   /* Closing is in progress */
-};
-typedef uint8_t tBTA_HL_CCH_STATE;
-
-enum {
-  BTA_HL_DCH_IDLE_ST = 0, /* Idle  */
-  BTA_HL_DCH_OPENING_ST,  /* Opening a connection*/
-  BTA_HL_DCH_OPEN_ST,     /* Connection is open */
-  BTA_HL_DCH_CLOSING_ST   /* Closing is in progress */
-};
-typedef uint8_t tBTA_HL_DCH_STATE;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_CTRL_CBACK* p_cback; /* pointer to control callback function */
-} tBTA_HL_API_ENABLE;
-
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_id;
-  bool is_register; /* Update HL application due to register or deregister */
-  tBTA_HL_CBACK* p_cback;       /* pointer to application callback function */
-  tBTA_HL_DEVICE_TYPE dev_type; /* sink, source or dual roles */
-  tBTA_SEC sec_mask;            /* security mask for accepting conenction*/
-  char srv_name[BTA_SERVICE_NAME_LEN +
-                1]; /* service name to be used in the SDP; null terminated*/
-  char srv_desp[BTA_SERVICE_DESP_LEN + 1]; /* service description to be used in
-                                              the SDP; null terminated */
-  char provider_name[BTA_PROVIDER_NAME_LEN + 1]; /* provide name to be used in
-                                                    the SDP; null terminated */
-
-} tBTA_HL_API_UPDATE;
-
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_id;
-  tBTA_HL_CBACK* p_cback;       /* pointer to application callback function */
-  tBTA_HL_DEVICE_TYPE dev_type; /* sink, source or dual roles */
-  tBTA_SEC sec_mask;            /* security mask for accepting conenction*/
-  char srv_name[BTA_SERVICE_NAME_LEN +
-                1]; /* service name to be used in the SDP; null terminated*/
-  char srv_desp[BTA_SERVICE_DESP_LEN + 1]; /* service description to be used in
-                                              the SDP; null terminated */
-  char provider_name[BTA_PROVIDER_NAME_LEN + 1]; /* provide name to be used in
-                                                    the SDP; null terminated */
-} tBTA_HL_API_REGISTER;
-
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_id;
-  tBTA_HL_CBACK* p_cback; /* pointer to application callback function */
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_API_DEREGISTER;
-
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_id;
-  tBTA_HL_APP_HANDLE app_handle;
-  uint16_t ctrl_psm;
-  RawAddress bd_addr;  /* Address of peer device */
-  tBTA_SEC sec_mask;   /* security mask for initiating connection*/
-} tBTA_HL_API_CCH_OPEN;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-} tBTA_HL_API_CCH_CLOSE;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  uint16_t ctrl_psm;
-  tBTA_HL_MDEP_ID local_mdep_id; /* local MDEP ID */
-  tBTA_HL_MDEP_ID peer_mdep_id;  /* peer mdep id */
-  tBTA_HL_DCH_CFG local_cfg;
-  tBTA_SEC sec_mask; /* security mask for initiating connection*/
-} tBTA_HL_API_DCH_OPEN;
-
-typedef struct {
-  BT_HDR hdr;
-
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  uint16_t ctrl_psm;
-  tBTA_HL_MDL_ID mdl_id;
-} tBTA_HL_API_DCH_RECONNECT;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-} tBTA_HL_API_DCH_CLOSE;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_MDL_ID mdl_id;
-} tBTA_HL_API_DELETE_MDL;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-} tBTA_HL_API_DCH_ABORT;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  uint16_t pkt_size;
-} tBTA_HL_API_SEND_DATA;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  uint16_t ctrl_psm;
-  uint16_t pkt_size;
-  tBTA_HL_DCH_CFG local_cfg;
-} tBTA_HL_API_DCH_ECHO_TEST;
-
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_idx;
-  uint8_t mcl_idx;
-  bool release_mcl_cb;
-} tBTA_HL_CCH_SDP;
-
-/* MCA callback event parameters. */
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_APP_HANDLE app_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tMCA_CTRL mca_data;
-} tBTA_HL_MCA_EVT;
-
-/* MCA callback event parameters. */
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_idx;
-  uint8_t mcl_idx;
-  uint8_t mdl_idx;
-  BT_HDR* p_pkt;
-} tBTA_HL_MCA_RCV_DATA_EVT;
-
-typedef struct {
-  BT_HDR hdr;
-  uint8_t app_idx;
-  uint8_t mcl_idx;
-  uint8_t mdl_idx;
-} tBTA_HL_DCH_SDP;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_APP_HANDLE app_handle;
-  uint8_t app_id;
-  RawAddress bd_addr; /* Address of peer device */
-} tBTA_HL_API_SDP_QUERY;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_MDL_ID mdl_id;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  tBTA_HL_DCH_CREATE_RSP rsp_code;
-  tBTA_HL_DCH_CFG cfg_rsp;
-} tBTA_HL_API_DCH_CREATE_RSP;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_STATUS status;
-} tBTA_HL_CI_GET_PUT_DATA;
-
-typedef struct {
-  BT_HDR hdr;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_STATUS status;
-} tBTA_HL_CI_ECHO_DATA;
-
-/* union of all state machine event data types */
-typedef union {
-  BT_HDR hdr;
-  tBTA_HL_API_ENABLE api_enable; /* data for BTA_MSE_API_ENABLE_EVT */
-  tBTA_HL_API_UPDATE api_update;
-  tBTA_HL_API_REGISTER api_reg;
-  tBTA_HL_API_DEREGISTER api_dereg;
-  tBTA_HL_API_CCH_OPEN api_cch_open;
-  tBTA_HL_API_CCH_CLOSE api_cch_close;
-  tBTA_HL_API_DCH_CREATE_RSP api_dch_create_rsp;
-  tBTA_HL_API_DCH_OPEN api_dch_open;
-  tBTA_HL_API_DCH_RECONNECT api_dch_reconnect;
-  tBTA_HL_API_DCH_CLOSE api_dch_close;
-  tBTA_HL_API_DELETE_MDL api_delete_mdl;
-  tBTA_HL_API_DCH_ABORT api_dch_abort;
-  tBTA_HL_API_SEND_DATA api_send_data;
-  tBTA_HL_API_DCH_ECHO_TEST api_dch_echo_test;
-  tBTA_HL_API_SDP_QUERY api_sdp_query;
-
-  tBTA_HL_CCH_SDP cch_sdp;
-  tBTA_HL_MCA_EVT mca_evt;
-  tBTA_HL_MCA_RCV_DATA_EVT mca_rcv_data_evt;
-  tBTA_HL_DCH_SDP dch_sdp; /* for DCH_OPEN_EVT and DCH_RECONNECT_EVT */
-  tBTA_HL_CI_GET_PUT_DATA ci_get_put_data;
-  tBTA_HL_CI_ECHO_DATA ci_get_put_echo_data;
-} tBTA_HL_DATA;
-
-typedef struct {
-  bool in_use;
-  uint16_t mdl_id;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_DCH_OPER dch_oper;
-  bool intentional_close;
-  tBTA_HL_DCH_STATE dch_state;
-  uint8_t abort_oper;
-  uint16_t req_data_psm;
-  uint16_t max_rx_apdu_size;
-  uint16_t max_tx_apdu_size;
-  BT_HDR* p_tx_pkt;
-  BT_HDR* p_rx_pkt;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  uint8_t local_mdep_cfg_idx;
-  tBTA_HL_DCH_CFG local_cfg;
-  tBTA_HL_DCH_CFG remote_cfg;
-  tBTA_HL_MDEP_ID peer_mdep_id;
-  uint16_t peer_data_type;
-  tBTA_HL_MDEP_ROLE peer_mdep_role;
-  tBTA_HL_DCH_MODE dch_mode;
-  tBTA_SEC sec_mask;
-  bool is_the_first_reliable;
-  bool delete_mdl;
-  uint16_t mtu;
-  tMCA_CHNL_CFG chnl_cfg;
-  bool mdl_cfg_idx_included;
-  uint8_t mdl_cfg_idx;
-  uint8_t echo_oper;
-  bool cong;
-  bool close_pending;
-  uint8_t cout_oper;
-  BT_HDR* p_echo_tx_pkt;
-  BT_HDR* p_echo_rx_pkt;
-  tBTA_HL_STATUS ci_put_echo_data_status;
-} tBTA_HL_MDL_CB;
-
-typedef struct {
-  tBTA_HL_MDL_CB mdl[BTA_HL_NUM_MDLS_PER_MCL];
-  tBTA_HL_DELETE_MDL delete_mdl;
-  bool in_use;
-  tBTA_HL_CCH_STATE cch_state;
-  uint16_t req_ctrl_psm;
-  uint16_t ctrl_psm;
-  uint16_t data_psm;
-  RawAddress bd_addr;
-  uint16_t cch_mtu;
-  uint16_t sec_mask;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tSDP_DISCOVERY_DB* p_db; /* pointer to discovery database */
-  tSDP_DISC_CMPL_CB* sdp_cback;
-  tBTA_HL_SDP_OPER sdp_oper;
-  bool close_pending;
-  uint8_t sdp_mdl_idx;
-  tBTA_HL_SDP sdp;
-  uint8_t cch_oper;
-  uint8_t force_close_local_cch_opening;
-  bool intentional_close;
-  bool rsp_tout;
-  uint8_t timer_oper;
-  bool echo_test;
-  uint8_t echo_mdl_idx;
-  uint8_t cch_close_dch_oper;
-  uint8_t app_id;
-} tBTA_HL_MCL_CB;
-
-typedef struct {
-  tBTA_HL_MCL_CB mcb[BTA_HL_NUM_MCLS]; /* application Control Blocks */
-  tBTA_HL_CBACK* p_cback; /* pointer to control callback function */
-  bool in_use;            /* this CB is in use*/
-  bool deregistering;
-  uint8_t app_id;
-  uint32_t sdp_handle; /* SDP record handle */
-  tBTA_HL_SUP_FEATURE sup_feature;
-  tBTA_HL_MDL_CFG mdl_cfg[BTA_HL_NUM_MDL_CFGS];
-  tBTA_HL_DEVICE_TYPE dev_type;
-  tBTA_HL_APP_HANDLE app_handle;
-  uint16_t ctrl_psm; /* L2CAP PSM for the MCAP control channel */
-  uint16_t data_psm; /* L2CAP PSM for the MCAP data channel */
-  uint16_t sec_mask; /* Security mask for BTM_SetSecurityLevel() */
-
-  char srv_name[BTA_SERVICE_NAME_LEN +
-                1]; /* service name to be used in the SDP; null terminated*/
-  char srv_desp[BTA_SERVICE_DESP_LEN + 1]; /* service description to be used in
-                                              the SDP; null terminated */
-  char provider_name[BTA_PROVIDER_NAME_LEN + 1]; /* provide name to be used in
-                                                    the SDP; null terminated */
-
-  tMCA_CTRL_CBACK* p_mcap_cback; /* pointer to MCAP callback function */
-  tMCA_DATA_CBACK* p_data_cback;
-} tBTA_HL_APP_CB;
-
-typedef struct {
-  bool in_use;
-  tBTA_HL_SDP_OPER sdp_oper;
-  uint8_t app_idx;
-  uint8_t mcl_idx;
-  uint8_t mdl_idx;
-} tBTA_HL_SDP_CB;
-
-typedef struct {
-  bool in_use;
-  uint8_t app_idx;
-  uint8_t mcl_idx;
-} tBTA_HL_TIMER_CB;
-
-typedef struct {
-  tBTA_HL_APP_CB acb[BTA_HL_NUM_APPS]; /* HL Control Blocks */
-  tBTA_HL_CTRL_CBACK* p_ctrl_cback; /* pointer to control callback function */
-  bool enable;
-  bool disabling;
-
-  tBTA_HL_SDP_CB scb[BTA_HL_NUM_SDP_CBACKS];
-  tBTA_HL_TIMER_CB tcb[BTA_HL_NUM_TIMERS];
-  bool enable_random_psm;
-  tBTA_HL_ALLOCATE_PSM* p_alloc_psm;
-} tBTA_HL_CB;
-
-/******************************************************************************
- *  Configuration Definitions
- ******************************************************************************/
-/* Configuration structure */
-
-/*****************************************************************************
- *  Global data
- ****************************************************************************/
-
-/* HL control block */
-extern tBTA_HL_CB bta_hl_cb;
-
-#define BTA_HL_GET_CB_PTR() &(bta_hl_cb)
-#define BTA_HL_GET_APP_CB_PTR(app_idx) &(bta_hl_cb.acb[(app_idx)])
-#define BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx) \
-  &(bta_hl_cb.acb[(app_idx)].mcb[(mcl_idx)])
-#define BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx) \
-  &(bta_hl_cb.acb[(app_idx)].mcb[(mcl_idx)].mdl[(mdl_idx)])
-#define BTA_HL_GET_MDL_CFG_PTR(app_idx, item_idx) \
-  &(bta_hl_cb.acb[(app_idx)].mdl_cfg[(item_idx)])
-#define BTA_HL_GET_ECHO_CFG_PTR(app_idx) \
-  &(bta_hl_cb.acb[(app_idx)].sup_feature.echo_cfg)
-#define BTA_HL_GET_MDEP_CFG_PTR(app_idx, mdep_cfg_idx) \
-  &(bta_hl_cb.acb[(app_idx)].sup_feature.mdep[(mdep_cfg_idx)].mdep_cfg)
-#define BTA_HL_GET_DATA_CFG_PTR(app_idx, mdep_cfg_idx, data_cfg_idx) \
-  &(bta_hl_cb.acb[(app_idx)]                                         \
-        .sup_feature.mdep[(mdep_cfg_idx)]                            \
-        .mdep_cfg.data_cfg[(data_cfg_idx)])
-#define BTA_HL_GET_BUF_PTR(p_pkt) \
-  ((uint8_t*)((uint8_t*)((p_pkt) + 1) + (p_pkt)->offset))
-
-/*****************************************************************************
- *  Function prototypes
- ****************************************************************************/
-/* main */
-extern bool bta_hl_hdl_event(BT_HDR* p_msg);
-/* sdp */
-extern bool bta_hl_fill_sup_feature_list(const tSDP_DISC_ATTR* p_attr,
-                                         tBTA_HL_SUP_FEATURE_LIST_ELEM* p_list);
-extern tBTA_HL_STATUS bta_hl_sdp_update(uint8_t app_id);
-extern tBTA_HL_STATUS bta_hl_sdp_register(uint8_t app_idx);
-extern tSDP_DISC_REC* bta_hl_find_sink_or_src_srv_class_in_db(
-    const tSDP_DISCOVERY_DB* p_db, const tSDP_DISC_REC* p_start_rec);
-
-/* action routines */
-extern void bta_hl_dch_ci_get_tx_data(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_ci_put_rx_data(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_ci_get_echo_data(uint8_t app_idx, uint8_t mcl_idx,
-                                        uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-
-extern void bta_hl_dch_echo_test(uint8_t app_idx, uint8_t mcl_idx,
-                                 uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_ci_put_echo_data(uint8_t app_idx, uint8_t mcl_idx,
-                                        uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_send_data(uint8_t app_idx, uint8_t mcl_idx,
-                                 uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_sdp_fail(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_cong_change(uint8_t app_idx, uint8_t mcl_idx,
-                                       uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_reconnect_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                         uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_reconnect_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                         uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_reconnect(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_sdp_init(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_close_echo_test(uint8_t app_idx, uint8_t mcl_idx,
-                                       uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_create_rsp(uint8_t app_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_rcv_data(uint8_t app_idx, uint8_t mcl_idx,
-                                    uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_close_cmpl(uint8_t app_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_close_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_close_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_close(uint8_t app_idx, uint8_t mcl_idx,
-                                 uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_delete_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-
-extern void bta_hl_dch_mca_delete_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_delete(uint8_t app_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_abort_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_abort_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_abort(uint8_t app_idx, uint8_t mcl_idx,
-                                 uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_open_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                    uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_open_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                    uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_create_ind(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_create_cfm(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_mca_create(uint8_t app_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_deallocate_spd_cback(uint8_t sdp_cback_idx);
-extern tSDP_DISC_CMPL_CB* bta_hl_allocate_spd_cback(tBTA_HL_SDP_OPER sdp_oper,
-                                                    uint8_t app_idx,
-                                                    uint8_t mcl_idx,
-                                                    uint8_t mdl_idx,
-                                                    uint8_t* p_sdp_cback_idx);
-extern tBTA_HL_STATUS bta_hl_init_sdp(tBTA_HL_SDP_OPER sdp_oper,
-                                      uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t mdl_idx);
-extern void bta_hl_cch_sdp_init(uint8_t app_idx, uint8_t mcl_idx,
-                                tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_mca_open(uint8_t app_idx, uint8_t mcl_idx,
-                                tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_mca_close(uint8_t app_idx, uint8_t mcl_idx,
-                                 tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_close_cmpl(uint8_t app_idx, uint8_t mcl_idx,
-                                  tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_mca_disconnect(uint8_t app_idx, uint8_t mcl_idx,
-                                      tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_mca_disc_open(uint8_t app_idx, uint8_t mcl_idx,
-                                     tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_mca_rsp_tout(uint8_t app_idx, uint8_t mcl_idx,
-                                    tBTA_HL_DATA* p_data);
-extern void bta_hl_cch_mca_connect(uint8_t app_idx, uint8_t mcl_idx,
-                                   tBTA_HL_DATA* p_data);
-
-/* State machine drivers  */
-extern void bta_hl_cch_sm_execute(uint8_t inst_idx, uint8_t mcl_idx,
-                                  uint16_t event, tBTA_HL_DATA* p_data);
-extern void bta_hl_dch_sm_execute(uint8_t inst_idx, uint8_t mcl_idx,
-                                  uint8_t mdl_idx, uint16_t event,
-                                  tBTA_HL_DATA* p_data);
-/* MCAP callback functions  */
-extern void bta_hl_mcap_ctrl_cback(tMCA_HANDLE handle, tMCA_CL mcl,
-                                   uint8_t event, tMCA_CTRL* p_data);
-
-extern void bta_hl_mcap_data_cback(tMCA_DL mdl, BT_HDR* p_pkt);
-
-/* utility functions  */
-extern bool bta_hl_set_ctrl_psm_for_dch(uint8_t app_idx, uint8_t mcl_idx,
-                                        uint8_t mdl_idx, uint16_t ctrl_psm);
-extern bool bta_hl_find_sdp_idx_using_ctrl_psm(tBTA_HL_SDP* p_sdp,
-                                               uint16_t ctrl_psm,
-                                               uint8_t* p_sdp_idx);
-extern uint16_t bta_hl_set_user_tx_buf_size(uint16_t max_tx_size);
-extern uint16_t bta_hl_set_user_rx_buf_size(uint16_t mtu);
-extern uint8_t bta_hl_set_tx_win_size(uint16_t mtu, uint16_t mps);
-extern uint16_t bta_hl_set_mps(uint16_t mtu);
-extern void bta_hl_clean_mdl_cb(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx);
-extern BT_HDR* bta_hl_get_buf(uint16_t data_size, bool fcs_use);
-extern bool bta_hl_find_service_in_db(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint16_t service_uuid,
-                                      tSDP_DISC_REC** pp_rec);
-extern uint16_t bta_hl_get_service_uuids(uint8_t sdp_oper, uint8_t app_idx,
-                                         uint8_t mcl_idx, uint8_t mdl_idx);
-extern bool bta_hl_find_echo_cfg_rsp(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdep_idx, uint8_t cfg,
-                                     uint8_t* p_cfg_rsp);
-extern bool bta_hl_validate_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx, uint8_t cfg);
-extern bool bta_hl_find_cch_cb_indexes(tBTA_HL_DATA* p_msg, uint8_t* p_app_idx,
-                                       uint8_t* p_mcl_idx);
-extern bool bta_hl_find_dch_cb_indexes(tBTA_HL_DATA* p_msg, uint8_t* p_app_idx,
-                                       uint8_t* p_mcl_idx, uint8_t* p_mdl_idx);
-extern uint16_t bta_hl_allocate_mdl_id(uint8_t app_idx, uint8_t mcl_idx,
-                                       uint8_t mdl_idx);
-extern bool bta_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
-                                             uint8_t* p_app_idx,
-                                             uint8_t* p_mcl_idx,
-                                             uint8_t* p_mdl_idx);
-extern bool bta_hl_find_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                uint16_t mdl_id, uint8_t* p_mdl_idx);
-extern bool bta_hl_find_an_active_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                          uint8_t* p_mdl_idx);
-extern bool bta_hl_find_dch_setup_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                          uint8_t* p_mdl_idx);
-extern bool bta_hl_find_an_in_use_mcl_idx(uint8_t app_idx, uint8_t* p_mcl_idx);
-extern bool bta_hl_find_an_in_use_app_idx(uint8_t* p_app_idx);
-extern bool bta_hl_find_app_idx(uint8_t app_id, uint8_t* p_app_idx);
-extern bool bta_hl_find_app_idx_using_handle(tBTA_HL_APP_HANDLE app_handle,
-                                             uint8_t* p_app_idx);
-extern bool bta_hl_find_mcl_idx_using_handle(tBTA_HL_MCL_HANDLE mcl_handle,
-                                             uint8_t* p_app_idx,
-                                             uint8_t* p_mcl_idx);
-extern bool bta_hl_find_mcl_idx(uint8_t app_idx, const RawAddress& p_bd_addr,
-                                uint8_t* p_mcl_idx);
-extern bool bta_hl_is_the_first_reliable_existed(uint8_t app_idx,
-                                                 uint8_t mcl_idx);
-extern bool bta_hl_find_non_active_mdl_cfg(uint8_t app_idx,
-                                           uint8_t start_mdl_cfg_idx,
-                                           uint8_t* p_mdl_cfg_idx);
-extern bool bta_hl_find_avail_mdl_cfg_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                          uint8_t* p_mdl_cfg_idx);
-extern bool bta_hl_find_mdl_cfg_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                    tBTA_HL_MDL_ID mdl_id,
-                                    uint8_t* p_mdl_cfg_idx);
-extern bool bta_hl_get_cur_time(uint8_t app_idx, uint8_t* p_cur_time);
-extern void bta_hl_sort_cfg_time_idx(uint8_t app_idx, uint8_t* a, uint8_t n);
-extern void bta_hl_compact_mdl_cfg_time(uint8_t app_idx, uint8_t mdep_id);
-extern bool bta_hl_is_mdl_exsit_in_mcl(uint8_t app_idx,
-                                       const RawAddress& bd_addr,
-                                       tBTA_HL_MDL_ID mdl_id);
-extern bool bta_hl_delete_mdl_cfg(uint8_t app_idx, const RawAddress& bd_addr,
-                                  tBTA_HL_MDL_ID mdl_id);
-extern bool bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id);
-extern bool bta_hl_find_mdep_cfg_idx(uint8_t app_idx,
-                                     tBTA_HL_MDEP_ID local_mdep_id,
-                                     uint8_t* p_mdep_cfg_idx);
-extern void bta_hl_find_rxtx_apdu_size(uint8_t app_idx, uint8_t mdep_cfg_idx,
-                                       uint16_t* p_rx_apu_size,
-                                       uint16_t* p_tx_apu_size);
-extern bool bta_hl_validate_peer_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx,
-                                     tBTA_HL_MDEP_ID peer_mdep_id,
-                                     tBTA_HL_MDEP_ROLE peer_mdep_role,
-                                     uint8_t sdp_idx);
-extern tBTA_HL_STATUS bta_hl_chk_local_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                           uint8_t mdep_cfg_idx,
-                                           tBTA_HL_DCH_CFG local_cfg);
-
-extern bool bta_hl_validate_reconnect_params(
-    uint8_t app_idx, uint8_t mcl_idx, tBTA_HL_API_DCH_RECONNECT* p_reconnect,
-    uint8_t* p_mdep_cfg_idx, uint8_t* p_mdl_cfg_idx);
-extern bool bta_hl_find_avail_mcl_idx(uint8_t app_idx, uint8_t* p_mcl_idx);
-extern bool bta_hl_find_avail_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                      uint8_t* p_mdl_idx);
-extern bool bta_hl_is_a_duplicate_id(uint8_t app_id);
-extern bool bta_hl_find_avail_app_idx(uint8_t* p_idx);
-extern tBTA_HL_STATUS bta_hl_app_update(uint8_t app_id, bool is_register);
-extern tBTA_HL_STATUS bta_hl_app_registration(uint8_t app_idx);
-extern void bta_hl_discard_data(uint16_t event, tBTA_HL_DATA* p_data);
-extern void bta_hl_save_mdl_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx);
-extern void bta_hl_set_dch_chan_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                    uint8_t mdl_idx, tBTA_HL_DATA* p_data);
-extern bool bta_hl_get_l2cap_cfg(tBTA_HL_MDL_HANDLE mdl_hnd,
-                                 tBTA_HL_L2CAP_CFG_INFO* p_cfg);
-extern bool bta_hl_validate_chan_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                     uint8_t mdl_idx);
-extern bool bta_hl_is_cong_on(uint8_t app_id, const RawAddress& bd_addr,
-                              tBTA_HL_MDL_ID mdl_id);
-extern void bta_hl_check_cch_close(uint8_t app_idx, uint8_t mcl_idx,
-                                   tBTA_HL_DATA* p_data, bool check_dch_setup);
-extern void bta_hl_clean_app(uint8_t app_idx);
-extern void bta_hl_check_deregistration(uint8_t app_idx, tBTA_HL_DATA* p_data);
-extern void bta_hl_check_disable(tBTA_HL_DATA* p_data);
-extern void bta_hl_build_abort_ind(tBTA_HL* p_evt_data,
-                                   tBTA_HL_APP_HANDLE app_handle,
-                                   tBTA_HL_MCL_HANDLE mcl_handle);
-extern void bta_hl_build_abort_cfm(tBTA_HL* p_evt_data,
-                                   tBTA_HL_APP_HANDLE app_handle,
-                                   tBTA_HL_MCL_HANDLE mcl_handle,
-                                   tBTA_HL_STATUS status);
-extern void bta_hl_build_dch_close_cfm(tBTA_HL* p_evt_data,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       tBTA_HL_MCL_HANDLE mcl_handle,
-                                       tBTA_HL_MDL_HANDLE mdl_handle,
-                                       tBTA_HL_STATUS status);
-extern void bta_hl_build_dch_close_ind(tBTA_HL* p_evt_data,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       tBTA_HL_MCL_HANDLE mcl_handle,
-                                       tBTA_HL_MDL_HANDLE mdl_handle,
-                                       bool intentional);
-extern void bta_hl_build_send_data_cfm(tBTA_HL* p_evt_data,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       tBTA_HL_MCL_HANDLE mcl_handle,
-                                       tBTA_HL_MDL_HANDLE mdl_handle,
-                                       tBTA_HL_STATUS status);
-extern void bta_hl_build_rcv_data_ind(tBTA_HL* p_evt_data,
-                                      tBTA_HL_APP_HANDLE app_handle,
-                                      tBTA_HL_MCL_HANDLE mcl_handle,
-                                      tBTA_HL_MDL_HANDLE mdl_handle);
-extern void bta_hl_build_cch_open_cfm(tBTA_HL* p_evt_data, uint8_t app_id,
-                                      tBTA_HL_APP_HANDLE app_handle,
-                                      tBTA_HL_MCL_HANDLE mcl_handle,
-                                      const RawAddress& bd_addr,
-                                      tBTA_HL_STATUS status);
-extern void bta_hl_build_cch_open_ind(tBTA_HL* p_evt_data,
-                                      tBTA_HL_APP_HANDLE app_handle,
-                                      tBTA_HL_MCL_HANDLE mcl_handle,
-                                      const RawAddress& bd_addr);
-extern void bta_hl_build_cch_close_cfm(tBTA_HL* p_evt_data,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       tBTA_HL_MCL_HANDLE mcl_handle,
-                                       tBTA_HL_STATUS status);
-extern void bta_hl_build_cch_close_ind(tBTA_HL* p_evt_data,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       tBTA_HL_MCL_HANDLE mcl_handle,
-                                       bool intentional);
-
-extern void bta_hl_build_dch_open_cfm(
-    tBTA_HL* p_evt_data, tBTA_HL_APP_HANDLE app_handle,
-    tBTA_HL_MCL_HANDLE mcl_handle, tBTA_HL_MDL_HANDLE mdl_handle,
-    tBTA_HL_MDEP_ID local_mdep_id, tBTA_HL_MDL_ID mdl_id,
-    tBTA_HL_DCH_MODE dch_mode, bool first_reliable, uint16_t mtu,
-    tBTA_HL_STATUS status);
-
-extern void bta_hl_build_delete_mdl_cfm(tBTA_HL* p_evt_data,
-                                        tBTA_HL_APP_HANDLE app_handle,
-                                        tBTA_HL_MCL_HANDLE mcl_handle,
-                                        tBTA_HL_MDL_ID mdl_id,
-                                        tBTA_HL_STATUS status);
-extern void bta_hl_build_echo_test_cfm(tBTA_HL* p_evt_data,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       tBTA_HL_MCL_HANDLE mcl_handle,
-                                       tBTA_HL_STATUS status);
-extern void bta_hl_build_sdp_query_cfm(tBTA_HL* p_evt_data, uint8_t app_id,
-                                       tBTA_HL_APP_HANDLE app_handle,
-                                       const RawAddress& bd_addr,
-                                       tBTA_HL_SDP* p_sdp,
-                                       tBTA_HL_STATUS status);
-
-#if (BTA_HL_DEBUG == TRUE)
-extern const char* bta_hl_status_code(tBTA_HL_STATUS status);
-extern const char* bta_hl_evt_code(tBTA_HL_INT_EVT evt_code);
-#endif
-
-#endif /* BTA_MSE_INT_H */
diff --git a/bta/hl/bta_hl_main.cc b/bta/hl/bta_hl_main.cc
index c224a76..597c5d3 100644
--- a/bta/hl/bta_hl_main.cc
+++ b/bta/hl/bta_hl_main.cc
@@ -678,11 +678,11 @@
         p_acb->sec_mask = p_data->api_reg.sec_mask;
         p_acb->dev_type = p_data->api_reg.dev_type;
         strlcpy(p_acb->srv_name, p_data->api_reg.srv_name,
-                BTA_SERVICE_NAME_LEN);
+                sizeof(p_acb->srv_name));
         strlcpy(p_acb->srv_desp, p_data->api_reg.srv_desp,
-                BTA_SERVICE_DESP_LEN);
+                sizeof(p_acb->srv_desp));
         strlcpy(p_acb->provider_name, p_data->api_reg.provider_name,
-                BTA_PROVIDER_NAME_LEN);
+                sizeof(p_acb->provider_name));
         bta_hl_cb.p_alloc_psm = L2CA_AllocatePSM;
         p_acb->ctrl_psm = bta_hl_cb.p_alloc_psm();
         p_acb->data_psm = bta_hl_cb.p_alloc_psm();
diff --git a/bta/hl/bta_hl_sdp.cc b/bta/hl/bta_hl_sdp.cc
deleted file mode 100644
index 0a357f0..0000000
--- a/bta/hl/bta_hl_sdp.cc
+++ /dev/null
@@ -1,572 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 1998-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.
- *
- ******************************************************************************/
-
-#include <string.h>
-
-#include "bt_target.h"
-#if (HL_INCLUDED == TRUE)
-
-#include "bta_hl_int.h"
-#include "osi/include/osi.h"
-#include "sdp_api.h"
-#include "utl.h"
-
-/*******************************************************************************
- *
- * Function         bta_hl_fill_sup_feature_list
- *
- * Description      Fill the supported features from teh SDP record
- *
- * Returns          true if found, false if not
- *                  If found, the passed protocol list element is filled in.
- *
- ******************************************************************************/
-bool bta_hl_fill_sup_feature_list(const tSDP_DISC_ATTR* p_attr,
-                                  tBTA_HL_SUP_FEATURE_LIST_ELEM* p_list) {
-  tSDP_DISC_ATTR* p_sattr;
-  uint8_t item_cnt;
-  uint8_t list_cnt = 0;
-  bool status = true;
-
-  for (p_attr = p_attr->attr_value.v.p_sub_attr; p_attr;
-       p_attr = p_attr->p_next_attr) {
-    /* mdep sequence */
-    if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) {
-      return (false);
-    }
-
-    item_cnt = 0;
-
-    for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr && (item_cnt < 4);
-         p_sattr = p_sattr->p_next_attr) {
-      /* for each mdep list */
-
-      p_list->list_elem[list_cnt].p_mdep_desp = NULL;
-      switch (item_cnt) {
-        case 0:
-          p_list->list_elem[list_cnt].mdep_id = p_sattr->attr_value.v.u8;
-          break;
-        case 1:
-          p_list->list_elem[list_cnt].data_type = p_sattr->attr_value.v.u16;
-          break;
-        case 2:
-          p_list->list_elem[list_cnt].mdep_role =
-              (tBTA_HL_MDEP_ROLE)p_sattr->attr_value.v.u8;
-          break;
-        case 3:
-          p_list->list_elem[list_cnt].p_mdep_desp =
-              (char*)p_sattr->attr_value.v.array;
-          break;
-      }
-
-      item_cnt++;
-    }
-    list_cnt++;
-  }
-  p_list->num_elems = list_cnt;
-  return (status);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_compose_supported_feature_list
- *
- * Description      This function is called to compose a data sequence from
- *                  the supported  feature element list struct pointer
- *
- * Returns          the length of the data sequence
- *
- ******************************************************************************/
-int bta_hl_compose_supported_feature_list(
-    uint8_t* p, uint16_t num_elem,
-    const tBTA_HL_SUP_FEATURE_ELEM* p_elem_list) {
-  uint16_t xx, str_len, seq_len;
-  uint8_t* p_head = p;
-
-  for (xx = 0; xx < num_elem; xx++, p_elem_list++) {
-    UINT8_TO_BE_STREAM(p, (DATA_ELE_SEQ_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
-    seq_len = 7;
-    str_len = 0;
-    if (p_elem_list->p_mdep_desp) {
-      str_len = strlen(p_elem_list->p_mdep_desp) + 1;
-      seq_len += str_len + 2; /* todo add a # symbol for 2 */
-    }
-
-    *p++ = (uint8_t)seq_len;
-
-    UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
-    UINT8_TO_BE_STREAM(p, p_elem_list->mdep_id);
-    UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_TWO_BYTES);
-    UINT16_TO_BE_STREAM(p, p_elem_list->data_type);
-    UINT8_TO_BE_STREAM(p, (UINT_DESC_TYPE << 3) | SIZE_ONE_BYTE);
-    UINT8_TO_BE_STREAM(p, p_elem_list->mdep_role);
-
-    if (str_len) {
-      UINT8_TO_BE_STREAM(p, (TEXT_STR_DESC_TYPE << 3) | SIZE_IN_NEXT_BYTE);
-      UINT8_TO_BE_STREAM(p, str_len);
-      ARRAY_TO_BE_STREAM(p, p_elem_list->p_mdep_desp, str_len);
-    }
-  }
-
-  return (p - p_head);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_add_sup_feature_list
- *
- * Description      This function is called to add a protocol descriptor list to
- *                  a record. This would be through the SDP database maintenance
- *                  API. If the protocol list already exists in the record, it
- *                  is replaced with the new list.
- *
- * Returns          true if added OK, else false
- *
- ******************************************************************************/
-bool bta_hl_add_sup_feature_list(uint32_t handle, uint16_t num_elem,
-                                 const tBTA_HL_SUP_FEATURE_ELEM* p_elem_list) {
-  int offset;
-  bool result;
-  uint8_t* p_buf = (uint8_t*)osi_malloc(BTA_HL_SUP_FEATURE_SDP_BUF_SIZE);
-
-  offset = bta_hl_compose_supported_feature_list(p_buf, num_elem, p_elem_list);
-  result = SDP_AddAttribute(handle, ATTR_ID_HDP_SUP_FEAT_LIST,
-                            DATA_ELE_SEQ_DESC_TYPE, (uint32_t)offset, p_buf);
-  osi_free(p_buf);
-
-  return result;
-}
-
-/*****************************************************************************
- *
- *  Function:    bta_hl_sdp_update
- *
- *  Purpose:     Register an HDP application with SDP
- *
- *  Parameters:
- *
- *  Returns:     void
- *
- ****************************************************************************/
-tBTA_HL_STATUS bta_hl_sdp_update(UNUSED_ATTR uint8_t app_id) {
-  uint16_t svc_class_id_list[BTA_HL_NUM_SVC_ELEMS];
-  tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HL_NUM_PROTO_ELEMS];
-  tSDP_PROTO_LIST_ELEM add_proto_list;
-  tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature_list;
-  uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
-  uint8_t i, j, cnt, mdep_id, mdep_role;
-  uint8_t data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
-  uint8_t mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
-  uint16_t profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
-  uint16_t version = BTA_HL_VERSION;
-  uint8_t num_services = 1;
-  tBTA_HL_APP_CB* p_cb = BTA_HL_GET_APP_CB_PTR(0);
-  bool result = true;
-  tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
-
-  if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) &&
-      (!p_cb->sup_feature.advertize_source_sdp)) {
-    return BTA_HL_STATUS_OK;
-  }
-
-  num_services = 1;
-  svc_class_id_list[0] = UUID_SERVCLASS_HDP_SOURCE;
-  if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK) {
-    svc_class_id_list[0] = UUID_SERVCLASS_HDP_SINK;
-  } else {
-    if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE) {
-      /* dual role */
-      num_services = 2;
-      svc_class_id_list[1] = UUID_SERVCLASS_HDP_SINK;
-    }
-  }
-  result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services,
-                                      svc_class_id_list);
-
-  if (result) {
-    /* add the protocol element sequence */
-    proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-    proto_elem_list[0].num_params = 1;
-    proto_elem_list[0].params[0] = p_cb->ctrl_psm;
-    proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL;
-    proto_elem_list[1].num_params = 1;
-    proto_elem_list[1].params[0] = version;
-    result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS,
-                                  proto_elem_list);
-
-    result &=
-        SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version);
-  }
-
-  if (result) {
-    add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS;
-    add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-    add_proto_list.list_elem[0].num_params = 1;
-    add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
-    add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
-    add_proto_list.list_elem[1].num_params = 0;
-    result &= SDP_AddAdditionProtoLists(
-        p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS, &add_proto_list);
-  }
-
-  if (result) {
-    if (p_cb->srv_name[0]) {
-      result &= SDP_AddAttribute(
-          p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
-          (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_name) + 1),
-          (uint8_t*)p_cb->srv_name);
-    } /* end of setting optional service name */
-  }
-
-  if (result) {
-    if (p_cb->srv_desp[0]) {
-      result &= SDP_AddAttribute(
-          p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_DESCRIPTION,
-          (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_desp) + 1),
-          (uint8_t*)p_cb->srv_desp);
-
-    } /* end of setting optional service description */
-  }
-
-  if (result) {
-    if (p_cb->provider_name[0]) {
-      result &=
-          SDP_AddAttribute(p_cb->sdp_handle, (uint16_t)ATTR_ID_PROVIDER_NAME,
-                           (uint8_t)TEXT_STR_DESC_TYPE,
-                           (uint32_t)(strlen(p_cb->provider_name) + 1),
-                           (uint8_t*)p_cb->provider_name);
-    } /* end of setting optional provider name */
-  }
-
-  /* add supported feture list */
-
-  if (result) {
-    cnt = 0;
-    for (i = 1; i < BTA_HL_NUM_MDEPS; i++) {
-      if (p_cb->sup_feature.mdep[i].mdep_id) {
-        mdep_id = (uint8_t)p_cb->sup_feature.mdep[i].mdep_id;
-        mdep_role = (uint8_t)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role;
-
-        APPL_TRACE_DEBUG(
-            "num_of_mdep_data_types %d ",
-            p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types);
-        for (j = 0;
-             j < p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types;
-             j++) {
-          sup_feature_list.list_elem[cnt].mdep_id = mdep_id;
-          sup_feature_list.list_elem[cnt].mdep_role = mdep_role;
-          sup_feature_list.list_elem[cnt].data_type =
-              p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type;
-          if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0') {
-            sup_feature_list.list_elem[cnt].p_mdep_desp =
-                p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp;
-          } else {
-            sup_feature_list.list_elem[cnt].p_mdep_desp = NULL;
-          }
-
-          cnt++;
-          if (cnt == BTA_HL_NUM_SUP_FEATURE_ELEMS) {
-            result = false;
-            break;
-          }
-        }
-      }
-    }
-    sup_feature_list.num_elems = cnt;
-    result &= bta_hl_add_sup_feature_list(p_cb->sdp_handle,
-                                          sup_feature_list.num_elems,
-                                          sup_feature_list.list_elem);
-  }
-  if (result) {
-    result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC,
-                               UINT_DESC_TYPE, (uint32_t)1,
-                               (uint8_t*)&data_exchange_spec);
-  }
-
-  if (result) {
-    result &=
-        SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC,
-                         UINT_DESC_TYPE, (uint32_t)1, (uint8_t*)&mcap_sup_proc);
-  }
-
-  if (result) {
-    result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
-                                  1, browse_list);
-  }
-
-  if (result) {
-    for (i = 0; i < num_services; i++) {
-      bta_sys_add_uuid(svc_class_id_list[i]);
-      APPL_TRACE_DEBUG("dbg bta_sys_add_uuid i=%d uuid=0x%x", i,
-                       svc_class_id_list[i]);  // todo
-    }
-  } else {
-    if (p_cb->sdp_handle) {
-      SDP_DeleteRecord(p_cb->sdp_handle);
-      p_cb->sdp_handle = 0;
-    }
-    status = BTA_HL_STATUS_SDP_FAIL;
-  }
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_sdp_update status=%s", bta_hl_status_code(status));
-#endif
-  return status;
-}
-
-/*****************************************************************************
- *
- *  Function:    bta_hl_sdp_register
- *
- *  Purpose:     Register an HDP application with SDP
- *
- *  Parameters:  p_cb           - Pointer to MA instance control block
- *               p_service_name - MA server name
- *               inst_id        - MAS instance ID
- *               msg_type       - Supported message type(s)
- *
- *
- *  Returns:     void
- *
- ****************************************************************************/
-tBTA_HL_STATUS bta_hl_sdp_register(uint8_t app_idx) {
-  uint16_t svc_class_id_list[BTA_HL_NUM_SVC_ELEMS];
-  tSDP_PROTOCOL_ELEM proto_elem_list[BTA_HL_NUM_PROTO_ELEMS];
-  tSDP_PROTO_LIST_ELEM add_proto_list;
-  tBTA_HL_SUP_FEATURE_LIST_ELEM sup_feature_list;
-  uint16_t browse_list[] = {UUID_SERVCLASS_PUBLIC_BROWSE_GROUP};
-  uint8_t i, j, cnt, mdep_id, mdep_role;
-  uint8_t data_exchange_spec = BTA_HL_SDP_IEEE_11073_20601;
-  uint8_t mcap_sup_proc = BTA_HL_MCAP_SUP_PROC_MASK;
-  uint16_t profile_uuid = UUID_SERVCLASS_HDP_PROFILE;
-  uint16_t version = BTA_HL_VERSION;
-  uint8_t num_services = 1;
-  tBTA_HL_APP_CB* p_cb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  bool result = true;
-  tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_sdp_register app_idx=%d", app_idx);
-#endif
-
-  if ((p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE) &&
-      (!p_cb->sup_feature.advertize_source_sdp)) {
-    return BTA_HL_STATUS_OK;
-  }
-
-  p_cb->sdp_handle = SDP_CreateRecord();
-  if (p_cb->sdp_handle == 0) {
-    return BTA_HL_STATUS_SDP_NO_RESOURCE;
-  }
-
-  num_services = 1;
-  svc_class_id_list[0] = UUID_SERVCLASS_HDP_SOURCE;
-  if (p_cb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SINK) {
-    svc_class_id_list[0] = UUID_SERVCLASS_HDP_SINK;
-  } else {
-    if (p_cb->sup_feature.app_role_mask != BTA_HL_MDEP_ROLE_MASK_SOURCE) {
-      /* dual role */
-      num_services = 2;
-      svc_class_id_list[1] = UUID_SERVCLASS_HDP_SINK;
-    }
-  }
-  result &= SDP_AddServiceClassIdList(p_cb->sdp_handle, num_services,
-                                      svc_class_id_list);
-
-  if (result) {
-    /* add the protocol element sequence */
-    proto_elem_list[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-    proto_elem_list[0].num_params = 1;
-    proto_elem_list[0].params[0] = p_cb->ctrl_psm;
-    proto_elem_list[1].protocol_uuid = UUID_PROTOCOL_MCAP_CTRL;
-    proto_elem_list[1].num_params = 1;
-    proto_elem_list[1].params[0] = version;
-    result &= SDP_AddProtocolList(p_cb->sdp_handle, BTA_HL_NUM_PROTO_ELEMS,
-                                  proto_elem_list);
-
-    result &=
-        SDP_AddProfileDescriptorList(p_cb->sdp_handle, profile_uuid, version);
-  }
-
-  if (result) {
-    add_proto_list.num_elems = BTA_HL_NUM_ADD_PROTO_ELEMS;
-    add_proto_list.list_elem[0].protocol_uuid = UUID_PROTOCOL_L2CAP;
-    add_proto_list.list_elem[0].num_params = 1;
-    add_proto_list.list_elem[0].params[0] = p_cb->data_psm;
-    add_proto_list.list_elem[1].protocol_uuid = UUID_PROTOCOL_MCAP_DATA;
-    add_proto_list.list_elem[1].num_params = 0;
-    result &= SDP_AddAdditionProtoLists(
-        p_cb->sdp_handle, BTA_HL_NUM_ADD_PROTO_LISTS, &add_proto_list);
-  }
-
-  if (result) {
-    if (p_cb->srv_name[0]) {
-      result &= SDP_AddAttribute(
-          p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
-          (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_name) + 1),
-          (uint8_t*)p_cb->srv_name);
-    } /* end of setting optional service name */
-  }
-
-  if (result) {
-    if (p_cb->srv_desp[0]) {
-      result &= SDP_AddAttribute(
-          p_cb->sdp_handle, (uint16_t)ATTR_ID_SERVICE_DESCRIPTION,
-          (uint8_t)TEXT_STR_DESC_TYPE, (uint32_t)(strlen(p_cb->srv_desp) + 1),
-          (uint8_t*)p_cb->srv_desp);
-
-    } /* end of setting optional service description */
-  }
-
-  if (result) {
-    if (p_cb->provider_name[0]) {
-      result &=
-          SDP_AddAttribute(p_cb->sdp_handle, (uint16_t)ATTR_ID_PROVIDER_NAME,
-                           (uint8_t)TEXT_STR_DESC_TYPE,
-                           (uint32_t)(strlen(p_cb->provider_name) + 1),
-                           (uint8_t*)p_cb->provider_name);
-    } /* end of setting optional provider name */
-  }
-
-  /* add supported feture list */
-
-  if (result) {
-    cnt = 0;
-    for (i = 1; i <= p_cb->sup_feature.num_of_mdeps; i++) {
-      mdep_id = (uint8_t)p_cb->sup_feature.mdep[i].mdep_id;
-      mdep_role = (uint8_t)p_cb->sup_feature.mdep[i].mdep_cfg.mdep_role;
-
-      for (j = 0; j < p_cb->sup_feature.mdep[i].mdep_cfg.num_of_mdep_data_types;
-           j++) {
-        sup_feature_list.list_elem[cnt].mdep_id = mdep_id;
-        sup_feature_list.list_elem[cnt].mdep_role = mdep_role;
-        sup_feature_list.list_elem[cnt].data_type =
-            p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].data_type;
-        if (p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp[0] != '\0') {
-          sup_feature_list.list_elem[cnt].p_mdep_desp =
-              p_cb->sup_feature.mdep[i].mdep_cfg.data_cfg[j].desp;
-        } else {
-          sup_feature_list.list_elem[cnt].p_mdep_desp = NULL;
-        }
-
-        cnt++;
-        if (cnt == BTA_HL_NUM_SUP_FEATURE_ELEMS) {
-          result = false;
-          break;
-        }
-      }
-    }
-    sup_feature_list.num_elems = cnt;
-    result &= bta_hl_add_sup_feature_list(p_cb->sdp_handle,
-                                          sup_feature_list.num_elems,
-                                          sup_feature_list.list_elem);
-  }
-  if (result) {
-    result &= SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_DATA_EXCH_SPEC,
-                               UINT_DESC_TYPE, (uint32_t)1,
-                               (uint8_t*)&data_exchange_spec);
-  }
-
-  if (result) {
-    result &=
-        SDP_AddAttribute(p_cb->sdp_handle, ATTR_ID_HDP_MCAP_SUP_PROC,
-                         UINT_DESC_TYPE, (uint32_t)1, (uint8_t*)&mcap_sup_proc);
-  }
-
-  if (result) {
-    result &= SDP_AddUuidSequence(p_cb->sdp_handle, ATTR_ID_BROWSE_GROUP_LIST,
-                                  1, browse_list);
-  }
-
-  if (result) {
-    for (i = 0; i < num_services; i++) {
-      bta_sys_add_uuid(svc_class_id_list[i]);
-      APPL_TRACE_DEBUG("dbg bta_sys_add_uuid i=%d uuid=0x%x", i,
-                       svc_class_id_list[i]);  // todo
-    }
-  } else {
-    if (p_cb->sdp_handle) {
-      SDP_DeleteRecord(p_cb->sdp_handle);
-      p_cb->sdp_handle = 0;
-    }
-    status = BTA_HL_STATUS_SDP_FAIL;
-  }
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_sdp_register status=%s", bta_hl_status_code(status));
-#endif
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_find_sink_or_src_srv_class_in_db
- *
- * Description      This function queries an SDP database for either a HDP Sink
- *                  or Source service class ID.
- *                  If the p_start_rec pointer is NULL, it looks from the
- *                  beginning of the database, else it continues from the next
- *                  record after p_start_rec.
- *
- * Returns          Pointer to record containing service class, or NULL
- *
- ******************************************************************************/
-tSDP_DISC_REC* bta_hl_find_sink_or_src_srv_class_in_db(
-    const tSDP_DISCOVERY_DB* p_db, const tSDP_DISC_REC* p_start_rec) {
-  tSDP_DISC_REC* p_rec;
-  tSDP_DISC_ATTR *p_attr, *p_sattr;
-
-  /* Must have a valid database */
-  if (p_db == NULL) return (NULL);
-
-  if (!p_start_rec) {
-    p_rec = p_db->p_first_rec;
-  } else {
-    p_rec = p_start_rec->p_next_rec;
-  }
-
-  while (p_rec) {
-    p_attr = p_rec->p_first_attr;
-    while (p_attr) {
-      if ((p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST) &&
-          (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) ==
-           DATA_ELE_SEQ_DESC_TYPE)) {
-        for (p_sattr = p_attr->attr_value.v.p_sub_attr; p_sattr;
-             p_sattr = p_sattr->p_next_attr) {
-          if ((SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) == UUID_DESC_TYPE) &&
-              (SDP_DISC_ATTR_LEN(p_sattr->attr_len_type) == 2) &&
-              ((p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SINK) ||
-               (p_sattr->attr_value.v.u16 == UUID_SERVCLASS_HDP_SOURCE))) {
-            return (p_rec);
-          }
-        }
-        break;
-      }
-
-      p_attr = p_attr->p_next_attr;
-    }
-
-    p_rec = p_rec->p_next_rec;
-  }
-/* If here, no matching UUID found */
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_find_sink_or_src_srv_class_in_db failed");
-#endif
-
-  return (NULL);
-}
-#endif /* HL_INCLUDED */
diff --git a/bta/hl/bta_hl_utils.cc b/bta/hl/bta_hl_utils.cc
deleted file mode 100644
index 0aa93b3..0000000
--- a/bta/hl/bta_hl_utils.cc
+++ /dev/null
@@ -1,3083 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2003-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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This file implements utility functions for the HeaLth device profile
- *  (HL).
- *
- ******************************************************************************/
-
-#include <stdio.h>
-#include <string.h>
-
-#include "bt_target.h"
-#if (HL_INCLUDED == TRUE)
-
-#include "bt_common.h"
-#include "bta_hl_co.h"
-#include "bta_hl_int.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "osi/include/osi.h"
-#include "utl.h"
-
-/*******************************************************************************
- *
- * Function      bta_hl_set_ctrl_psm_for_dch
- *
- * Description    This function set the control PSM for the DCH setup
- *
- * Returns     bool - true - control PSM setting is successful
- ******************************************************************************/
-bool bta_hl_set_ctrl_psm_for_dch(uint8_t app_idx, uint8_t mcl_idx,
-                                 UNUSED_ATTR uint8_t mdl_idx,
-                                 uint16_t ctrl_psm) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool success = true, update_ctrl_psm = false;
-
-  if (p_mcb->sdp.num_recs) {
-    if (p_mcb->ctrl_psm != ctrl_psm) {
-      /* can not use a different ctrl PSM than the current one*/
-      success = false;
-    }
-  } else {
-    /* No SDP info control i.e. channel was opened by the peer */
-    update_ctrl_psm = true;
-  }
-
-  if (success && update_ctrl_psm) {
-    p_mcb->ctrl_psm = ctrl_psm;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!success) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_set_ctrl_psm_for_dch num_recs=%d success=%d update_ctrl_psm=%d "
-        "ctrl_psm=0x%x ",
-        p_mcb->sdp.num_recs, success, update_ctrl_psm, ctrl_psm);
-  }
-#endif
-
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_sdp_idx_using_ctrl_psm
- *
- * Description
- *
- * Returns      true if found
- *
- ******************************************************************************/
-bool bta_hl_find_sdp_idx_using_ctrl_psm(tBTA_HL_SDP* p_sdp, uint16_t ctrl_psm,
-                                        uint8_t* p_sdp_idx) {
-  bool found = false;
-  tBTA_HL_SDP_REC* p_rec;
-  uint8_t i;
-
-  if (ctrl_psm != 0) {
-    for (i = 0; i < p_sdp->num_recs; i++) {
-      p_rec = &p_sdp->sdp_rec[i];
-      if (p_rec->ctrl_psm == ctrl_psm) {
-        *p_sdp_idx = i;
-        found = true;
-        break;
-      }
-    }
-  } else {
-    *p_sdp_idx = 0;
-    found = true;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_sdp_idx_using_ctrl_psm found=%d sdp_idx=%d ctrl_psm=0x%x ",
-        found, *p_sdp_idx, ctrl_psm);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_set_user_tx_buf_size
- *
- * Description  This function sets the user tx buffer size
- *
- * Returns      uint16_t buf_size
- *
- ******************************************************************************/
-
-uint16_t bta_hl_set_user_tx_buf_size(uint16_t max_tx_size) {
-  if (max_tx_size > BT_DEFAULT_BUFFER_SIZE) return BTA_HL_LRG_DATA_BUF_SIZE;
-  return L2CAP_INVALID_ERM_BUF_SIZE;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_set_user_rx_buf_size
- *
- * Description  This function sets the user rx buffer size
- *
- * Returns      uint16_t buf_size
- *
- ******************************************************************************/
-
-uint16_t bta_hl_set_user_rx_buf_size(uint16_t mtu) {
-  if (mtu > BT_DEFAULT_BUFFER_SIZE) return BTA_HL_LRG_DATA_BUF_SIZE;
-  return L2CAP_INVALID_ERM_BUF_SIZE;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_set_tx_win_size
- *
- * Description  This function sets the tx window size
- *
- * Returns      uint8_t tx_win_size
- *
- ******************************************************************************/
-uint8_t bta_hl_set_tx_win_size(uint16_t mtu, uint16_t mps) {
-  uint8_t tx_win_size;
-
-  if (mtu <= mps) {
-    tx_win_size = 1;
-  } else {
-    if (mps > 0) {
-      tx_win_size = (mtu / mps) + 1;
-    } else {
-      APPL_TRACE_ERROR("The MPS is zero");
-      tx_win_size = 10;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_set_tx_win_size win_size=%d mtu=%d mps=%d",
-                   tx_win_size, mtu, mps);
-#endif
-  return tx_win_size;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_set_mps
- *
- * Description  This function sets the MPS
- *
- * Returns      uint16_t MPS
- *
- ******************************************************************************/
-uint16_t bta_hl_set_mps(uint16_t mtu) {
-  uint16_t mps;
-  if (mtu > BTA_HL_L2C_MPS) {
-    mps = BTA_HL_L2C_MPS;
-  } else {
-    mps = mtu;
-  }
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_set_mps mps=%d mtu=%d", mps, mtu);
-#endif
-  return mps;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_clean_mdl_cb
- *
- * Description  This function clean up the specified MDL control block
- *
- * Returns      void
- *
- ******************************************************************************/
-void bta_hl_clean_mdl_cb(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_clean_mdl_cb app_idx=%d mcl_idx=%d mdl_idx=%d",
-                   app_idx, mcl_idx, mdl_idx);
-#endif
-  osi_free_and_reset((void**)&p_dcb->p_tx_pkt);
-  osi_free_and_reset((void**)&p_dcb->p_rx_pkt);
-  osi_free_and_reset((void**)&p_dcb->p_echo_tx_pkt);
-  osi_free_and_reset((void**)&p_dcb->p_echo_rx_pkt);
-
-  memset((void*)p_dcb, 0, sizeof(tBTA_HL_MDL_CB));
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_get_buf
- *
- * Description  This function allocate a buffer based on the specified data size
- *
- * Returns      BT_HDR *.
- *
- ******************************************************************************/
-BT_HDR* bta_hl_get_buf(uint16_t data_size, bool fcs_use) {
-  size_t size = data_size + L2CAP_MIN_OFFSET + BT_HDR_SIZE + L2CAP_FCS_LEN +
-                L2CAP_EXT_CONTROL_OVERHEAD;
-
-  if (fcs_use) size += L2CAP_FCS_LEN;
-
-  BT_HDR* p_new = (BT_HDR*)osi_malloc(size);
-  p_new->len = data_size;
-  p_new->offset = L2CAP_MIN_OFFSET;
-
-  return p_new;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_service_in_db
- *
- * Description  This function check the specified service class(es) can be find
- *              in the received SDP database
- *
- * Returns      bool true - found
- *                      false - not found
- *
- ******************************************************************************/
-bool bta_hl_find_service_in_db(uint8_t app_idx, uint8_t mcl_idx,
-                               uint16_t service_uuid, tSDP_DISC_REC** pp_rec) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool found = true;
-
-  switch (service_uuid) {
-    case UUID_SERVCLASS_HDP_SINK:
-    case UUID_SERVCLASS_HDP_SOURCE:
-      *pp_rec = SDP_FindServiceInDb(p_mcb->p_db, service_uuid, *pp_rec);
-      if (*pp_rec == NULL) {
-        found = false;
-      }
-      break;
-    default:
-      *pp_rec = bta_hl_find_sink_or_src_srv_class_in_db(p_mcb->p_db, *pp_rec);
-      if (*pp_rec == NULL) {
-        found = false;
-      }
-      break;
-  }
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_get_service_uuids
- *
- *
- * Description  This function finds the service class(es) for both CCH and DCH
- *              operations
- *
- * Returns      uint16_t - service_id
- *                       if service_uuid = 0xFFFF then it means service uuid
- *                       can be either Sink or Source
- *
- ******************************************************************************/
-uint16_t bta_hl_get_service_uuids(uint8_t sdp_oper, uint8_t app_idx,
-                                  uint8_t mcl_idx, uint8_t mdl_idx) {
-  tBTA_HL_MDL_CB* p_dcb;
-  uint16_t service_uuid = 0xFFFF; /* both Sink and Source */
-
-  switch (sdp_oper) {
-    case BTA_HL_SDP_OP_DCH_OPEN_INIT:
-    case BTA_HL_SDP_OP_DCH_RECONNECT_INIT:
-      p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-      if (p_dcb->local_mdep_id != BTA_HL_ECHO_TEST_MDEP_ID) {
-        if (p_dcb->peer_mdep_role == BTA_HL_MDEP_ROLE_SINK) {
-          service_uuid = UUID_SERVCLASS_HDP_SINK;
-        } else {
-          service_uuid = UUID_SERVCLASS_HDP_SOURCE;
-        }
-      }
-      break;
-    case BTA_HL_SDP_OP_CCH_INIT:
-    default:
-      /* use default that is both Sink and Source */
-      break;
-  }
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_get_service_uuids service_uuid=0x%x", service_uuid);
-#endif
-  return service_uuid;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_echo_cfg_rsp
- *
- *
- * Description  This function finds the configuration response for the echo test
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_echo_cfg_rsp(uint8_t app_idx, uint8_t mcl_idx,
-                              uint8_t mdep_idx, uint8_t cfg,
-                              uint8_t* p_cfg_rsp) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MDEP* p_mdep = &p_acb->sup_feature.mdep[mdep_idx];
-  bool status = true;
-
-  if (p_mdep->mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-    if ((cfg == BTA_HL_DCH_CFG_RELIABLE) || (cfg == BTA_HL_DCH_CFG_STREAMING)) {
-      *p_cfg_rsp = cfg;
-    } else if (cfg == BTA_HL_DCH_CFG_NO_PREF) {
-      *p_cfg_rsp = BTA_HL_DEFAULT_ECHO_TEST_SRC_DCH_CFG;
-    } else {
-      status = false;
-      APPL_TRACE_ERROR("Inavlid echo cfg value");
-    }
-    return status;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!status) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_echo_cfg_rsp status=failed app_idx=%d mcl_idx=%d "
-        "mdep_idx=%d cfg=%d",
-        app_idx, mcl_idx, mdep_idx, cfg);
-  }
-#endif
-
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_validate_dch_cfg
- *
- * Description  This function validate the DCH configuration
- *
- * Returns      bool - true cfg is valid
- *                        false not valid
- *
- ******************************************************************************/
-bool bta_hl_validate_cfg(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                         uint8_t cfg) {
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-  bool is_valid = false;
-
-  if (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx) &&
-      (cfg != BTA_HL_DCH_CFG_RELIABLE)) {
-    APPL_TRACE_ERROR("the first DCH should be a reliable channel");
-    return is_valid;
-  }
-
-  switch (p_dcb->local_cfg) {
-    case BTA_HL_DCH_CFG_NO_PREF:
-
-      if ((cfg == BTA_HL_DCH_CFG_RELIABLE) ||
-          (cfg == BTA_HL_DCH_CFG_STREAMING)) {
-        is_valid = true;
-      }
-      break;
-    case BTA_HL_DCH_CFG_RELIABLE:
-    case BTA_HL_DCH_CFG_STREAMING:
-      if (p_dcb->local_cfg == cfg) {
-        is_valid = true;
-      }
-      break;
-    default:
-      break;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!is_valid) {
-    APPL_TRACE_DEBUG("bta_hl_validate_dch_open_cfg is_valid=%d, cfg=%d",
-                     is_valid, cfg);
-  }
-#endif
-  return is_valid;
-}
-
-/*******************************************************************************
- *
- * Function       bta_hl_find_cch_cb_indexes
- *
- * Description  This function finds the indexes needed for the CCH state machine
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_cch_cb_indexes(tBTA_HL_DATA* p_msg, uint8_t* p_app_idx,
-                                uint8_t* p_mcl_idx) {
-  bool found = false;
-  tBTA_HL_MCL_CB* p_mcb;
-  uint8_t app_idx = 0, mcl_idx = 0;
-
-  switch (p_msg->hdr.event) {
-    case BTA_HL_CCH_SDP_OK_EVT:
-    case BTA_HL_CCH_SDP_FAIL_EVT:
-      app_idx = p_msg->cch_sdp.app_idx;
-      mcl_idx = p_msg->cch_sdp.mcl_idx;
-      found = true;
-      break;
-
-    case BTA_HL_MCA_CONNECT_IND_EVT:
-
-      if (bta_hl_find_app_idx_using_handle(p_msg->mca_evt.app_handle,
-                                           &app_idx)) {
-        if (bta_hl_find_mcl_idx(app_idx,
-                                p_msg->mca_evt.mca_data.connect_ind.bd_addr,
-                                &mcl_idx)) {
-          /* local initiated */
-          found = true;
-        } else if (!bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle,
-                                                     &app_idx, &mcl_idx) &&
-                   bta_hl_find_avail_mcl_idx(app_idx, &mcl_idx)) {
-          /* remote initiated */
-          p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-          p_mcb->in_use = true;
-          p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_OPEN;
-          found = true;
-        }
-      }
-      break;
-
-    case BTA_HL_MCA_DISCONNECT_IND_EVT:
-
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx)) {
-        found = true;
-      } else if (bta_hl_find_app_idx_using_handle(p_msg->mca_evt.app_handle,
-                                                  &app_idx) &&
-                 bta_hl_find_mcl_idx(
-                     app_idx, p_msg->mca_evt.mca_data.disconnect_ind.bd_addr,
-                     &mcl_idx)) {
-        found = true;
-      }
-
-      if (found) {
-        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-        if ((p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE) &&
-            (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_OPEN)) {
-          p_mcb->cch_oper = BTA_HL_CCH_OP_REMOTE_CLOSE;
-        }
-      }
-      break;
-
-    case BTA_HL_MCA_RSP_TOUT_IND_EVT:
-
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx)) {
-        found = true;
-      }
-
-      if (found) {
-        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-        if ((p_mcb->cch_oper != BTA_HL_CCH_OP_REMOTE_CLOSE) &&
-            (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_OPEN)) {
-          p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
-        }
-      }
-      break;
-    default:
-      break;
-  }
-
-  if (found) {
-    *p_app_idx = app_idx;
-    *p_mcl_idx = mcl_idx;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_cch_cb_indexes event=%s found=%d app_idx=%d mcl_idx=%d",
-        bta_hl_evt_code(p_msg->hdr.event), found, app_idx, mcl_idx);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function       bta_hl_find_dch_cb_indexes
- *
- * Description  This function finds the indexes needed for the DCH state machine
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_dch_cb_indexes(tBTA_HL_DATA* p_msg, uint8_t* p_app_idx,
-                                uint8_t* p_mcl_idx, uint8_t* p_mdl_idx) {
-  bool found = false;
-  tBTA_HL_MCL_CB* p_mcb;
-  uint8_t app_idx = 0, mcl_idx = 0, mdl_idx = 0;
-
-  switch (p_msg->hdr.event) {
-    case BTA_HL_MCA_CREATE_CFM_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->mca_evt.mca_data.create_cfm.mdl_id,
-                              &mdl_idx)) {
-        found = true;
-      }
-      break;
-
-    case BTA_HL_MCA_CREATE_IND_EVT:
-    case BTA_HL_MCA_RECONNECT_IND_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_avail_mdl_idx(app_idx, mcl_idx, &mdl_idx)) {
-        found = true;
-      }
-      break;
-
-    case BTA_HL_MCA_OPEN_CFM_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->mca_evt.mca_data.open_cfm.mdl_id,
-                              &mdl_idx)) {
-        found = true;
-      }
-      break;
-
-    case BTA_HL_MCA_OPEN_IND_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->mca_evt.mca_data.open_ind.mdl_id,
-                              &mdl_idx)) {
-        found = true;
-      }
-      break;
-
-    case BTA_HL_MCA_CLOSE_CFM_EVT:
-
-      if (bta_hl_find_mdl_idx_using_handle(
-              (tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.close_cfm.mdl,
-              &app_idx, &mcl_idx, &mdl_idx)) {
-        found = true;
-      }
-      break;
-    case BTA_HL_MCA_CLOSE_IND_EVT:
-
-      if (bta_hl_find_mdl_idx_using_handle(
-              (tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.close_ind.mdl,
-              &app_idx, &mcl_idx, &mdl_idx)) {
-        found = true;
-      }
-      break;
-    case BTA_HL_API_SEND_DATA_EVT:
-
-      if (bta_hl_find_mdl_idx_using_handle(p_msg->api_send_data.mdl_handle,
-                                           &app_idx, &mcl_idx, &mdl_idx)) {
-        found = true;
-      }
-
-      break;
-
-    case BTA_HL_MCA_CONG_CHG_EVT:
-
-      if (bta_hl_find_mdl_idx_using_handle(
-              (tBTA_HL_MDL_HANDLE)p_msg->mca_evt.mca_data.cong_chg.mdl,
-              &app_idx, &mcl_idx, &mdl_idx)) {
-        found = true;
-      }
-
-      break;
-
-    case BTA_HL_MCA_RCV_DATA_EVT:
-      app_idx = p_msg->mca_rcv_data_evt.app_idx;
-      mcl_idx = p_msg->mca_rcv_data_evt.mcl_idx;
-      mdl_idx = p_msg->mca_rcv_data_evt.mdl_idx;
-      found = true;
-      break;
-    case BTA_HL_DCH_RECONNECT_EVT:
-    case BTA_HL_DCH_OPEN_EVT:
-    case BTA_HL_DCH_ECHO_TEST_EVT:
-    case BTA_HL_DCH_SDP_FAIL_EVT:
-      app_idx = p_msg->dch_sdp.app_idx;
-      mcl_idx = p_msg->dch_sdp.mcl_idx;
-      mdl_idx = p_msg->dch_sdp.mdl_idx;
-      found = true;
-      break;
-    case BTA_HL_MCA_RECONNECT_CFM_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->mca_evt.mca_data.reconnect_cfm.mdl_id,
-                              &mdl_idx)) {
-        found = true;
-      }
-      break;
-
-    case BTA_HL_API_DCH_CREATE_RSP_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->api_dch_create_rsp.mcl_handle,
-                                           &app_idx, &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->api_dch_create_rsp.mdl_id, &mdl_idx)) {
-        found = true;
-      }
-      break;
-    case BTA_HL_MCA_ABORT_IND_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->mca_evt.mca_data.abort_ind.mdl_id,
-                              &mdl_idx)) {
-        found = true;
-      }
-      break;
-    case BTA_HL_MCA_ABORT_CFM_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(p_msg->mca_evt.mcl_handle, &app_idx,
-                                           &mcl_idx) &&
-          bta_hl_find_mdl_idx(app_idx, mcl_idx,
-                              p_msg->mca_evt.mca_data.abort_cfm.mdl_id,
-                              &mdl_idx)) {
-        found = true;
-      }
-      break;
-    case BTA_HL_CI_GET_TX_DATA_EVT:
-    case BTA_HL_CI_PUT_RX_DATA_EVT:
-      if (bta_hl_find_mdl_idx_using_handle(p_msg->ci_get_put_data.mdl_handle,
-                                           &app_idx, &mcl_idx, &mdl_idx)) {
-        found = true;
-      }
-      break;
-    case BTA_HL_CI_GET_ECHO_DATA_EVT:
-    case BTA_HL_CI_PUT_ECHO_DATA_EVT:
-      if (bta_hl_find_mcl_idx_using_handle(
-              p_msg->ci_get_put_echo_data.mcl_handle, &app_idx, &mcl_idx)) {
-        p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-        mdl_idx = p_mcb->echo_mdl_idx;
-        found = true;
-      }
-      break;
-
-    default:
-      break;
-  }
-
-  if (found) {
-    *p_app_idx = app_idx;
-    *p_mcl_idx = mcl_idx;
-    *p_mdl_idx = mdl_idx;
-  }
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_dch_cb_indexes event=%s found=%d app_idx=%d mcl_idx=%d "
-        "mdl_idx=%d",
-        bta_hl_evt_code(p_msg->hdr.event), found, *p_app_idx, *p_mcl_idx,
-        *p_mdl_idx);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_allocate_mdl_id
- *
- * Description  This function allocates a MDL ID
- *
- * Returns      uint16_t - MDL ID
- *
- ******************************************************************************/
-uint16_t bta_hl_allocate_mdl_id(uint8_t app_idx, uint8_t mcl_idx,
-                                uint8_t mdl_idx) {
-  uint16_t mdl_id = 0;
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool duplicate_id;
-  uint8_t i, mdl_cfg_idx;
-
-  do {
-    duplicate_id = false;
-    mdl_id = ((mdl_id + 1) & 0xFEFF);
-    /* check mdl_ids that are used for the current conenctions */
-    for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-      if (p_mcb->mdl[i].in_use && (i != mdl_idx) &&
-          (p_mcb->mdl[i].mdl_id == mdl_id)) {
-        duplicate_id = true;
-        break;
-      }
-    }
-
-    if (duplicate_id) {
-      /* start from the beginning to get another MDL value*/
-      continue;
-    } else {
-      /* check mdl_ids that are stored in the persistent memory */
-      if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, mdl_id, &mdl_cfg_idx)) {
-        duplicate_id = true;
-      } else {
-        /* found a new MDL value */
-        break;
-      }
-    }
-
-  } while (true);
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_allocate_mdl OK mdl_id=%d", mdl_id);
-#endif
-  return mdl_id;
-}
-/*******************************************************************************
- *
- * Function      bta_hl_find_mdl_idx
- *
- * Description  This function finds the MDL index based on mdl_id
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_mdl_idx(uint8_t app_idx, uint8_t mcl_idx, uint16_t mdl_id,
-                         uint8_t* p_mdl_idx) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-    if (p_mcb->mdl[i].in_use && (mdl_id != 0) &&
-        (p_mcb->mdl[i].mdl_id == mdl_id)) {
-      found = true;
-      *p_mdl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_mdl_idx found=%d mdl_id=%d mdl_idx=%d ",
-                     found, mdl_id, i);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_an_active_mdl_idx
- *
- * Description  This function finds an active MDL
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_an_active_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                   uint8_t* p_mdl_idx) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-    if (p_mcb->mdl[i].in_use &&
-        (p_mcb->mdl[i].dch_state == BTA_HL_DCH_OPEN_ST)) {
-      found = true;
-      *p_mdl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_an_opened_mdl_idx found=%d app_idx=%d mcl_idx=%d "
-        "mdl_idx=%d",
-        found, app_idx, mcl_idx, i);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_dch_setup_mdl_idx
- *
- * Description  This function finds a MDL which in the DCH setup state
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_dch_setup_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                   uint8_t* p_mdl_idx) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-    if (p_mcb->mdl[i].in_use &&
-        (p_mcb->mdl[i].dch_state == BTA_HL_DCH_OPENING_ST)) {
-      found = true;
-      *p_mdl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_dch_setup_mdl_idx found=%d app_idx=%d mcl_idx=%d "
-        "mdl_idx=%d",
-        found, app_idx, mcl_idx, i);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_an_in_use_mcl_idx
- *
- * Description  This function finds an in-use MCL control block index
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_an_in_use_mcl_idx(uint8_t app_idx, uint8_t* p_mcl_idx) {
-  tBTA_HL_MCL_CB* p_mcb;
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MCLS; i++) {
-    p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, i);
-    if (p_mcb->in_use && (p_mcb->cch_state != BTA_HL_CCH_IDLE_ST)) {
-      found = true;
-      *p_mcl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_an_in_use_mcl_idx found=%d app_idx=%d mcl_idx=%d ", found,
-        app_idx, i);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_an_in_use_app_idx
- *
- * Description  This function finds an in-use application control block index
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_an_in_use_app_idx(uint8_t* p_app_idx) {
-  tBTA_HL_APP_CB* p_acb;
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    p_acb = BTA_HL_GET_APP_CB_PTR(i);
-    if (p_acb->in_use) {
-      found = true;
-      *p_app_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (found) {
-    APPL_TRACE_DEBUG("bta_hl_find_an_in_use_app_idx found=%d app_idx=%d ",
-                     found, i);
-  }
-#endif
-
-  return found;
-}
-/*******************************************************************************
- *
- * Function      bta_hl_find_app_idx
- *
- * Description  This function finds the application control block index based on
- *              the application ID
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_app_idx(uint8_t app_id, uint8_t* p_app_idx) {
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    if (bta_hl_cb.acb[i].in_use && (bta_hl_cb.acb[i].app_id == app_id)) {
-      found = true;
-      *p_app_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_find_app_idx found=%d app_id=%d idx=%d ", found,
-                   app_id, i);
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_app_idx_using_handle
- *
- * Description  This function finds the application control block index based on
- *              the application handle
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_app_idx_using_handle(tBTA_HL_APP_HANDLE app_handle,
-                                      uint8_t* p_app_idx) {
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    if (bta_hl_cb.acb[i].in_use &&
-        (bta_hl_cb.acb[i].app_handle == app_handle)) {
-      found = true;
-      *p_app_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_app_idx_using_mca_handle status=%d handle=%d app_idx=%d ",
-        found, app_handle, i);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_mcl_idx_using_handle
- *
- * Description  This function finds the MCL control block index based on
- *              the MCL handle
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_mcl_idx_using_handle(tBTA_HL_MCL_HANDLE mcl_handle,
-                                      uint8_t* p_app_idx, uint8_t* p_mcl_idx) {
-  tBTA_HL_APP_CB* p_acb;
-  bool found = false;
-  uint8_t i = 0, j = 0;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    p_acb = BTA_HL_GET_APP_CB_PTR(i);
-    if (p_acb->in_use) {
-      for (j = 0; j < BTA_HL_NUM_MCLS; j++) {
-        if (p_acb->mcb[j].mcl_handle == mcl_handle) {
-          found = true;
-          *p_app_idx = i;
-          *p_mcl_idx = j;
-          break;
-        }
-      }
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_mcl_idx_using_handle found=%d app_idx=%d mcl_idx=%d",
-        found, i, j);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_mcl_idx
- *
- * Description  This function finds the MCL control block index based on
- *              the peer BD address
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_mcl_idx(uint8_t app_idx, const RawAddress& p_bd_addr,
-                         uint8_t* p_mcl_idx) {
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MCLS; i++) {
-    if (bta_hl_cb.acb[app_idx].mcb[i].in_use &&
-        bta_hl_cb.acb[app_idx].mcb[i].bd_addr == p_bd_addr) {
-      found = true;
-      *p_mcl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_mcl_idx found=%d idx=%d", found, i);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_mdl_idx_using_handle
- *
- * Description  This function finds the MDL control block index based on
- *              the MDL handle
- *
- * Returns      bool true-found
- *
- ******************************************************************************/
-bool bta_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
-                                      uint8_t* p_app_idx, uint8_t* p_mcl_idx,
-                                      uint8_t* p_mdl_idx) {
-  tBTA_HL_APP_CB* p_acb;
-  tBTA_HL_MCL_CB* p_mcb;
-  tBTA_HL_MDL_CB* p_dcb;
-  bool found = false;
-  uint8_t i, j, k;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    p_acb = BTA_HL_GET_APP_CB_PTR(i);
-    if (p_acb->in_use) {
-      for (j = 0; j < BTA_HL_NUM_MCLS; j++) {
-        p_mcb = BTA_HL_GET_MCL_CB_PTR(i, j);
-        if (p_mcb->in_use) {
-          for (k = 0; k < BTA_HL_NUM_MDLS_PER_MCL; k++) {
-            p_dcb = BTA_HL_GET_MDL_CB_PTR(i, j, k);
-            if (p_dcb->in_use) {
-              if (p_dcb->mdl_handle == mdl_handle) {
-                found = true;
-                *p_app_idx = i;
-                *p_mcl_idx = j;
-                *p_mdl_idx = k;
-                break;
-              }
-            }
-          }
-        }
-      }
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_mdl_idx_using_handle found=%d mdl_handle=%d  ", found,
-        mdl_handle);
-  }
-#endif
-  return found;
-}
-/*******************************************************************************
- *
- * Function      bta_hl_is_the_first_reliable_existed
- *
- * Description  This function checks whether the first reliable DCH channel
- *              has been setup on the MCL or not
- *
- * Returns      bool - true exist
- *                        false does not exist
- *
- ******************************************************************************/
-bool bta_hl_is_the_first_reliable_existed(uint8_t app_idx, uint8_t mcl_idx) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool is_existed = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-    if (p_mcb->mdl[i].in_use && p_mcb->mdl[i].is_the_first_reliable) {
-      is_existed = true;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_is_the_first_reliable_existed is_existed=%d  ",
-                   is_existed);
-#endif
-  return is_existed;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_non_active_mdl_cfg
- *
- * Description  This function finds a valid MDL configiration index and this
- *              MDL ID is not active
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_non_active_mdl_cfg(uint8_t app_idx, uint8_t start_mdl_cfg_idx,
-                                    uint8_t* p_mdl_cfg_idx) {
-  tBTA_HL_MCL_CB* p_mcb;
-  tBTA_HL_MDL_CB* p_dcb;
-  tBTA_HL_MDL_CFG* p_mdl;
-  bool mdl_in_use;
-  bool found = false;
-  uint8_t i, j, k;
-
-  for (i = start_mdl_cfg_idx; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    mdl_in_use = false;
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    for (j = 0; j < BTA_HL_NUM_MCLS; j++) {
-      p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, j);
-      if (p_mcb->in_use && p_mdl->peer_bd_addr == p_mcb->bd_addr) {
-        for (k = 0; k < BTA_HL_NUM_MDLS_PER_MCL; k++) {
-          p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, j, k);
-
-          if (p_dcb->in_use && p_mdl->mdl_id == p_dcb->mdl_id) {
-            mdl_in_use = true;
-            break;
-          }
-        }
-      }
-
-      if (mdl_in_use) {
-        break;
-      }
-    }
-
-    if (!mdl_in_use) {
-      *p_mdl_cfg_idx = i;
-      found = true;
-      break;
-    }
-  }
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_mdl_cfg_idx
- *
- * Description  This function finds an available MDL configuration index
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_avail_mdl_cfg_idx(uint8_t app_idx, UNUSED_ATTR uint8_t mcl_idx,
-                                   uint8_t* p_mdl_cfg_idx) {
-  tBTA_HL_MDL_CFG *p_mdl, *p_mdl1, *p_mdl2;
-  uint8_t i;
-  bool found = false;
-  uint8_t first_mdl_cfg_idx, second_mdl_cfg_idx, older_mdl_cfg_idx;
-  bool done;
-
-  for (i = 0; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    if (!p_mdl->active) {
-      /* found an unused space to store mdl cfg*/
-      found = true;
-      *p_mdl_cfg_idx = i;
-      break;
-    }
-  }
-
-  if (!found) {
-    /* all available mdl cfg spaces are in use so we need to find the mdl cfg
-    which is
-    not currently in use and has the the oldest time stamp to remove*/
-
-    found = true;
-    if (bta_hl_find_non_active_mdl_cfg(app_idx, 0, &first_mdl_cfg_idx)) {
-      if (bta_hl_find_non_active_mdl_cfg(
-              app_idx, (uint8_t)(first_mdl_cfg_idx + 1), &second_mdl_cfg_idx)) {
-        done = false;
-        while (!done) {
-          p_mdl1 = BTA_HL_GET_MDL_CFG_PTR(app_idx, first_mdl_cfg_idx);
-          p_mdl2 = BTA_HL_GET_MDL_CFG_PTR(app_idx, second_mdl_cfg_idx);
-
-          if (p_mdl1->time < p_mdl2->time) {
-            older_mdl_cfg_idx = first_mdl_cfg_idx;
-          } else {
-            older_mdl_cfg_idx = second_mdl_cfg_idx;
-          }
-
-          if (bta_hl_find_non_active_mdl_cfg(app_idx,
-                                             (uint8_t)(second_mdl_cfg_idx + 1),
-                                             &second_mdl_cfg_idx)) {
-            first_mdl_cfg_idx = older_mdl_cfg_idx;
-          } else {
-            done = true;
-          }
-        }
-
-        *p_mdl_cfg_idx = older_mdl_cfg_idx;
-
-      } else {
-        *p_mdl_cfg_idx = first_mdl_cfg_idx;
-      }
-
-    } else {
-      found = false;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_avail_mdl_cfg_idx found=%d mdl_cfg_idx=%d ",
-                     found, *p_mdl_cfg_idx);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_mdl_cfg_idx
- *
- * Description  This function finds the MDL configuration index based on
- *              the MDL ID
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_mdl_cfg_idx(uint8_t app_idx, uint8_t mcl_idx,
-                             tBTA_HL_MDL_ID mdl_id, uint8_t* p_mdl_cfg_idx) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  tBTA_HL_MDL_CFG* p_mdl;
-  uint8_t i;
-  bool found = false;
-
-  *p_mdl_cfg_idx = 0;
-  for (i = 0; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    if (p_mdl->active)
-      APPL_TRACE_DEBUG("bta_hl_find_mdl_cfg_idx: mdl_id =%d, p_mdl->mdl_id=%d",
-                       mdl_id, p_mdl->mdl_id);
-    if (p_mdl->active && p_mcb->bd_addr == p_mdl->peer_bd_addr &&
-        (p_mdl->mdl_id == mdl_id)) {
-      found = true;
-      *p_mdl_cfg_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_mdl_cfg_idx found=%d mdl_cfg_idx=%d ", found,
-                     i);
-  }
-#endif
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_get_cur_time
- *
- * Description  This function get the cuurent time value
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_get_cur_time(uint8_t app_idx, uint8_t* p_cur_time) {
-  tBTA_HL_MDL_CFG* p_mdl;
-  uint8_t i, j, time_latest, time;
-  bool found = false, result = true;
-
-  for (i = 0; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    if (p_mdl->active) {
-      found = true;
-      time_latest = p_mdl->time;
-      for (j = (i + 1); j < BTA_HL_NUM_MDL_CFGS; j++) {
-        p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, j);
-        if (p_mdl->active) {
-          time = p_mdl->time;
-          if (time > time_latest) {
-            time_latest = time;
-          }
-        }
-      }
-      break;
-    }
-  }
-
-  if (found) {
-    if (time_latest < BTA_HL_MAX_TIME) {
-      *p_cur_time = time_latest + 1;
-    } else {
-      /* need to wrap around */
-      result = false;
-    }
-  } else {
-    *p_cur_time = BTA_HL_MIN_TIME;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!result) {
-    APPL_TRACE_DEBUG("bta_hl_get_cur_time result=%s cur_time=%d",
-                     (result ? "OK" : "FAIL"), *p_cur_time);
-  }
-#endif
-
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_sort_cfg_time_idx
- *
- * Description  This function sort the mdl configuration idx stored in array a
- *              based on decending time value
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-void bta_hl_sort_cfg_time_idx(uint8_t app_idx, uint8_t* a, uint8_t n) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  uint8_t temp_time, temp_idx;
-  int16_t i, j;
-  for (i = 1; i < n; ++i) {
-    temp_idx = a[i];
-    temp_time = p_acb->mdl_cfg[temp_idx].time;
-    j = i - 1;
-    while ((j >= 0) && (temp_time < p_acb->mdl_cfg[a[j]].time)) {
-      a[j + 1] = a[j];
-      --j;
-    }
-    a[j + 1] = temp_idx;
-  }
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_compact_mdl_cfg_time
- *
- * Description  This function finds the MDL configuration index based on
- *              the MDL ID
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-void bta_hl_compact_mdl_cfg_time(uint8_t app_idx, uint8_t mdep_id) {
-  tBTA_HL_MDL_CFG* p_mdl;
-  uint8_t i, time_min, cnt = 0;
-  uint8_t s_arr[BTA_HL_NUM_MDL_CFGS];
-
-  for (i = 0; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    if (p_mdl->active) {
-      s_arr[cnt] = i;
-      cnt++;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_compact_mdl_cfg_time cnt=%d ", cnt);
-#endif
-
-  if (cnt) {
-    bta_hl_sort_cfg_time_idx(app_idx, s_arr, cnt);
-    time_min = BTA_HL_MIN_TIME;
-    for (i = 0; i < cnt; i++) {
-      p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, s_arr[i]);
-      p_mdl->time = time_min + i;
-      bta_hl_co_save_mdl(mdep_id, s_arr[i], p_mdl);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_is_mdl_exsit_in_mcl
- *
- * Description  This function checks whether the MDL ID
- *              has already existed in teh MCL or not
- *
- * Returns      bool - true exist
- *                        false does not exist
- *
- ******************************************************************************/
-bool bta_hl_is_mdl_exsit_in_mcl(uint8_t app_idx, const RawAddress& bd_addr,
-                                tBTA_HL_MDL_ID mdl_id) {
-  tBTA_HL_MDL_CFG* p_mdl;
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    if (p_mdl->active && p_mdl->peer_bd_addr == bd_addr) {
-      if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS) {
-        if (p_mdl->mdl_id == mdl_id) {
-          found = true;
-          break;
-        }
-      } else {
-        found = true;
-        break;
-      }
-    }
-  }
-
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_delete_mdl_cfg
- *
- * Description  This function delete the specified MDL ID
- *
- * Returns      bool - true Success
- *                        false Failed
- *
- ******************************************************************************/
-bool bta_hl_delete_mdl_cfg(uint8_t app_idx, const RawAddress& bd_addr,
-                           tBTA_HL_MDL_ID mdl_id) {
-  tBTA_HL_MDL_CFG* p_mdl;
-  bool success = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDL_CFGS; i++) {
-    p_mdl = BTA_HL_GET_MDL_CFG_PTR(app_idx, i);
-    if (p_mdl->active && p_mdl->peer_bd_addr == bd_addr) {
-      if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS) {
-        if (p_mdl->mdl_id == mdl_id) {
-          bta_hl_co_delete_mdl(p_mdl->local_mdep_id, i);
-          memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG));
-          success = true;
-          break;
-        }
-      } else {
-        bta_hl_co_delete_mdl(p_mdl->local_mdep_id, i);
-        memset(p_mdl, 0, sizeof(tBTA_HL_MDL_CFG));
-        success = true;
-      }
-    }
-  }
-
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_is_mdl_value_valid
- *
- *
- * Description  This function checks the specified MDL ID is in valid range.
- *
- * Returns      bool - true Success
- *                        false Failed
- *
- * note:   mdl_id range   0x0000 reserved,
- *                        0x0001-oxFEFF dynamic range,
- *                        0xFF00-0xFFFE reserved,
- *                        0xFFFF indicates all MDLs (for delete operation only)
- *
- ******************************************************************************/
-bool bta_hl_is_mdl_value_valid(tBTA_HL_MDL_ID mdl_id) {
-  bool status = true;
-
-  if (mdl_id != BTA_HL_DELETE_ALL_MDL_IDS) {
-    if (mdl_id != 0) {
-      if (mdl_id > BTA_HL_MAX_MDL_VAL) {
-        status = false;
-      }
-    } else {
-      status = false;
-    }
-  }
-
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_mdep_cfg_idx
- *
- * Description  This function finds the MDEP configuration index based
- *                on the local MDEP ID
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_mdep_cfg_idx(uint8_t app_idx, tBTA_HL_MDEP_ID local_mdep_id,
-                              uint8_t* p_mdep_cfg_idx) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_SUP_FEATURE* p_sup_feature = &p_acb->sup_feature;
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < p_sup_feature->num_of_mdeps; i++) {
-    if (p_sup_feature->mdep[i].mdep_id == local_mdep_id) {
-      found = true;
-      *p_mdep_cfg_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_find_mdep_cfg_idx found=%d mdep_idx=%d local_mdep_id=%d ",
-        found, i, local_mdep_id);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_rxtx_apdu_size
- *
- * Description  This function finds the maximum APDU rx and tx sizes based on
- *              the MDEP configuration data
- *
- * Returns      void
- *
- ******************************************************************************/
-void bta_hl_find_rxtx_apdu_size(uint8_t app_idx, uint8_t mdep_cfg_idx,
-                                uint16_t* p_rx_apu_size,
-                                uint16_t* p_tx_apu_size) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MDEP_CFG* p_mdep_cfg;
-  uint8_t i;
-  uint16_t max_rx_apdu_size = 0, max_tx_apdu_size = 0;
-
-  p_mdep_cfg = &p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg;
-
-  for (i = 0; i < p_mdep_cfg->num_of_mdep_data_types; i++) {
-    if (max_rx_apdu_size < p_mdep_cfg->data_cfg[i].max_rx_apdu_size) {
-      max_rx_apdu_size = p_mdep_cfg->data_cfg[i].max_rx_apdu_size;
-    }
-
-    if (max_tx_apdu_size < p_mdep_cfg->data_cfg[i].max_tx_apdu_size) {
-      max_tx_apdu_size = p_mdep_cfg->data_cfg[i].max_tx_apdu_size;
-    }
-  }
-
-  *p_rx_apu_size = max_rx_apdu_size;
-  *p_tx_apu_size = max_tx_apdu_size;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG(
-      "bta_hl_find_rxtx_apdu_size max_rx_apdu_size=%d max_tx_apdu_size=%d ",
-      max_rx_apdu_size, max_tx_apdu_size);
-#endif
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_validate_peer_cfg
- *
- * Description  This function validates the peer DCH configuration
- *
- * Returns      bool - true validation is successful
- *                        false validation failed
- *
- ******************************************************************************/
-bool bta_hl_validate_peer_cfg(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                              tBTA_HL_MDEP_ID peer_mdep_id,
-                              tBTA_HL_MDEP_ROLE peer_mdep_role,
-                              uint8_t sdp_idx) {
-  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);
-  tBTA_HL_SDP_REC* p_rec;
-  bool peer_found = false;
-  uint8_t i;
-
-  APPL_TRACE_DEBUG("bta_hl_validate_peer_cfg sdp_idx=%d app_idx %d", sdp_idx,
-                   app_idx);
-
-  if (p_dcb->local_mdep_id == BTA_HL_ECHO_TEST_MDEP_ID) {
-    return true;
-  }
-
-  p_rec = &p_mcb->sdp.sdp_rec[sdp_idx];
-  for (i = 0; i < p_rec->num_mdeps; i++) {
-    APPL_TRACE_DEBUG("mdep_id %d peer_mdep_id %d", p_rec->mdep_cfg[i].mdep_id,
-                     peer_mdep_id);
-    APPL_TRACE_DEBUG("mdep_role %d peer_mdep_role %d",
-                     p_rec->mdep_cfg[i].mdep_role, peer_mdep_role)
-    if ((p_rec->mdep_cfg[i].mdep_id == peer_mdep_id) &&
-        (p_rec->mdep_cfg[i].mdep_role == peer_mdep_role)) {
-      peer_found = true;
-
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!peer_found) {
-    APPL_TRACE_DEBUG("bta_hl_validate_peer_cfg failed num_mdeps=%d",
-                     p_rec->num_mdeps);
-  }
-#endif
-  return peer_found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_chk_local_cfg
- *
- * Description  This function check whether the local DCH configuration is OK.
- *
- * Returns      tBTA_HL_STATUS - OK - local DCH configuration is OK
- *                               NO_FIRST_RELIABLE - the streaming DCH
- *                                                   configuration is not OK and
- *                                                   it needs to use reliable
- *                                                   DCH configuration
- *
- ******************************************************************************/
-tBTA_HL_STATUS bta_hl_chk_local_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                                    uint8_t mdep_cfg_idx,
-                                    tBTA_HL_DCH_CFG local_cfg) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
-
-  if (mdep_cfg_idx &&
-      (p_acb->sup_feature.mdep[mdep_cfg_idx].mdep_cfg.mdep_role ==
-       BTA_HL_MDEP_ROLE_SOURCE) &&
-      (!bta_hl_is_the_first_reliable_existed(app_idx, mcl_idx)) &&
-      (local_cfg != BTA_HL_DCH_CFG_RELIABLE)) {
-    status = BTA_HL_STATUS_NO_FIRST_RELIABLE;
-    APPL_TRACE_ERROR("BTA_HL_STATUS_INVALID_DCH_CFG");
-  }
-
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_validate_reconnect_params
- *
- * Description  This function validates the reconnect parameters
- *
- * Returns      bool - true validation is successful
- *                        false validation failed
- ******************************************************************************/
-bool bta_hl_validate_reconnect_params(uint8_t app_idx, uint8_t mcl_idx,
-                                      tBTA_HL_API_DCH_RECONNECT* p_reconnect,
-                                      uint8_t* p_mdep_cfg_idx,
-                                      uint8_t* p_mdl_cfg_idx) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_SUP_FEATURE* p_sup_feature = &p_acb->sup_feature;
-  uint8_t num_mdeps;
-  uint8_t mdl_cfg_idx;
-  bool local_mdep_id_found = false;
-  bool mdl_cfg_found = false;
-  bool status = false;
-  uint8_t i, in_use_mdl_idx = 0;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_validate_reconnect_params  mdl_id=%d app_idx=%d",
-                   p_reconnect->mdl_id, app_idx);
-#endif
-  if (bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_reconnect->mdl_id,
-                              &mdl_cfg_idx)) {
-    mdl_cfg_found = true;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!mdl_cfg_found) {
-    APPL_TRACE_DEBUG("mdl_cfg_found not found");
-  }
-#endif
-
-  if (mdl_cfg_found) {
-    num_mdeps = p_sup_feature->num_of_mdeps;
-    for (i = 0; i < num_mdeps; i++) {
-      if (p_sup_feature->mdep[i].mdep_id ==
-          p_acb->mdl_cfg[mdl_cfg_idx].local_mdep_id) {
-        local_mdep_id_found = true;
-        *p_mdep_cfg_idx = i;
-        *p_mdl_cfg_idx = mdl_cfg_idx;
-        break;
-      }
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!local_mdep_id_found) {
-    APPL_TRACE_DEBUG("local_mdep_id not found");
-  }
-#endif
-
-  if (local_mdep_id_found) {
-    if (!bta_hl_find_mdl_idx(app_idx, mcl_idx, p_reconnect->mdl_id,
-                             &in_use_mdl_idx)) {
-      status = true;
-    } else {
-      APPL_TRACE_ERROR("mdl_id=%d is curreltly in use", p_reconnect->mdl_id);
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!status) {
-    APPL_TRACE_DEBUG(
-        "Reconnect validation failed local_mdep_id found=%d mdl_cfg_idx "
-        "found=%d in_use_mdl_idx=%d ",
-        local_mdep_id_found, mdl_cfg_found, in_use_mdl_idx);
-  }
-#endif
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_avail_mcl_idx
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_avail_mcl_idx(uint8_t app_idx, uint8_t* p_mcl_idx) {
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MCLS; i++) {
-    if (!bta_hl_cb.acb[app_idx].mcb[i].in_use) {
-      found = true;
-      *p_mcl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_avail_mcl_idx found=%d idx=%d", found, i);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_avail_mdl_idx
- *
- * Description  This function finds an available MDL control block index
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_avail_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                               uint8_t* p_mdl_idx) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_MDLS_PER_MCL; i++) {
-    if (!p_mcb->mdl[i].in_use) {
-      memset((void*)&p_mcb->mdl[i], 0, sizeof(tBTA_HL_MDL_CB));
-      found = true;
-      *p_mdl_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_avail_mdl_idx found=%d idx=%d", found, i);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_is_a_duplicate_id
- *
- * Description  This function finds the application has been used or not
- *
- * Returns      bool - true the app_id is a duplicate ID
- *                        false not a duplicate ID
- ******************************************************************************/
-bool bta_hl_is_a_duplicate_id(uint8_t app_id) {
-  bool is_duplicate = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    if (bta_hl_cb.acb[i].in_use && (bta_hl_cb.acb[i].app_id == app_id)) {
-      is_duplicate = true;
-
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (is_duplicate) {
-    APPL_TRACE_DEBUG("bta_hl_is_a_duplicate_id app_id=%d is_duplicate=%d",
-                     app_id, is_duplicate);
-  }
-#endif
-
-  return is_duplicate;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_find_avail_app_idx
- *
- * Description  This function finds an available application control block index
- *
- * Returns      bool - true found
- *                        false not found
- *
- ******************************************************************************/
-bool bta_hl_find_avail_app_idx(uint8_t* p_idx) {
-  bool found = false;
-  uint8_t i;
-
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    if (!bta_hl_cb.acb[i].in_use) {
-      found = true;
-      *p_idx = i;
-      break;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!found) {
-    APPL_TRACE_DEBUG("bta_hl_find_avail_app_idx found=%d app_idx=%d", found, i);
-  }
-#endif
-  return found;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_app_update
- *
- * Description  This function registers an HDP application MCAP and DP
- *
- * Returns      tBTA_HL_STATUS -registration status
- *
- ******************************************************************************/
-tBTA_HL_STATUS bta_hl_app_update(uint8_t app_id, bool is_register) {
-  tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(0);
-  tMCA_CS mca_cs;
-  uint8_t i, mdep_idx, num_of_mdeps;
-  uint8_t mdep_counter = 0;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_app_update app_id=%d", app_id);
-#endif
-
-  if (is_register) {
-    if ((status == BTA_HL_STATUS_OK) &&
-        bta_hl_co_get_num_of_mdep(app_id, &num_of_mdeps)) {
-      for (i = 0; i < num_of_mdeps; i++) {
-        mca_cs.type = MCA_TDEP_DATA;
-        mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
-        mca_cs.p_data_cback = bta_hl_mcap_data_cback;
-        /* Find the first available mdep index, and create a MDL Endpoint */
-        // make a function later if needed
-        for (mdep_idx = 1; mdep_idx < BTA_HL_NUM_MDEPS; mdep_idx++) {
-          if (p_acb->sup_feature.mdep[mdep_idx].mdep_id == 0) {
-            break; /* We found an available index */
-          } else {
-            mdep_counter++;
-          }
-        }
-        /* If no available MDEPs, return error */
-        if (mdep_idx == BTA_HL_NUM_MDEPS) {
-          APPL_TRACE_ERROR("bta_hl_app_update: Out of MDEP IDs");
-          status = BTA_HL_STATUS_MCAP_REG_FAIL;
-          break;
-        }
-        if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
-                          &(p_acb->sup_feature.mdep[mdep_idx].mdep_id),
-                          &mca_cs) == MCA_SUCCESS) {
-          if (bta_hl_co_get_mdep_config(
-                  app_id, mdep_idx, mdep_counter,
-                  p_acb->sup_feature.mdep[mdep_idx].mdep_id,
-                  &p_acb->sup_feature.mdep[mdep_idx].mdep_cfg)) {
-            p_acb->sup_feature.mdep[mdep_idx].ori_app_id = app_id;
-            APPL_TRACE_DEBUG("mdep idx %d id %d ori_app_id %d num data type %d",
-                             mdep_idx,
-                             p_acb->sup_feature.mdep[mdep_idx].mdep_id,
-                             p_acb->sup_feature.mdep[mdep_idx].ori_app_id,
-                             p_acb->sup_feature.mdep[mdep_idx]
-                                 .mdep_cfg.num_of_mdep_data_types);
-            if (p_acb->sup_feature.mdep[mdep_idx].mdep_cfg.mdep_role ==
-                BTA_HL_MDEP_ROLE_SOURCE) {
-              p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SOURCE;
-            } else if (p_acb->sup_feature.mdep[mdep_idx].mdep_cfg.mdep_role ==
-                       BTA_HL_MDEP_ROLE_SINK) {
-              p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SINK;
-            } else {
-              APPL_TRACE_ERROR(
-                  "bta_hl_app_registration: Invalid Role %d",
-                  p_acb->sup_feature.mdep[mdep_idx].mdep_cfg.mdep_role);
-              status = BTA_HL_STATUS_MDEP_CO_FAIL;
-              break;
-            }
-          } else {
-            APPL_TRACE_ERROR("bta_hl_app_registration: Cfg callout failed");
-            status = BTA_HL_STATUS_MDEP_CO_FAIL;
-            break;
-          }
-        } else {
-          APPL_TRACE_ERROR("bta_hl_app_registration: MCA_CreateDep failed");
-          status = BTA_HL_STATUS_MCAP_REG_FAIL;
-          break;
-        }
-      }
-      p_acb->sup_feature.num_of_mdeps += num_of_mdeps;
-      APPL_TRACE_DEBUG("num_of_mdeps %d", p_acb->sup_feature.num_of_mdeps);
-
-      if ((status == BTA_HL_STATUS_OK) &&
-          (p_acb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE)) {
-        p_acb->sup_feature.advertize_source_sdp =
-            bta_hl_co_advrtise_source_sdp(app_id);
-      }
-
-      if ((status == BTA_HL_STATUS_OK) &&
-          (!bta_hl_co_get_echo_config(app_id, &p_acb->sup_feature.echo_cfg))) {
-        status = BTA_HL_STATUS_ECHO_CO_FAIL;
-      }
-
-      if ((status == BTA_HL_STATUS_OK) &&
-          (!bta_hl_co_load_mdl_config(app_id, BTA_HL_NUM_MDL_CFGS,
-                                      &p_acb->mdl_cfg[0]))) {
-        status = BTA_HL_STATUS_MDL_CFG_CO_FAIL;
-      }
-    } else {
-      status = BTA_HL_STATUS_MDEP_CO_FAIL;
-    }
-  } else {
-    for (i = 1; i < BTA_HL_NUM_MDEPS; i++) {
-      if (p_acb->sup_feature.mdep[i].ori_app_id == app_id) {
-        APPL_TRACE_DEBUG("Found index %", i);
-
-        if (MCA_DeleteDep((tMCA_HANDLE)p_acb->app_handle,
-                          (p_acb->sup_feature.mdep[i].mdep_id)) !=
-            MCA_SUCCESS) {
-          APPL_TRACE_ERROR("Error deregistering");
-          status = BTA_HL_STATUS_MCAP_REG_FAIL;
-          return status;
-        }
-        memset(&p_acb->sup_feature.mdep[i], 0, sizeof(tBTA_HL_MDEP));
-      }
-    }
-  }
-
-  if (status == BTA_HL_STATUS_OK) {
-    /* Register/Update MDEP(s) in SDP Record */
-    status = bta_hl_sdp_update(app_id);
-  }
-  /* else do cleanup */
-
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_app_registration
- *
- * Description  This function registers an HDP application MCAP and DP
- *
- * Returns      tBTA_HL_STATUS -registration status
- *
- ******************************************************************************/
-tBTA_HL_STATUS bta_hl_app_registration(uint8_t app_idx) {
-  tBTA_HL_STATUS status = BTA_HL_STATUS_OK;
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tMCA_REG reg;
-  tMCA_CS mca_cs;
-  uint8_t i, num_of_mdeps;
-  uint8_t mdep_counter = 0;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_app_registration app_idx=%d", app_idx);
-#endif
-
-  reg.ctrl_psm = p_acb->ctrl_psm;
-  reg.data_psm = p_acb->data_psm;
-  reg.sec_mask = p_acb->sec_mask;
-  reg.rsp_tout = BTA_HL_MCAP_RSP_TOUT;
-
-  p_acb->app_handle =
-      (tBTA_HL_APP_HANDLE)MCA_Register(&reg, bta_hl_mcap_ctrl_cback);
-  if (p_acb->app_handle != 0) {
-    mca_cs.type = MCA_TDEP_ECHO;
-    mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
-    mca_cs.p_data_cback = bta_hl_mcap_data_cback;
-
-    if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
-                      &(p_acb->sup_feature.mdep[0].mdep_id),
-                      &mca_cs) == MCA_SUCCESS) {
-      if (p_acb->sup_feature.mdep[0].mdep_id != BTA_HL_ECHO_TEST_MDEP_ID) {
-        status = BTA_HL_STATUS_MCAP_REG_FAIL;
-        APPL_TRACE_ERROR("BAD MDEP ID for echo test mdep_id=%d",
-                         p_acb->sup_feature.mdep[0].mdep_id);
-      }
-    } else {
-      status = BTA_HL_STATUS_MCAP_REG_FAIL;
-      APPL_TRACE_ERROR("MCA_CreateDep for echo test(mdep_id=0) failed");
-    }
-
-    if ((status == BTA_HL_STATUS_OK) &&
-        bta_hl_co_get_num_of_mdep(p_acb->app_id, &num_of_mdeps)) {
-      p_acb->sup_feature.num_of_mdeps = num_of_mdeps + 1;
-
-      for (i = 1; i < p_acb->sup_feature.num_of_mdeps; i++) {
-        mca_cs.type = MCA_TDEP_DATA;
-        mca_cs.max_mdl = BTA_HL_NUM_MDLS_PER_MDEP;
-        mca_cs.p_data_cback = bta_hl_mcap_data_cback;
-
-        if (MCA_CreateDep((tMCA_HANDLE)p_acb->app_handle,
-                          &(p_acb->sup_feature.mdep[i].mdep_id),
-                          &mca_cs) == MCA_SUCCESS) {
-          if (bta_hl_co_get_mdep_config(p_acb->app_id, i, mdep_counter,
-                                        p_acb->sup_feature.mdep[i].mdep_id,
-                                        &p_acb->sup_feature.mdep[i].mdep_cfg)) {
-            if (p_acb->sup_feature.mdep[i].mdep_cfg.mdep_role ==
-                BTA_HL_MDEP_ROLE_SOURCE) {
-              p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SOURCE;
-            } else if (p_acb->sup_feature.mdep[i].mdep_cfg.mdep_role ==
-                       BTA_HL_MDEP_ROLE_SINK) {
-              p_acb->sup_feature.app_role_mask |= BTA_HL_MDEP_ROLE_MASK_SINK;
-            } else {
-              status = BTA_HL_STATUS_MDEP_CO_FAIL;
-              break;
-            }
-            p_acb->sup_feature.mdep[i].ori_app_id = p_acb->app_id;
-            APPL_TRACE_DEBUG("index %d ori_app_id %d", i,
-                             p_acb->sup_feature.mdep[i].ori_app_id);
-          } else {
-            status = BTA_HL_STATUS_MDEP_CO_FAIL;
-            break;
-          }
-        } else {
-          status = BTA_HL_STATUS_MCAP_REG_FAIL;
-          break;
-        }
-      }
-
-      if ((status == BTA_HL_STATUS_OK) &&
-          (p_acb->sup_feature.app_role_mask == BTA_HL_MDEP_ROLE_MASK_SOURCE)) {
-        /* this is a source only applciation */
-        p_acb->sup_feature.advertize_source_sdp =
-            bta_hl_co_advrtise_source_sdp(p_acb->app_id);
-      }
-
-      if ((status == BTA_HL_STATUS_OK) &&
-          (!bta_hl_co_get_echo_config(p_acb->app_id,
-                                      &p_acb->sup_feature.echo_cfg))) {
-        status = BTA_HL_STATUS_ECHO_CO_FAIL;
-      }
-
-      if ((status == BTA_HL_STATUS_OK) &&
-          (!bta_hl_co_load_mdl_config(p_acb->app_id, BTA_HL_NUM_MDL_CFGS,
-                                      &p_acb->mdl_cfg[0]))) {
-        status = BTA_HL_STATUS_MDL_CFG_CO_FAIL;
-      }
-    } else {
-      status = BTA_HL_STATUS_MDEP_CO_FAIL;
-    }
-  } else {
-    status = BTA_HL_STATUS_MCAP_REG_FAIL;
-  }
-
-  if (status == BTA_HL_STATUS_OK) {
-    status = bta_hl_sdp_register(app_idx);
-  }
-
-  return status;
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_discard_data
- *
- * Description  This function discard an HDP event
- *
- * Returns     void
- *
- ******************************************************************************/
-void bta_hl_discard_data(uint16_t event, tBTA_HL_DATA* p_data) {
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_ERROR("BTA HL Discard event=%s", bta_hl_evt_code(event));
-
-#endif
-
-  switch (event) {
-    case BTA_HL_API_SEND_DATA_EVT:
-      break;
-
-    case BTA_HL_MCA_RCV_DATA_EVT:
-      osi_free_and_reset((void**)&p_data->mca_rcv_data_evt.p_pkt);
-      break;
-
-    default:
-      /*Nothing to free*/
-      break;
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_save_mdl_cfg
- *
- * Description    This function saves the MDL configuration
- *
- * Returns     void
- *
- ******************************************************************************/
-void bta_hl_save_mdl_cfg(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  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);
-  uint8_t mdl_cfg_idx;
-  tBTA_HL_MDL_ID mdl_id;
-  bool found = true;
-  tBTA_HL_MDL_CFG mdl_cfg;
-  tBTA_HL_MDEP* p_mdep_cfg;
-  tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
-  uint8_t time_val = 0;
-  mdl_id = p_dcb->mdl_id;
-  if (!bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, mdl_id, &mdl_cfg_idx)) {
-    if (!bta_hl_find_avail_mdl_cfg_idx(app_idx, mcl_idx, &mdl_cfg_idx)) {
-      APPL_TRACE_ERROR("No space to save the MDL config");
-      found = false; /*no space available*/
-    }
-  }
-
-  if (found) {
-    bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg);
-    if (!bta_hl_get_cur_time(app_idx, &time_val)) {
-      bta_hl_compact_mdl_cfg_time(app_idx, p_dcb->local_mdep_id);
-      bta_hl_get_cur_time(app_idx, &time_val);
-    }
-    mdl_cfg.active = true;
-    mdl_cfg.time = time_val;
-    mdl_cfg.mdl_id = p_dcb->mdl_id;
-    mdl_cfg.dch_mode = p_dcb->dch_mode;
-    mdl_cfg.mtu = l2cap_cfg.mtu;
-    mdl_cfg.fcs = l2cap_cfg.fcs;
-
-    mdl_cfg.peer_bd_addr = p_mcb->bd_addr;
-    mdl_cfg.local_mdep_id = p_dcb->local_mdep_id;
-    p_mdep_cfg = &p_acb->sup_feature.mdep[p_dcb->local_mdep_cfg_idx];
-    mdl_cfg.local_mdep_role = p_mdep_cfg->mdep_cfg.mdep_role;
-    memcpy(&p_acb->mdl_cfg[mdl_cfg_idx], &mdl_cfg, sizeof(tBTA_HL_MDL_CFG));
-    bta_hl_co_save_mdl(mdl_cfg.local_mdep_id, mdl_cfg_idx, &mdl_cfg);
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (found) {
-    if (p_dcb->mtu != l2cap_cfg.mtu) {
-      APPL_TRACE_WARNING(
-          "MCAP and L2CAP peer mtu size out of sync from MCAP mtu=%d from "
-          "l2cap mtu=%d",
-          p_dcb->mtu, l2cap_cfg.mtu);
-    }
-    APPL_TRACE_DEBUG("bta_hl_save_mdl_cfg saved=%d", found);
-    APPL_TRACE_DEBUG("Saved. L2cap cfg mdl_id=%d mtu=%d fcs=%d dch_mode=%d",
-                     mdl_cfg.mdl_id, mdl_cfg.mtu, mdl_cfg.fcs,
-                     mdl_cfg.dch_mode);
-  }
-#endif
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_set_dch_chan_cfg
- *
- * Description    This function setups the L2CAP DCH channel configuration
- *
- * Returns     void
- ******************************************************************************/
-void bta_hl_set_dch_chan_cfg(uint8_t app_idx, uint8_t mcl_idx, uint8_t mdl_idx,
-                             tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-  uint8_t l2cap_mode = L2CAP_FCR_ERTM_MODE;
-  tBTA_HL_SUP_FEATURE* p_sup_feature = &p_acb->sup_feature;
-  uint8_t local_mdep_cfg_idx = p_dcb->local_mdep_cfg_idx;
-
-  switch (p_dcb->dch_oper) {
-    case BTA_HL_DCH_OP_LOCAL_RECONNECT:
-    case BTA_HL_DCH_OP_REMOTE_RECONNECT:
-      if (p_dcb->dch_mode == BTA_HL_DCH_MODE_STREAMING)
-        l2cap_mode = L2CAP_FCR_STREAM_MODE;
-      break;
-    case BTA_HL_DCH_OP_LOCAL_OPEN:
-      if (p_data->mca_evt.mca_data.create_cfm.cfg == BTA_HL_DCH_CFG_STREAMING)
-        l2cap_mode = L2CAP_FCR_STREAM_MODE;
-      break;
-    case BTA_HL_DCH_OP_REMOTE_OPEN:
-      if (p_dcb->local_cfg == BTA_HL_DCH_CFG_STREAMING)
-        l2cap_mode = L2CAP_FCR_STREAM_MODE;
-      break;
-    default:
-      APPL_TRACE_ERROR("Invalid dch oper=%d for set dch chan cfg",
-                       p_dcb->dch_oper);
-      break;
-  }
-  p_dcb->chnl_cfg.fcr_opt.mode = l2cap_mode;
-  p_dcb->chnl_cfg.fcr_opt.mps = bta_hl_set_mps(p_dcb->max_rx_apdu_size);
-  p_dcb->chnl_cfg.fcr_opt.tx_win_sz = bta_hl_set_tx_win_size(
-      p_dcb->max_rx_apdu_size, p_dcb->chnl_cfg.fcr_opt.mps);
-  p_dcb->chnl_cfg.fcr_opt.max_transmit = BTA_HL_L2C_MAX_TRANSMIT;
-  p_dcb->chnl_cfg.fcr_opt.rtrans_tout = BTA_HL_L2C_RTRANS_TOUT;
-  p_dcb->chnl_cfg.fcr_opt.mon_tout = BTA_HL_L2C_MON_TOUT;
-
-  p_dcb->chnl_cfg.user_rx_buf_size =
-      bta_hl_set_user_rx_buf_size(p_dcb->max_rx_apdu_size);
-  p_dcb->chnl_cfg.user_tx_buf_size =
-      bta_hl_set_user_tx_buf_size(p_dcb->max_tx_apdu_size);
-  p_dcb->chnl_cfg.fcr_rx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
-  p_dcb->chnl_cfg.fcr_tx_buf_size = L2CAP_INVALID_ERM_BUF_SIZE;
-  p_dcb->chnl_cfg.data_mtu = p_dcb->max_rx_apdu_size;
-
-  p_dcb->chnl_cfg.fcs = BTA_HL_MCA_NO_FCS;
-  if (local_mdep_cfg_idx != BTA_HL_ECHO_TEST_MDEP_CFG_IDX) {
-    if (p_sup_feature->mdep[local_mdep_cfg_idx].mdep_cfg.mdep_role ==
-        BTA_HL_MDEP_ROLE_SOURCE) {
-      p_dcb->chnl_cfg.fcs = BTA_HL_DEFAULT_SOURCE_FCS;
-    }
-  } else {
-    p_dcb->chnl_cfg.fcs = BTA_HL_MCA_USE_FCS;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("L2CAP Params l2cap_mode[3-ERTM 4-STREAM]=%d", l2cap_mode);
-  APPL_TRACE_DEBUG("Use FCS =%s mtu=%d",
-                   ((p_dcb->chnl_cfg.fcs & 1) ? "YES" : "NO"),
-                   p_dcb->chnl_cfg.data_mtu);
-  APPL_TRACE_DEBUG(
-      "tx_win_sz=%d, max_transmit=%d, rtrans_tout=%d, mon_tout=%d, mps=%d",
-      p_dcb->chnl_cfg.fcr_opt.tx_win_sz, p_dcb->chnl_cfg.fcr_opt.max_transmit,
-      p_dcb->chnl_cfg.fcr_opt.rtrans_tout, p_dcb->chnl_cfg.fcr_opt.mon_tout,
-      p_dcb->chnl_cfg.fcr_opt.mps);
-
-  APPL_TRACE_DEBUG(
-      "USER rx_buf_size=%d, tx_buf_size=%d, FCR rx_buf_size=%d, tx_buf_size=%d",
-      p_dcb->chnl_cfg.user_rx_buf_size, p_dcb->chnl_cfg.user_tx_buf_size,
-      p_dcb->chnl_cfg.fcr_rx_buf_size, p_dcb->chnl_cfg.fcr_tx_buf_size);
-
-#endif
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_get_l2cap_cfg
- *
- * Description    This function get the current L2CAP channel configuration
- *
- * Returns     bool - true - operation is successful
- ******************************************************************************/
-bool bta_hl_get_l2cap_cfg(tBTA_HL_MDL_HANDLE mdl_hnd,
-                          tBTA_HL_L2CAP_CFG_INFO* p_cfg) {
-  bool success = false;
-  uint16_t lcid;
-  tL2CAP_CFG_INFO* p_our_cfg;
-  tL2CAP_CH_CFG_BITS our_cfg_bits;
-  tL2CAP_CFG_INFO* p_peer_cfg;
-  tL2CAP_CH_CFG_BITS peer_cfg_bits;
-
-  lcid = MCA_GetL2CapChannel((tMCA_DL)mdl_hnd);
-  if (lcid && L2CA_GetCurrentConfig(lcid, &p_our_cfg, &our_cfg_bits,
-                                    &p_peer_cfg, &peer_cfg_bits)) {
-    p_cfg->fcs = BTA_HL_MCA_NO_FCS;
-    if (our_cfg_bits & L2CAP_CH_CFG_MASK_FCS) {
-      p_cfg->fcs |= p_our_cfg->fcs;
-    } else {
-      p_cfg->fcs = BTA_HL_MCA_USE_FCS;
-    }
-
-    if (p_cfg->fcs != BTA_HL_MCA_USE_FCS) {
-      if (peer_cfg_bits & L2CAP_CH_CFG_MASK_FCS) {
-        p_cfg->fcs |= p_peer_cfg->fcs;
-      } else {
-        p_cfg->fcs = BTA_HL_MCA_USE_FCS;
-      }
-    }
-
-    p_cfg->mtu = 0;
-    if (peer_cfg_bits & L2CAP_CH_CFG_MASK_MTU) {
-      p_cfg->mtu = p_peer_cfg->mtu;
-    } else {
-      p_cfg->mtu = L2CAP_DEFAULT_MTU;
-    }
-    success = true;
-  } else {
-    p_cfg->mtu = L2CAP_DEFAULT_MTU;
-    p_cfg->fcs = BTA_HL_L2C_NO_FCS;
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-  if (!success) {
-    APPL_TRACE_DEBUG("bta_hl_get_l2cap_cfg success=%d mdl=%d lcid=%d", success,
-                     mdl_hnd, lcid);
-    APPL_TRACE_DEBUG("l2cap mtu=%d fcs=%d", p_cfg->mtu, p_cfg->fcs);
-  }
-#endif
-
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_validate_chan_cfg
- *
- * Description    This function validates the L2CAP channel configuration
- *
- * Returns     bool - true - validation is successful
- ******************************************************************************/
-bool bta_hl_validate_chan_cfg(uint8_t app_idx, uint8_t mcl_idx,
-                              uint8_t mdl_idx) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MDL_CB* p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-  bool success = false;
-  uint8_t mdl_cfg_idx = 0;
-  tBTA_HL_L2CAP_CFG_INFO l2cap_cfg;
-  bool get_l2cap_result, get_mdl_result;
-
-  get_l2cap_result = bta_hl_get_l2cap_cfg(p_dcb->mdl_handle, &l2cap_cfg);
-  get_mdl_result =
-      bta_hl_find_mdl_cfg_idx(app_idx, mcl_idx, p_dcb->mdl_id, &mdl_cfg_idx);
-
-  if (get_l2cap_result && get_mdl_result) {
-    if ((p_acb->mdl_cfg[mdl_cfg_idx].mtu <= l2cap_cfg.mtu) &&
-        (p_acb->mdl_cfg[mdl_cfg_idx].fcs == l2cap_cfg.fcs) &&
-        (p_acb->mdl_cfg[mdl_cfg_idx].dch_mode == p_dcb->dch_mode)) {
-      success = true;
-    }
-  }
-
-#if (BTA_HL_DEBUG == TRUE)
-
-  if (p_dcb->mtu != l2cap_cfg.mtu) {
-    APPL_TRACE_WARNING(
-        "MCAP and L2CAP peer mtu size out of sync from MCAP mtu=%d from l2cap "
-        "mtu=%d",
-        p_dcb->mtu, l2cap_cfg.mtu);
-  }
-
-  if (!success) {
-    APPL_TRACE_DEBUG(
-        "bta_hl_validate_chan_cfg success=%d app_idx=%d mcl_idx=%d mdl_idx=%d",
-        success, app_idx, mcl_idx, mdl_idx);
-    APPL_TRACE_DEBUG("Cur. L2cap cfg mtu=%d fcs=%d dch_mode=%d", l2cap_cfg.mtu,
-                     l2cap_cfg.fcs, p_dcb->dch_mode);
-    APPL_TRACE_DEBUG("From saved: L2cap cfg mtu=%d fcs=%d dch_mode=%d",
-                     p_acb->mdl_cfg[mdl_cfg_idx].mtu,
-                     p_acb->mdl_cfg[mdl_cfg_idx].fcs,
-                     p_acb->mdl_cfg[mdl_cfg_idx].dch_mode);
-  }
-#endif
-
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_is_cong_on
- *
- * Description    This function checks whether the congestion condition is on.
- *
- * Returns      bool - true DCH is congested
- *                        false not congested
- *
- ******************************************************************************/
-bool bta_hl_is_cong_on(uint8_t app_id, const RawAddress& bd_addr,
-                       tBTA_HL_MDL_ID mdl_id)
-
-{
-  tBTA_HL_MDL_CB* p_dcb;
-  uint8_t app_idx = 0, mcl_idx, mdl_idx;
-  bool cong_status = true;
-
-  if (bta_hl_find_app_idx(app_id, &app_idx)) {
-    if (bta_hl_find_mcl_idx(app_idx, bd_addr, &mcl_idx)) {
-      if (bta_hl_find_mdl_idx(app_idx, mcl_idx, mdl_id, &mdl_idx)) {
-        p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-        cong_status = p_dcb->cong;
-      }
-    }
-  }
-
-  return cong_status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_check_cch_close
- *
- * Description   This function checks whether there is a pending CCH close
- *               request or not
- *
- * Returns      void
- ******************************************************************************/
-void bta_hl_check_cch_close(uint8_t app_idx, uint8_t mcl_idx,
-                            tBTA_HL_DATA* p_data, bool check_dch_setup) {
-  tBTA_HL_MCL_CB* p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-  tBTA_HL_MDL_CB* p_dcb;
-  uint8_t mdl_idx;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_check_cch_close cch_close_dch_oper=%d",
-                   p_mcb->cch_close_dch_oper);
-#endif
-
-  if (p_mcb->cch_oper == BTA_HL_CCH_OP_LOCAL_CLOSE) {
-    if (check_dch_setup &&
-        bta_hl_find_dch_setup_mdl_idx(app_idx, mcl_idx, &mdl_idx)) {
-      p_dcb = BTA_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-      if (!p_mcb->rsp_tout) {
-        p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_ABORT;
-
-        if (!p_dcb->abort_oper) {
-          p_dcb->abort_oper |= BTA_HL_ABORT_CCH_CLOSE_MASK;
-          bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_ABORT_EVT,
-                                p_data);
-        }
-      } else {
-        p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_CLOSE;
-        bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx,
-                              BTA_HL_DCH_CLOSE_CMPL_EVT, p_data);
-      }
-    } else if (bta_hl_find_an_active_mdl_idx(app_idx, mcl_idx, &mdl_idx)) {
-      p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_CLOSE;
-      bta_hl_dch_sm_execute(app_idx, mcl_idx, mdl_idx, BTA_HL_DCH_CLOSE_EVT,
-                            p_data);
-    } else {
-      p_mcb->cch_close_dch_oper = BTA_HL_CCH_CLOSE_OP_DCH_NONE;
-      bta_hl_cch_sm_execute(app_idx, mcl_idx, BTA_HL_CCH_CLOSE_EVT, p_data);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_clean_app
- *
- * Description      Cleans up the HDP application resources and control block
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_clean_app(uint8_t app_idx) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  int i, num_act_apps = 0;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_clean_app");
-#endif
-  MCA_Deregister((tMCA_HANDLE)p_acb->app_handle);
-
-  if (p_acb->sdp_handle) SDP_DeleteRecord(p_acb->sdp_handle);
-
-  memset((void*)p_acb, 0, sizeof(tBTA_HL_APP_CB));
-
-  /* check any application is still active */
-  for (i = 0; i < BTA_HL_NUM_APPS; i++) {
-    p_acb = BTA_HL_GET_APP_CB_PTR(i);
-    if (p_acb->in_use) num_act_apps++;
-  }
-
-  if (!num_act_apps) {
-    bta_sys_remove_uuid(UUID_SERVCLASS_HDP_PROFILE);
-  }
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_check_deregistration
- *
- * Description   This function checks whether there is a pending deregistration
- *               request or not
- *
- * Returns      void
- ******************************************************************************/
-void bta_hl_check_deregistration(uint8_t app_idx, tBTA_HL_DATA* p_data) {
-  tBTA_HL_APP_CB* p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-  tBTA_HL_MCL_CB* p_mcb;
-  uint8_t mcl_idx;
-  tBTA_HL evt_data;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_check_deregistration");
-#endif
-
-  if (p_acb->deregistering) {
-    if (bta_hl_find_an_in_use_mcl_idx(app_idx, &mcl_idx)) {
-      p_mcb = BTA_HL_GET_MCL_CB_PTR(app_idx, mcl_idx);
-      if (p_mcb->cch_oper != BTA_HL_CCH_OP_LOCAL_CLOSE) {
-        if (p_mcb->cch_state == BTA_HL_CCH_OPENING_ST)
-          p_mcb->force_close_local_cch_opening = true;
-        p_mcb->cch_oper = BTA_HL_CCH_OP_LOCAL_CLOSE;
-        APPL_TRACE_DEBUG("p_mcb->force_close_local_cch_opening=%d",
-                         p_mcb->force_close_local_cch_opening);
-        bta_hl_check_cch_close(app_idx, mcl_idx, p_data, true);
-      }
-    } else {
-      /* all cchs are closed */
-      evt_data.dereg_cfm.app_handle = p_acb->app_handle;
-      evt_data.dereg_cfm.app_id = p_data->api_dereg.app_id;
-      evt_data.dereg_cfm.status = BTA_HL_STATUS_OK;
-      p_acb->p_cback(BTA_HL_DEREGISTER_CFM_EVT, (tBTA_HL*)&evt_data);
-      bta_hl_clean_app(app_idx);
-      bta_hl_check_disable(p_data);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_check_disable
- *
- * Description   This function checks whether there is a pending disable
- *               request or not
- *
- * Returns      void
- *
- ******************************************************************************/
-void bta_hl_check_disable(tBTA_HL_DATA* p_data) {
-  tBTA_HL_CB* p_cb = &bta_hl_cb;
-  tBTA_HL_APP_CB* p_acb;
-  uint8_t app_idx;
-  tBTA_HL_CTRL evt_data;
-
-#if (BTA_HL_DEBUG == TRUE)
-  APPL_TRACE_DEBUG("bta_hl_check_disable");
-#endif
-
-  if (bta_hl_cb.disabling) {
-    if (bta_hl_find_an_in_use_app_idx(&app_idx)) {
-      p_acb = BTA_HL_GET_APP_CB_PTR(app_idx);
-      if (!p_acb->deregistering) {
-        p_acb->deregistering = true;
-        bta_hl_check_deregistration(app_idx, p_data);
-      }
-    } else {
-      /* all apps are deregistered */
-      bta_sys_deregister(BTA_ID_HL);
-      evt_data.disable_cfm.status = BTA_HL_STATUS_OK;
-      if (p_cb->p_ctrl_cback)
-        p_cb->p_ctrl_cback(BTA_HL_CTRL_DISABLE_CFM_EVT,
-                           (tBTA_HL_CTRL*)&evt_data);
-      memset((void*)p_cb, 0, sizeof(tBTA_HL_CB));
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_abort_cfm
- *
- * Description   This function builds the abort confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_abort_cfm(tBTA_HL* p_evt_data, tBTA_HL_APP_HANDLE app_handle,
-                            tBTA_HL_MCL_HANDLE mcl_handle,
-                            tBTA_HL_STATUS status) {
-  p_evt_data->dch_abort_cfm.status = status;
-  p_evt_data->dch_abort_cfm.mcl_handle = mcl_handle;
-  p_evt_data->dch_abort_cfm.app_handle = app_handle;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_abort_ind
- *
- * Description   This function builds the abort indication event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_abort_ind(tBTA_HL* p_evt_data, tBTA_HL_APP_HANDLE app_handle,
-                            tBTA_HL_MCL_HANDLE mcl_handle) {
-  p_evt_data->dch_abort_ind.mcl_handle = mcl_handle;
-  p_evt_data->dch_abort_ind.app_handle = app_handle;
-}
-/*******************************************************************************
- *
- * Function      bta_hl_build_close_cfm
- *
- * Description   This function builds the close confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_dch_close_cfm(tBTA_HL* p_evt_data,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                tBTA_HL_MCL_HANDLE mcl_handle,
-                                tBTA_HL_MDL_HANDLE mdl_handle,
-                                tBTA_HL_STATUS status) {
-  p_evt_data->dch_close_cfm.status = status;
-  p_evt_data->dch_close_cfm.mdl_handle = mdl_handle;
-  p_evt_data->dch_close_cfm.mcl_handle = mcl_handle;
-  p_evt_data->dch_close_cfm.app_handle = app_handle;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_dch_close_ind
- *
- * Description   This function builds the close indication event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_dch_close_ind(tBTA_HL* p_evt_data,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                tBTA_HL_MCL_HANDLE mcl_handle,
-                                tBTA_HL_MDL_HANDLE mdl_handle,
-                                bool intentional) {
-  p_evt_data->dch_close_ind.mdl_handle = mdl_handle;
-  p_evt_data->dch_close_ind.mcl_handle = mcl_handle;
-  p_evt_data->dch_close_ind.app_handle = app_handle;
-  p_evt_data->dch_close_ind.intentional = intentional;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_send_data_cfm
- *
- * Description   This function builds the send data confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_send_data_cfm(tBTA_HL* p_evt_data,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                tBTA_HL_MCL_HANDLE mcl_handle,
-                                tBTA_HL_MDL_HANDLE mdl_handle,
-                                tBTA_HL_STATUS status) {
-  p_evt_data->dch_send_data_cfm.mdl_handle = mdl_handle;
-  p_evt_data->dch_send_data_cfm.mcl_handle = mcl_handle;
-  p_evt_data->dch_send_data_cfm.app_handle = app_handle;
-  p_evt_data->dch_send_data_cfm.status = status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_rcv_data_ind
- *
- * Description   This function builds the received data indication event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_rcv_data_ind(tBTA_HL* p_evt_data,
-                               tBTA_HL_APP_HANDLE app_handle,
-                               tBTA_HL_MCL_HANDLE mcl_handle,
-                               tBTA_HL_MDL_HANDLE mdl_handle) {
-  p_evt_data->dch_rcv_data_ind.mdl_handle = mdl_handle;
-  p_evt_data->dch_rcv_data_ind.mcl_handle = mcl_handle;
-  p_evt_data->dch_rcv_data_ind.app_handle = app_handle;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_cch_open_cfm
- *
- * Description   This function builds the CCH open confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_cch_open_cfm(tBTA_HL* p_evt_data, uint8_t app_id,
-                               tBTA_HL_APP_HANDLE app_handle,
-                               tBTA_HL_MCL_HANDLE mcl_handle,
-                               const RawAddress& bd_addr,
-                               tBTA_HL_STATUS status) {
-  p_evt_data->cch_open_cfm.app_id = app_id;
-  p_evt_data->cch_open_cfm.app_handle = app_handle;
-  p_evt_data->cch_open_cfm.mcl_handle = mcl_handle;
-  p_evt_data->cch_open_cfm.bd_addr = bd_addr;
-  p_evt_data->cch_open_cfm.status = status;
-  APPL_TRACE_DEBUG("bta_hl_build_cch_open_cfm: status=%d", status);
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_cch_open_ind
- *
- * Description   This function builds the CCH open indication event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_cch_open_ind(tBTA_HL* p_evt_data,
-                               tBTA_HL_APP_HANDLE app_handle,
-                               tBTA_HL_MCL_HANDLE mcl_handle,
-                               const RawAddress& bd_addr) {
-  p_evt_data->cch_open_ind.app_handle = app_handle;
-  p_evt_data->cch_open_ind.mcl_handle = mcl_handle;
-  p_evt_data->cch_open_ind.bd_addr = bd_addr;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_cch_close_cfm
- *
- * Description   This function builds the CCH close confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_cch_close_cfm(tBTA_HL* p_evt_data,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                tBTA_HL_MCL_HANDLE mcl_handle,
-                                tBTA_HL_STATUS status) {
-  p_evt_data->cch_close_cfm.mcl_handle = mcl_handle;
-  p_evt_data->cch_close_cfm.app_handle = app_handle;
-  p_evt_data->cch_close_cfm.status = status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_cch_close_ind
- *
- * Description   This function builds the CCH colse indication event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_cch_close_ind(tBTA_HL* p_evt_data,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                tBTA_HL_MCL_HANDLE mcl_handle,
-                                bool intentional) {
-  p_evt_data->cch_close_ind.mcl_handle = mcl_handle;
-  p_evt_data->cch_close_ind.app_handle = app_handle;
-  p_evt_data->cch_close_ind.intentional = intentional;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_dch_open_cfm
- *
- * Description   This function builds the DCH open confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_dch_open_cfm(tBTA_HL* p_evt_data,
-                               tBTA_HL_APP_HANDLE app_handle,
-                               tBTA_HL_MCL_HANDLE mcl_handle,
-                               tBTA_HL_MDL_HANDLE mdl_handle,
-                               tBTA_HL_MDEP_ID local_mdep_id,
-                               tBTA_HL_MDL_ID mdl_id, tBTA_HL_DCH_MODE dch_mode,
-                               bool first_reliable, uint16_t mtu,
-                               tBTA_HL_STATUS status)
-
-{
-  p_evt_data->dch_open_cfm.mdl_handle = mdl_handle;
-  p_evt_data->dch_open_cfm.mcl_handle = mcl_handle;
-  p_evt_data->dch_open_cfm.app_handle = app_handle;
-  p_evt_data->dch_open_cfm.local_mdep_id = local_mdep_id;
-  p_evt_data->dch_open_cfm.mdl_id = mdl_id;
-  p_evt_data->dch_open_cfm.dch_mode = dch_mode;
-  p_evt_data->dch_open_cfm.first_reliable = first_reliable;
-  p_evt_data->dch_open_cfm.mtu = mtu;
-  p_evt_data->dch_open_cfm.status = status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_sdp_query_cfm
- *
- * Description   This function builds the SDP query indication event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_sdp_query_cfm(tBTA_HL* p_evt_data, uint8_t app_id,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                const RawAddress& bd_addr, tBTA_HL_SDP* p_sdp,
-                                tBTA_HL_STATUS status)
-
-{
-  APPL_TRACE_DEBUG("bta_hl_build_sdp_query_cfm: app_id = %d, app_handle=%d",
-                   app_id, app_handle);
-  p_evt_data->sdp_query_cfm.app_id = app_id;
-  p_evt_data->sdp_query_cfm.app_handle = app_handle;
-  p_evt_data->sdp_query_cfm.bd_addr = bd_addr;
-  p_evt_data->sdp_query_cfm.p_sdp = p_sdp;
-  p_evt_data->sdp_query_cfm.status = status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_delete_mdl_cfm
- *
- * Description   This function builds the delete MDL confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_delete_mdl_cfm(tBTA_HL* p_evt_data,
-                                 tBTA_HL_APP_HANDLE app_handle,
-                                 tBTA_HL_MCL_HANDLE mcl_handle,
-                                 tBTA_HL_MDL_ID mdl_id, tBTA_HL_STATUS status)
-
-{
-  p_evt_data->delete_mdl_cfm.mcl_handle = mcl_handle;
-  p_evt_data->delete_mdl_cfm.app_handle = app_handle;
-  p_evt_data->delete_mdl_cfm.mdl_id = mdl_id;
-  p_evt_data->delete_mdl_cfm.status = status;
-}
-
-/*******************************************************************************
- *
- * Function      bta_hl_build_echo_test_cfm
- *
- * Description   This function builds the echo test confirmation event data
- *
- * Returns      None
- *
- ******************************************************************************/
-void bta_hl_build_echo_test_cfm(tBTA_HL* p_evt_data,
-                                tBTA_HL_APP_HANDLE app_handle,
-                                tBTA_HL_MCL_HANDLE mcl_handle,
-                                tBTA_HL_STATUS status) {
-  p_evt_data->echo_test_cfm.mcl_handle = mcl_handle;
-  p_evt_data->echo_test_cfm.app_handle = app_handle;
-  p_evt_data->echo_test_cfm.status = status;
-}
-
-/*****************************************************************************
- *  Debug Functions
- ****************************************************************************/
-#if (BTA_HL_DEBUG == TRUE)
-
-/*******************************************************************************
- *
- * Function         bta_hl_status_code
- *
- * Description      get the status string pointer
- *
- * Returns          char * - status string pointer
- *
- ******************************************************************************/
-const char* bta_hl_status_code(tBTA_HL_STATUS status) {
-  switch (status) {
-    case BTA_HL_STATUS_OK:
-      return "BTA_HL_STATUS_OK";
-    case BTA_HL_STATUS_FAIL:
-      return "BTA_HL_STATUS_FAIL";
-    case BTA_HL_STATUS_ABORTED:
-      return "BTA_HL_STATUS_ABORTED";
-    case BTA_HL_STATUS_NO_RESOURCE:
-      return "BTA_HL_STATUS_NO_RESOURCE";
-    case BTA_HL_STATUS_LAST_ITEM:
-      return "BTA_HL_STATUS_LAST_ITEM";
-    case BTA_HL_STATUS_DUPLICATE_APP_ID:
-      return "BTA_HL_STATUS_DUPLICATE_APP_ID";
-    case BTA_HL_STATUS_INVALID_APP_HANDLE:
-      return "BTA_HL_STATUS_INVALID_APP_HANDLE";
-    case BTA_HL_STATUS_INVALID_MCL_HANDLE:
-      return "BTA_HL_STATUS_INVALID_MCL_HANDLE";
-    case BTA_HL_STATUS_MCAP_REG_FAIL:
-      return "BTA_HL_STATUS_MCAP_REG_FAIL";
-    case BTA_HL_STATUS_MDEP_CO_FAIL:
-      return "BTA_HL_STATUS_MDEP_CO_FAIL";
-    case BTA_HL_STATUS_ECHO_CO_FAIL:
-      return "BTA_HL_STATUS_ECHO_CO_FAIL";
-    case BTA_HL_STATUS_MDL_CFG_CO_FAIL:
-      return "BTA_HL_STATUS_MDL_CFG_CO_FAIL";
-    case BTA_HL_STATUS_SDP_NO_RESOURCE:
-      return "BTA_HL_STATUS_SDP_NO_RESOURCE";
-    case BTA_HL_STATUS_SDP_FAIL:
-      return "BTA_HL_STATUS_SDP_FAIL";
-    case BTA_HL_STATUS_NO_CCH:
-      return "BTA_HL_STATUS_NO_CCH";
-    case BTA_HL_STATUS_NO_MCL:
-      return "BTA_HL_STATUS_NO_MCL";
-
-    case BTA_HL_STATUS_NO_FIRST_RELIABLE:
-      return "BTA_HL_STATUS_NO_FIRST_RELIABLE";
-    case BTA_HL_STATUS_INVALID_DCH_CFG:
-      return "BTA_HL_STATUS_INVALID_DCH_CFG";
-    case BTA_HL_STATUS_INVALID_BD_ADDR:
-      return "BTA_HL_STATUS_INVALID_BD_ADDR";
-    case BTA_HL_STATUS_INVALID_RECONNECT_CFG:
-      return "BTA_HL_STATUS_INVALID_RECONNECT_CFG";
-    case BTA_HL_STATUS_ECHO_TEST_BUSY:
-      return "BTA_HL_STATUS_ECHO_TEST_BUSY";
-    case BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID:
-      return "BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID";
-    case BTA_HL_STATUS_INVALID_MDL_ID:
-      return "BTA_HL_STATUS_INVALID_MDL_ID";
-    case BTA_HL_STATUS_NO_MDL_ID_FOUND:
-      return "BTA_HL_STATUS_NO_MDL_ID_FOUND";
-    case BTA_HL_STATUS_DCH_BUSY:
-      return "BTA_HL_STATUS_DCH_BUSY";
-    default:
-      return "Unknown status code";
-  }
-}
-/*******************************************************************************
- *
- * Function         bta_hl_evt_code
- *
- * Description      Maps HL event code to the corresponding event string
- *
- * Returns          string pointer for the associated event name
- *
- ******************************************************************************/
-const char* bta_hl_evt_code(tBTA_HL_INT_EVT evt_code) {
-  switch (evt_code) {
-    case BTA_HL_CCH_OPEN_EVT:
-      return "BTA_HL_CCH_OPEN_EVT";
-    case BTA_HL_CCH_SDP_OK_EVT:
-      return "BTA_HL_CCH_SDP_OK_EVT";
-    case BTA_HL_CCH_SDP_FAIL_EVT:
-      return "BTA_HL_CCH_SDP_FAIL_EVT";
-    case BTA_HL_MCA_CONNECT_IND_EVT:
-      return "BTA_HL_MCA_CONNECT_IND_EVT";
-    case BTA_HL_MCA_DISCONNECT_IND_EVT:
-      return "BTA_HL_MCA_DISCONNECT_IND_EVT";
-
-    case BTA_HL_CCH_CLOSE_EVT:
-      return "BTA_HL_CCH_CLOSE_EVT";
-    case BTA_HL_CCH_CLOSE_CMPL_EVT:
-      return "BTA_HL_CCH_CLOSE_CMPL_EVT";
-    case BTA_HL_DCH_OPEN_EVT:
-      return "BTA_HL_DCH_OPEN_EVT";
-    case BTA_HL_MCA_CREATE_IND_EVT:
-      return "BTA_HL_MCA_CREATE_IND_EVT";
-    case BTA_HL_MCA_CREATE_CFM_EVT:
-      return "BTA_HL_MCA_CREATE_CFM_EVT";
-    case BTA_HL_MCA_OPEN_IND_EVT:
-      return "BTA_HL_MCA_OPEN_IND_EVT";
-    case BTA_HL_MCA_OPEN_CFM_EVT:
-      return "BTA_HL_MCA_OPEN_CFM_EVT";
-    case BTA_HL_DCH_CLOSE_EVT:
-      return "BTA_HL_DCH_CLOSE_EVT";
-    case BTA_HL_MCA_CLOSE_IND_EVT:
-      return "BTA_HL_MCA_CLOSE_IND_EVT";
-    case BTA_HL_MCA_CLOSE_CFM_EVT:
-      return "BTA_HL_MCA_CLOSE_CFM_EVT";
-    case BTA_HL_API_SEND_DATA_EVT:
-      return "BTA_HL_API_SEND_DATA_EVT";
-    case BTA_HL_MCA_RCV_DATA_EVT:
-      return "BTA_HL_MCA_RCV_DATA_EVT";
-    case BTA_HL_DCH_CLOSE_CMPL_EVT:
-      return "BTA_HL_DCH_CLOSE_CMPL_EVT";
-
-    case BTA_HL_API_ENABLE_EVT:
-      return "BTA_HL_API_ENABLE_EVT";
-    case BTA_HL_API_DISABLE_EVT:
-      return "BTA_HL_API_DISABLE_EVT";
-    case BTA_HL_API_UPDATE_EVT:
-      return "BTA_HL_API_UPDATE_EVT";
-    case BTA_HL_API_REGISTER_EVT:
-      return "BTA_HL_API_REGISTER_EVT";
-    case BTA_HL_API_DEREGISTER_EVT:
-      return "BTA_HL_API_DEREGISTER_EVT";
-
-    case BTA_HL_API_CCH_OPEN_EVT:
-      return "BTA_HL_API_CCH_OPEN_EVT";
-
-    case BTA_HL_API_CCH_CLOSE_EVT:
-      return "BTA_HL_API_CCH_CLOSE_EVT";
-    case BTA_HL_API_DCH_OPEN_EVT:
-      return "BTA_HL_API_DCH_OPEN_EVT";
-
-    case BTA_HL_API_DCH_RECONNECT_EVT:
-      return "BTA_HL_API_DCH_RECONNECT_EVT";
-    case BTA_HL_API_DCH_CLOSE_EVT:
-      return "BTA_HL_API_DCH_CLOSE_EVT";
-    case BTA_HL_API_DELETE_MDL_EVT:
-      return "BTA_HL_API_DELETE_MDL_EVT";
-    case BTA_HL_API_DCH_ABORT_EVT:
-      return "BTA_HL_API_DCH_ABORT_EVT";
-
-    case BTA_HL_DCH_RECONNECT_EVT:
-      return "BTA_HL_DCH_RECONNECT_EVT";
-    case BTA_HL_DCH_SDP_INIT_EVT:
-      return "BTA_HL_DCH_SDP_INIT_EVT";
-    case BTA_HL_DCH_SDP_FAIL_EVT:
-      return "BTA_HL_DCH_SDP_FAIL_EVT";
-    case BTA_HL_API_DCH_ECHO_TEST_EVT:
-      return "BTA_HL_API_DCH_ECHO_TEST_EVT";
-    case BTA_HL_DCH_CLOSE_ECHO_TEST_EVT:
-      return "BTA_HL_DCH_CLOSE_ECHO_TEST_EVT";
-    case BTA_HL_MCA_RECONNECT_IND_EVT:
-      return "BTA_HL_MCA_RECONNECT_IND_EVT";
-    case BTA_HL_MCA_RECONNECT_CFM_EVT:
-      return "BTA_HL_MCA_RECONNECT_CFM_EVT";
-    case BTA_HL_API_DCH_CREATE_RSP_EVT:
-      return "BTA_HL_API_DCH_CREATE_RSP_EVT";
-    case BTA_HL_DCH_ABORT_EVT:
-      return "BTA_HL_DCH_ABORT_EVT";
-    case BTA_HL_MCA_ABORT_IND_EVT:
-      return "BTA_HL_MCA_ABORT_IND_EVT";
-    case BTA_HL_MCA_ABORT_CFM_EVT:
-      return "BTA_HL_MCA_ABORT_CFM_EVT";
-    case BTA_HL_MCA_DELETE_IND_EVT:
-      return "BTA_HL_MCA_DELETE_IND_EVT";
-    case BTA_HL_MCA_DELETE_CFM_EVT:
-      return "BTA_HL_MCA_DELETE_CFM_EVT";
-    case BTA_HL_MCA_CONG_CHG_EVT:
-      return "BTA_HL_MCA_CONG_CHG_EVT";
-    case BTA_HL_CI_GET_TX_DATA_EVT:
-      return "BTA_HL_CI_GET_TX_DATA_EVT";
-    case BTA_HL_CI_PUT_RX_DATA_EVT:
-      return "BTA_HL_CI_PUT_RX_DATA_EVT";
-    case BTA_HL_CI_GET_ECHO_DATA_EVT:
-      return "BTA_HL_CI_GET_ECHO_DATA_EVT";
-    case BTA_HL_DCH_ECHO_TEST_EVT:
-      return "BTA_HL_DCH_ECHO_TEST_EVT";
-    case BTA_HL_CI_PUT_ECHO_DATA_EVT:
-      return "BTA_HL_CI_PUT_ECHO_DATA_EVT";
-    case BTA_HL_API_SDP_QUERY_EVT:
-      return "BTA_HL_API_SDP_QUERY_EVT";
-    case BTA_HL_SDP_QUERY_OK_EVT:
-      return "BTA_HL_SDP_QUERY_OK_EVT";
-    case BTA_HL_SDP_QUERY_FAIL_EVT:
-      return "BTA_HL_SDP_QUERY_FAIL_EVT";
-    case BTA_HL_MCA_RSP_TOUT_IND_EVT:
-      return "BTA_HL_MCA_RSP_TOUT_IND_EVT";
-
-    default:
-      return "Unknown HL event code";
-  }
-}
-
-#endif  /* Debug Functions */
-#endif  // HL_INCLUDED
diff --git a/bta/include/bta_ag_api.h b/bta/include/bta_ag_api.h
index b968ae6..c5d4f36 100644
--- a/bta/include/bta_ag_api.h
+++ b/bta/include/bta_ag_api.h
@@ -264,6 +264,12 @@
 #define BTA_AG_BTRH_READ 3     /* Read the current value */
 #define BTA_AG_BTRH_NO_RESP 4  /* Not in RH States (reply to read) */
 
+/* clip type constants */
+#define BTA_AG_CLIP_TYPE_MIN 128
+#define BTA_AG_CLIP_TYPE_MAX 175
+#define BTA_AG_CLIP_TYPE_DEFAULT 129
+#define BTA_AG_CLIP_TYPE_VOIP 255
+
 /* ASCII character string of arguments to the AT command or result */
 #ifndef BTA_AG_AT_MAX_LEN
 #define BTA_AG_AT_MAX_LEN 256
diff --git a/bta/include/bta_api.h b/bta/include/bta_api.h
index 9d4693e..d58f183 100644
--- a/bta/include/bta_api.h
+++ b/bta/include/bta_api.h
@@ -50,11 +50,9 @@
  * Service ID
  *
  * NOTES: When you add a new Service ID for BTA AND require to change the value
- * of BTA_MAX_SERVICE_ID,
- *        make sure that the correct security ID of the new service from
- * Security service definitions (btm_api.h)
- *        should be added to bta_service_id_to_btm_srv_id_lkup_tbl table in
- * bta_dm_act.c.
+ * of BTA_MAX_SERVICE_ID, make sure that the correct security ID of the new
+ * service from Security service definitions (btm_api.h) should be added to
+ * bta_service_id_to_btm_srv_id_lkup_tbl table in bta_dm_act.cc
  */
 
 #define BTA_RES_SERVICE_ID 0         /* Reserved */
@@ -485,9 +483,9 @@
 typedef uint8_t tBTA_DM_BLE_LOCAL_KEY_MASK;
 
 typedef struct {
-  BT_OCTET16 ir;
-  BT_OCTET16 irk;
-  BT_OCTET16 dhk;
+  Octet16 ir;
+  Octet16 irk;
+  Octet16 dhk;
 } tBTA_BLE_LOCAL_ID_KEYS;
 
 #define BTA_DM_SEC_GRANTED BTA_SUCCESS
@@ -512,7 +510,7 @@
   RawAddress bd_addr;  /* BD address peer device. */
   BD_NAME bd_name;     /* Name of peer device. */
   bool key_present;    /* Valid link key value in key element */
-  LINK_KEY key;        /* Link key associated with peer device. */
+  LinkKey key;         /* Link key associated with peer device. */
   uint8_t key_type;    /* The type of Link Key */
   bool success;        /* true of authentication succeeded, false if failed. */
   uint8_t fail_reason; /* The HCI reason/error code for when success=false */
@@ -689,7 +687,7 @@
   tBTA_DM_BLE_SEC_REQ ble_req;        /* BLE SMP related request */
   tBTA_DM_BLE_KEY ble_key;            /* BLE SMP keys used when pairing */
   tBTA_BLE_LOCAL_ID_KEYS ble_id_keys; /* IR event */
-  BT_OCTET16 ble_er;                  /* ER event data */
+  Octet16 ble_er;                     /* ER event data */
 } tBTA_DM_SEC;
 
 /* Security callback */
@@ -877,7 +875,7 @@
 
 #ifndef BTA_DM_PM_PARK_IDX
 #define BTA_DM_PM_PARK_IDX \
-  5 /* the actual index to bta_dm_pm_md[] for PARK mode */
+  6 /* the actual index to bta_dm_pm_md[] for PARK mode */
 #endif
 
 #ifndef BTA_DM_PM_SNIFF_A2DP_IDX
@@ -968,6 +966,13 @@
 #define BTA_DM_PM_SNIFF5_TIMEOUT 0
 #endif
 
+#ifndef BTA_DM_PM_SNIFF6_MAX
+#define BTA_DM_PM_SNIFF6_MAX 18
+#define BTA_DM_PM_SNIFF6_MIN 14
+#define BTA_DM_PM_SNIFF6_ATTEMPT 1
+#define BTA_DM_PM_SNIFF6_TIMEOUT 0
+#endif
+
 #ifndef BTA_DM_PM_PARK_MAX
 #define BTA_DM_PM_PARK_MAX 800
 #define BTA_DM_PM_PARK_MIN 400
@@ -1282,9 +1287,10 @@
  *
  ******************************************************************************/
 extern void BTA_DmAddDevice(const RawAddress& bd_addr, DEV_CLASS dev_class,
-                            LINK_KEY link_key, tBTA_SERVICE_MASK trusted_mask,
-                            bool is_trusted, uint8_t key_type,
-                            tBTA_IO_CAP io_cap, uint8_t pin_length);
+                            const LinkKey& link_key,
+                            tBTA_SERVICE_MASK trusted_mask, bool is_trusted,
+                            uint8_t key_type, tBTA_IO_CAP io_cap,
+                            uint8_t pin_length);
 
 /*******************************************************************************
  *
@@ -1376,11 +1382,6 @@
 extern void BTA_DmBleSecurityGrant(const RawAddress& bd_addr,
                                    tBTA_DM_BLE_SEC_GRANT res);
 
-/**
- * Set BLE connectable mode to auto connect
- */
-extern void BTA_DmBleStartAutoConn();
-
 /*******************************************************************************
  *
  * Function         BTA_DmBlePasskeyReply
diff --git a/bta/include/bta_av_api.h b/bta/include/bta_av_api.h
index 4c0539e..418f012 100644
--- a/bta/include/bta_av_api.h
+++ b/bta/include/bta_av_api.h
@@ -96,11 +96,6 @@
 #define BTA_AV_NUM_STRS 6
 #endif
 
-#ifndef BTA_AV_MAX_A2DP_MTU
-/*#define BTA_AV_MAX_A2DP_MTU     668 //224 (DM5) * 3 - 4(L2CAP header) */
-#define BTA_AV_MAX_A2DP_MTU 1008
-#endif
-
 /* operation id list for BTA_AvRemoteCmd */
 typedef uint8_t tBTA_AV_RC;
 
diff --git a/bta/include/bta_closure_api.h b/bta/include/bta_closure_api.h
deleted file mode 100644
index c57f07f..0000000
--- a/bta/include/bta_closure_api.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2016 The Android Open Source Project
- *
- *  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.
- *
- ******************************************************************************/
-
-#ifndef BTA_CLOSURE_API_H
-#define BTA_CLOSURE_API_H
-
-#include <base/bind.h>
-#include <base/callback_forward.h>
-#include <base/location.h>
-
-#include <hardware/bluetooth.h>
-
-/*
- * This method post a closure for execution on bta thread. Please see
- * documentation at
- * https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures
- * for how to handle dynamic memory ownership/smart pointers with base::Owned(),
- * base::Passed(), base::ConstRef() and others.
- */
-bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here,
-                             const base::Closure& task);
-bt_status_t do_in_bta_thread_once(const tracked_objects::Location& from_here,
-                                  base::OnceClosure task);
-
-#endif /* BTA_CLOSURE_API_H */
diff --git a/bta/include/bta_dm_ci.h b/bta/include/bta_dm_ci.h
index dbbace6..a89854a 100644
--- a/bta/include/bta_dm_ci.h
+++ b/bta/include/bta_dm_ci.h
@@ -55,7 +55,7 @@
  *
  ******************************************************************************/
 extern void bta_dm_ci_rmt_oob(bool accept, const RawAddress& bd_addr,
-                              BT_OCTET16 c, BT_OCTET16 r);
+                              const Octet16& c, const Octet16& r);
 /*******************************************************************************
  *
  * Function         bta_dm_sco_ci_data_ready
diff --git a/bta/include/bta_dm_co.h b/bta/include/bta_dm_co.h
index ddb9d22..4561cbf 100644
--- a/bta/include/bta_dm_co.h
+++ b/bta/include/bta_dm_co.h
@@ -105,7 +105,7 @@
  * Returns          void.
  *
  ******************************************************************************/
-extern void bta_dm_co_loc_oob(bool valid, BT_OCTET16 c, BT_OCTET16 r);
+extern void bta_dm_co_loc_oob(bool valid, const Octet16& c, const Octet16& r);
 
 /*******************************************************************************
  *
@@ -207,7 +207,7 @@
  *
  ******************************************************************************/
 extern void bta_dm_co_ble_load_local_keys(
-    tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask, BT_OCTET16 er,
+    tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask, Octet16* p_er,
     tBTA_BLE_LOCAL_ID_KEYS* p_id_keys);
 
 #endif /* BTA_DM_CO_H */
diff --git a/bta/include/bta_gatt_api.h b/bta/include/bta_gatt_api.h
index 4dcc76a..41151f8 100644
--- a/bta/include/bta_gatt_api.h
+++ b/bta/include/bta_gatt_api.h
@@ -25,6 +25,7 @@
 #ifndef BTA_GATT_API_H
 #define BTA_GATT_API_H
 
+#include "bta/gatt/database.h"
 #include "bta_api.h"
 #include "gatt_api.h"
 
@@ -53,6 +54,7 @@
 #define BTA_GATTC_CLOSE_EVT 5        /* GATTC  close request status event */
 #define BTA_GATTC_SEARCH_CMPL_EVT 6  /* GATT discovery complete event */
 #define BTA_GATTC_SEARCH_RES_EVT 7   /* GATT discovery result event */
+#define BTA_GATTC_SRVC_DISC_DONE_EVT 8 /* GATT service discovery done event */
 #define BTA_GATTC_NOTIF_EVT 10       /* GATT attribute notification event */
 #define BTA_GATTC_EXEC_EVT 12        /* execute write complete event */
 #define BTA_GATTC_ACL_EVT 13         /* ACL up event */
@@ -97,25 +99,6 @@
   uint16_t handles[BTA_GATTC_MULTI_MAX];
 } tBTA_GATTC_MULTI;
 
-enum {
-  BTA_GATTC_ATTR_TYPE_INCL_SRVC,
-  BTA_GATTC_ATTR_TYPE_CHAR,
-  BTA_GATTC_ATTR_TYPE_CHAR_DESCR,
-  BTA_GATTC_ATTR_TYPE_SRVC
-};
-typedef uint8_t tBTA_GATTC_ATTR_TYPE;
-
-typedef struct {
-  bluetooth::Uuid uuid;
-  uint16_t s_handle;
-  uint16_t e_handle; /* used for service only */
-  uint8_t attr_type;
-  uint8_t id;
-  uint8_t prop;              /* used when attribute type is characteristic */
-  bool is_primary;           /* used when attribute type is service */
-  uint16_t incl_srvc_handle; /* used when attribute type is included service */
-} tBTA_GATTC_NV_ATTR;
-
 /* callback data structure */
 typedef struct {
   tGATT_STATUS status;
@@ -374,41 +357,6 @@
 /* Server callback function */
 typedef void(tBTA_GATTS_CBACK)(tBTA_GATTS_EVT event, tBTA_GATTS* p_data);
 
-struct tBTA_GATTC_CHARACTERISTIC;
-struct tBTA_GATTC_DESCRIPTOR;
-struct tBTA_GATTC_INCLUDED_SVC;
-
-struct tBTA_GATTC_SERVICE {
-  bluetooth::Uuid uuid;
-  bool is_primary;
-  uint16_t handle;
-  uint16_t s_handle;
-  uint16_t e_handle;
-  std::vector<tBTA_GATTC_CHARACTERISTIC> characteristics;
-  std::vector<tBTA_GATTC_INCLUDED_SVC> included_svc;
-};
-
-struct tBTA_GATTC_CHARACTERISTIC {
-  bluetooth::Uuid uuid;
-  // this is used only during discovery, and not persisted in cache
-  uint16_t declaration_handle;
-  uint16_t value_handle;
-  tGATT_CHAR_PROP properties;
-  std::vector<tBTA_GATTC_DESCRIPTOR> descriptors;
-};
-
-struct tBTA_GATTC_DESCRIPTOR {
-  bluetooth::Uuid uuid;
-  uint16_t handle;
-};
-
-struct tBTA_GATTC_INCLUDED_SVC {
-  bluetooth::Uuid uuid;
-  uint16_t handle;
-  tBTA_GATTC_SERVICE* owning_service; /* owning service*/
-  tBTA_GATTC_SERVICE* included_service;
-};
-
 /*****************************************************************************
  *  External Function Declarations
  ****************************************************************************/
@@ -529,7 +477,7 @@
  * PTS tests.
  */
 extern void BTA_GATTC_DiscoverServiceByUuid(uint16_t conn_id,
-                                            const bluetooth::Uuid& p_srvc_uuid);
+                                            const bluetooth::Uuid& srvc_uuid);
 
 /*******************************************************************************
  *
@@ -540,11 +488,10 @@
  *
  * Parameters       conn_id: connection ID which identify the server.
  *
- * Returns          returns list of tBTA_GATTC_SERVICE or NULL.
+ * Returns          returns list of gatt::Service or NULL.
  *
  ******************************************************************************/
-extern const std::vector<tBTA_GATTC_SERVICE>* BTA_GATTC_GetServices(
-    uint16_t conn_id);
+extern const std::list<gatt::Service>* BTA_GATTC_GetServices(uint16_t conn_id);
 
 /*******************************************************************************
  *
@@ -556,11 +503,11 @@
  * Parameters       conn_id: connection ID which identify the server.
  *                  handle: characteristic handle
  *
- * Returns          returns pointer to tBTA_GATTC_CHARACTERISTIC or NULL.
+ * Returns          returns pointer to gatt::Characteristic or NULL.
  *
  ******************************************************************************/
-extern const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetCharacteristic(
-    uint16_t conn_id, uint16_t handle);
+extern const gatt::Characteristic* BTA_GATTC_GetCharacteristic(uint16_t conn_id,
+                                                               uint16_t handle);
 
 /*******************************************************************************
  *
@@ -572,21 +519,21 @@
  * Parameters       conn_id: connection ID which identify the server.
  *                  handle: descriptor handle
  *
- * Returns          returns pointer to tBTA_GATTC_DESCRIPTOR or NULL.
+ * Returns          returns pointer to gatt::Descriptor or NULL.
  *
  ******************************************************************************/
-extern const tBTA_GATTC_DESCRIPTOR* BTA_GATTC_GetDescriptor(uint16_t conn_id,
-                                                            uint16_t handle);
+extern const gatt::Descriptor* BTA_GATTC_GetDescriptor(uint16_t conn_id,
+                                                       uint16_t handle);
 
 /* Return characteristic that owns descriptor with handle equal to |handle|, or
  * NULL */
-extern const tBTA_GATTC_CHARACTERISTIC* BTA_GATTC_GetOwningCharacteristic(
+extern const gatt::Characteristic* BTA_GATTC_GetOwningCharacteristic(
     uint16_t conn_id, uint16_t handle);
 
 /* Return service that owns descriptor or characteristic with handle equal to
  * |handle|, or NULL */
-extern const tBTA_GATTC_SERVICE* BTA_GATTC_GetOwningService(uint16_t conn_id,
-                                                            uint16_t handle);
+extern const gatt::Service* BTA_GATTC_GetOwningService(uint16_t conn_id,
+                                                       uint16_t handle);
 
 /*******************************************************************************
  *
diff --git a/bta/include/bta_hearing_aid_api.h b/bta/include/bta_hearing_aid_api.h
index 6595060..9026262 100644
--- a/bta/include/bta_hearing_aid_api.h
+++ b/bta/include/bta_hearing_aid_api.h
@@ -20,18 +20,177 @@
 
 #include <base/callback_forward.h>
 #include <hardware/bt_hearing_aid.h>
+#include <deque>
 #include <future>
+#include <vector>
+
+constexpr uint16_t HEARINGAID_MAX_NUM_UUIDS = 1;
 
 constexpr uint16_t HA_INTERVAL_10_MS = 10;
 constexpr uint16_t HA_INTERVAL_20_MS = 20;
 
+// Masks for checking capability support
+constexpr uint8_t CAPABILITY_SIDE = 0x01;
+constexpr uint8_t CAPABILITY_BINAURAL = 0x02;
+constexpr uint8_t CAPABILITY_RESERVED = 0xFC;
+
 /** Implementations of HearingAid will also implement this interface */
 class HearingAidAudioReceiver {
  public:
   virtual ~HearingAidAudioReceiver() = default;
   virtual void OnAudioDataReady(const std::vector<uint8_t>& data) = 0;
-  virtual void OnAudioSuspend(std::promise<void> do_suspend_promise);
-  virtual void OnAudioResume(std::promise<void> do_resume_promise);
+  virtual void OnAudioSuspend(std::promise<void> do_suspend_promise) = 0;
+  virtual void OnAudioResume(std::promise<void> do_resume_promise) = 0;
+};
+
+// Number of rssi reads to attempt when requested
+constexpr int READ_RSSI_NUM_TRIES = 10;
+constexpr int PERIOD_TO_READ_RSSI_IN_INTERVALS = 5;
+// Depth of RSSI History in DumpSys
+constexpr int MAX_RSSI_HISTORY = 15;
+
+struct rssi_log {
+  struct timespec timestamp;
+  std::vector<int8_t> rssi;
+};
+
+struct AudioStats {
+  size_t packet_flush_count;
+  size_t packet_send_count;
+  size_t frame_flush_count;
+  size_t frame_send_count;
+  std::deque<rssi_log> rssi_history;
+
+  AudioStats() { Reset(); }
+
+  void Reset() {
+    packet_flush_count = 0;
+    packet_send_count = 0;
+    frame_flush_count = 0;
+    frame_send_count = 0;
+  }
+};
+
+/** Possible states for the Connection Update status */
+typedef enum {
+  NONE,      // Not Connected
+  AWAITING,  // Waiting for start the Connection Update operation
+  STARTED,   // Connection Update has started
+  COMPLETED  // Connection Update is completed successfully
+} connection_update_status_t;
+
+struct HearingDevice {
+  RawAddress address;
+  /* This is true only during first connection to profile, until we store the
+   * device */
+  bool first_connection;
+  bool service_changed_rcvd;
+
+  /* we are making active attempt to connect to this device, 'direct connect'.
+   * This is true only during initial phase of first connection. */
+  bool connecting_actively;
+
+  /* For two hearing aids, you must update their parameters one after another,
+   * not simulteanously, to ensure start of connection events for both devices
+   * are far from each other. This status tracks whether this device is waiting
+   * for update of parameters, that should happen after "LE Connection Update
+   * Complete" event
+   */
+  connection_update_status_t connection_update_status;
+  uint16_t requested_connection_interval;
+
+  /* if true, we are connected, L2CAP socket is open, we can stream audio.
+     However, the actual audio stream also depends on whether the
+     Audio Service has resumed.
+   */
+  bool accepting_audio;
+
+  uint16_t conn_id;
+  uint16_t gap_handle;
+  uint16_t audio_control_point_handle;
+  uint16_t audio_status_handle;
+  uint16_t audio_status_ccc_handle;
+  uint16_t service_changed_ccc_handle;
+  uint16_t volume_handle;
+  uint16_t read_psm_handle;
+
+  uint8_t capabilities;
+  uint64_t hi_sync_id;
+  uint16_t render_delay;
+  uint16_t preparation_delay;
+  uint16_t codecs;
+
+  AudioStats audio_stats;
+  /* Keep tracks of whether the "Start Cmd" has been send to this device. When
+     the "Stop Cmd" is send or when this device disconnects, then this flag is
+     cleared. Please note that the "Start Cmd" is not send during device
+     connection in the case when the audio is suspended. */
+  bool playback_started;
+  /* This tracks whether the last command to Hearing Aids device is
+   * ACKnowledged. */
+  bool command_acked;
+
+  /* When read_rssi_count is > 0, then read the rssi. The interval between rssi
+     reads is tracked by num_intervals_since_last_rssi_read. */
+  int read_rssi_count;
+  int num_intervals_since_last_rssi_read;
+
+  HearingDevice(const RawAddress& address, uint8_t capabilities,
+                uint16_t codecs, uint16_t audio_control_point_handle,
+                uint16_t audio_status_handle, uint16_t audio_status_ccc_handle,
+                uint16_t service_changed_ccc_handle, uint16_t volume_handle,
+                uint16_t read_psm_handle, uint64_t hiSyncId,
+                uint16_t render_delay, uint16_t preparation_delay)
+      : address(address),
+        first_connection(false),
+        service_changed_rcvd(false),
+        connecting_actively(false),
+        connection_update_status(NONE),
+        accepting_audio(false),
+        conn_id(0),
+        gap_handle(0),
+        audio_control_point_handle(audio_control_point_handle),
+        audio_status_handle(audio_status_handle),
+        audio_status_ccc_handle(audio_status_ccc_handle),
+        service_changed_ccc_handle(service_changed_ccc_handle),
+        volume_handle(volume_handle),
+        read_psm_handle(read_psm_handle),
+        capabilities(capabilities),
+        hi_sync_id(hiSyncId),
+        render_delay(render_delay),
+        preparation_delay(preparation_delay),
+        codecs(codecs),
+        playback_started(false),
+        command_acked(false),
+        read_rssi_count(0) {}
+
+  HearingDevice(const RawAddress& address, bool first_connection)
+      : address(address),
+        first_connection(first_connection),
+        service_changed_rcvd(false),
+        connecting_actively(first_connection),
+        connection_update_status(NONE),
+        accepting_audio(false),
+        conn_id(0),
+        gap_handle(0),
+        audio_status_handle(0),
+        audio_status_ccc_handle(0),
+        service_changed_ccc_handle(0),
+        read_psm_handle(0),
+        capabilities(0),
+        hi_sync_id(0),
+        render_delay(0),
+        preparation_delay(0),
+        codecs(0),
+        playback_started(false),
+        command_acked(false),
+        read_rssi_count(0) {}
+
+  HearingDevice() : HearingDevice(RawAddress::kEmpty, false) {}
+
+  /* return true if this device represents left Hearing Aid. Returned value is
+   * valid only after capabilities are discovered */
+  bool isLeft() const { return !(capabilities & CAPABILITY_SIDE); }
 };
 
 class HearingAid {
@@ -41,15 +200,11 @@
   static void Initialize(bluetooth::hearing_aid::HearingAidCallbacks* callbacks,
                          base::Closure initCb);
   static void CleanUp();
-  static bool IsInitialized();
+  static bool IsHearingAidRunning();
   static HearingAid* Get();
   static void DebugDump(int fd);
 
-  static void AddFromStorage(const RawAddress& address, uint16_t psm,
-                             uint8_t capabilities, uint16_t codec,
-                             uint16_t audioControlPointHandle,
-                             uint16_t volumeHandle, uint64_t hiSyncId,
-                             uint16_t render_delay, uint16_t preparation_delay,
+  static void AddFromStorage(const HearingDevice& dev_info,
                              uint16_t is_white_listed);
 
   static int GetDeviceCount();
@@ -57,7 +212,6 @@
   virtual void Connect(const RawAddress& address) = 0;
   virtual void Disconnect(const RawAddress& address) = 0;
   virtual void AddToWhiteList(const RawAddress& address) = 0;
-  virtual void RemoveFromWhiteList(const RawAddress& address) = 0;
   virtual void SetVolume(int8_t volume) = 0;
 };
 
@@ -87,7 +241,8 @@
 class HearingAidAudioSource {
  public:
   static void Start(const CodecConfiguration& codecConfiguration,
-                    HearingAidAudioReceiver* audioReceiver);
+                    HearingAidAudioReceiver* audioReceiver,
+                    uint16_t remote_delay_ms);
   static void Stop();
   static void Initialize();
   static void CleanUp();
diff --git a/bta/include/bta_hh_co.h b/bta/include/bta_hh_co.h
index da884bc..44e5a9f 100644
--- a/bta/include/bta_hh_co.h
+++ b/bta/include/bta_hh_co.h
@@ -77,6 +77,31 @@
  ******************************************************************************/
 extern void bta_hh_co_close(uint8_t dev_handle, uint8_t 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_t dev_handle, uint8_t 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_t dev_handle, uint8_t status,
+                                  uint8_t* p_rpt, uint16_t len);
+
 #if (BTA_HH_LE_INCLUDED == TRUE)
 /*******************************************************************************
  *
diff --git a/bta/include/bta_hl_api.h b/bta/include/bta_hl_api.h
deleted file mode 100644
index 12532d7..0000000
--- a/bta/include/bta_hl_api.h
+++ /dev/null
@@ -1,824 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the public interface file for the HeaLth device profile (HL)
- *  subsystem of BTA, Broadcom's Bluetooth application layer for mobile
- *  phones.
- *
- ******************************************************************************/
-#ifndef BTA_HL_API_H
-#define BTA_HL_API_H
-
-#include "bta_api.h"
-#include "btm_api.h"
-#include "mca_api.h"
-
-/*****************************************************************************
- *  Constants and data types
- ****************************************************************************/
-/* Extra Debug Code */
-#ifndef BTA_HL_DEBUG
-#define BTA_HL_DEBUG TRUE
-#endif
-
-#ifndef BTA_HL_NUM_APPS
-#define BTA_HL_NUM_APPS 12
-#endif
-
-#ifndef BTA_HL_NUM_MDEPS
-#define BTA_HL_NUM_MDEPS 13
-#endif
-
-#ifndef BTA_HL_NUM_MCLS
-#define BTA_HL_NUM_MCLS 7
-#endif
-
-#ifndef BTA_HL_NUM_MDLS_PER_MDEP
-#define BTA_HL_NUM_MDLS_PER_MDEP 4
-#endif
-
-#ifndef BTA_HL_NUM_MDLS_PER_MCL
-#define BTA_HL_NUM_MDLS_PER_MCL 10
-#endif
-
-#ifndef BTA_HL_NUM_DATA_TYPES
-#define BTA_HL_NUM_DATA_TYPES                        \
-  5 /* maximum number of data types can be supported \
-       per MDEP ID */
-#endif
-
-#define BTA_HL_MCAP_RSP_TOUT 2 /* 2 seconds */
-
-#ifndef BTA_HL_CCH_NUM_FILTER_ELEMS
-#define BTA_HL_CCH_NUM_FILTER_ELEMS 3
-#endif
-
-#ifndef BTA_HL_NUM_SDP_CBACKS
-#define BTA_HL_NUM_SDP_CBACKS 7
-#endif
-
-#ifndef BTA_HL_NUM_SDP_RECS
-#define BTA_HL_NUM_SDP_RECS 5
-#endif
-
-#ifndef BTA_HL_NUM_SDP_MDEPS
-#define BTA_HL_NUM_SDP_MDEPS 12
-#endif
-
-#ifndef BTA_HL_NUM_SVC_ELEMS
-#define BTA_HL_NUM_SVC_ELEMS 2
-#endif
-
-#ifndef BTA_HL_NUM_PROTO_ELEMS
-#define BTA_HL_NUM_PROTO_ELEMS 2
-#endif
-
-#define BTA_HL_VERSION 0x0101
-#define BTA_HL_NUM_ADD_PROTO_LISTS 1
-#define BTA_HL_NUM_ADD_PROTO_ELEMS 2
-#define BTA_HL_MDEP_SEQ_SIZE 20
-#define BTA_HL_VAL_ARRY_SIZE 320
-
-#ifndef BTA_HL_NUM_MDL_CFGS
-#define BTA_HL_NUM_MDL_CFGS \
-  16 /* numer of MDL cfg saved in the persistent memory*/
-#endif
-
-#define BTA_HL_NUM_TIMERS 7
-
-#define BTA_HL_CCH_RSP_TOUT 2000
-#define BTA_HL_MAX_TIME 255
-#define BTA_HL_MIN_TIME 1
-#define BTA_HL_INVALID_APP_HANDLE 0xFF
-#define BTA_HL_INVALID_MCL_HANDLE 0xFF
-#define BTA_HL_INVALID_MDL_HANDLE 0xFFFF
-
-#define BTA_HL_STATUS_OK 0
-#define BTA_HL_STATUS_FAIL 1 /* Used to pass all other errors */
-#define BTA_HL_STATUS_ABORTED 2
-#define BTA_HL_STATUS_NO_RESOURCE 3
-#define BTA_HL_STATUS_LAST_ITEM 4
-#define BTA_HL_STATUS_DUPLICATE_APP_ID 5
-#define BTA_HL_STATUS_INVALID_APP_HANDLE 6
-#define BTA_HL_STATUS_INVALID_MCL_HANDLE 7
-#define BTA_HL_STATUS_MCAP_REG_FAIL 8
-#define BTA_HL_STATUS_MDEP_CO_FAIL 9
-#define BTA_HL_STATUS_ECHO_CO_FAIL 10
-#define BTA_HL_STATUS_MDL_CFG_CO_FAIL 11
-#define BTA_HL_STATUS_SDP_NO_RESOURCE 12
-#define BTA_HL_STATUS_SDP_FAIL 13
-#define BTA_HL_STATUS_NO_CCH 14
-#define BTA_HL_STATUS_NO_MCL 15
-
-#define BTA_HL_STATUS_NO_FIRST_RELIABLE 17
-#define BTA_HL_STATUS_INVALID_DCH_CFG 18
-#define BTA_HL_STATUS_INVALID_MDL_HANDLE 19
-#define BTA_HL_STATUS_INVALID_BD_ADDR 20
-#define BTA_HL_STATUS_INVALID_RECONNECT_CFG 21
-#define BTA_HL_STATUS_ECHO_TEST_BUSY 22
-#define BTA_HL_STATUS_INVALID_LOCAL_MDEP_ID 23
-#define BTA_HL_STATUS_INVALID_MDL_ID 24
-#define BTA_HL_STATUS_NO_MDL_ID_FOUND 25
-#define BTA_HL_STATUS_DCH_BUSY 26 /* DCH is congested*/
-#define BTA_HL_STATUS_INVALID_CTRL_PSM 27
-#define BTA_HL_STATUS_DUPLICATE_CCH_OPEN 28
-
-typedef uint8_t tBTA_HL_STATUS;
-typedef tMCA_HANDLE tBTA_HL_APP_HANDLE;
-typedef tMCA_CL tBTA_HL_MCL_HANDLE;
-typedef tMCA_DL tBTA_HL_MDL_HANDLE;
-enum {
-  BTA_HL_DEVICE_TYPE_SINK,
-  BTA_HL_DEVICE_TYPE_SOURCE,
-  BTA_HL_DEVICE_TYPE_DUAL
-};
-
-typedef uint8_t tBTA_HL_DEVICE_TYPE;
-
-#define BTA_HL_SDP_IEEE_11073_20601 0x01
-
-#define BTA_HL_MCAP_SUP_RECONNECT_MASK_INIT 2   /* 0x02 */
-#define BTA_HL_MCAP_SUP_RECONNECT_MASK_ACCEPT 4 /* 0x04 */
-#define BTA_HL_MCAP_SUP_CSP_MASK_SYNC_SLAVE 0   /* 0x08 */
-#define BTA_HL_MCAP_SUP_CSP_MASK_SYNC_MASTER 0  /* 0x10 */
-
-#define BTA_HL_MCAP_SUP_PROC_MASK          \
-  (BTA_HL_MCAP_SUP_RECONNECT_MASK_INIT |   \
-   BTA_HL_MCAP_SUP_RECONNECT_MASK_ACCEPT | \
-   BTA_HL_MCAP_SUP_CSP_MASK_SYNC_SLAVE | BTA_HL_MCAP_SUP_CSP_MASK_SYNC_MASTER)
-#define BTA_HL_MDEP_ROLE_SOURCE 0x00
-#define BTA_HL_MDEP_ROLE_SINK 0x01
-
-typedef uint8_t tBTA_HL_MDEP_ROLE;
-
-#define BTA_HL_MDEP_ROLE_MASK_SOURCE 0x01 /* bit mask */
-#define BTA_HL_MDEP_ROLE_MASK_SINK 0x02
-typedef uint8_t tBTA_HL_MDEP_ROLE_MASK;
-
-#define BTA_HL_ECHO_TEST_MDEP_ID 0
-#define BTA_HL_ECHO_TEST_MDEP_CFG_IDX 0
-
-#define BTA_HL_INVALID_MDEP_ID 0xFF
-typedef tMCA_DEP tBTA_HL_MDEP_ID; /* 0 is for echo test,
-                                   0x01-0x7F availave for use,
-                                   0x80-0xFF reserved*/
-
-#define BTA_HL_DELETE_ALL_MDL_IDS 0xFFFF
-#define BTA_HL_MAX_MDL_VAL 0xFEFF
-typedef uint16_t tBTA_HL_MDL_ID; /* 0x0000 reserved,
-                                  0x0001-0xFEFF dynamic range,
-                                  0xFF00-0xFFFE reserved,
-                                  0xFFFF indicates all MDLs*/
-
-#define BTA_HL_MDEP_DESP_LEN 35
-
-#define BTA_HL_DCH_MODE_RELIABLE 0
-#define BTA_HL_DCH_MODE_STREAMING 1
-
-typedef uint8_t tBTA_HL_DCH_MODE;
-
-#define BTA_HL_DCH_CFG_NO_PREF 0
-#define BTA_HL_DCH_CFG_RELIABLE 1
-#define BTA_HL_DCH_CFG_STREAMING 2
-#define BTA_HL_DCH_CFG_UNKNOWN 0xFF
-
-typedef uint8_t tBTA_HL_DCH_CFG;
-
-/* The Default DCH CFG for the echo test when the device is a Source */
-#define BTA_HL_DEFAULT_ECHO_TEST_SRC_DCH_CFG BTA_HL_DCH_CFG_RELIABLE
-
-#define BTA_HL_DCH_CREATE_RSP_SUCCESS 0
-#define BTA_HL_DCH_CREATE_RSP_CFG_REJ 1
-
-typedef uint8_t tBTA_HL_DCH_CREATE_RSP;
-
-#define BTA_HL_MCAP_SUP_PROC_RECONNECT_INIT 0x02
-#define BTA_HL_MCAP_SUP_PROC_RECONNECT_APT 0x04
-#define BTA_HL_MCAP_SUP_PROC_CSP_SLAVE 0x08
-#define BTA_HL_MCAP_SUP_PROC_CSP_MASTER 0x10
-
-typedef uint8_t tBTA_HL_SUP_PROC_MASK;
-
-typedef struct {
-  uint16_t max_rx_apdu_size; /* local rcv MTU */
-  uint16_t max_tx_apdu_size; /* maximum TX APDU size*/
-} tBTA_HL_ECHO_CFG;
-
-typedef struct {
-  uint16_t data_type;
-  uint16_t max_rx_apdu_size; /* local rcv MTU */
-  uint16_t max_tx_apdu_size; /* maximum TX APDU size*/
-  char desp[BTA_HL_MDEP_DESP_LEN + 1];
-} tBTA_HL_MDEP_DATA_TYPE_CFG;
-
-typedef struct {
-  tBTA_HL_MDEP_ROLE mdep_role;
-  uint8_t num_of_mdep_data_types;
-  tBTA_HL_MDEP_DATA_TYPE_CFG data_cfg[BTA_HL_NUM_DATA_TYPES];
-} tBTA_HL_MDEP_CFG;
-
-typedef struct {
-  tBTA_HL_MDEP_ID mdep_id; /* MDEP ID 0x01-0x7F */
-  tBTA_HL_MDEP_CFG mdep_cfg;
-  uint8_t ori_app_id;
-} tBTA_HL_MDEP;
-
-typedef struct {
-  tBTA_HL_MDEP mdep[BTA_HL_NUM_MDEPS];
-  tBTA_HL_ECHO_CFG echo_cfg;
-  tBTA_HL_MDEP_ROLE_MASK app_role_mask;
-  bool advertize_source_sdp;
-  uint8_t num_of_mdeps;
-} tBTA_HL_SUP_FEATURE;
-
-typedef struct {
-  bool delete_req_pending;
-  tBTA_HL_MDL_ID mdl_id;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-} tBTA_HL_DELETE_MDL;
-
-typedef struct {
-  uint8_t time;
-  uint16_t mtu;
-  tBTA_HL_MDL_ID mdl_id;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  tBTA_HL_MDEP_ROLE local_mdep_role;
-  bool active; /* true if this item is in use */
-  tBTA_HL_DCH_MODE dch_mode;
-  uint8_t fcs;
-  RawAddress peer_bd_addr;
-} tBTA_HL_MDL_CFG;
-
-/* Maximum number of supported feature list items (list_elem in
- * tSDP_SUP_FEATURE_ELEM) */
-#define BTA_HL_NUM_SUP_FEATURE_ELEMS 13
-#define BTA_HL_SUP_FEATURE_SDP_BUF_SIZE 512
-/* This structure is used to add supported feature lists and find supported
- * feature elements */
-typedef struct {
-  uint8_t mdep_id;
-  uint16_t data_type;
-  tBTA_HL_MDEP_ROLE mdep_role;
-  char* p_mdep_desp;
-} tBTA_HL_SUP_FEATURE_ELEM;
-
-typedef struct {
-  uint16_t num_elems;
-  tBTA_HL_SUP_FEATURE_ELEM list_elem[BTA_HL_NUM_SUP_FEATURE_ELEMS];
-} tBTA_HL_SUP_FEATURE_LIST_ELEM;
-
-typedef struct {
-  tBTA_HL_DEVICE_TYPE dev_type; /* sink, source or dual roles */
-  tBTA_SEC sec_mask;            /* security mask for accepting conenction*/
-  const char*
-      p_srv_name; /* service name to be used in the SDP; null terminated*/
-  const char* p_srv_desp; /* service description to be used in the SDP; null
-                             terminated */
-  const char*
-      p_provider_name; /* provide name to be used in the SDP; null terminated */
-} tBTA_HL_REG_PARAM;
-
-typedef struct {
-  uint16_t ctrl_psm;
-  RawAddress bd_addr; /* Address of peer device */
-  tBTA_SEC sec_mask; /* security mask for initiating connection*/
-} tBTA_HL_CCH_OPEN_PARAM;
-
-typedef struct {
-  uint16_t ctrl_psm;
-  tBTA_HL_MDEP_ID local_mdep_id; /* local MDEP ID */
-  tBTA_HL_MDEP_ID peer_mdep_id;  /* peer mdep id */
-  tBTA_HL_DCH_CFG local_cfg;
-  tBTA_SEC sec_mask; /* security mask for initiating connection*/
-} tBTA_HL_DCH_OPEN_PARAM;
-
-typedef struct {
-  uint16_t ctrl_psm;
-  tBTA_HL_MDL_ID mdl_id;
-} tBTA_HL_DCH_RECONNECT_PARAM;
-
-typedef struct {
-  uint16_t ctrl_psm;
-  uint16_t pkt_size;
-  tBTA_HL_DCH_CFG local_cfg;
-} tBTA_HL_DCH_ECHO_TEST_PARAM;
-
-typedef struct {
-  uint16_t buf_size;
-  uint8_t p_buf; /* buffer pointer */
-} tBTA_HL_DCH_BUF_INFO;
-
-typedef struct {
-  tBTA_HL_MDEP_ID local_mdep_id; /* local MDEP ID */
-  tBTA_HL_MDL_ID mdl_id;
-  tBTA_HL_DCH_CREATE_RSP rsp_code;
-  tBTA_HL_DCH_CFG cfg_rsp;
-} tBTA_HL_DCH_CREATE_RSP_PARAM;
-
-typedef struct {
-  uint16_t data_type;
-  uint8_t mdep_id;
-  tBTA_HL_MDEP_ROLE mdep_role;
-  char mdep_desp[BTA_HL_MDEP_DESP_LEN + 1];
-} tBTA_HL_SDP_MDEP_CFG;
-
-typedef struct {
-  uint16_t ctrl_psm;
-  uint16_t data_psm;
-  uint8_t mcap_sup_proc;
-  uint8_t num_mdeps; /* number of mdep elements from SDP*/
-  char srv_name[BTA_SERVICE_NAME_LEN + 1];
-  char srv_desp[BTA_SERVICE_DESP_LEN + 1];
-  char provider_name[BTA_PROVIDER_NAME_LEN + 1];
-  tBTA_HL_SDP_MDEP_CFG mdep_cfg[BTA_HL_NUM_SDP_MDEPS];
-} tBTA_HL_SDP_REC;
-
-typedef struct {
-  uint8_t num_recs;
-  tBTA_HL_SDP_REC sdp_rec[BTA_HL_NUM_SDP_RECS];
-} tBTA_HL_SDP;
-
-/* HL control callback function events */
-enum { BTA_HL_CTRL_ENABLE_CFM_EVT = 0, BTA_HL_CTRL_DISABLE_CFM_EVT };
-typedef uint8_t tBTA_HL_CTRL_EVT;
-/* Structure associated with BTA_HL_ENABLE_EVT
-   BTA_HL_DISABLE_EVT */
-
-typedef struct { tBTA_HL_STATUS status; } tBTA_HL_CTRL_ENABLE_DISABLE;
-
-typedef union {
-  tBTA_HL_CTRL_ENABLE_DISABLE enable_cfm;
-  tBTA_HL_CTRL_ENABLE_DISABLE disable_cfm;
-} tBTA_HL_CTRL;
-
-/* HL instance callback function events */
-enum {
-  BTA_HL_REGISTER_CFM_EVT = 0,
-  BTA_HL_DEREGISTER_CFM_EVT,
-  BTA_HL_CCH_OPEN_IND_EVT,
-  BTA_HL_CCH_OPEN_CFM_EVT,
-  BTA_HL_CCH_CLOSE_IND_EVT,
-  BTA_HL_CCH_CLOSE_CFM_EVT,
-  BTA_HL_DCH_CREATE_IND_EVT,
-  BTA_HL_DCH_OPEN_IND_EVT,
-  BTA_HL_DCH_OPEN_CFM_EVT,
-  BTA_HL_DCH_CLOSE_IND_EVT,
-  BTA_HL_DCH_CLOSE_CFM_EVT,
-  BTA_HL_DCH_RECONNECT_IND_EVT,
-  BTA_HL_DCH_RECONNECT_CFM_EVT,
-
-  BTA_HL_DCH_ABORT_IND_EVT,
-  BTA_HL_DCH_ABORT_CFM_EVT,
-  BTA_HL_DELETE_MDL_IND_EVT,
-  BTA_HL_DELETE_MDL_CFM_EVT,
-  BTA_HL_DCH_SEND_DATA_CFM_EVT,
-  BTA_HL_DCH_RCV_DATA_IND_EVT,
-  BTA_HL_CONG_CHG_IND_EVT,
-  BTA_HL_DCH_ECHO_TEST_CFM_EVT,
-  BTA_HL_SDP_QUERY_CFM_EVT,
-  BTA_HL_SDP_INFO_IND_EVT
-};
-typedef uint8_t tBTA_HL_EVT;
-
-typedef struct {
-  tBTA_HL_STATUS status; /* start status */
-  uint8_t app_id;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_REGISTER_CFM;
-
-typedef struct {
-  tBTA_HL_STATUS status; /* start status */
-  uint8_t app_id;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_DEREGISTER_CFM;
-
-typedef struct {
-  bool intentional;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_CCH_CLOSE_IND;
-
-typedef struct {
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_MCL_IND;
-
-typedef struct {
-  tBTA_HL_STATUS status; /* connection status */
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_MCL_CFM;
-
-typedef struct {
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  RawAddress bd_addr; /* address of peer device */
-} tBTA_HL_CCH_OPEN_IND;
-
-typedef struct {
-  tBTA_HL_STATUS status; /* connection status */
-  uint8_t app_id;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  RawAddress bd_addr; /* address of peer device */
-} tBTA_HL_CCH_OPEN_CFM;
-
-typedef struct {
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  tBTA_HL_MDL_ID mdl_id; /* MCAP data link ID for this
-                            data channel conenction    */
-  tBTA_HL_DCH_CFG cfg;   /* dch cfg requested by the peer device */
-  RawAddress bd_addr;    /* address of peer device */
-
-} tBTA_HL_DCH_CREATE_IND;
-
-typedef struct {
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  tBTA_HL_MDL_ID mdl_id;     /* MCAP data link ID for this
-                                data channel conenction    */
-  tBTA_HL_DCH_MODE dch_mode; /* data channel mode - reliable or streaming*/
-
-  bool first_reliable; /* whether this is the first reliable data channel */
-  uint16_t mtu;
-} tBTA_HL_DCH_OPEN_IND;
-
-typedef struct {
-  tBTA_HL_STATUS status; /* connection status */
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  tBTA_HL_MDL_ID mdl_id;     /* MCAP data link ID for this
-                                data channel conenction    */
-  tBTA_HL_DCH_MODE dch_mode; /* data channel mode - reliable or streaming*/
-  bool first_reliable; /* whether this is the first reliable data channel */
-  uint16_t mtu;
-} tBTA_HL_DCH_OPEN_CFM;
-
-typedef struct {
-  bool intentional;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_DCH_CLOSE_IND;
-
-typedef struct {
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_MDL_IND;
-
-typedef struct {
-  tBTA_HL_STATUS status;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-} tBTA_HL_MDL_CFM;
-
-typedef struct {
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  tBTA_HL_MDL_ID mdl_id;
-} tBTA_HL_DELETE_MDL_IND;
-
-typedef struct {
-  tBTA_HL_STATUS status;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  tBTA_HL_MDL_ID mdl_id;
-} tBTA_HL_DELETE_MDL_CFM;
-
-typedef struct {
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  tBTA_HL_APP_HANDLE app_handle;
-  bool cong;
-} tBTA_HL_DCH_CONG_IND;
-
-typedef struct {
-  tBTA_HL_APP_HANDLE app_handle;
-  uint16_t ctrl_psm;
-  uint16_t data_psm;
-  uint8_t data_x_spec;
-  uint8_t mcap_sup_procs;
-} tBTA_HL_SDP_INFO_IND;
-
-typedef struct {
-  tBTA_HL_STATUS status;
-  uint8_t app_id;
-  tBTA_HL_APP_HANDLE app_handle;
-  RawAddress bd_addr;
-  tBTA_HL_SDP* p_sdp;
-} tBTA_HL_SDP_QUERY_CFM;
-
-typedef union {
-  tBTA_HL_REGISTER_CFM reg_cfm;
-  tBTA_HL_DEREGISTER_CFM dereg_cfm;
-  tBTA_HL_CCH_OPEN_IND cch_open_ind;
-  tBTA_HL_CCH_OPEN_CFM cch_open_cfm;
-  tBTA_HL_CCH_CLOSE_IND cch_close_ind;
-  tBTA_HL_MCL_CFM cch_close_cfm;
-  tBTA_HL_DCH_CREATE_IND dch_create_ind;
-  tBTA_HL_DCH_OPEN_IND dch_open_ind;
-  tBTA_HL_DCH_OPEN_CFM dch_open_cfm;
-  tBTA_HL_DCH_CLOSE_IND dch_close_ind;
-  tBTA_HL_MDL_CFM dch_close_cfm;
-  tBTA_HL_DCH_OPEN_IND dch_reconnect_ind;
-  tBTA_HL_DCH_OPEN_CFM dch_reconnect_cfm;
-  tBTA_HL_MCL_IND dch_abort_ind;
-  tBTA_HL_MCL_CFM dch_abort_cfm;
-  tBTA_HL_DELETE_MDL_IND delete_mdl_ind;
-  tBTA_HL_DELETE_MDL_CFM delete_mdl_cfm;
-  tBTA_HL_MDL_CFM dch_send_data_cfm;
-  tBTA_HL_MDL_IND dch_rcv_data_ind;
-  tBTA_HL_DCH_CONG_IND dch_cong_ind;
-  tBTA_HL_MCL_CFM echo_test_cfm;
-  tBTA_HL_SDP_QUERY_CFM sdp_query_cfm;
-  tBTA_HL_SDP_INFO_IND sdp_info_ind;
-
-} tBTA_HL;
-
-/* HL callback functions */
-typedef void tBTA_HL_CTRL_CBACK(tBTA_HL_CTRL_EVT event, tBTA_HL_CTRL* p_data);
-typedef void tBTA_HL_CBACK(tBTA_HL_EVT event, tBTA_HL* p_data);
-
-/*****************************************************************************
- *  External Function Declarations
- ****************************************************************************/
-
-/**************************
- *  API Functions
- **************************/
-
-/*******************************************************************************
- *
- * Function         BTA_HlEnable
- *
- * Description      Enable the HL subsystems.  This function must be
- *                  called before any other functions in the HL API are called.
- *                  When the enable operation is completed the callback function
- *                  will be called with an BTA_HL_CTRL_ENABLE_CFM_EVT event.
- *
- * Parameters       p_cback - HL event call back function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlEnable(tBTA_HL_CTRL_CBACK* p_ctrl_cback);
-/*******************************************************************************
- *
- * Function         BTA_HlDisable
- *
- * Description     Disable the HL subsystem.
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDisable(void);
-
-/*******************************************************************************
- *
- * Function         BTA_HlUpdate
- *
- * Description      Register an HDP application
- *
- * Parameters       app_id        - Application ID
- *                  p_reg_param   - non-platform related parameters for the
- *                                  HDP application
- *                  p_cback       - HL event callback fucntion
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlUpdate(uint8_t app_id, tBTA_HL_REG_PARAM* p_reg_param,
-                         bool is_register, tBTA_HL_CBACK* p_cback);
-
-/*******************************************************************************
- *
- * Function         BTA_HlRegister
- *
- * Description      Register a HDP application
- *
- *
- * Parameters       app_id        - hdp application ID
- *                  p_reg_param   - non-platform related parameters for the
- *                                  HDP application
- *                  p_cback       - HL event callback fucntion
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlRegister(uint8_t app_id, tBTA_HL_REG_PARAM* p_reg_param,
-                           tBTA_HL_CBACK* p_cback);
-
-/*******************************************************************************
- *
- * Function         BTA_HlDeregister
- *
- * Description      Deregister an HDP application
- *
- * Parameters       app_handle - Application handle
- *
- * Returns         void
- *
- ******************************************************************************/
-extern void BTA_HlDeregister(uint8_t app_id, tBTA_HL_APP_HANDLE app_handle);
-
-/*******************************************************************************
- *
- * Function         BTA_HlCchOpen
- *
- * Description      Open a Control channel connection with the specified BD
- *                  address and the control PSM value is used to select which
- *                  HDP insatnce should be used in case the peer device support
- *                  multiple HDP instances.
- *
- *
- * Parameters       app_handle - Application Handle
- *                  p_open_param - parameters for opening a control channel
- *
- * Returns          void
- *
- *                  Note: If the control PSM value is zero then the first HDP
- *                        instance is used for the control channel setup
- ******************************************************************************/
-extern void BTA_HlCchOpen(uint8_t app_id, tBTA_HL_APP_HANDLE app_handle,
-                          tBTA_HL_CCH_OPEN_PARAM* p_open_param);
-
-/*******************************************************************************
- *
- * Function         BTA_HlCchClose
- *
- * Description      Close a Control channel connection with the specified MCL
- *                  handle
- *
- * Parameters       mcl_handle - MCL handle
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlCchClose(tBTA_HL_MCL_HANDLE mcl_handle);
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchOpen
- *
- * Description      Open a data channel connection with the specified DCH
- *                  parameters
- *
- * Parameters       mcl_handle - MCL handle
- *                  p_open_param - parameters for opening a data channel
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDchOpen(tBTA_HL_MCL_HANDLE mcl_handle,
-                          tBTA_HL_DCH_OPEN_PARAM* p_open_param);
-/*******************************************************************************
- *
- * Function         BTA_HlDchReconnect
- *
- * Description      Reconnect a data channel with the specified MDL_ID
- *
- * Parameters       mcl_handle      - MCL handle
-*8                  p_recon_param   - parameters for reconnecting a data channel
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDchReconnect(tBTA_HL_MCL_HANDLE mcl_handle,
-                               tBTA_HL_DCH_RECONNECT_PARAM* p_recon_param);
-/*******************************************************************************
- *
- * Function         BTA_HlDchClose
- *
- * Description      Close a data channel with the specified MDL handle
- *
- * Parameters       mdl_handle  - MDL handle
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDchClose(tBTA_HL_MDL_HANDLE mdl_handle);
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchAbort
- *
- * Description      Abort the current data channel setup with the specified MCL
- *                  handle
- *
- * Parameters       mcl_handle  - MCL handle
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDchAbort(tBTA_HL_MCL_HANDLE mcl_handle);
-
-/*******************************************************************************
- *
- * Function         BTA_HlSendData
- *
- * Description      Send an APDU to the peer device
- *
- * Parameters       mdl_handle  - MDL handle
- *                  pkt_size    - size of the data packet to be sent
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlSendData(tBTA_HL_MDL_HANDLE mdl_handle, uint16_t pkt_size);
-
-/*******************************************************************************
- *
- * Function         BTA_HlDeleteMdl
- *
- * Description      Delete the specified MDL_ID within the specified MCL handle
- *
- * Parameters       mcl_handle  - MCL handle
- *                  mdl_id      - MDL ID
- *
- * Returns          void
- *
- *                  note: If mdl_id = 0xFFFF then this means to delete all MDLs
- *                        and this value can only be used with DeleteMdl request
- *                        only not other requests
- *
- ******************************************************************************/
-extern void BTA_HlDeleteMdl(tBTA_HL_MCL_HANDLE mcl_handle,
-                            tBTA_HL_MDL_ID mdl_id);
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchEchoTest
- *
- * Description      Initiate an echo test with the specified MCL handle
- *
- * Parameters       mcl_handle           - MCL handle
-*8                  p_echo_test_param   -  parameters for echo testing
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDchEchoTest(tBTA_HL_MCL_HANDLE mcl_handle,
-                              tBTA_HL_DCH_ECHO_TEST_PARAM* p_echo_test_param);
-
-/*******************************************************************************
- *
- * Function         BTA_HlSdpQuery
- *
- * Description      SDP query request for the specified BD address
- *
- * Parameters       app_id
-                        app_handle      - application handle
- *                  bd_addr         - BD address
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlSdpQuery(uint8_t app_id, tBTA_HL_APP_HANDLE app_handle,
-                           const RawAddress& bd_addr);
-
-/*******************************************************************************
- *
- * Function         BTA_HlDchCreateMdlRsp
- *
- * Description      Set the Response and configuration values for the Create MDL
- *                  request
- *
- * Parameters       mcl_handle  - MCL handle
- *                  p_rsp_param - parameters specified whether the request
- *                                should be accepted or not and if it should be
- *                                accepted then it also specified the
- *                                configuration response value
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTA_HlDchCreateRsp(tBTA_HL_MCL_HANDLE mcl_handle,
-                               tBTA_HL_DCH_CREATE_RSP_PARAM* p_rsp_param);
-
-#endif /* BTA_HL_API_H */
diff --git a/bta/include/bta_hl_ci.h b/bta/include/bta_hl_ci.h
deleted file mode 100644
index 73a7cd4..0000000
--- a/bta/include/bta_hl_ci.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the interface file for the HL (HeaLth device profile) subsystem
- *  call-in functions.
- *
- ******************************************************************************/
-#ifndef BTA_HL_CI_H
-#define BTA_HL_CI_H
-
-#include "bta_api.h"
-#include "bta_hl_api.h"
-
-/*****************************************************************************
- *  Constants and Data Types
- ****************************************************************************/
-/**************************
- *  Common Definitions
- **************************/
-/* Read Ready Event */
-/*****************************************************************************
- *  Function Declarations
- ****************************************************************************/
-/**************************
- *  Common Functions
- **************************/
-/*******************************************************************************
- *
- * Function         bta_hl_ci_get_tx_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_get_tx_data call-out function.
- *
- * Parameters       mdl_handle -MDL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_get_tx_data(tBTA_HL_MDL_HANDLE mdl_handle,
-                                  tBTA_HL_STATUS status, uint16_t evt);
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_put_rx_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_put_rx_data call-out function.
- *
- * Parameters       mdl_handle -MDL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_put_rx_data(tBTA_HL_MDL_HANDLE mdl_handle,
-                                  tBTA_HL_STATUS status, uint16_t evt);
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_get_echo_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_get_echo_data call-out function.
- *
- * Parameters       mcl_handle -MCL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_get_echo_data(tBTA_HL_MCL_HANDLE mcl_handle,
-                                    tBTA_HL_STATUS status, uint16_t evt);
-
-/*******************************************************************************
- *
- * Function         bta_hl_ci_put_echo_data
- *
- * Description      This function is called in response to the
- *                  bta_hl_co_put_echo_data call-out function.
- *
- * Parameters       mcl_handle -MCL handle
- *                  status - BTA_MA_STATUS_OK if operation is successful
- *                           BTA_MA_STATUS_FAIL if any errors have occurred.
- *                  evt    - evt from the call-out function
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_ci_put_echo_data(tBTA_HL_MCL_HANDLE mcl_handle,
-                                    tBTA_HL_STATUS status, uint16_t evt);
-
-#endif /* BTA_HL_CI_H */
diff --git a/bta/include/bta_hl_co.h b/bta/include/bta_hl_co.h
deleted file mode 100644
index 9a36911..0000000
--- a/bta/include/bta_hl_co.h
+++ /dev/null
@@ -1,240 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the interface file for the HL (HeaLth device profile) subsystem
- *  call-out functions.
- *
- ******************************************************************************/
-#ifndef BTA_HL_CO_H
-#define BTA_HL_CO_H
-
-#include "bta_api.h"
-#include "bta_hl_api.h"
-
-/*****************************************************************************
- *  Constants and Data Types
- ****************************************************************************/
-/**************************
- *  Common Definitions
- **************************/
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_get_num_of_mdep
- *
- * Description     This function is called to get the number of MDEPs for this
- *                 application ID
- *
- * Parameters      app_id - application ID
- *                 p_num_of_mdep (output) - number of MDEP configurations
- *                                          supported
- *                                          by the application
- *
- * Returns         Bloolean - true success
- *
- ******************************************************************************/
-extern bool bta_hl_co_get_num_of_mdep(uint8_t app_id, uint8_t* p_num_of_mdep);
-/*******************************************************************************
- *
- * Function        bta_hl_co_advrtise_source_sdp
- *
- * Description     This function is called to find out whether the SOURCE MDEP
- *                 configuration information should be advertize in the SDP or
- *                 not
- *
- * Parameters      app_id - application ID
- *
- * Returns         Bloolean - true advertise the SOURCE MDEP configuration
- *                            information
- *
- ******************************************************************************/
-extern bool bta_hl_co_advrtise_source_sdp(uint8_t app_id);
-/*******************************************************************************
- *
- * Function        bta_hl_co_get_mdep_config
- *
- * Description     This function is called to get the supported feature
- *                 configuration for the specified mdep index and it also
- *                 assigns
- *                 the MDEP ID for the specified mdep index
- *
- * Parameters      app_id - HDP application ID
- *                 mdep_idx - the mdep index
- *                  mdep_counter - mdep_counter
- *                 mdep_id  - the assigned MDEP ID for the specified medp_idx
- *                 p_mdl_cfg (output) - pointer to the MDEP configuration
- *
- *
- * Returns         Bloolean - true success
- ******************************************************************************/
-extern bool bta_hl_co_get_mdep_config(uint8_t app_id, uint8_t mdep_idx,
-                                      uint8_t mdep_counter,
-                                      tBTA_HL_MDEP_ID mdep_id,
-                                      tBTA_HL_MDEP_CFG* p_mdep_cfg);
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_get_echo_config
- *
- * Description     This function is called to get the echo test
- *                 maximum APDU size configuration
- *
- * Parameters      app_id - HDP application ID
- *                 p_echo_cfg (output) - pointer to the Echo test maximum APDU
- *                                       size configuration
- *
- * Returns         Bloolean - true success
- ******************************************************************************/
-extern bool bta_hl_co_get_echo_config(uint8_t app_id,
-                                      tBTA_HL_ECHO_CFG* p_echo_cfg);
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_save_mdl
- *
- * Description     This function is called to save a MDL configuration item in
- *                 persistent storage
- *
- * Parameters      app_id - HDP application ID
- *                 item_idx - the MDL configuration storage index
- *                 p_mdl_cfg - pointer to the MDL configuration data
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_co_save_mdl(uint8_t app_id, uint8_t item_idx,
-                               tBTA_HL_MDL_CFG* p_mdl_cfg);
-/*******************************************************************************
- *
- * Function        bta_hl_co_delete_mdl
- *
- * Description     This function is called to delete a MDL configuration item in
- *                 persistent storage
- *
- * Parameters      app_id - HDP application ID
- *                 item_idx - the MDL configuration storage index
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void bta_hl_co_delete_mdl(uint8_t app_id, uint8_t item_idx);
-/*******************************************************************************
- *
- * Function         bta_hl_co_get_mdl_config
- *
- * Description     This function is called to get the MDL configuration
- *                 from teh persistent memory. This function shall only be
-*called
-*8                 once after the device is powered up
- *
- * Parameters      app_id - HDP application ID
- *                 buffer_size - the unit of the buffer size is
-*sizeof(tBTA_HL_MDL_CFG)
- *                 p_mdl_buf - Point to the starting location of the buffer
- *
- * Returns         bool
- *
- *
- ******************************************************************************/
-extern bool bta_hl_co_load_mdl_config(uint8_t app_id, uint8_t buffer_size,
-                                      tBTA_HL_MDL_CFG* p_mdl_buf);
-
-/*******************************************************************************
- *
- * Function         bta_hl_co_get_tx_data
- *
- * Description     Get the data to be sent
- *
- * Parameters      app_id - HDP application ID
- *                 mdl_handle - MDL handle
- *                 buf_size - the size of the buffer
- *                 p_buf - the buffer pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_get_tx_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-extern void bta_hl_co_get_tx_data(uint8_t app_id, tBTA_HL_MDL_HANDLE mdl_handle,
-                                  uint16_t buf_size, uint8_t* p_buf,
-                                  uint16_t evt);
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_put_rx_data
- *
- * Description     Put the received data
- *
- * Parameters      app_id - HDP application ID
- *                 mdl_handle - MDL handle
- *                 data_size - the size of the data
- *                 p_data - the data pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_put_rx_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-extern void bta_hl_co_put_rx_data(uint8_t app_id, tBTA_HL_MDL_HANDLE mdl_handle,
-                                  uint16_t data_size, uint8_t* p_data,
-                                  uint16_t evt);
-/*******************************************************************************
- *
- * Function         bta_hl_co_get_tx_data
- *
- * Description     Get the Echo data to be sent
- *
- * Parameters      app_id - HDP application ID
- *                 mcl_handle - MCL handle
- *                 buf_size - the size of the buffer
- *                 p_buf - the buffer pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_get_tx_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-extern void bta_hl_co_get_echo_data(uint8_t app_id,
-                                    tBTA_HL_MCL_HANDLE mcl_handle,
-                                    uint16_t buf_size, uint8_t* p_buf,
-                                    uint16_t evt);
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_put_echo_data
- *
- * Description     Put the received loopback echo data
- *
- * Parameters      app_id - HDP application ID
- *                 mcl_handle - MCL handle
- *                 data_size - the size of the data
- *                 p_data - the data pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_put_echo_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-extern void bta_hl_co_put_echo_data(uint8_t app_id,
-                                    tBTA_HL_MCL_HANDLE mcl_handle,
-                                    uint16_t data_size, uint8_t* p_data,
-                                    uint16_t evt);
-
-#endif /* BTA_HL_CO_H */
diff --git a/bta/jv/bta_jv_act.cc b/bta/jv/bta_jv_act.cc
index 69fa3f2..462ee9d 100644
--- a/bta/jv/bta_jv_act.cc
+++ b/bta/jv/bta_jv_act.cc
@@ -194,9 +194,7 @@
     }
   }
   if (p_cb == NULL) {
-    LOG(ERROR) << __func__ << "port_handle=" << port_handle
-               << " ctrl block exceeds limit:" << port_handle,
-        BTA_JV_MAX_RFC_CONN;
+    LOG(ERROR) << __func__ << "port_handle=" << port_handle << " ctrl block exceeds limit:" << BTA_JV_MAX_RFC_CONN;
   }
   return p_cb;
 }
@@ -480,7 +478,7 @@
 static tBTA_JV_PM_CB* bta_jv_alloc_set_pm_profile_cb(uint32_t jv_handle,
                                                      tBTA_JV_PM_ID app_id) {
   bool bRfcHandle = (jv_handle & BTA_JV_RFCOMM_MASK) != 0;
-  RawAddress peer_bd_addr;
+  RawAddress peer_bd_addr = RawAddress::kEmpty;
   int i, j;
   tBTA_JV_PM_CB** pp_cb;
 
@@ -494,8 +492,9 @@
             pp_cb = &bta_jv_cb.port_cb[j].p_pm_cb;
             if (PORT_SUCCESS !=
                 PORT_CheckConnection(bta_jv_cb.port_cb[j].port_handle,
-                                     peer_bd_addr, NULL))
+                                     &peer_bd_addr, NULL)) {
               i = BTA_JV_PM_MAX_NUM;
+            }
             break;
           }
         }
@@ -604,7 +603,7 @@
 }
 
 /** Disables the BT device manager free the resources used by java */
-void bta_jv_disable() { LOG(ERROR) << __func__; }
+void bta_jv_disable() { LOG(INFO) << __func__; }
 
 /**
  * We keep a list of PSM's that have been freed from JAVA, for reuse.
@@ -788,7 +787,7 @@
   }
 
   /* init the database/set up the filter */
-  VLOG(2) << __func__ << ": call SDP_InitDiscoveryDb, num_uuid=", num_uuid;
+  VLOG(2) << __func__ << ": call SDP_InitDiscoveryDb, num_uuid=" << num_uuid;
   SDP_InitDiscoveryDb(p_bta_jv_cfg->p_sdp_db, p_bta_jv_cfg->sdp_db_size,
                       num_uuid, uuid_list, 0, NULL);
 
@@ -1254,7 +1253,7 @@
   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);
   tBTA_JV evt_data;
-  RawAddress rem_bda;
+  RawAddress rem_bda = RawAddress::kEmpty;
   uint16_t lcid;
   tBTA_JV_RFCOMM_CBACK* p_cback; /* the callback function */
 
@@ -1264,7 +1263,7 @@
   VLOG(2) << __func__ << ": code=" << code << ", port_handle=" << port_handle
           << ", handle=" << p_cb->handle;
 
-  PORT_CheckConnection(port_handle, rem_bda, &lcid);
+  PORT_CheckConnection(port_handle, &rem_bda, &lcid);
 
   if (code == PORT_SUCCESS) {
     evt_data.rfc_open.handle = p_cb->handle;
@@ -1451,7 +1450,7 @@
   tBTA_JV_PCB* p_pcb = bta_jv_rfc_port_to_pcb(port_handle);
   tBTA_JV_RFC_CB* p_cb = bta_jv_rfc_port_to_cb(port_handle);
   tBTA_JV evt_data;
-  RawAddress rem_bda;
+  RawAddress rem_bda = RawAddress::kEmpty;
   uint16_t lcid;
   VLOG(2) << __func__ << ": code=" << code << ", port_handle=" << port_handle;
   if (NULL == p_cb || NULL == p_cb->p_cback) {
@@ -1465,9 +1464,13 @@
           << ", handle=" << loghex(p_cb->handle) << ", p_pcb" << p_pcb
           << ", user=" << p_pcb->rfcomm_slot_id;
 
-  PORT_CheckConnection(port_handle, rem_bda, &lcid);
+  int status = PORT_CheckConnection(port_handle, &rem_bda, &lcid);
   int failed = true;
   if (code == PORT_SUCCESS) {
+    if (status != PORT_SUCCESS) {
+      LOG(ERROR) << __func__ << ": PORT_CheckConnection returned " << status
+                 << ", although port is supposed to be connected";
+    }
     evt_data.rfc_srv_open.handle = p_pcb->handle;
     evt_data.rfc_srv_open.status = BTA_JV_SUCCESS;
     evt_data.rfc_srv_open.rem_bda = rem_bda;
@@ -1521,7 +1524,11 @@
   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) return;
+  if (NULL == p_cb || NULL == p_cb->p_cback) {
+    LOG(ERROR) << __func__ << ": p_cb=" << p_cb
+               << ", p_cb->p_cback=" << (p_cb ? p_cb->p_cback : 0);
+    return;
+  }
 
   VLOG(2) << __func__ << ": code=" << loghex(code)
           << ", port_handle=" << port_handle << ", handle=" << p_cb->handle;
@@ -2110,11 +2117,12 @@
   if (tc) {
     // try to find an open socked for that addr and channel
     t = fcclient_find_by_addr(tc->clients, &bd_addr);
-    if (!t) {
-      // no socket -> drop it
-      return;
-    }
   }
+  if (!t) {
+    // no socket -> drop it
+    return;
+  }
+
 
   sock_cback = t->p_cback;
   sock_id = t->l2cap_socket_id;
@@ -2157,13 +2165,17 @@
   // it could have been deleted/moved from under us, so re-find it */
   t = fcclient_find_by_id(id);
   if (t) {
-    if (evt.l2c_cl_init.status == BTA_JV_SUCCESS)
+    if (evt.l2c_cl_init.status == BTA_JV_SUCCESS) {
       call_init_f = !t->init_called;
-    else
+    } else {
       fcclient_free(t);
+      t = NULL;
+    }
   }
   if (call_init_f) p_cback(BTA_JV_L2CAP_CL_INIT_EVT, &evt, l2cap_socket_id);
-  t->init_called = true;
+  if (t) {
+    t->init_called = true;
+  }
 }
 
 /* stops an LE L2CAP server */
diff --git a/bta/jv/bta_jv_api.cc b/bta/jv/bta_jv_api.cc
index 74818b6..6702e0d 100644
--- a/bta/jv/bta_jv_api.cc
+++ b/bta/jv/bta_jv_api.cc
@@ -29,13 +29,13 @@
 
 #include "bt_common.h"
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bta_jv_api.h"
 #include "bta_jv_int.h"
 #include "bta_sys.h"
 #include "gap_api.h"
 #include "port_api.h"
 #include "sdp_api.h"
+#include "stack/include/btu.h"
 #include "utl.h"
 
 using base::Bind;
@@ -75,7 +75,7 @@
 
   bta_jv_enabled = true;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_enable, p_cback));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_enable, p_cback));
   return BTA_JV_SUCCESS;
 }
 
@@ -85,7 +85,7 @@
 
   bta_jv_enabled = false;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_disable));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_disable));
 }
 
 /*******************************************************************************
@@ -140,8 +140,8 @@
     CHECK(false) << "Invalid conn_type=" << conn_type;
   }
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_get_channel_id, conn_type, channel, id, id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_get_channel_id, conn_type, channel, id, id));
 }
 
 /*******************************************************************************
@@ -161,7 +161,7 @@
 tBTA_JV_STATUS BTA_JvFreeChannel(uint16_t channel, int conn_type) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_free_scn, conn_type, channel));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_free_scn, conn_type, channel));
   return BTA_JV_SUCCESS;
 }
 
@@ -186,9 +186,9 @@
   Uuid* uuid_list_copy = new Uuid[num_uuid];
   memcpy(uuid_list_copy, p_uuid_list, num_uuid * sizeof(Uuid));
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_start_discovery, bd_addr, num_uuid,
-                        base::Owned(uuid_list_copy), rfcomm_slot_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_start_discovery, bd_addr, num_uuid,
+                         base::Owned(uuid_list_copy), rfcomm_slot_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -207,7 +207,7 @@
 tBTA_JV_STATUS BTA_JvCreateRecordByUser(uint32_t rfcomm_slot_id) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_create_record, rfcomm_slot_id));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_create_record, rfcomm_slot_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -224,7 +224,7 @@
 tBTA_JV_STATUS BTA_JvDeleteRecord(uint32_t handle) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_delete_record, handle));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_delete_record, handle));
   return BTA_JV_SUCCESS;
 }
 
@@ -245,8 +245,8 @@
                           uint32_t l2cap_socket_id) {
   VLOG(2) << __func__;
   CHECK(p_cback);
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_connect_le, remote_chan,
-                                   peer_bd_addr, p_cback, l2cap_socket_id));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_l2cap_connect_le, remote_chan,
+                                    peer_bd_addr, p_cback, l2cap_socket_id));
 }
 
 /*******************************************************************************
@@ -271,10 +271,10 @@
   VLOG(2) << __func__;
   CHECK(p_cback);
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_l2cap_connect, conn_type, sec_mask, role,
-                        remote_psm, rx_mtu, peer_bd_addr, base::Passed(&cfg),
-                        base::Passed(&ertm_info), p_cback, l2cap_socket_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_l2cap_connect, conn_type, sec_mask, role,
+                         remote_psm, rx_mtu, peer_bd_addr, base::Passed(&cfg),
+                         base::Passed(&ertm_info), p_cback, l2cap_socket_id));
 }
 
 /*******************************************************************************
@@ -293,7 +293,7 @@
   if (handle >= BTA_JV_MAX_L2C_CONN || !bta_jv_cb.l2c_cb[handle].p_cback)
     return BTA_JV_FAILURE;
 
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, Bind(&bta_jv_l2cap_close, handle, &bta_jv_cb.l2c_cb[handle]));
   return BTA_JV_SUCCESS;
 }
@@ -312,7 +312,7 @@
 tBTA_JV_STATUS BTA_JvL2capCloseLE(uint32_t handle) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_close_fixed, handle));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_l2cap_close_fixed, handle));
   return BTA_JV_SUCCESS;
 }
 
@@ -339,10 +339,10 @@
   VLOG(2) << __func__;
   CHECK(p_cback);
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_l2cap_start_server, conn_type, sec_mask, role,
-                        local_psm, rx_mtu, base::Passed(&cfg),
-                        base::Passed(&ertm_info), p_cback, l2cap_socket_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_l2cap_start_server, conn_type, sec_mask, role,
+                         local_psm, rx_mtu, base::Passed(&cfg),
+                         base::Passed(&ertm_info), p_cback, l2cap_socket_id));
 }
 
 /*******************************************************************************
@@ -363,8 +363,8 @@
                               uint32_t l2cap_socket_id) {
   VLOG(2) << __func__;
   CHECK(p_cback);
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_start_server_le, local_chan,
-                                   p_cback, l2cap_socket_id));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_l2cap_start_server_le, local_chan,
+                                    p_cback, l2cap_socket_id));
 }
 
 /*******************************************************************************
@@ -382,8 +382,8 @@
                                      uint32_t l2cap_socket_id) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_l2cap_stop_server, local_psm, l2cap_socket_id));
+  do_in_main_thread(
+      FROM_HERE, Bind(&bta_jv_l2cap_stop_server, local_psm, l2cap_socket_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -402,7 +402,7 @@
                                        uint32_t l2cap_socket_id) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_stop_server_le, local_chan));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_l2cap_stop_server_le, local_chan));
   return BTA_JV_SUCCESS;
 }
 
@@ -491,8 +491,8 @@
     return BTA_JV_FAILURE;
   }
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write, handle, req_id, msg,
-                                   user_id, &bta_jv_cb.l2c_cb[handle]));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_l2cap_write, handle, req_id, msg,
+                                    user_id, &bta_jv_cb.l2c_cb[handle]));
   return BTA_JV_SUCCESS;
 }
 
@@ -512,8 +512,8 @@
                            BT_HDR* msg, uint32_t user_id) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_l2cap_write_fixed, channel, addr,
-                                   req_id, msg, user_id, p_cback));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_l2cap_write_fixed, channel, addr,
+                                    req_id, msg, user_id, p_cback));
 }
 
 /*******************************************************************************
@@ -541,9 +541,9 @@
 
   if (!p_cback) return BTA_JV_FAILURE; /* Nothing to do */
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_rfcomm_connect, sec_mask, role, remote_scn,
-                        peer_bd_addr, p_cback, rfcomm_slot_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_rfcomm_connect, sec_mask, role, remote_scn,
+                         peer_bd_addr, p_cback, rfcomm_slot_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -567,8 +567,8 @@
       si >= BTA_JV_MAX_RFC_SR_SESSION || !bta_jv_cb.rfc_cb[hi].rfc_hdl[si])
     return BTA_JV_FAILURE;
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_rfcomm_close, handle, rfcomm_slot_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_rfcomm_close, handle, rfcomm_slot_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -602,9 +602,9 @@
     max_session = BTA_JV_MAX_RFC_SR_SESSION;
   }
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_rfcomm_start_server, sec_mask, role, local_scn,
-                        max_session, p_cback, rfcomm_slot_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_rfcomm_start_server, sec_mask, role, local_scn,
+                         max_session, p_cback, rfcomm_slot_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -623,8 +623,8 @@
                                       uint32_t rfcomm_slot_id) {
   VLOG(2) << __func__;
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_rfcomm_stop_server, handle, rfcomm_slot_id));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_rfcomm_stop_server, handle, rfcomm_slot_id));
   return BTA_JV_SUCCESS;
 }
 
@@ -675,8 +675,8 @@
   VLOG(2) << "write ok";
 
   tBTA_JV_RFC_CB* p_cb = &bta_jv_cb.rfc_cb[hi];
-  do_in_bta_thread(FROM_HERE, Bind(&bta_jv_rfcomm_write, handle, req_id, p_cb,
-                                   &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1]));
+  do_in_main_thread(FROM_HERE, Bind(&bta_jv_rfcomm_write, handle, req_id, p_cb,
+                                    &bta_jv_cb.port_cb[p_cb->rfc_hdl[si] - 1]));
   return BTA_JV_SUCCESS;
 }
 
@@ -707,7 +707,7 @@
                                   tBTA_JV_CONN_STATE init_st) {
   VLOG(2) << __func__ << " handle=" << loghex(handle) << ", app_id:" << app_id;
 
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&bta_jv_set_pm_profile, handle, app_id, init_st));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&bta_jv_set_pm_profile, handle, app_id, init_st));
   return BTA_JV_SUCCESS;
 }
diff --git a/bta/pan/bta_pan_act.cc b/bta/pan/bta_pan_act.cc
index 04c06d0..548d6fd 100644
--- a/bta/pan/bta_pan_act.cc
+++ b/bta/pan/bta_pan_act.cc
@@ -28,7 +28,7 @@
 
 #include <string.h>
 
-#include <cutils/log.h>
+#include <log/log.h>
 
 #include "bt_common.h"
 #include "bta_api.h"
diff --git a/bta/sys/bta_sys.h b/bta/sys/bta_sys.h
index a72f34b..29e9a3f 100644
--- a/bta/sys/bta_sys.h
+++ b/bta/sys/bta_sys.h
@@ -31,8 +31,6 @@
 #include <base/logging.h>
 #include <base/threading/thread.h>
 
-#include "bta/include/bta_closure_api.h"
-
 /*****************************************************************************
  *  Constants and data types
  ****************************************************************************/
@@ -224,7 +222,7 @@
 extern bool bta_sys_is_register(uint8_t id);
 extern uint16_t bta_sys_get_sys_features(void);
 extern void bta_sys_sendmsg(void* p_msg);
-extern void bta_sys_start_timer(alarm_t* alarm, period_ms_t interval,
+extern void bta_sys_start_timer(alarm_t* alarm, uint64_t interval_ms,
                                 uint16_t event, uint16_t layer_specific);
 extern void bta_sys_disable(tBTA_SYS_HW_MODULE module);
 
diff --git a/bta/sys/bta_sys_main.cc b/bta/sys/bta_sys_main.cc
index dda3977..1036e74 100644
--- a/bta/sys/bta_sys_main.cc
+++ b/bta/sys/bta_sys_main.cc
@@ -26,8 +26,6 @@
 
 #include <base/bind.h>
 #include <base/logging.h>
-#include <base/threading/thread.h>
-#include <pthread.h>
 #include <string.h>
 
 #include "bt_common.h"
@@ -40,7 +38,6 @@
 #include "osi/include/fixed_queue.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "osi/include/thread.h"
 #include "utl.h"
 
 #if (defined BTA_AR_INCLUDED) && (BTA_AR_INCLUDED == TRUE)
@@ -50,8 +47,6 @@
 /* system manager control block definition */
 tBTA_SYS_CB bta_sys_cb;
 
-extern thread_t* bt_workqueue_thread;
-
 /* trace level */
 /* TODO Hard-coded trace levels -  Needs to be configurable */
 uint8_t appl_trace_level = BT_TRACE_LEVEL_WARNING;  // APPL_INITIAL_TRACE_LEVEL;
@@ -530,77 +525,11 @@
  *
  ******************************************************************************/
 void bta_sys_sendmsg(void* p_msg) {
-  base::MessageLoop* bta_message_loop = get_message_loop();
-
-  if (!bta_message_loop || !bta_message_loop->task_runner().get()) {
-    APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
-    return;
+  if (do_in_main_thread(
+          FROM_HERE, base::Bind(&bta_sys_event, static_cast<BT_HDR*>(p_msg))) !=
+      BT_STATUS_SUCCESS) {
+    LOG(ERROR) << __func__ << ": do_in_main_thread failed";
   }
-
-  bta_message_loop->task_runner()->PostTask(
-      FROM_HERE, base::Bind(&bta_sys_event, static_cast<BT_HDR*>(p_msg)));
-}
-
-/*******************************************************************************
- *
- * Function         do_in_bta_thread
- *
- * Description      Post a closure to be ran in the bta thread
- *
- * Returns          BT_STATUS_SUCCESS on success
- *
- ******************************************************************************/
-bt_status_t do_in_bta_thread(const tracked_objects::Location& from_here,
-                             const base::Closure& task) {
-  base::MessageLoop* bta_message_loop = get_message_loop();
-  if (!bta_message_loop) {
-    APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
-    return BT_STATUS_FAIL;
-  }
-
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-      bta_message_loop->task_runner();
-  if (!task_runner.get()) {
-    APPL_TRACE_ERROR("%s: task runner is dead", __func__);
-    return BT_STATUS_FAIL;
-  }
-
-  if (!task_runner->PostTask(from_here, task)) {
-    APPL_TRACE_ERROR("%s: Post task to task runner failed!", __func__);
-    return BT_STATUS_FAIL;
-  }
-  return BT_STATUS_SUCCESS;
-}
-
-/*******************************************************************************
- *
- * Function         do_in_bta_thread_once
- *
- * Description      Post a closure to be ran in the bta thread once
- *
- * Returns          BT_STATUS_SUCCESS on success
- *
- ******************************************************************************/
-bt_status_t do_in_bta_thread_once(const tracked_objects::Location& from_here,
-                                  base::OnceClosure task) {
-  base::MessageLoop* bta_message_loop = get_message_loop();
-  if (!bta_message_loop) {
-    APPL_TRACE_ERROR("%s: MessageLooper not initialized", __func__);
-    return BT_STATUS_FAIL;
-  }
-
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-      bta_message_loop->task_runner();
-  if (!task_runner.get()) {
-    APPL_TRACE_ERROR("%s: task runner is dead", __func__);
-    return BT_STATUS_FAIL;
-  }
-
-  if (!task_runner->PostTask(from_here, std::move(task))) {
-    APPL_TRACE_ERROR("%s: Post task to task runner failed!", __func__);
-    return BT_STATUS_FAIL;
-  }
-  return BT_STATUS_SUCCESS;
 }
 
 /*******************************************************************************
@@ -613,14 +542,14 @@
  * Returns          void
  *
  ******************************************************************************/
-void bta_sys_start_timer(alarm_t* alarm, period_ms_t interval, uint16_t event,
+void bta_sys_start_timer(alarm_t* alarm, uint64_t interval_ms, uint16_t event,
                          uint16_t layer_specific) {
   BT_HDR* p_buf = (BT_HDR*)osi_malloc(sizeof(BT_HDR));
 
   p_buf->event = event;
   p_buf->layer_specific = layer_specific;
 
-  alarm_set_on_mloop(alarm, interval, bta_sys_sendmsg, p_buf);
+  alarm_set_on_mloop(alarm, interval_ms, bta_sys_sendmsg, p_buf);
 }
 
 /*******************************************************************************
diff --git a/bta/test/bta_hf_client_test.cc b/bta/test/bta_hf_client_test.cc
index 107a2e5..9b9ade2 100644
--- a/bta/test/bta_hf_client_test.cc
+++ b/bta/test/bta_hf_client_test.cc
@@ -25,7 +25,7 @@
 class MessageLoop;
 }  // namespace base
 
-base::MessageLoop* get_message_loop() { return NULL; }
+base::MessageLoop* get_main_message_loop() { return NULL; }
 
 namespace {
 const RawAddress bdaddr1({0x11, 0x22, 0x33, 0x44, 0x55, 0x66});
diff --git a/bta/test/gatt/database_builder_sample_device_test.cc b/bta/test/gatt/database_builder_sample_device_test.cc
new file mode 100644
index 0000000..2bfaa04
--- /dev/null
+++ b/bta/test/gatt/database_builder_sample_device_test.cc
@@ -0,0 +1,274 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include <base/logging.h>
+#include <iterator>
+#include <utility>
+
+#include "gatt/database_builder.h"
+
+using bluetooth::Uuid;
+
+namespace gatt {
+
+namespace {
+/* EXPECT_EQ doesn't work well with static constexpr fields, need a variable
+ * with address */
+constexpr std::pair<uint16_t, uint16_t> EXPLORE_END =
+    DatabaseBuilder::EXPLORE_END;
+
+/* make_pair doesn't work well with EXPECT_EQ, have own helper instead */
+inline std::pair<uint16_t, uint16_t> make_pair_u16(uint16_t first,
+                                                   uint16_t second) {
+  return std::make_pair(first, second);
+}
+
+// clang-format off
+Uuid SERVICE_1_UUID = Uuid::FromString("00001800-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_2_UUID = Uuid::FromString("00001801-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_3_UUID = Uuid::FromString("0000180f-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_4_UUID = Uuid::FromString("0000fef5-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_UUID = Uuid::FromString("0000180a-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_6_UUID = Uuid::FromString("0000fe55-0000-1000-8000-00805f9b34fb");
+
+Uuid SERVICE_1_CHAR_1_UUID = Uuid::FromString("00002a00-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_1_CHAR_2_UUID = Uuid::FromString("00002a01-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_1_CHAR_3_UUID = Uuid::FromString("00002a04-0000-1000-8000-00805f9b34fb");
+
+Uuid SERVICE_3_CHAR_1_UUID = Uuid::FromString("00002a19-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_3_CHAR_1_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
+
+Uuid SERVICE_4_CHAR_1_UUID = Uuid::FromString("8082caa8-41a6-4021-91c6-56f9b954cc34");
+Uuid SERVICE_4_CHAR_2_UUID = Uuid::FromString("724249f0-5ec3-4b5f-8804-42345af08651");
+Uuid SERVICE_4_CHAR_3_UUID = Uuid::FromString("6c53db25-47a1-45fe-a022-7c92fb334fd4");
+Uuid SERVICE_4_CHAR_4_UUID = Uuid::FromString("9d84b9a3-000c-49d8-9183-855b673fda31");
+Uuid SERVICE_4_CHAR_5_UUID = Uuid::FromString("457871e8-d516-4ca1-9116-57d0b17b9cb2");
+Uuid SERVICE_4_CHAR_6_UUID = Uuid::FromString("5f78df94-798c-46f5-990a-b3eb6a065c88");
+Uuid SERVICE_4_CHAR_6_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
+
+Uuid SERVICE_5_CHAR_1_UUID = Uuid::FromString("00002a29-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_CHAR_2_UUID = Uuid::FromString("00002a24-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_CHAR_3_UUID = Uuid::FromString("00002a25-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_CHAR_4_UUID = Uuid::FromString("00002a27-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_CHAR_5_UUID = Uuid::FromString("00002a26-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_CHAR_6_UUID = Uuid::FromString("00002a28-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_CHAR_7_UUID = Uuid::FromString("00002a50-0000-1000-8000-00805f9b34fb");
+
+Uuid SERVICE_6_CHAR_1_UUID = Uuid::FromString("00000001-1000-1000-8000-00805f9b34fb");
+Uuid SERVICE_6_CHAR_1_DESC_1_UUID = Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_6_CHAR_2_UUID = Uuid::FromString("00000002-1000-1000-8000-00805f9b34fb");
+Uuid SERVICE_6_CHAR_3_UUID = Uuid::FromString("00000003-1000-1000-8000-00805f9b34fb");
+// clang-format on
+
+}  // namespace
+
+// clang-format off
+/* Content of sample database, comes from Daydream controller:
+Service: handle=0x0001, end_handle=0x0007, uuid=00001800-0000-1000-8000-00805f9b34fb
+	 Characteristic: declaration_handle=0x0002, value_handle=0x0003, uuid=00002a00-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0004, value_handle=0x0005, uuid=00002a01-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0006, value_handle=0x0007, uuid=00002a04-0000-1000-8000-00805f9b34fb, prop=0x02
+Service: handle=0x0008, end_handle=0x0008, uuid=00001801-0000-1000-8000-00805f9b34fb
+Service: handle=0x0009, end_handle=0x000c, uuid=0000180f-0000-1000-8000-00805f9b34fb
+	 Characteristic: declaration_handle=0x000a, value_handle=0x000b, uuid=00002a19-0000-1000-8000-00805f9b34fb, prop=0x12
+		 Descriptor: handle=0x000c, uuid=00002902-0000-1000-8000-00805f9b34fb
+Service: handle=0x000d, end_handle=0x001a, uuid=0000fef5-0000-1000-8000-00805f9b34fb
+	 Characteristic: declaration_handle=0x000e, value_handle=0x000f, uuid=8082caa8-41a6-4021-91c6-56f9b954cc34, prop=0x0a
+	 Characteristic: declaration_handle=0x0010, value_handle=0x0011, uuid=724249f0-5ec3-4b5f-8804-42345af08651, prop=0x0a
+	 Characteristic: declaration_handle=0x0012, value_handle=0x0013, uuid=6c53db25-47a1-45fe-a022-7c92fb334fd4, prop=0x02
+	 Characteristic: declaration_handle=0x0014, value_handle=0x0015, uuid=9d84b9a3-000c-49d8-9183-855b673fda31, prop=0x0a
+	 Characteristic: declaration_handle=0x0016, value_handle=0x0017, uuid=457871e8-d516-4ca1-9116-57d0b17b9cb2, prop=0x0e
+	 Characteristic: declaration_handle=0x0018, value_handle=0x0019, uuid=5f78df94-798c-46f5-990a-b3eb6a065c88, prop=0x12
+		 Descriptor: handle=0x001a, uuid=00002902-0000-1000-8000-00805f9b34fb
+Service: handle=0x001b, end_handle=0x0029, uuid=0000180a-0000-1000-8000-00805f9b34fb
+	 Characteristic: declaration_handle=0x001c, value_handle=0x001d, uuid=00002a29-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x001e, value_handle=0x001f, uuid=00002a24-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0020, value_handle=0x0021, uuid=00002a25-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0022, value_handle=0x0023, uuid=00002a27-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0024, value_handle=0x0025, uuid=00002a26-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0026, value_handle=0x0027, uuid=00002a28-0000-1000-8000-00805f9b34fb, prop=0x02
+	 Characteristic: declaration_handle=0x0028, value_handle=0x0029, uuid=00002a50-0000-1000-8000-00805f9b34fb, prop=0x02
+Service: handle=0x002a, end_handle=0x0031, uuid=0000fe55-0000-1000-8000-00805f9b34fb
+	 Characteristic: declaration_handle=0x002b, value_handle=0x002c, uuid=00000001-1000-1000-8000-00805f9b34fb, prop=0x10
+		 Descriptor: handle=0x002d, uuid=00002902-0000-1000-8000-00805f9b34fb
+	 Characteristic: declaration_handle=0x002e, value_handle=0x002f, uuid=00000002-1000-1000-8000-00805f9b34fb, prop=0x08
+	 Characteristic: declaration_handle=0x0030, value_handle=0x0031, uuid=00000003-1000-1000-8000-00805f9b34fb, prop=0x02
+*/
+// clang-format on
+
+/* This test verifies that DatabaseBuilder will properly discover database
+ * content from a remote device. It also verify that after the discovery is
+ * done, returned database is equal to the discovered one */
+TEST(DatabaseBuilderSampleDeviceTest, DoDiscovery) {
+  DatabaseBuilder builder;
+
+  EXPECT_FALSE(builder.InProgress());
+
+  // At start of discovery, builder will receive All services in order from
+  // lower layers.
+  builder.AddService(0x0001, 0x0007, SERVICE_1_UUID, true);
+
+  // The moment we receive first service, we are in progress
+  // TODO: we should be able to set InProgress state once we sent GATT request,
+  // not when it's back and parsed
+  EXPECT_TRUE(builder.InProgress());
+
+  builder.AddService(0x0008, 0x0008, SERVICE_2_UUID, true);
+  builder.AddService(0x0009, 0x000c, SERVICE_3_UUID, true);
+  builder.AddService(0x000d, 0x001a, SERVICE_4_UUID, true);
+  builder.AddService(0x001b, 0x0029, SERVICE_5_UUID, true);
+  builder.AddService(0x002a, 0x0031, SERVICE_6_UUID, true);
+
+  // At this moment, all services are received, stack will grab them one and one
+  // to discover their content.
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+
+  // Grabbing first service, to start Included Service and Characteristic
+  // discovery
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0001, 0x0007));
+
+  builder.AddCharacteristic(0x0002, 0x0003, SERVICE_1_CHAR_1_UUID, 0x02);
+  builder.AddCharacteristic(0x0004, 0x0005, SERVICE_1_CHAR_2_UUID, 0x02);
+  builder.AddCharacteristic(0x0006, 0x0007, SERVICE_1_CHAR_3_UUID, 0x02);
+
+  // All characteristics were discovered, stack will try to look for
+  // descriptors. Since there is no space for descriptors, builder should return
+  // nothing more to discover
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
+
+  // Service with handles 0x0008, 0x0008 is skipped for exploration - we know
+  // it's empty.
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0009, 0x000c));
+
+  builder.AddCharacteristic(0x000a, 0x000b, SERVICE_3_CHAR_1_UUID, 0x12);
+
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(),
+            make_pair_u16(0x000c, 0x000c));
+
+  builder.AddDescriptor(0x000c, SERVICE_3_CHAR_1_DESC_1_UUID);
+
+  // All descriptors were explored
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
+
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x000d, 0x001a));
+
+  builder.AddCharacteristic(0x000e, 0x000f, SERVICE_4_CHAR_1_UUID, 0x0a);
+  builder.AddCharacteristic(0x0010, 0x0011, SERVICE_4_CHAR_2_UUID, 0x0a);
+  builder.AddCharacteristic(0x0012, 0x0013, SERVICE_4_CHAR_3_UUID, 0x02);
+  builder.AddCharacteristic(0x0014, 0x0015, SERVICE_4_CHAR_4_UUID, 0x0a);
+  builder.AddCharacteristic(0x0016, 0x0017, SERVICE_4_CHAR_5_UUID, 0x0e);
+  builder.AddCharacteristic(0x0018, 0x0019, SERVICE_4_CHAR_6_UUID, 0x12);
+
+  // Just last Characteristic have space for descriptor
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(),
+            make_pair_u16(0x001a, 0x001a));
+
+  builder.AddDescriptor(0x001a, SERVICE_4_CHAR_6_DESC_1_UUID);
+
+  // All descriptors were explored
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
+
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x001b, 0x0029));
+
+  builder.AddCharacteristic(0x001c, 0x001d, SERVICE_5_CHAR_1_UUID, 0x02);
+  builder.AddCharacteristic(0x001e, 0x001f, SERVICE_5_CHAR_2_UUID, 0x02);
+  builder.AddCharacteristic(0x0020, 0x0021, SERVICE_5_CHAR_3_UUID, 0x02);
+  builder.AddCharacteristic(0x0022, 0x0023, SERVICE_5_CHAR_4_UUID, 0x02);
+  builder.AddCharacteristic(0x0024, 0x0025, SERVICE_5_CHAR_5_UUID, 0x02);
+  builder.AddCharacteristic(0x0026, 0x0027, SERVICE_5_CHAR_6_UUID, 0x02);
+  builder.AddCharacteristic(0x0028, 0x0029, SERVICE_5_CHAR_7_UUID, 0x02);
+
+  // No space for descriptors
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
+
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x002a, 0x0031));
+
+  builder.AddCharacteristic(0x002b, 0x002c, SERVICE_6_CHAR_1_UUID, 0x10);
+  builder.AddCharacteristic(0x002e, 0x002f, SERVICE_6_CHAR_2_UUID, 0x08);
+  builder.AddCharacteristic(0x0030, 0x0031, SERVICE_6_CHAR_3_UUID, 0x02);
+
+  // Just one Characteristic have space for descriptor
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(),
+            make_pair_u16(0x002d, 0x002d));
+
+  builder.AddDescriptor(0x002d, SERVICE_6_CHAR_1_DESC_1_UUID);
+
+  // All descriptors were explored
+  EXPECT_EQ(builder.NextDescriptorRangeToExplore(), EXPLORE_END);
+
+  EXPECT_FALSE(builder.StartNextServiceExploration());
+
+  EXPECT_TRUE(builder.InProgress());
+  Database result = builder.Build();
+  EXPECT_FALSE(builder.InProgress());
+
+  // verify that the returned database matches what was discovered
+  auto service = result.Services().begin();
+  EXPECT_EQ(service->handle, 0x0001);
+  EXPECT_EQ(service->uuid, SERVICE_1_UUID);
+
+  EXPECT_EQ(service->characteristics[0].uuid, SERVICE_1_CHAR_1_UUID);
+  EXPECT_EQ(service->characteristics[1].uuid, SERVICE_1_CHAR_2_UUID);
+  EXPECT_EQ(service->characteristics[2].uuid, SERVICE_1_CHAR_3_UUID);
+
+  service++;
+  EXPECT_EQ(service->uuid, SERVICE_2_UUID);
+
+  service++;
+  EXPECT_EQ(service->uuid, SERVICE_3_UUID);
+  EXPECT_EQ(service->characteristics[0].uuid, SERVICE_3_CHAR_1_UUID);
+  EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
+            SERVICE_3_CHAR_1_DESC_1_UUID);
+
+  service++;
+  EXPECT_EQ(service->uuid, SERVICE_4_UUID);
+  EXPECT_EQ(service->characteristics[0].uuid, SERVICE_4_CHAR_1_UUID);
+  EXPECT_EQ(service->characteristics[1].uuid, SERVICE_4_CHAR_2_UUID);
+  EXPECT_EQ(service->characteristics[2].uuid, SERVICE_4_CHAR_3_UUID);
+  EXPECT_EQ(service->characteristics[3].uuid, SERVICE_4_CHAR_4_UUID);
+  EXPECT_EQ(service->characteristics[4].uuid, SERVICE_4_CHAR_5_UUID);
+  EXPECT_EQ(service->characteristics[5].uuid, SERVICE_4_CHAR_6_UUID);
+  EXPECT_EQ(service->characteristics[5].descriptors[0].uuid,
+            SERVICE_4_CHAR_6_DESC_1_UUID);
+
+  service++;
+  EXPECT_EQ(service->uuid, SERVICE_5_UUID);
+  EXPECT_EQ(service->characteristics[0].uuid, SERVICE_5_CHAR_1_UUID);
+  EXPECT_EQ(service->characteristics[1].uuid, SERVICE_5_CHAR_2_UUID);
+  EXPECT_EQ(service->characteristics[2].uuid, SERVICE_5_CHAR_3_UUID);
+  EXPECT_EQ(service->characteristics[3].uuid, SERVICE_5_CHAR_4_UUID);
+  EXPECT_EQ(service->characteristics[4].uuid, SERVICE_5_CHAR_5_UUID);
+  EXPECT_EQ(service->characteristics[5].uuid, SERVICE_5_CHAR_6_UUID);
+  EXPECT_EQ(service->characteristics[6].uuid, SERVICE_5_CHAR_7_UUID);
+
+  service++;
+  EXPECT_EQ(service->uuid, SERVICE_6_UUID);
+  EXPECT_EQ(service->characteristics[0].uuid, SERVICE_6_CHAR_1_UUID);
+  EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
+            SERVICE_6_CHAR_1_DESC_1_UUID);
+  EXPECT_EQ(service->characteristics[1].uuid, SERVICE_6_CHAR_2_UUID);
+  EXPECT_EQ(service->characteristics[2].uuid, SERVICE_6_CHAR_3_UUID);
+}
+
+}  // namespace gatt
\ No newline at end of file
diff --git a/bta/test/gatt/database_builder_test.cc b/bta/test/gatt/database_builder_test.cc
new file mode 100644
index 0000000..0a7e928
--- /dev/null
+++ b/bta/test/gatt/database_builder_test.cc
@@ -0,0 +1,174 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include <base/logging.h>
+#include <iterator>
+#include <utility>
+
+#include "gatt/database_builder.h"
+
+using bluetooth::Uuid;
+
+namespace gatt {
+
+namespace {
+/* make_pair doesn't work well with EXPECT_EQ, have own helper instead */
+inline std::pair<uint16_t, uint16_t> make_pair_u16(uint16_t first,
+                                                   uint16_t second) {
+  return std::make_pair(first, second);
+}
+
+Uuid SERVICE_1_UUID = Uuid::FromString("00001800-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_2_UUID = Uuid::FromString("00001801-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_3_UUID = Uuid::FromString("0000180f-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_4_UUID = Uuid::FromString("0000fef5-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_5_UUID = Uuid::FromString("0000180a-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_1_CHAR_1_UUID =
+    Uuid::FromString("00002a00-0000-1000-8000-00805f9b34fb");
+Uuid SERVICE_1_CHAR_1_DESC_1_UUID =
+    Uuid::FromString("00002902-0000-1000-8000-00805f9b34fb");
+
+}  // namespace
+
+/* Verify adding empty service works ok */
+TEST(DatabaseBuilderTest, EmptyServiceAddTest) {
+  DatabaseBuilder builder;
+
+  EXPECT_FALSE(builder.InProgress());
+
+  // Simple database, just one empty
+  builder.AddService(0x0001, 0x0001, SERVICE_1_UUID, true);
+  EXPECT_FALSE(builder.StartNextServiceExploration());
+
+  Database result = builder.Build();
+
+  // verify that the returned database matches what was discovered
+  auto service = result.Services().begin();
+  EXPECT_EQ(service->handle, 0x0001);
+  EXPECT_EQ(service->end_handle, 0x0001);
+  EXPECT_EQ(service->is_primary, true);
+  EXPECT_EQ(service->uuid, SERVICE_1_UUID);
+}
+
+/* Verify adding service, characteristic and descriptor work */
+TEST(DatabaseBuilderTest, DescriptorAddTest) {
+  DatabaseBuilder builder;
+
+  EXPECT_FALSE(builder.InProgress());
+
+  // Simple database, just one empty
+  builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
+  builder.AddCharacteristic(0x0002, 0x0003, SERVICE_1_CHAR_1_UUID, 0x02);
+  builder.AddDescriptor(0x0004, SERVICE_1_CHAR_1_DESC_1_UUID);
+
+  Database result = builder.Build();
+
+  // verify that the returned database matches what was discovered
+  auto service = result.Services().begin();
+  EXPECT_EQ(service->handle, 0x0001);
+  EXPECT_EQ(service->end_handle, 0x000f);
+  EXPECT_EQ(service->is_primary, true);
+  EXPECT_EQ(service->uuid, SERVICE_1_UUID);
+
+  EXPECT_EQ(service->characteristics[0].uuid, SERVICE_1_CHAR_1_UUID);
+  EXPECT_EQ(service->characteristics[0].declaration_handle, 0x0002);
+  EXPECT_EQ(service->characteristics[0].value_handle, 0x0003);
+  EXPECT_EQ(service->characteristics[0].properties, 0x02);
+
+  EXPECT_EQ(service->characteristics[0].descriptors[0].uuid,
+            SERVICE_1_CHAR_1_DESC_1_UUID);
+  EXPECT_EQ(service->characteristics[0].descriptors[0].handle, 0x0004);
+}
+
+/* This test verifies that DatabaseBuilder properly handle discovery of
+ * secondary service, that is added to the discovery queue from included service
+ * definition. Such service might come out of order.  */
+TEST(DatabaseBuilderTest, SecondaryServiceOutOfOrderTest) {
+  DatabaseBuilder builder;
+
+  EXPECT_FALSE(builder.InProgress());
+
+  // At start of discovery, builder will receive All services in order from
+  // lower layers.
+  builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
+  builder.AddService(0x0030, 0x003f, SERVICE_3_UUID, true);
+  builder.AddService(0x0050, 0x005f, SERVICE_5_UUID, true);
+
+  // First service skipped, no place for handles
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0001, 0x000f));
+
+  // For this test, content of first service is irrevelant
+
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  // Grabbing first service, to start Included Service and Characteristic
+  // discovery
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0030, 0x003f));
+
+  builder.AddIncludedService(0x0031, SERVICE_4_UUID, 0x0040, 0x004f);
+  builder.AddIncludedService(0x0032, SERVICE_2_UUID, 0x0020, 0x002f);
+
+  /* Secondary service exploration */
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0020, 0x002f));
+
+  /* Secondary service exploration */
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0040, 0x004f));
+
+  /* Back to primary service exploration */
+  EXPECT_TRUE(builder.StartNextServiceExploration());
+  EXPECT_EQ(builder.CurrentlyExploredService(), make_pair_u16(0x0050, 0x005f));
+
+  Database result = builder.Build();
+
+  // verify that the returned database matches what was discovered
+  auto service = result.Services().begin();
+  EXPECT_EQ(service->handle, 0x0001);
+  EXPECT_EQ(service->is_primary, true);
+  EXPECT_EQ(service->uuid, SERVICE_1_UUID);
+
+  service++;
+  EXPECT_EQ(service->handle, 0x0020);
+  EXPECT_EQ(service->end_handle, 0x002f);
+  EXPECT_EQ(service->uuid, SERVICE_2_UUID);
+  EXPECT_EQ(service->is_primary, false);
+
+  service++;
+  EXPECT_EQ(service->handle, 0x0030);
+  EXPECT_EQ(service->end_handle, 0x003f);
+  EXPECT_EQ(service->uuid, SERVICE_3_UUID);
+  EXPECT_EQ(service->is_primary, true);
+
+  service++;
+  EXPECT_EQ(service->handle, 0x0040);
+  EXPECT_EQ(service->uuid, SERVICE_4_UUID);
+  EXPECT_EQ(service->is_primary, false);
+
+  service++;
+  EXPECT_EQ(service->handle, 0x0050);
+  EXPECT_EQ(service->uuid, SERVICE_5_UUID);
+  EXPECT_EQ(service->is_primary, true);
+
+  service++;
+  ASSERT_EQ(service, result.Services().end());
+}
+
+}  // namespace gatt
\ No newline at end of file
diff --git a/bta/test/gatt/database_test.cc b/bta/test/gatt/database_test.cc
new file mode 100644
index 0000000..78250ec
--- /dev/null
+++ b/bta/test/gatt/database_test.cc
@@ -0,0 +1,207 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include "gatt/database.h"
+#include "gatt/database_builder.h"
+#include "stack/include/gattdefs.h"
+
+using bluetooth::Uuid;
+
+namespace gatt {
+
+namespace {
+const Uuid PRIMARY_SERVICE = Uuid::From16Bit(GATT_UUID_PRI_SERVICE);
+const Uuid SECONDARY_SERVICE = Uuid::From16Bit(GATT_UUID_SEC_SERVICE);
+const Uuid INCLUDE = Uuid::From16Bit(GATT_UUID_INCLUDE_SERVICE);
+const Uuid CHARACTERISTIC = Uuid::From16Bit(GATT_UUID_CHAR_DECLARE);
+
+Uuid SERVICE_1_UUID = Uuid::FromString("1800");
+Uuid SERVICE_2_UUID = Uuid::FromString("1801");
+Uuid SERVICE_1_CHAR_1_UUID = Uuid::FromString("2a00");
+Uuid SERVICE_1_CHAR_1_DESC_1_UUID = Uuid::FromString("2902");
+}  // namespace
+
+/* This test makes sure that each possible GATT cache element is properly
+ * serialized into StoredAttribute */
+TEST(GattDatabaseTest, serialize_deserialize_binary_test) {
+  DatabaseBuilder builder;
+  builder.AddService(0x0001, 0x000f, SERVICE_1_UUID, true);
+  builder.AddService(0x0010, 0x001f, SERVICE_2_UUID, false);
+  builder.AddIncludedService(0x0002, SERVICE_2_UUID, 0x0010, 0x001f);
+  builder.AddCharacteristic(0x0003, 0x0004, SERVICE_1_CHAR_1_UUID, 0x02);
+  builder.AddDescriptor(0x0005, SERVICE_1_CHAR_1_DESC_1_UUID);
+
+  Database db = builder.Build();
+  std::vector<StoredAttribute> serialized = db.Serialize();
+
+  // Primary Service
+  EXPECT_EQ(serialized[0].handle, 0x0001);
+  EXPECT_EQ(serialized[0].type, PRIMARY_SERVICE);
+  EXPECT_EQ(serialized[0].value.service.uuid, SERVICE_1_UUID);
+  EXPECT_EQ(serialized[0].value.service.end_handle, 0x000f);
+
+  // Secondary Service
+  EXPECT_EQ(serialized[1].handle, 0x0010);
+  EXPECT_EQ(serialized[1].type, SECONDARY_SERVICE);
+  EXPECT_EQ(serialized[1].value.service.uuid, SERVICE_2_UUID);
+  EXPECT_EQ(serialized[1].value.service.end_handle, 0x001f);
+
+  // Included Service
+  EXPECT_EQ(serialized[2].handle, 0x0002);
+  EXPECT_EQ(serialized[2].type, INCLUDE);
+  EXPECT_EQ(serialized[2].value.included_service.handle, 0x0010);
+  EXPECT_EQ(serialized[2].value.included_service.end_handle, 0x001f);
+  EXPECT_EQ(serialized[2].value.included_service.uuid, SERVICE_2_UUID);
+
+  // Characteristic
+  EXPECT_EQ(serialized[3].handle, 0x0003);
+  EXPECT_EQ(serialized[3].type, CHARACTERISTIC);
+  EXPECT_EQ(serialized[3].value.characteristic.properties, 0x02);
+  EXPECT_EQ(serialized[3].value.characteristic.value_handle, 0x0004);
+  EXPECT_EQ(serialized[3].value.characteristic.uuid, SERVICE_1_CHAR_1_UUID);
+
+  // Descriptor
+  EXPECT_EQ(serialized[4].handle, 0x0005);
+  EXPECT_EQ(serialized[4].type, SERVICE_1_CHAR_1_DESC_1_UUID);
+}
+
+/* This test makes sure that Service represented in StoredAttribute have proper
+ * binary format. */
+TEST(GattCacheTest, stored_attribute_to_binary_service_test) {
+  StoredAttribute attr;
+
+  /* make sure padding at end of union is cleared */
+  memset(&attr, 0, sizeof(attr));
+
+  attr = {
+      .handle = 0x0001,
+      .type = PRIMARY_SERVICE,
+      .value = {.service = {.uuid = Uuid::FromString("1800"),
+                            .end_handle = 0x001c}},
+  };
+
+  constexpr size_t len = sizeof(StoredAttribute);
+  // clang-format off
+  uint8_t binary_form[len] = {
+      /*handle */ 0x01, 0x00,
+      /* type*/ 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
+      /* service uuid */ 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
+      /* end handle */ 0x1C, 0x00,
+      /* cleared padding at end of union*/ 0x00, 0x00};
+  // clang-format on
+
+  // useful for debugging:
+  // LOG(ERROR) << " " << base::HexEncode(&attr, len);
+  EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
+}
+
+/* This test makes sure that Service represented in StoredAttribute have proper
+ * binary format. */
+TEST(GattCacheTest, stored_attribute_to_binary_included_service_test) {
+  StoredAttribute attr;
+
+  /* make sure padding at end of union is cleared */
+  memset(&attr, 0, sizeof(attr));
+
+  attr = {
+      .handle = 0x0001,
+      .type = INCLUDE,
+      .value = {.included_service =
+                    {
+                        .handle = 0x0010,
+                        .end_handle = 0x001f,
+                        .uuid = Uuid::FromString("1801"),
+                    }},
+  };
+
+  constexpr size_t len = sizeof(StoredAttribute);
+  // clang-format off
+  uint8_t binary_form[len] = {
+      /*handle */ 0x01, 0x00,
+      /* type*/ 0x00, 0x00, 0x28, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
+      /* handle */ 0x10, 0x00,
+      /* end handle */ 0x1f, 0x00,
+      /* service uuid */ 0x00, 0x00, 0x18, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+  // clang-format on
+
+  // useful for debugging:
+  // LOG(ERROR) << " " << base::HexEncode(&attr, len);
+  EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
+}
+
+/* This test makes sure that Characteristic represented in StoredAttribute have
+ * proper binary format. */
+TEST(GattCacheTest, stored_attribute_to_binary_characteristic_test) {
+  StoredAttribute attr;
+
+  /* make sure padding at end of union is cleared */
+  memset(&attr, 0, sizeof(attr));
+
+  attr = {
+      .handle = 0x0002,
+      .type = CHARACTERISTIC,
+      .value = {.characteristic = {.properties = 0x02,
+                                   .value_handle = 0x0003,
+                                   .uuid = Uuid::FromString("2a00")}},
+  };
+
+  constexpr size_t len = sizeof(StoredAttribute);
+  // clang-format off
+  uint8_t binary_form[len] = {
+      /*handle */ 0x02, 0x00,
+      /* type */ 0x00, 0x00, 0x28, 0x03, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
+      /* properties */ 0x02,
+      /* after properties there is one byte padding. This might cause troube
+         on other platforms, investigate if it's ever a problem */ 0x00,
+      /* value handle */ 0x03, 0x00,
+      /* uuid */ 0x00, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB};
+  // clang-format on
+
+  // useful for debugging:
+  // LOG(ERROR) << " " << base::HexEncode(&attr, len);
+  EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
+}
+
+/* This test makes sure that Descriptor represented in StoredAttribute have
+ * proper binary format. */
+TEST(GattCacheTest, stored_attribute_to_binary_descriptor_test) {
+  StoredAttribute attr;
+
+  /* make sure padding at end of union is cleared */
+  memset(&attr, 0, sizeof(attr));
+
+  attr = {.handle = 0x0003, .type = Uuid::FromString("2902"), .value = {}};
+
+  constexpr size_t len = sizeof(StoredAttribute);
+  // clang-format off
+  uint8_t binary_form[len] = {
+      /*handle */ 0x03, 0x00,
+      /* type */ 0x00, 0x00, 0x29, 0x02, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B, 0x34, 0xFB,
+      /* clear padding    */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                             0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+  // clang-format on
+
+  // useful for debugging:
+  // LOG(ERROR) << " " << base::HexEncode(&attr, len);
+  EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
+}
+}  // namespace gatt
\ No newline at end of file
diff --git a/bta/test/gatt_cache_file_test.cc b/bta/test/gatt_cache_file_test.cc
deleted file mode 100644
index 3ea8902..0000000
--- a/bta/test/gatt_cache_file_test.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2018 The Android Open Source Project
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-#include <gtest/gtest.h>
-
-#include <base/logging.h>
-#include <base/strings/string_number_conversions.h>
-#include "bta/include/bta_gatt_api.h"
-
-using bluetooth::Uuid;
-
-/* This test makes sure that v3 cache element is properly encoded into file*/
-TEST(GattCacheTest, nv_attr_to_binary_test) {
-  tBTA_GATTC_NV_ATTR attr{
-      .uuid = Uuid::FromString("1800"),
-      .s_handle = 0x0001,
-      .e_handle = 0xFFFF,
-      .attr_type = 0x01,
-      .id = 0x02,
-      .prop = 0x03,
-      .is_primary = false,
-      .incl_srvc_handle = 0x4543,
-  };
-
-  constexpr size_t len = sizeof(tBTA_GATTC_NV_ATTR);
-  uint8_t binary_form[len] = {0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x10,
-                              0x00, 0x80, 0x00, 0x00, 0x80, 0x5F, 0x9B,
-                              0x34, 0xFB, 0x01, 0x00, 0xFF, 0xFF, 0x01,
-                              0x02, 0x03, 0x00, 0x43, 0x45};
-
-  // USEFUL for debugging:
-  // LOG(ERROR) << " " << base::HexEncode(binary_form, len);
-  EXPECT_EQ(memcmp(binary_form, &attr, len), 0);
-}
diff --git a/btcore/AndroidTest.xml b/btcore/AndroidTest.xml
deleted file mode 100644
index 27cd569..0000000
--- a/btcore/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2017 The Android Open Source Project
-
-     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.
--->
-<configuration description="Config for net_test_btcore">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="net_test_btcore->/data/local/tmp/net_test_btcore" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="net_test_btcore" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/btcore/include/module.h b/btcore/include/module.h
index 949d147..ca1d8b4 100644
--- a/btcore/include/module.h
+++ b/btcore/include/module.h
@@ -20,6 +20,7 @@
 
 #include <stdbool.h>
 
+#include "common/message_loop_thread.h"
 #include "osi/include/future.h"
 #include "osi/include/thread.h"
 
@@ -63,6 +64,6 @@
 // has finished, |callback| is called within the context of |callback_thread|
 // with |FUTURE_SUCCESS| or |FUTURE_FAIL| depending on whether startup succeeded
 // or not.
-void module_start_up_callbacked_wrapper(const module_t* module,
-                                        thread_t* callback_thread,
-                                        thread_fn callback);
+void module_start_up_callbacked_wrapper(
+    const module_t* module,
+    bluetooth::common::MessageLoopThread* callback_thread, thread_fn callback);
diff --git a/btcore/src/module.cc b/btcore/src/module.cc
index 88d4f80..d226006 100644
--- a/btcore/src/module.cc
+++ b/btcore/src/module.cc
@@ -26,10 +26,13 @@
 #include <unordered_map>
 
 #include "btcore/include/module.h"
+#include "common/message_loop_thread.h"
 #include "osi/include/allocator.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
+using bluetooth::common::MessageLoopThread;
+
 typedef enum {
   MODULE_STATE_NONE = 0,
   MODULE_STATE_INITIALIZED = 1,
@@ -159,55 +162,45 @@
 
 // TODO(zachoverflow): remove when everything modulized
 // Temporary callback-wrapper-related code
-
-typedef struct {
+class CallbackWrapper {
+ public:
+  explicit CallbackWrapper(const module_t* module,
+                           MessageLoopThread* callback_thread,
+                           thread_fn callback)
+      : module(module),
+        lifecycle_thread("bt_module_lifecycle_thread"),
+        callback_thread(callback_thread),
+        callback(callback),
+        success(false) {}
   const module_t* module;
-  thread_t* lifecycle_thread;
-  thread_t* callback_thread;  // we don't own this thread
+  MessageLoopThread lifecycle_thread;
+  // we don't own this thread
+  MessageLoopThread* callback_thread;
   thread_fn callback;
   bool success;
-} callbacked_wrapper_t;
+};
 
-static void run_wrapped_start_up(void* context);
-static void post_result_to_callback(void* context);
+static void post_result_to_callback(std::shared_ptr<CallbackWrapper> wrapper) {
+  CHECK(wrapper);
+  wrapper->lifecycle_thread.ShutDown();
+  wrapper->callback(wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL);
+}
+
+static void run_wrapped_start_up(std::shared_ptr<CallbackWrapper> wrapper) {
+  CHECK(wrapper);
+  wrapper->success = module_start_up(wrapper->module);
+  // Post the result back to the callback
+  wrapper->callback_thread->DoInThread(
+      FROM_HERE, base::BindOnce(post_result_to_callback, wrapper));
+}
 
 void module_start_up_callbacked_wrapper(const module_t* module,
-                                        thread_t* callback_thread,
+                                        MessageLoopThread* callback_thread,
                                         thread_fn callback) {
-  callbacked_wrapper_t* wrapper =
-      (callbacked_wrapper_t*)osi_calloc(sizeof(callbacked_wrapper_t));
-
-  wrapper->module = module;
-  wrapper->lifecycle_thread = thread_new("module_wrapper");
-  wrapper->callback_thread = callback_thread;
-  wrapper->callback = callback;
-
+  std::shared_ptr<CallbackWrapper> wrapper =
+      std::make_shared<CallbackWrapper>(module, callback_thread, callback);
+  wrapper->lifecycle_thread.StartUp();
   // Run the actual module start up
-  thread_post(wrapper->lifecycle_thread, run_wrapped_start_up, wrapper);
-}
-
-static void run_wrapped_start_up(void* context) {
-  CHECK(context);
-
-  callbacked_wrapper_t* wrapper = (callbacked_wrapper_t*)context;
-  wrapper->success = module_start_up(wrapper->module);
-
-  // Post the result back to the callback
-  thread_post(wrapper->callback_thread, post_result_to_callback, wrapper);
-}
-
-static void post_result_to_callback(void* context) {
-  CHECK(context);
-
-  callbacked_wrapper_t* wrapper = (callbacked_wrapper_t*)context;
-
-  // Save the values we need for callback
-  void* result = wrapper->success ? FUTURE_SUCCESS : FUTURE_FAIL;
-  thread_fn callback = wrapper->callback;
-
-  // Clean up the resources we used
-  thread_free(wrapper->lifecycle_thread);
-  osi_free(wrapper);
-
-  callback(result);
+  wrapper->lifecycle_thread.DoInThread(
+      FROM_HERE, base::BindOnce(run_wrapped_start_up, wrapper));
 }
diff --git a/btif/Android.bp b/btif/Android.bp
index dadd76a..f33d174 100644
--- a/btif/Android.bp
+++ b/btif/Android.bp
@@ -41,7 +41,6 @@
         "co/bta_dm_co.cc",
         "co/bta_av_co.cc",
         "co/bta_hh_co.cc",
-        "co/bta_hl_co.cc",
         "co/bta_pan_co.cc",
         "co/bta_gatts_co.cc",
         // HAL layer
@@ -56,6 +55,7 @@
         "src/btif_avrcp_audio_track.cc",
         "src/btif_ble_advertiser.cc",
         "src/btif_ble_scanner.cc",
+        "src/btif_bqr.cc",
         "src/btif_config.cc",
         "src/btif_config_transcode.cc",
         "src/btif_core.cc",
@@ -73,7 +73,6 @@
         "src/btif_hf_client.cc",
         "src/btif_hh.cc",
         "src/btif_hd.cc",
-        "src/btif_hl.cc",
         "src/btif_keystore.cc",
         "src/btif_mce.cc",
         "src/btif_pan.cc",
@@ -96,10 +95,12 @@
     shared_libs: [
         "libaudioclient",
         "libcutils",
+        "libfmq",
         "liblog",
         "libz",
         "libtinyxml2",
         "android.hardware.bluetooth.a2dp@1.0",
+        "android.hardware.bluetooth.audio@2.0",
         "libhidlbase",
         "libhidltransport",
         "libhwbinder",
@@ -116,8 +117,12 @@
         "avrcp-target-service",
         "libaudio-a2dp-hw-utils",
         "lib-bt-packets",
+        "libbt-audio-hal-interface",
     ],
-    cflags: ["-DBUILDCFG"],
+    cflags: [
+        "-DBUILDCFG",
+        "-Wno-implicit-fallthrough",
+    ],
 
 }
 
@@ -126,6 +131,7 @@
 cc_test {
     name: "net_test_btif",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     include_dirs: btifCommonIncludes,
     srcs: [
         "test/btif_storage_test.cc",
@@ -135,10 +141,14 @@
     shared_libs: [
         "libaudioclient",
         "android.hardware.bluetooth.a2dp@1.0",
+        "android.hardware.bluetooth.audio@2.0",
+        "libfmq",
         "libhidlbase",
+        "libhidltransport",
         "liblog",
         "libprotobuf-cpp-lite",
         "libcutils",
+        "libprocessgroup",
         "libutils",
         "libcrypto",
         "android.hardware.keymaster@4.0",
@@ -148,12 +158,13 @@
         "libkeystore_binder",
         "libkeystore_parcelables",
         "libbinder",
-        "libstatslog",
     ],
     static_libs: [
         "libbt-bta",
         "libbtcore",
+        "libbt-common",
         "libbt-stack",
+        "libbt-sbc-decoder",
         "libbt-sbc-encoder",
         "libbt-utils",
         "libFraunhoferAAC",
@@ -180,6 +191,7 @@
 cc_test {
     name: "net_test_btif_profile_queue",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     include_dirs: btifCommonIncludes,
     srcs: [
       "src/btif_profile_queue.cc",
@@ -196,25 +208,3 @@
     ],
     cflags: ["-DBUILDCFG"],
 }
-
-// btif state machine unit tests for target
-// ========================================================
-cc_test {
-    name: "net_test_btif_state_machine",
-    defaults: ["fluoride_defaults"],
-    include_dirs: btifCommonIncludes,
-    host_supported: true,
-    srcs: [
-      "test/btif_state_machine_test.cc"
-    ],
-    header_libs: ["libbluetooth_headers"],
-    shared_libs: [
-        "liblog",
-        "libcutils",
-    ],
-    static_libs: [
-        "libbluetooth-types",
-        "libosi",
-    ],
-    cflags: ["-DBUILDCFG"],
-}
diff --git a/btif/BUILD.gn b/btif/BUILD.gn
index de50a97..5e78d7d 100644
--- a/btif/BUILD.gn
+++ b/btif/BUILD.gn
@@ -17,14 +17,18 @@
 static_library("btif") {
   sources = [
     "//audio_a2dp_hw/src/audio_a2dp_hw_utils.cc",
+    "//audio_hearing_aid_hw/src/audio_hearing_aid_hw_utils.cc",
     "src/btif_a2dp.cc",
+    "src/btif_a2dp_audio_interface_linux.cc",
     "src/btif_a2dp_control.cc",
     "src/btif_a2dp_sink.cc",
     "src/btif_a2dp_source.cc",
     "src/btif_av.cc",
+    "avrcp/avrcp_service.cc",
 
     #TODO(jpawlowski): heavily depends on Android,
     #   "src/btif_avrcp_audio_track.cc",
+    "src/btif_avrcp_audio_track_linux.cc",
     "src/btif_ble_advertiser.cc",
     "src/btif_ble_scanner.cc",
     "src/btif_config.cc",
@@ -44,7 +48,6 @@
     "src/btif_hf_client.cc",
     "src/btif_hh.cc",
     "src/btif_hd.cc",
-    "src/btif_hl.cc",
     "src/btif_mce.cc",
     "src/btif_pan.cc",
     "src/btif_profile_queue.cc",
@@ -66,11 +69,9 @@
 
   # BTIF callouts
   sources += [
-    "co/bta_ag_co.cc",
     "co/bta_dm_co.cc",
     "co/bta_av_co.cc",
     "co/bta_hh_co.cc",
-    "co/bta_hl_co.cc",
     "co/bta_pan_co.cc",
     "co/bta_gatts_co.cc",
   ]
@@ -78,7 +79,9 @@
   include_dirs = [
     "include",
     "//",
+    "//linux_include",
     "//audio_a2dp_hw/include",
+    "//audio_hearing_aid_hw/include",
     "//bta/include",
     "//bta/sys",
     "//btcore/include",
@@ -88,15 +91,19 @@
     "//hci/include",
     "//stack/a2dp",
     "//stack/btm",
+    "//stack/l2cap",
     "//stack/include",
     "//third_party/tinyxml2",
     "//internal_include",
     "//udrv/include",
     "//utils/include",
     "//vnd/include",
+    "//profile/avrcp",
   ]
 
   deps = [
-    "//third_party/libchrome:base"
+    "//common",
+    "//third_party/libchrome:base",
+    "//profile/avrcp:profile_avrcp"
   ]
 }
diff --git a/btif/avrcp/avrcp_service.cc b/btif/avrcp/avrcp_service.cc
index 5a058f4..1308461 100644
--- a/btif/avrcp/avrcp_service.cc
+++ b/btif/avrcp/avrcp_service.cc
@@ -23,10 +23,10 @@
 #include <mutex>
 #include <sstream>
 
-#include "bta_closure_api.h"
 #include "btif_av.h"
 #include "btif_common.h"
 #include "device.h"
+#include "stack/include/btu.h"
 
 namespace bluetooth {
 namespace avrcp {
@@ -52,6 +52,10 @@
 
 class A2dpInterfaceImpl : public A2dpInterface {
   RawAddress active_peer() override { return btif_av_source_active_peer(); }
+
+  bool is_peer_in_silence_mode(const RawAddress& peer_address) override {
+    return btif_av_is_peer_silenced(peer_address);
+  }
 } a2dp_interface_;
 
 class AvrcpInterfaceImpl : public AvrcpInterface {
@@ -141,7 +145,7 @@
 
   void GetSongInfo(SongInfoCallback info_cb) override {
     auto cb_lambda = [](SongInfoCallback cb, SongInfo data) {
-      do_in_bta_thread(FROM_HERE, base::Bind(cb, data));
+      do_in_main_thread(FROM_HERE, base::Bind(cb, data));
     };
 
     auto bound_cb = base::Bind(cb_lambda, info_cb);
@@ -152,7 +156,7 @@
 
   void GetPlayStatus(PlayStatusCallback status_cb) override {
     auto cb_lambda = [](PlayStatusCallback cb, PlayStatus status) {
-      do_in_bta_thread(FROM_HERE, base::Bind(cb, status));
+      do_in_main_thread(FROM_HERE, base::Bind(cb, status));
     };
 
     auto bound_cb = base::Bind(cb_lambda, status_cb);
@@ -164,8 +168,8 @@
   void GetNowPlayingList(NowPlayingCallback now_playing_cb) override {
     auto cb_lambda = [](NowPlayingCallback cb, std::string curr_media_id,
                         std::vector<SongInfo> song_list) {
-      do_in_bta_thread(FROM_HERE,
-                       base::Bind(cb, curr_media_id, std::move(song_list)));
+      do_in_main_thread(FROM_HERE,
+                        base::Bind(cb, curr_media_id, std::move(song_list)));
     };
 
     auto bound_cb = base::Bind(cb_lambda, now_playing_cb);
@@ -177,8 +181,8 @@
   void GetMediaPlayerList(MediaListCallback list_cb) override {
     auto cb_lambda = [](MediaListCallback cb, uint16_t curr_player,
                         std::vector<MediaPlayerInfo> player_list) {
-      do_in_bta_thread(FROM_HERE,
-                       base::Bind(cb, curr_player, std::move(player_list)));
+      do_in_main_thread(FROM_HERE,
+                        base::Bind(cb, curr_player, std::move(player_list)));
     };
 
     auto bound_cb = base::Bind(cb_lambda, list_cb);
@@ -191,7 +195,7 @@
                       FolderItemsCallback folder_cb) override {
     auto cb_lambda = [](FolderItemsCallback cb,
                         std::vector<ListItem> item_list) {
-      do_in_bta_thread(FROM_HERE, base::Bind(cb, std::move(item_list)));
+      do_in_main_thread(FROM_HERE, base::Bind(cb, std::move(item_list)));
     };
 
     auto bound_cb = base::Bind(cb_lambda, folder_cb);
@@ -205,7 +209,7 @@
                         SetBrowsedPlayerCallback browse_cb) override {
     auto cb_lambda = [](SetBrowsedPlayerCallback cb, bool success,
                         std::string root_id, uint32_t num_items) {
-      do_in_bta_thread(FROM_HERE, base::Bind(cb, success, root_id, num_items));
+      do_in_main_thread(FROM_HERE, base::Bind(cb, success, root_id, num_items));
     };
 
     auto bound_cb = base::Bind(cb_lambda, browse_cb);
@@ -254,7 +258,7 @@
 
   void DeviceConnected(const RawAddress& bdaddr, VolumeChangedCb cb) override {
     auto cb_lambda = [](VolumeChangedCb cb, int8_t volume) {
-      do_in_bta_thread(FROM_HERE, base::Bind(cb, volume));
+      do_in_main_thread(FROM_HERE, base::Bind(cb, volume));
     };
 
     auto bound_cb = base::Bind(cb_lambda, cb);
@@ -348,9 +352,8 @@
   // device update happens on the main thread.
   for (const auto& device :
        instance_->connection_handler_->GetListOfDevices()) {
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&Device::SendMediaUpdate, device.get()->Get(),
-                                track_changed, play_state, queue));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&Device::SendMediaUpdate, device.get()->Get(), track_changed, play_state, queue));
   }
 }
 
@@ -364,9 +367,8 @@
   // Ensure that the update is posted to the correct thread
   for (const auto& device :
        instance_->connection_handler_->GetListOfDevices()) {
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&Device::SendFolderUpdate, device.get()->Get(),
-                                available_players, addressed_players, uids));
+    do_in_main_thread(FROM_HERE, base::Bind(&Device::SendFolderUpdate, device.get()->Get(), available_players,
+                                            addressed_players, uids));
   }
 }
 
@@ -401,17 +403,17 @@
     jni_message_loop_ = get_jni_message_loop();
   }
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&AvrcpService::Init, base::Unretained(instance_),
-                              media_interface, volume_interface));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&AvrcpService::Init, base::Unretained(instance_),
+                               media_interface, volume_interface));
 }
 
 bool AvrcpService::ServiceInterfaceImpl::ConnectDevice(
     const RawAddress& bdaddr) {
   std::lock_guard<std::mutex> lock(service_interface_lock_);
   CHECK(instance_ != nullptr);
-  do_in_bta_thread(FROM_HERE, base::Bind(&AvrcpService::ConnectDevice,
-                                         base::Unretained(instance_), bdaddr));
+  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::ConnectDevice,
+                                          base::Unretained(instance_), bdaddr));
   return true;
 }
 
@@ -419,8 +421,8 @@
     const RawAddress& bdaddr) {
   std::lock_guard<std::mutex> lock(service_interface_lock_);
   CHECK(instance_ != nullptr);
-  do_in_bta_thread(FROM_HERE, base::Bind(&AvrcpService::DisconnectDevice,
-                                         base::Unretained(instance_), bdaddr));
+  do_in_main_thread(FROM_HERE, base::Bind(&AvrcpService::DisconnectDevice,
+                                          base::Unretained(instance_), bdaddr));
   return true;
 }
 
@@ -435,8 +437,8 @@
     jni_message_loop_ = nullptr;
   }
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&AvrcpService::Cleanup, base::Owned(instance_)));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&AvrcpService::Cleanup, base::Owned(instance_)));
 
   // Setting instance to nullptr here is fine since it will be deleted on the
   // other thread.
@@ -456,11 +458,15 @@
           device_list.size());
 
   std::stringstream stream;
-  for (auto device : device_list) {
-    stream << *device << std::endl;
+  {
+    ScopedIndent indent(stream);
+    for (const auto& device : device_list) {
+      stream << *device << std::endl;
+    }
   }
+
   dprintf(fd, "%s", stream.str().c_str());
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/btif/avrcp/avrcp_service.h b/btif/avrcp/avrcp_service.h
index d26b200..e19899d 100644
--- a/btif/avrcp/avrcp_service.h
+++ b/btif/avrcp/avrcp_service.h
@@ -19,9 +19,9 @@
 #include <map>
 #include <memory>
 
-#include "avrcp.h"
-#include "connection_handler.h"
+#include "hardware/avrcp/avrcp.h"
 #include "osi/include/properties.h"
+#include "profile/avrcp/connection_handler.h"
 #include "raw_address.h"
 
 namespace bluetooth {
diff --git a/btif/co/bta_av_co.cc b/btif/co/bta_av_co.cc
index 6147744..9f17d4a 100644
--- a/btif/co/bta_av_co.cc
+++ b/btif/co/bta_av_co.cc
@@ -179,6 +179,14 @@
   void Init(const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
 
   /**
+   * Checks whether a codec is supported.
+   *
+   * @param codec_index the index of the codec to check
+   * @return true if the codec is supported, otherwise false
+   */
+  bool IsSupportedCodec(btav_a2dp_codec_index_t codec_index);
+
+  /**
    * Get the current codec configuration for the active peer.
    *
    * @return the current codec configuration if found, otherwise nullptr
@@ -769,6 +777,14 @@
   }
 }
 
+bool BtaAvCo::IsSupportedCodec(btav_a2dp_codec_index_t codec_index) {
+  // All peer state is initialized with the same local codec config,
+  // hence we check only the first peer.
+  A2dpCodecs* codecs = peers_[0].GetCodecs();
+  CHECK(codecs != nullptr);
+  return codecs->isSupportedCodec(codec_index);
+}
+
 A2dpCodecConfig* BtaAvCo::GetActivePeerCurrentCodec() {
   std::lock_guard<std::recursive_mutex> lock(codec_lock_);
 
@@ -1626,16 +1642,32 @@
   // Nothing to do (for now)
   return true;
 }
+
 void BtaAvCo::DebugDump(int fd) {
   std::lock_guard<std::recursive_mutex> lock(codec_lock_);
 
-  dprintf(fd, "\nA2DP Codecs and Peers State:\n");
+  //
+  // Active peer codec-specific stats
+  //
+  if (active_peer_ != nullptr) {
+    A2dpCodecs* a2dp_codecs = active_peer_->GetCodecs();
+    if (a2dp_codecs != nullptr) {
+      a2dp_codecs->debug_codec_dump(fd);
+    }
+  }
+
+  if (appl_trace_level < BT_TRACE_LEVEL_DEBUG) return;
+
+  dprintf(fd, "\nA2DP Peers State:\n");
   dprintf(fd, "  Active peer: %s\n",
           (active_peer_ != nullptr) ? active_peer_->addr.ToString().c_str()
                                     : "null");
 
   for (size_t i = 0; i < BTA_AV_CO_NUM_ELEMENTS(peers_); i++) {
     const BtaAvCoPeer& peer = peers_[i];
+    if (peer.addr.IsEmpty()) {
+      continue;
+    }
     dprintf(fd, "  Peer: %s\n", peer.addr.ToString().c_str());
     dprintf(fd, "    Number of sinks: %u\n", peer.num_sinks);
     dprintf(fd, "    Number of sources: %u\n", peer.num_sources);
@@ -1652,16 +1684,6 @@
     dprintf(fd, "    UUID to connect: 0x%x\n", peer.uuid_to_connect);
     dprintf(fd, "    BTA AV handle: %u\n", peer.BtaAvHandle());
   }
-
-  //
-  // Active peer codec-specific stats
-  //
-  if (active_peer_ != nullptr) {
-    A2dpCodecs* a2dp_codecs = active_peer_->GetCodecs();
-    if (a2dp_codecs != nullptr) {
-      a2dp_codecs->debug_codec_dump(fd);
-    }
-  }
 }
 
 bool BtaAvCo::ContentProtectIsScmst(const uint8_t* p_protect_info) {
@@ -2020,6 +2042,10 @@
   bta_av_co_cb.Init(codec_priorities);
 }
 
+bool bta_av_co_is_supported_codec(btav_a2dp_codec_index_t codec_index) {
+  return bta_av_co_cb.IsSupportedCodec(codec_index);
+}
+
 A2dpCodecConfig* bta_av_get_a2dp_current_codec(void) {
   return bta_av_co_cb.GetActivePeerCurrentCodec();
 }
diff --git a/btif/co/bta_dm_co.cc b/btif/co/bta_dm_co.cc
index dfd512b..200ce55 100644
--- a/btif/co/bta_dm_co.cc
+++ b/btif/co/bta_dm_co.cc
@@ -25,12 +25,17 @@
 #include "bta_sys.h"
 #include "bte_appl.h"
 #include "btif_dm.h"
+#include "btif_storage.h"
 #include "osi/include/osi.h"
 
+// tBTE_APPL_CFG.ble_io_cap is set to BTM_IO_CAP_UNKNOWN at structure
+// initialization since btif_storage isn't ready yet for data to be fetched.
+// This value is initialized properly during first use by fetching properly
+// from btif_storage.
 tBTE_APPL_CFG bte_appl_cfg = {
     BTA_LE_AUTH_REQ_SC_MITM_BOND,  // Authentication requirements
-    BTM_LOCAL_IO_CAPS_BLE, BTM_BLE_INITIATOR_KEY_SIZE,
-    BTM_BLE_RESPONDER_KEY_SIZE, BTM_BLE_MAX_KEY_SIZE};
+    BTM_IO_CAP_UNKNOWN, BTM_BLE_INITIATOR_KEY_SIZE, BTM_BLE_RESPONDER_KEY_SIZE,
+    BTM_BLE_MAX_KEY_SIZE};
 
 /*******************************************************************************
  *
@@ -132,7 +137,7 @@
  * Returns          void.
  *
  ******************************************************************************/
-void bta_dm_co_loc_oob(bool valid, BT_OCTET16 c, BT_OCTET16 r) {
+void bta_dm_co_loc_oob(bool valid, const Octet16& c, const Octet16& r) {
   BTIF_TRACE_DEBUG("bta_dm_co_loc_oob, valid = %d", valid);
 #ifdef BTIF_DM_OOB_TEST
   btif_dm_proc_loc_oob(valid, c, r);
@@ -153,16 +158,16 @@
  *
  ******************************************************************************/
 void bta_dm_co_rmt_oob(const RawAddress& bd_addr) {
-  BT_OCTET16 p_c;
-  BT_OCTET16 p_r;
+  Octet16 c;
+  Octet16 r;
   bool result = false;
 
 #ifdef BTIF_DM_OOB_TEST
-  result = btif_dm_proc_rmt_oob(bd_addr, p_c, p_r);
+  result = btif_dm_proc_rmt_oob(bd_addr, &c, &r);
 #endif
 
   BTIF_TRACE_DEBUG("bta_dm_co_rmt_oob: result=%d", result);
-  bta_dm_ci_rmt_oob(result, bd_addr, p_c, p_r);
+  bta_dm_ci_rmt_oob(result, bd_addr, c, r);
 }
 
 /*******************************************************************************
@@ -207,13 +212,13 @@
  *
  ******************************************************************************/
 void bta_dm_co_ble_load_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask,
-                                   BT_OCTET16 er,
+                                   Octet16* p_er,
                                    tBTA_BLE_LOCAL_ID_KEYS* p_id_keys) {
   BTIF_TRACE_DEBUG("##################################");
   BTIF_TRACE_DEBUG(
       "bta_dm_co_ble_load_local_keys:  Load local keys if any are persisted");
   BTIF_TRACE_DEBUG("##################################");
-  btif_dm_get_ble_local_keys(p_key_mask, er, p_id_keys);
+  btif_dm_get_ble_local_keys(p_key_mask, p_er, p_id_keys);
 }
 
 /*******************************************************************************
@@ -241,6 +246,8 @@
                           tBTA_LE_AUTH_REQ* p_auth_req, uint8_t* p_max_key_size,
                           tBTA_LE_KEY_TYPE* p_init_key,
                           tBTA_LE_KEY_TYPE* p_resp_key) {
+  bte_appl_cfg.ble_io_cap = btif_storage_get_local_io_caps_ble();
+
   /* Retrieve the properties from file system if possible */
   tBTE_APPL_CFG nv_config;
   if (btif_dm_get_smp_config(&nv_config)) bte_appl_cfg = nv_config;
diff --git a/btif/co/bta_hh_co.cc b/btif/co/bta_hh_co.cc
index 2f507f9..5a7cad8 100644
--- a/btif/co/bta_hh_co.cc
+++ b/btif/co/bta_hh_co.cc
@@ -42,6 +42,9 @@
 #define BTA_HH_NV_LOAD_MAX 16
 static tBTA_HH_RPT_CACHE_ENTRY sReportCache[BTA_HH_NV_LOAD_MAX];
 #endif
+#define GET_RPT_RSP_OFFSET 9
+#define THREAD_NORMAL_PRIORITY 0
+#define BT_HH_THREAD "bt_hh_thread"
 
 void uhid_set_non_blocking(int fd) {
   int opts = fcntl(fd, F_GETFL);
@@ -128,8 +131,8 @@
         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);
+        APPL_TRACE_ERROR("%s: UHID_OUTPUT: Invalid report type = %d", __func__,
+                         ev.u.output.rtype);
       break;
     case UHID_OUTPUT_EV:
       if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.output_ev))) {
@@ -141,10 +144,24 @@
       APPL_TRACE_DEBUG("UHID_OUTPUT_EV from uhid-dev\n");
       break;
     case UHID_FEATURE:
-      APPL_TRACE_DEBUG("UHID_FEATURE from uhid-dev\n");
-      break;
-    case UHID_FEATURE_ANSWER:
-      APPL_TRACE_DEBUG("UHID_FEATURE_ANSWER from uhid-dev\n");
+      if (ret < (ssize_t)(sizeof(ev.type) + sizeof(ev.u.feature))) {
+        APPL_TRACE_ERROR(
+            "%s: UHID_FEATURE: Invalid size read from uhid-dev: %zd < %zu",
+            __func__, ret, sizeof(ev.type) + sizeof(ev.u.feature));
+        return -EFAULT;
+      }
+      APPL_TRACE_DEBUG("UHID_FEATURE: Report type = %d", ev.u.feature.rtype);
+      p_dev->get_rpt_snt++;
+      if (p_dev->get_rpt_id_queue) {
+        uint32_t* get_rpt_id = (uint32_t*)osi_malloc(sizeof(uint32_t));
+        *get_rpt_id = ev.u.feature.id;
+        fixed_queue_enqueue(p_dev->get_rpt_id_queue, (void*)get_rpt_id);
+      }
+      if (ev.u.feature.rtype == UHID_FEATURE_REPORT)
+        btif_hh_getreport(p_dev, BTHH_FEATURE_REPORT, ev.u.feature.rnum, 0);
+      else
+        APPL_TRACE_ERROR("%s: UHID_FEATURE: Invalid report type = %d", __func__,
+                         ev.u.feature.rtype);
       break;
 
     default:
@@ -193,6 +210,17 @@
   APPL_TRACE_DEBUG("%s: Thread created fd = %d", __func__, p_dev->fd);
   struct pollfd pfds[1];
 
+  // This thread is created by bt_main_thread with RT priority. Lower the thread
+  // priority here since the tasks in this thread is not timing critical.
+  struct sched_param sched_params;
+  sched_params.sched_priority = THREAD_NORMAL_PRIORITY;
+  if (sched_setscheduler(gettid(), SCHED_OTHER, &sched_params)) {
+    APPL_TRACE_ERROR("%s: Failed to set thread priority to normal", __func__);
+    p_dev->hh_poll_thread_id = -1;
+    return 0;
+  }
+  pthread_setname_np(pthread_self(), BT_HH_THREAD);
+
   pfds[0].fd = p_dev->fd;
   pfds[0].events = POLLIN;
 
@@ -278,16 +306,10 @@
         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",
-          __func__, p_dev->dev_status);
-      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",
-          __func__, p_dev->attr_mask, p_dev->sub_class, p_dev->app_id);
+          "%s: Found an existing device with the same handle dev_status=%d, "
+          "address=%s, attr_mask=0x%04x, sub_class=0x%02x, app_id=%d",
+          __func__, p_dev->dev_status, p_dev->bd_addr.ToString().c_str(),
+          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);
@@ -343,6 +365,9 @@
   }
 
   p_dev->dev_status = BTHH_CONN_STATE_CONNECTED;
+  p_dev->get_rpt_id_queue = fixed_queue_new(SIZE_MAX);
+  CHECK(p_dev->get_rpt_id_queue);
+
   APPL_TRACE_DEBUG("%s: Return device status %d", __func__, p_dev->dev_status);
 }
 
@@ -372,6 +397,9 @@
 
   for (i = 0; i < BTIF_HH_MAX_HID; i++) {
     p_dev = &btif_hh_cb.devices[i];
+    fixed_queue_flush(p_dev->get_rpt_id_queue, osi_free);
+    fixed_queue_free(p_dev->get_rpt_id_queue, NULL);
+    p_dev->get_rpt_id_queue = NULL;
     if (p_dev->dev_status != BTHH_CONN_STATE_UNKNOWN &&
         p_dev->dev_handle == dev_handle) {
       APPL_TRACE_WARNING(
@@ -499,6 +527,71 @@
   }
 }
 
+/*******************************************************************************
+ *
+ * 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_t dev_handle, uint8_t status) {
+  APPL_TRACE_ERROR("%s: Error: UHID_SET_REPORT_REPLY not supported", __func__);
+}
+
+/*******************************************************************************
+ *
+ * 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_t dev_handle, uint8_t status, uint8_t* p_rpt,
+                           uint16_t 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;
+  }
+
+  if (!p_dev->get_rpt_id_queue) {
+    APPL_TRACE_WARNING("%s: Error: missing UHID_GET_REPORT id queue", __func__);
+    return;
+  }
+
+  // Send the HID report to the kernel.
+  if (p_dev->fd >= 0 && p_dev->get_rpt_snt--) {
+    uint32_t* get_rpt_id =
+        (uint32_t*)fixed_queue_dequeue(p_dev->get_rpt_id_queue);
+    memset(&ev, 0, sizeof(ev));
+    ev.type = UHID_FEATURE_ANSWER;
+    ev.u.feature_answer.id = *get_rpt_id;
+    ev.u.feature_answer.err = status;
+    ev.u.feature_answer.size = len;
+    osi_free(get_rpt_id);
+    if (len > 0) {
+      if (len > UHID_DATA_MAX) {
+        APPL_TRACE_WARNING("%s: Report size greater than allowed size",
+                           __func__);
+        return;
+      }
+      memcpy(ev.u.feature_answer.data, p_rpt + GET_RPT_RSP_OFFSET, len);
+      uhid_write(p_dev->fd, &ev);
+    }
+  }
+}
+
 #if (BTA_HH_LE_INCLUDED == TRUE)
 /*******************************************************************************
  *
diff --git a/btif/co/bta_hl_co.cc b/btif/co/bta_hl_co.cc
deleted file mode 100644
index c818351..0000000
--- a/btif/co/bta_hl_co.cc
+++ /dev/null
@@ -1,415 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the HeaLth device profile (HL)
- *  subsystem call-out functions.
- *
- ******************************************************************************/
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/un.h>
-#include <time.h>
-
-#include "bta_api.h"
-#include "bta_hl_api.h"
-#include "bta_hl_ci.h"
-#include "bta_hl_co.h"
-#include "bta_sys.h"
-#include "btif_hl.h"
-#include "btif_util.h"
-#include "btm_api.h"
-#include "osi/include/osi.h"
-
-/*****************************************************************************
- *  Constants and Data Types
- ****************************************************************************/
-/**************************
- *  Common Definitions
- **************************/
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_get_num_of_mdep
- *
- * Description     This function is called to get the number of MDEPs for this
- *                 application ID
- *
- * Parameters      app_id - application ID
- *                 p_num_of_mdep (output) - number of MDEP configurations
- *                                          supported by the application
- *
- * Returns         true on success
- *
- ******************************************************************************/
-bool bta_hl_co_get_num_of_mdep(uint8_t app_id, uint8_t* p_num_of_mdep) {
-  uint8_t app_idx;
-  bool success = false;
-
-  if (btif_hl_find_app_idx(app_id, &app_idx)) {
-    *p_num_of_mdep = p_btif_hl_cb->acb[app_idx].sup_feature.num_of_mdeps;
-    success = true;
-  }
-
-  BTIF_TRACE_DEBUG("%s success=%d num_mdeps=%d", __func__, success,
-                   *p_num_of_mdep);
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_advrtise_source_sdp
- *
- * Description     This function is called to find out whether the SOURCE MDEP
- *                 configuration information should be advertise in the SDP or
- *                 not.
- *
- * Parameters      app_id - application ID
- *
- * Returns         true when advertise the SOURCE MDEP configuration
- *                            information
- *
- ******************************************************************************/
-bool bta_hl_co_advrtise_source_sdp(uint8_t app_id) {
-  bool advertize_source_sdp = false;
-  uint8_t app_idx;
-
-  if (btif_hl_find_app_idx(app_id, &app_idx)) {
-    advertize_source_sdp =
-        p_btif_hl_cb->acb[app_idx].sup_feature.advertize_source_sdp;
-  }
-
-  BTIF_TRACE_DEBUG("%s advertize_flag=%d", __func__, advertize_source_sdp);
-
-  return advertize_source_sdp;
-}
-/*******************************************************************************
- *
- * Function        bta_hl_co_get_mdep_config
- *
- * Description     This function is called to get the supported feature
- *                 configuration for the specified mdep index and it also
- *                 assigns the MDEP ID for the specified mdep index
- *
- * Parameters      app_id - HDP application ID
- *                 mdep_idx - the mdep index
- *                  mdep_counter - number of mdeps
- *                 mdep_id  - the assigned MDEP ID for the specified medp_idx
- *                 p_mdl_cfg (output) - pointer to the MDEP configuration
- *
- *
- * Returns         Bloolean - true success
- ******************************************************************************/
-bool bta_hl_co_get_mdep_config(uint8_t app_id, uint8_t mdep_idx,
-                               uint8_t mdep_counter, tBTA_HL_MDEP_ID mdep_id,
-                               tBTA_HL_MDEP_CFG* p_mdep_cfg) {
-  uint8_t idx;
-  uint8_t app_idx;
-  bool success = false;
-
-  BTIF_TRACE_DEBUG("%s app_id=%d mdep_idx=%d mdep_id=%d mdep_counter=%d",
-                   __func__, app_id, mdep_idx, mdep_id, mdep_counter);
-
-  if (btif_hl_find_app_idx(app_id, &app_idx)) {
-    idx = mdep_idx - mdep_counter - 1;
-    p_btif_hl_cb->acb[app_idx].sup_feature.mdep[idx].mdep_id = mdep_id;
-    memcpy(p_mdep_cfg,
-           &p_btif_hl_cb->acb[app_idx].sup_feature.mdep[idx].mdep_cfg,
-           sizeof(tBTA_HL_MDEP_CFG));
-
-    success = true;
-  }
-
-  BTIF_TRACE_DEBUG("%s success=%d mdep_idx=%d mdep_id=%d", __func__, success,
-                   mdep_idx, mdep_id);
-
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_get_echo_config
- *
- * Description     This function is called to get the echo test
- *                 maximum APDU size configurations
- *
- * Parameters      app_id - HDP application ID
- *                 p_echo_cfg (output) - pointer to the Echo test maximum APDU
- *                                       size configuration
- *
- * Returns         Bloolean - true success
- ******************************************************************************/
-bool bta_hl_co_get_echo_config(uint8_t app_id, tBTA_HL_ECHO_CFG* p_echo_cfg) {
-  uint8_t app_idx;
-  bool success = false;
-  btif_hl_app_cb_t* p_acb;
-  tBTA_HL_SUP_FEATURE* p_sup;
-
-  BTIF_TRACE_DEBUG("%s app_id=%d", __func__, app_id);
-
-  if (btif_hl_find_app_idx(app_id, &app_idx)) {
-    p_acb = BTIF_HL_GET_APP_CB_PTR(app_idx);
-    p_sup = &p_acb->sup_feature;
-    p_echo_cfg->max_rx_apdu_size = p_sup->echo_cfg.max_rx_apdu_size;
-    p_echo_cfg->max_tx_apdu_size = p_sup->echo_cfg.max_tx_apdu_size;
-    success = true;
-  }
-
-  BTIF_TRACE_DEBUG("%s success=%d max tx_size=%d rx_size=%d", __func__, success,
-                   p_echo_cfg->max_tx_apdu_size, p_echo_cfg->max_rx_apdu_size);
-
-  return success;
-}
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_save_mdl
- *
- * Description     This function is called to save a MDL configuration item in
- *                 persistent storage
- *
- * Parameters      app_id - HDP application ID
- *                 item_idx - the MDL configuration storage index
- *                 p_mdl_cfg - pointer to the MDL configuration data
- *
- * Returns        void
- *
- ******************************************************************************/
-void bta_hl_co_save_mdl(uint8_t mdep_id, uint8_t item_idx,
-                        tBTA_HL_MDL_CFG* p_mdl_cfg) {
-  BTIF_TRACE_DEBUG("%s mdep_id =%d, item_idx=%d active=%d mdl_id=%d time=%d",
-                   __func__, mdep_id, item_idx, p_mdl_cfg->active,
-                   p_mdl_cfg->mdl_id, p_mdl_cfg->time);
-
-  btif_hl_save_mdl_cfg(mdep_id, item_idx, p_mdl_cfg);
-}
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_delete_mdl
- *
- * Description     This function is called to delete a MDL configuration item in
- *                 persistent storage
- *
- * Parameters      app_id - HDP application ID
- *                 item_idx - the MDL configuration storage index
- *
- * Returns          void
- *
- ******************************************************************************/
-void bta_hl_co_delete_mdl(uint8_t mdep_id, uint8_t item_idx) {
-  BTIF_TRACE_DEBUG("%s mdep_id=%d, item_idx=%d", __func__, mdep_id, item_idx);
-
-  btif_hl_delete_mdl_cfg(mdep_id, item_idx);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_co_get_mdl_config
- *
- * Description     This function is called to get the MDL configuration
- *                 from the persistent memory. This function shall only be
- *                 called once after the device is powered up
- *
- * Parameters      app_id - HDP application ID
- *                 buffer_size - the unit of the buffer size is
- *                               sizeof(tBTA_HL_MDL_CFG)
- *                 p_mdl_buf - Point to the starting location of the buffer
- *
- * Returns         bool
- *
- *
- ******************************************************************************/
-bool bta_hl_co_load_mdl_config(uint8_t app_id, uint8_t buffer_size,
-                               tBTA_HL_MDL_CFG* p_mdl_buf) {
-  bool result = true;
-  uint8_t i;
-  tBTA_HL_MDL_CFG* p;
-
-  BTIF_TRACE_DEBUG("%s app_id=%d, num_items=%d", __func__, app_id, buffer_size);
-
-  if (buffer_size > BTA_HL_NUM_MDL_CFGS) {
-    result = false;
-    return result;
-  }
-  result = btif_hl_load_mdl_config(app_id, buffer_size, p_mdl_buf);
-
-  if (result) {
-    for (i = 0, p = p_mdl_buf; i < buffer_size; i++, p++) {
-      if (p->active) {
-        BTIF_TRACE_DEBUG(
-            "i=%d mdl_id=0x%x dch_mode=%d local mdep_role=%d mdep_id=%d mtu=%d",
-            i, p->mdl_id, p->dch_mode, p->local_mdep_role, p->local_mdep_role,
-            p->mtu);
-      }
-    }
-  }
-
-  BTIF_TRACE_DEBUG("%s success=%d num_items=%d", __func__, result, buffer_size);
-
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_co_get_tx_data
- *
- * Description     Get the data to be sent
- *
- * Parameters      app_id - HDP application ID
- *                 mdl_handle - MDL handle
- *                 buf_size - the size of the buffer
- *                 p_buf - the buffer pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_get_tx_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-void bta_hl_co_get_tx_data(uint8_t app_id, tBTA_HL_MDL_HANDLE mdl_handle,
-                           uint16_t buf_size, uint8_t* p_buf, uint16_t evt) {
-  uint8_t app_idx, mcl_idx, mdl_idx;
-  btif_hl_mdl_cb_t* p_dcb;
-  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
-
-  BTIF_TRACE_DEBUG("%s app_id=%d mdl_handle=0x%x buf_size=%d", __func__, app_id,
-                   mdl_handle, buf_size);
-
-  if (btif_hl_find_mdl_idx_using_handle(mdl_handle, &app_idx, &mcl_idx,
-                                        &mdl_idx)) {
-    p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-    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);
-      p_dcb->tx_size = 0;
-      status = BTA_HL_STATUS_OK;
-    }
-  }
-
-  bta_hl_ci_get_tx_data(mdl_handle, status, evt);
-}
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_put_rx_data
- *
- * Description     Put the received data
- *
- * Parameters      app_id - HDP application ID
- *                 mdl_handle - MDL handle
- *                 data_size - the size of the data
- *                 p_data - the data pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_put_rx_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-void bta_hl_co_put_rx_data(uint8_t app_id, tBTA_HL_MDL_HANDLE mdl_handle,
-                           uint16_t data_size, uint8_t* p_data, uint16_t evt) {
-  uint8_t app_idx, mcl_idx, mdl_idx;
-  btif_hl_mdl_cb_t* p_dcb;
-  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
-  BTIF_TRACE_DEBUG("%s app_id=%d mdl_handle=0x%x data_size=%d", __func__,
-                   app_id, mdl_handle, data_size);
-
-  if (btif_hl_find_mdl_idx_using_handle(mdl_handle, &app_idx, &mcl_idx,
-                                        &mdl_idx)) {
-    p_dcb = BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx);
-
-    p_dcb->p_rx_pkt = (uint8_t*)osi_malloc(data_size);
-    memcpy(p_dcb->p_rx_pkt, p_data, data_size);
-    if (p_dcb->p_scb) {
-      BTIF_TRACE_DEBUG("app_idx=%d mcl_idx=0x%x mdl_idx=0x%x data_size=%d",
-                       app_idx, mcl_idx, mdl_idx, data_size);
-      ssize_t r;
-      OSI_NO_INTR(
-          r = send(p_dcb->p_scb->socket_id[1], p_dcb->p_rx_pkt, data_size, 0));
-      if (r == data_size) {
-        BTIF_TRACE_DEBUG("socket send success data_size=%d", data_size);
-        status = BTA_HL_STATUS_OK;
-      } else {
-        BTIF_TRACE_ERROR("socket send failed r=%d data_size=%d", r, data_size);
-      }
-    }
-    osi_free_and_reset((void**)&p_dcb->p_rx_pkt);
-  }
-
-  bta_hl_ci_put_rx_data(mdl_handle, status, evt);
-}
-
-/*******************************************************************************
- *
- * Function         bta_hl_co_get_tx_data
- *
- * Description     Get the Echo data to be sent
- *
- * Parameters      app_id - HDP application ID
- *                 mcl_handle - MCL handle
- *                 buf_size - the size of the buffer
- *                 p_buf - the buffer pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_get_tx_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-void bta_hl_co_get_echo_data(UNUSED_ATTR uint8_t app_id,
-                             tBTA_HL_MCL_HANDLE mcl_handle,
-                             UNUSED_ATTR uint16_t buf_size,
-                             UNUSED_ATTR uint8_t* p_buf, uint16_t evt) {
-  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
-
-  BTIF_TRACE_ERROR("%s not supported", __func__);
-  bta_hl_ci_get_echo_data(mcl_handle, status, evt);
-}
-
-/*******************************************************************************
- *
- * Function        bta_hl_co_put_echo_data
- *
- * Description     Put the received loopback echo data
- *
- * Parameters      app_id - HDP application ID
- *                 mcl_handle - MCL handle
- *                 data_size - the size of the data
- *                 p_data - the data pointer
- *                 evt - the evt to be passed back to the HL in the
- *                       bta_hl_ci_put_echo_data call-in function
- *
- * Returns        Void
- *
- ******************************************************************************/
-void bta_hl_co_put_echo_data(UNUSED_ATTR uint8_t app_id,
-                             tBTA_HL_MCL_HANDLE mcl_handle,
-                             UNUSED_ATTR uint16_t data_size,
-                             UNUSED_ATTR uint8_t* p_data, uint16_t evt) {
-  tBTA_HL_STATUS status = BTA_HL_STATUS_FAIL;
-
-  BTIF_TRACE_ERROR("%s not supported", __func__);
-  bta_hl_ci_put_echo_data(mcl_handle, status, evt);
-}
diff --git a/btif/include/btif_a2dp.h b/btif/include/btif_a2dp.h
index 7b7b2ca..49e4f9c 100644
--- a/btif/include/btif_a2dp.h
+++ b/btif/include/btif_a2dp.h
@@ -31,11 +31,8 @@
 // streaming.
 // |peer_addr| is the peer address.
 // |p_av_start| is the data associated with the request - see |tBTA_AV_START|.
-// |pending_start| should be set to true if the BTIF state machine is in
-// 'pending start' state.
 // Returns true if an ACK for the local command was sent, otherwise false.
-bool btif_a2dp_on_started(const RawAddress& peer_addr,
-                          tBTA_AV_START* p_av_start, bool pending_start);
+bool btif_a2dp_on_started(const RawAddress& peer_addr, tBTA_AV_START* p_av_start);
 
 // Process 'stop' request from the BTIF state machine to stop A2DP streaming.
 // |p_av_suspend| is the data associated with the request - see
diff --git a/btif/include/btif_a2dp_sink.h b/btif/include/btif_a2dp_sink.h
index 25e65f4..0a9038c 100644
--- a/btif/include/btif_a2dp_sink.h
+++ b/btif/include/btif_a2dp_sink.h
@@ -22,6 +22,7 @@
 
 #include <inttypes.h>
 #include <stdbool.h>
+#include <future>
 
 #include "bt_types.h"
 #include "bta_av_api.h"
@@ -52,7 +53,8 @@
 // Start the A2DP Sink session.
 // This function should be called by the BTIF state machine after
 // btif_a2dp_sink_startup() to start the streaming session for |peer_address|.
-bool btif_a2dp_sink_start_session(const RawAddress& peer_address);
+bool btif_a2dp_sink_start_session(const RawAddress& peer_address,
+                                  std::promise<void> peer_ready_promise);
 
 // Restart the A2DP Sink session.
 // This function should be called by the BTIF state machine after
@@ -62,7 +64,8 @@
 // |new_peer_address| is the peer address of the new session. This address
 // cannot be empty.
 bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
-                                    const RawAddress& new_peer_address);
+                                    const RawAddress& new_peer_address,
+                                    std::promise<void> peer_ready_promise);
 
 // End the A2DP Sink session.
 // This function should be called by the BTIF state machine to end the
@@ -85,6 +88,9 @@
 // Get the audio channel count for the A2DP Sink module.
 tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count(void);
 
+// Get the audio bits per sample for the A2DP Sink module.
+tA2DP_BITS_PER_SAMPLE btif_a2dp_sink_get_bits_per_sample(void);
+
 // Update the decoder for the A2DP Sink module.
 // |p_codec_info| contains the new codec information.
 void btif_a2dp_sink_update_decoder(const uint8_t* p_codec_info);
diff --git a/btif/include/btif_a2dp_source.h b/btif/include/btif_a2dp_source.h
index bb96e1a..0649012 100644
--- a/btif/include/btif_a2dp_source.h
+++ b/btif/include/btif_a2dp_source.h
@@ -21,6 +21,7 @@
 #define BTIF_A2DP_SOURCE_H
 
 #include <stdbool.h>
+#include <future>
 
 #include "bta_av_api.h"
 
@@ -37,7 +38,8 @@
 // Start the A2DP Source session.
 // This function should be called by the BTIF state machine after
 // btif_a2dp_source_startup() to start the streaming session for |peer_address|.
-bool btif_a2dp_source_start_session(const RawAddress& peer_address);
+bool btif_a2dp_source_start_session(const RawAddress& peer_address,
+                                    std::promise<void> peer_ready_promise);
 
 // Restart the A2DP Source session.
 // This function should be called by the BTIF state machine after
@@ -47,7 +49,8 @@
 // |new_peer_address| is the peer address of the new session. This address
 // cannot be empty.
 bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
-                                      const RawAddress& new_peer_address);
+                                      const RawAddress& new_peer_address,
+                                      std::promise<void> peer_ready_promise);
 
 // End the A2DP Source session.
 // This function should be called by the BTIF state machine to end the
diff --git a/btif/include/btif_api.h b/btif/include/btif_api.h
index 519fc9c..cef1aad 100644
--- a/btif/include/btif_api.h
+++ b/btif/include/btif_api.h
@@ -105,6 +105,19 @@
 
 /*******************************************************************************
  *
+ * Function         is_single_user_mode_
+ *
+ * Description      Checks if BT was enabled in single user mode. In this
+ *                  mode, use of keystore for key attestation of LTK is limitee
+ *                  to this mode defined by UserManager.
+ *
+ * Returns          bool
+ *
+ ******************************************************************************/
+bool is_single_user_mode(void);
+
+/*******************************************************************************
+ *
  * Function         btif_get_adapter_properties
  *
  * Description      Fetches all local adapter properties
diff --git a/btif/include/btif_av.h b/btif/include/btif_av.h
index 486c2af..e42f056 100644
--- a/btif/include/btif_av.h
+++ b/btif/include/btif_av.h
@@ -92,27 +92,6 @@
 void btif_av_clear_remote_suspend_flag(void);
 
 /**
- * Process AVRCP Open event.
- *
- * @param peer_address the peer address
- */
-void btif_av_avrcp_event_open(const RawAddress& peer_address);
-
-/**
- * Process AVRCP Close event.
- *
- * @param peer_address the peer address
- */
-void btif_av_avrcp_event_close(const RawAddress& peer_address);
-
-/**
- * Process AVRCP Remote Play event.
- *
- * @param peer_address the peer address
- */
-void btif_av_avrcp_event_remote_play(const RawAddress& peer_address);
-
-/**
  * Check whether the connected A2DP peer supports EDR.
  *
  * The value can be provided only if the remote peer is connected.
@@ -207,4 +186,13 @@
  *  @param  none
  */
 bool btif_av_is_a2dp_offload_enabled(void);
+
+/**
+ * Check whether peer device is silenced
+ *
+ * @param peer_address to check
+ *
+ */
+bool btif_av_is_peer_silenced(const RawAddress& peer_address);
+
 #endif /* BTIF_AV_H */
diff --git a/btif/include/btif_av_co.h b/btif/include/btif_av_co.h
index df7454f..93d6d7e 100644
--- a/btif/include/btif_av_co.h
+++ b/btif/include/btif_av_co.h
@@ -65,6 +65,10 @@
 void bta_av_co_init(
     const std::vector<btav_a2dp_codec_config_t>& codec_priorities);
 
+// Checks whether the codec for |codec_index| is supported.
+// Returns true if the codec is supported, otherwise false.
+bool bta_av_co_is_supported_codec(btav_a2dp_codec_index_t codec_index);
+
 // Gets the current A2DP codec for the active peer.
 // Returns a pointer to the current |A2dpCodecConfig| if valid, otherwise
 // nullptr.
diff --git a/btif/include/btif_avrcp_audio_track.h b/btif/include/btif_avrcp_audio_track.h
index 720fe60..20b21ff 100644
--- a/btif/include/btif_avrcp_audio_track.h
+++ b/btif/include/btif_avrcp_audio_track.h
@@ -35,7 +35,8 @@
  * should eventually be
  * deleted using BtifAvrcpAudioTrackDelete (see below).
  */
-void* BtifAvrcpAudioTrackCreate(int trackFreq, int channelType);
+void* BtifAvrcpAudioTrackCreate(int trackFreq, int bits_per_sample,
+                                int channelType);
 
 /**
  * Starts the audio track.
diff --git a/btif/include/btif_bqr.h b/btif/include/btif_bqr.h
new file mode 100644
index 0000000..4407b0d
--- /dev/null
+++ b/btif/include/btif_bqr.h
@@ -0,0 +1,268 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#ifndef BTIF_BQR_H_
+#define BTIF_BQR_H_
+
+#include "btm_api_types.h"
+#include "common/leaky_bonded_queue.h"
+
+namespace bluetooth {
+namespace bqr {
+
+// Bluetooth Quality Report (BQR)
+//
+// It is a feature to start the mechanism in the Bluetooth controller to report
+// Bluetooth Quality event to the host and there are four options could be
+// enabled:
+//   [Quality Monitoring Mode]
+//     The controller shall periodically send Bluetooth Quality Report sub-event
+//     to the host.
+//
+//   [Approaching LSTO]
+//     Once no packets are received from the connected Bluetooth device for a
+//     duration longer than the half of LSTO (Link Supervision TimeOut) value,
+//     the controller shall report Approaching LSTO event to the host.
+//
+//   [A2DP Audio Choppy]
+//     When the controller detects the factors which will cause audio choppy,
+//     the controller shall report A2DP Audio Choppy event to the host.
+//
+//   [(e)SCO Voice Choppy]
+//     When the controller detects the factors which will cause voice choppy,
+//     the controller shall report (e)SCO Voice Choppy event to the host.
+
+// Bit masks for the selected quality event reporting.
+static constexpr uint32_t kQualityEventMaskAllOff = 0;
+static constexpr uint32_t kQualityEventMaskMonitorMode = 0x00000001;
+static constexpr uint32_t kQualityEventMaskApproachLsto = 0x00000002;
+static constexpr uint32_t kQualityEventMaskA2dpAudioChoppy = 0x00000004;
+static constexpr uint32_t kQualityEventMaskScoVoiceChoppy = 0x00000008;
+static constexpr uint32_t kQualityEventMaskAll =
+    kQualityEventMaskMonitorMode | kQualityEventMaskApproachLsto |
+    kQualityEventMaskA2dpAudioChoppy | kQualityEventMaskScoVoiceChoppy;
+// Define the minimum time interval (in ms) of quality event reporting for the
+// selected quality event(s). Controller Firmware should not report the next
+// event within the defined time interval.
+static constexpr uint16_t kMinReportIntervalNoLimit = 0;
+static constexpr uint16_t kMinReportIntervalMaxMs = 0xFFFF;
+// Total length of all BQR parameters except Vendor Specific Parameters.
+static constexpr uint8_t kBqrParamTotalLen = 48;
+// Warning criteria of the RSSI value.
+static constexpr int8_t kCriWarnRssi = -80;
+// Warning criteria of the unused AFH channel count.
+static constexpr uint8_t kCriWarnUnusedCh = 55;
+// The queue size of recording the BQR events.
+static constexpr uint8_t kBqrEventQueueSize = 25;
+// The Property of BQR event mask configuration.
+static constexpr const char* kpPropertyEventMask =
+    "persist.bluetooth.bqr.event_mask";
+// The Property of BQR minimum report interval configuration.
+static constexpr const char* kpPropertyMinReportIntervalMs =
+    "persist.bluetooth.bqr.min_interval_ms";
+
+// Action definition
+//
+// Action to Add, Delete or Clear the reporting of quality event(s).
+// Delete will clear specific quality event(s) reporting. Clear will clear all
+// quality events reporting.
+enum BqrReportAction : uint8_t {
+  REPORT_ACTION_ADD = 0x00,
+  REPORT_ACTION_DELETE = 0x01,
+  REPORT_ACTION_CLEAR = 0x02
+};
+
+// Report ID definition
+enum BqrQualityReportId : uint8_t {
+  QUALITY_REPORT_ID_MONITOR_MODE = 0x01,
+  QUALITY_REPORT_ID_APPROACH_LSTO = 0x02,
+  QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY = 0x03,
+  QUALITY_REPORT_ID_SCO_VOICE_CHOPPY = 0x04
+};
+
+// Packet Type definition
+enum BqrPacketType : uint8_t {
+  PACKET_TYPE_ID = 0x01,
+  PACKET_TYPE_NULL,
+  PACKET_TYPE_POLL,
+  PACKET_TYPE_FHS,
+  PACKET_TYPE_HV1,
+  PACKET_TYPE_HV2,
+  PACKET_TYPE_HV3,
+  PACKET_TYPE_DV,
+  PACKET_TYPE_EV3,
+  PACKET_TYPE_EV4,
+  PACKET_TYPE_EV5,
+  PACKET_TYPE_2EV3,
+  PACKET_TYPE_2EV5,
+  PACKET_TYPE_3EV3,
+  PACKET_TYPE_3EV5,
+  PACKET_TYPE_DM1,
+  PACKET_TYPE_DH1,
+  PACKET_TYPE_DM3,
+  PACKET_TYPE_DH3,
+  PACKET_TYPE_DM5,
+  PACKET_TYPE_DH5,
+  PACKET_TYPE_AUX1,
+  PACKET_TYPE_2DH1,
+  PACKET_TYPE_2DH3,
+  PACKET_TYPE_2DH5,
+  PACKET_TYPE_3DH1,
+  PACKET_TYPE_3DH3,
+  PACKET_TYPE_3DH5
+};
+
+// Configuration Parameters
+typedef struct {
+  BqrReportAction report_action;
+  uint32_t quality_event_mask;
+  uint16_t minimum_report_interval_ms;
+} BqrConfiguration;
+
+// BQR sub-event of Vendor Specific Event
+class BqrVseSubEvt {
+ public:
+  // Parse the Bluetooth Quality Report VSE sub-event.
+  //
+  // @param length Total length of all parameters contained in the sub-event.
+  // @param p_param_buf A pointer to the parameters contained in the sub-event.
+  // @return false If the parameter total length is abnormal.
+  //         true If all parameters are parsed successfully.
+  bool ParseBqrEvt(uint8_t length, uint8_t* p_param_buf);
+
+  // Get a string representation of the Bluetooth Quality event.
+  //
+  // @return a string representation of the Bluetooth Quality event.
+  std::string ToString() const;
+
+  friend std::ostream& operator<<(std::ostream& os, const BqrVseSubEvt& a) {
+    return os << a.ToString();
+  }
+
+  virtual ~BqrVseSubEvt() = default;
+
+  // Quality report ID.
+  uint8_t quality_report_id_ = 0;
+  // Packet type of the connection.
+  uint8_t packet_types_ = 0;
+  // Connection handle of the connection.
+  uint16_t connection_handle_ = 0;
+  // Performing Role for the connection.
+  uint8_t connection_role_ = 0;
+  // Current Transmit Power Level for the connection. This value is the same as
+  // the controller's response to the HCI_Read_Transmit_Power_Level HCI command.
+  uint8_t tx_power_level_ = 0;
+  // Received Signal Strength Indication (RSSI) value for the connection. This
+  // value is an absolute receiver signal strength value.
+  int8_t rssi_ = 0;
+  // Signal-to-Noise Ratio (SNR) value for the connection. It is the average
+  // SNR of all the channels used by the link currently.
+  uint8_t snr_ = 0;
+  // Indicates the number of unused channels in AFH_channel_map.
+  uint8_t unused_afh_channel_count_ = 0;
+  // Indicates the number of the channels which are interfered and quality is
+  // bad but are still selected for AFH.
+  uint8_t afh_select_unideal_channel_count_ = 0;
+  // Current Link Supervision Timeout Setting.
+  // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+  uint16_t lsto_ = 0;
+  // Piconet Clock for the specified Connection_Handle. This value is the same
+  // as the controller's response to HCI_Read_Clock HCI command with the
+  // parameter "Which_Clock" of 0x01 (Piconet Clock).
+  // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+  uint32_t connection_piconet_clock_ = 0;
+  // The count of retransmission.
+  uint32_t retransmission_count_ = 0;
+  // The count of no RX.
+  uint32_t no_rx_count_ = 0;
+  // The count of NAK (Negative Acknowledge).
+  uint32_t nak_count_ = 0;
+  // Timestamp of last TX ACK.
+  // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+  uint32_t last_tx_ack_timestamp_ = 0;
+  // The count of Flow-off (STOP).
+  uint32_t flow_off_count_ = 0;
+  // Timestamp of last Flow-on (GO).
+  // Unit: N * 0.3125 ms (1 Bluetooth Clock)
+  uint32_t last_flow_on_timestamp_ = 0;
+  // Buffer overflow count (how many bytes of TX data are dropped) since the
+  // last event.
+  uint32_t buffer_overflow_bytes_ = 0;
+  // Buffer underflow count (in byte).
+  uint32_t buffer_underflow_bytes_ = 0;
+  // Local wall clock timestamp of receiving BQR VSE sub-event
+  std::tm tm_timestamp_ = {};
+};
+
+// Get a string representation of the Quality Report ID.
+//
+// @param quality_report_id The quality report ID to convert.
+// @return a string representation of the Quality Report ID.
+std::string QualityReportIdToString(uint8_t quality_report_id);
+
+// Get a string representation of the Packet Type.
+//
+// @param packet_type The packet type to convert.
+// @return a string representation of the Packet Type.
+std::string PacketTypeToString(uint8_t packet_type);
+
+// Enable/Disable Bluetooth Quality Report mechanism.
+//
+// Which Quality event will be enabled is according to the setting of the
+// property "persist.bluetooth.bqr.event_mask".
+// And the minimum time interval of quality event reporting depends on the
+// setting of property "persist.bluetooth.bqr.min_interval_ms".
+//
+// @param is_enable True/False to enable/disable Bluetooth Quality Report
+//   mechanism in the Bluetooth controller.
+void EnableBtQualityReport(bool is_enable);
+
+// Dump Bluetooth Quality Report information.
+//
+// @param fd The file descriptor to use for dumping information.
+void DebugDump(int fd);
+
+// Configure Bluetooth Quality Report setting to the Bluetooth controller.
+//
+// @param bqr_config The struct of configuration parameters.
+void ConfigureBqr(const BqrConfiguration& bqr_config);
+
+// Invoked on completion of Bluetooth Quality Report configuration. Then it will
+// Register/Unregister for receiving VSE - Bluetooth Quality Report sub event.
+//
+// @param current_evt_mask Indicates current quality event bit mask setting in
+//   the Bluetooth controller.
+void ConfigureBqrCmpl(uint32_t current_evt_mask);
+
+// Callback invoked on completion of vendor specific Bluetooth Quality Report
+// command.
+//
+// @param p_vsc_cmpl_params A pointer to the parameters contained in the vendor
+//   specific command complete event.
+void BqrVscCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params);
+
+// Record a new incoming Bluetooth Quality Report in quality event queue.
+//
+// @param len Lengths of the quality report sent from the Bluetooth
+//   controller.
+// @param p_quality_report A pointer to the quality report which is sent from
+//   the Bluetooth controller via Vendor Specific Event.
+void AddBqrEventToQueue(uint8_t length, uint8_t* p_stream);
+
+}  // namespace bqr
+}  // namespace bluetooth
+
+#endif  // BTIF_BQR_H_
diff --git a/btif/include/btif_common.h b/btif/include/btif_common.h
index af0beb0..39034c3 100644
--- a/btif/include/btif_common.h
+++ b/btif/include/btif_common.h
@@ -23,8 +23,8 @@
 #include <stdlib.h>
 
 #include <base/bind.h>
+#include <base/location.h>
 #include <base/message_loop/message_loop.h>
-#include <base/tracked_objects.h>
 #include <hardware/bluetooth.h>
 
 #include "bt_types.h"
@@ -174,9 +174,9 @@
  *  Functions
  ******************************************************************************/
 
-extern bt_status_t do_in_jni_thread(const base::Closure& task);
-extern bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here,
-                                    const base::Closure& task);
+extern bt_status_t do_in_jni_thread(base::OnceClosure task);
+extern bt_status_t do_in_jni_thread(const base::Location& from_here,
+                                    base::OnceClosure task);
 extern bool is_on_jni_thread();
 extern base::MessageLoop* get_jni_message_loop();
 /**
@@ -184,11 +184,11 @@
  * thread
  */
 template <typename R, typename... Args>
-base::Callback<R(Args...)> jni_thread_wrapper(
-    const tracked_objects::Location& from_here, base::Callback<R(Args...)> cb) {
+base::Callback<R(Args...)> jni_thread_wrapper(const base::Location& from_here,
+                                              base::Callback<R(Args...)> cb) {
   return base::Bind(
-      [](const tracked_objects::Location& from_here,
-         base::Callback<R(Args...)> cb, Args... args) {
+      [](const base::Location& from_here, base::Callback<R(Args...)> cb,
+         Args... args) {
         do_in_jni_thread(from_here,
                          base::Bind(cb, std::forward<Args>(args)...));
       },
diff --git a/btif/include/btif_dm.h b/btif/include/btif_dm.h
index bdbce49..a9d4cb6 100644
--- a/btif/include/btif_dm.h
+++ b/btif/include/btif_dm.h
@@ -61,9 +61,9 @@
                                    tBTA_LE_AUTH_REQ* p_auth_req);
 #ifdef BTIF_DM_OOB_TEST
 void btif_dm_load_local_oob(void);
-void btif_dm_proc_loc_oob(bool valid, BT_OCTET16 c, BT_OCTET16 r);
-bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, BT_OCTET16 p_c,
-                          BT_OCTET16 p_r);
+void btif_dm_proc_loc_oob(bool valid, const Octet16& c, const Octet16& r);
+bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, Octet16* p_c,
+                          Octet16* p_r);
 #endif /* BTIF_DM_OOB_TEST */
 
 /*callout for reading SMP properties from Text file*/
@@ -98,7 +98,7 @@
 
 void btif_dm_load_ble_local_keys(void);
 void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask,
-                                BT_OCTET16 er,
+                                Octet16* p_er,
                                 tBTA_BLE_LOCAL_ID_KEYS* p_id_keys);
 void btif_dm_save_ble_bonding_keys(RawAddress& bd_addr);
 void btif_dm_remove_ble_bonding_keys(void);
diff --git a/btif/include/btif_hh.h b/btif/include/btif_hh.h
index 2364544..b71d347 100644
--- a/btif/include/btif_hh.h
+++ b/btif/include/btif_hh.h
@@ -25,6 +25,7 @@
 #include <stdint.h>
 #include "bta_hh_api.h"
 #include "btu.h"
+#include "osi/include/fixed_queue.h"
 
 /*******************************************************************************
  *  Constants & Macros
@@ -67,6 +68,8 @@
   pthread_t hh_poll_thread_id;
   uint8_t hh_keep_polling;
   alarm_t* vup_timer;
+  fixed_queue_t* get_rpt_id_queue;
+  uint8_t get_rpt_snt;
   bool local_vup;  // Indicated locally initiated VUP
 } btif_hh_device_t;
 
@@ -106,6 +109,9 @@
 extern void btif_hh_setreport(btif_hh_device_t* p_dev,
                               bthh_report_type_t r_type, uint16_t size,
                               uint8_t* report);
+extern void btif_hh_getreport(btif_hh_device_t* p_dev,
+                              bthh_report_type_t r_type, uint8_t reportId,
+                              uint16_t bufferSize);
 extern void btif_hh_service_registration(bool enable);
 
 #endif
diff --git a/btif/include/btif_hl.h b/btif/include/btif_hl.h
deleted file mode 100644
index 69a99b5..0000000
--- a/btif/include/btif_hl.h
+++ /dev/null
@@ -1,315 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-#ifndef BTIF_HL_H
-#define BTIF_HL_H
-
-#include <hardware/bluetooth.h>
-
-#include "bt_common.h"
-#include "bta_hl_api.h"
-#include "osi/include/alarm.h"
-
-/*******************************************************************************
- *  Constants & Macros
- ******************************************************************************/
-
-#define BTIF_HL_DATA_TYPE_NONE 0x0000
-#define BTIF_HL_DATA_TYPE_PULSE_OXIMETER 0x1004 /* from BT assigned number */
-#define BTIF_HL_DATA_TYPE_BLOOD_PRESSURE_MON 0x1007
-#define BTIF_HL_DATA_TYPE_BODY_THERMOMETER 0x1008
-#define BTIF_HL_DATA_TYPE_BODY_WEIGHT_SCALE 0x100F
-#define BTIF_HL_DATA_TYPE_GLUCOSE_METER 0x1011
-#define BTIF_HL_DATA_TYPE_STEP_COUNTER 0x1068
-#define BTIF_HL_DATA_TYPE_BCA 0x1014
-#define BTIF_HL_DATA_TYPE_PEAK_FLOW 0x1015
-#define BTIF_HL_DATA_TYPE_CARDIO 0x1029
-#define BTIF_HL_DATA_TYPE_ACTIVITY_HUB 0x1047
-#define BTIF_HL_DATA_TYPE_AMM 0x1048
-
-#define BTIF_HL_CCH_NUM_FILTER_ELEMS 3
-#define BTIF_HL_APPLICATION_NAME_LEN 512
-
-/*******************************************************************************
- *  Type definitions and return values
- ******************************************************************************/
-
-typedef enum {
-  BTIF_HL_SOC_STATE_IDLE,
-  BTIF_HL_SOC_STATE_W4_ADD,
-  BTIF_HL_SOC_STATE_W4_CONN,
-  BTIF_HL_SOC_STATE_W4_READ,
-  BTIF_HL_SOC_STATE_W4_REL
-} btif_hl_soc_state_t;
-
-typedef enum {
-  BTIF_HL_STATE_DISABLED,
-  BTIF_HL_STATE_DISABLING,
-  BTIF_HL_STATE_ENABLED,
-  BTIF_HL_STATE_ENABLING,
-} btif_hl_state_t;
-
-typedef enum {
-  BTIF_HL_CCH_OP_NONE,
-  BTIF_HL_CCH_OP_MDEP_FILTERING,
-  BTIF_HL_CCH_OP_MATCHED_CTRL_PSM,
-  BTIF_HL_CCH_OP_DCH_OPEN,
-  BTIF_HL_CCH_OP_DCH_RECONNECT,
-  BTIF_HL_CCH_OP_DCH_ECHO_TEST
-} btif_hl_cch_op_t;
-
-typedef enum {
-  BTIF_HL_PEND_DCH_OP_NONE,
-  BTIF_HL_PEND_DCH_OP_DELETE_MDL,
-  BTIF_HL_PEND_DCH_OP_OPEN,
-  BTIF_HL_PEND_DCH_OP_RECONNECT
-} btif_hl_pend_dch_op_t;
-
-typedef enum { BTIF_HL_DCH_OP_NONE, BTIF_HL_DCH_OP_DISC } btif_hl_dch_op_t;
-
-typedef enum {
-  BTIF_HL_CHAN_CB_STATE_NONE,
-  BTIF_HL_CHAN_CB_STATE_CONNECTING_PENDING,
-  BTIF_HL_CHAN_CB_STATE_CONNECTED_PENDING,
-
-  BTIF_HL_CHAN_CB_STATE_DISCONNECTING_PENDING,
-  BTIF_HL_CHAN_CB_STATE_DISCONNECTED_PENDING,
-  BTIF_HL_CHAN_CB_STATE_DESTROYED_PENDING,
-} btif_hl_chan_cb_state_t;
-
-enum {
-  BTIF_HL_SEND_CONNECTED_CB,
-  BTIF_HL_SEND_DISCONNECTED_CB,
-  BTIF_HL_REG_APP,
-  BTIF_HL_UNREG_APP,
-  BTIF_HL_UPDATE_MDL,
-};
-
-typedef struct {
-  uint8_t mdep_cfg_idx;
-  int data_type;
-  tBTA_HL_MDEP_ID peer_mdep_id;
-} btif_hl_extra_mdl_cfg_t;
-
-typedef struct {
-  tBTA_HL_MDL_CFG base;
-  btif_hl_extra_mdl_cfg_t extra;
-} btif_hl_mdl_cfg_t;
-
-typedef struct {
-  bool active;
-  uint8_t app_idx;
-} btif_hl_app_data_t;
-
-typedef struct {
-  int channel_id;
-  RawAddress bd_addr;
-  uint8_t mdep_cfg_idx;
-  int max_s;
-  int socket_id[2];
-  uint8_t app_idx;
-  uint8_t mcl_idx;
-  uint8_t mdl_idx;
-  btif_hl_soc_state_t state;
-} btif_hl_soc_cb_t;
-
-typedef struct {
-  uint16_t data_type;
-  uint16_t max_tx_apdu_size;
-  uint16_t max_rx_apdu_size;
-} btif_hl_data_type_cfg_t;
-
-typedef struct {
-  uint16_t data_type;
-  tBTA_HL_MDEP_ROLE peer_mdep_role;
-} btif_hl_filter_elem_t;
-
-typedef struct {
-  uint8_t num_elems;
-  btif_hl_filter_elem_t elem[BTIF_HL_CCH_NUM_FILTER_ELEMS];
-} btif_hl_cch_filter_t;
-
-typedef struct {
-  bool in_use;
-  uint16_t mdl_id;
-  tBTA_HL_MDL_HANDLE mdl_handle;
-  btif_hl_dch_op_t dch_oper;
-  tBTA_HL_MDEP_ID local_mdep_id;
-  uint8_t local_mdep_cfg_idx;
-  tBTA_HL_DCH_CFG local_cfg;
-  tBTA_HL_MDEP_ID peer_mdep_id;
-  uint16_t peer_data_type;
-  tBTA_HL_MDEP_ROLE peer_mdep_role;
-  tBTA_HL_DCH_MODE dch_mode;
-  tBTA_SEC sec_mask;
-  bool is_the_first_reliable;
-  bool delete_mdl;
-  uint16_t mtu;
-  tMCA_CHNL_CFG chnl_cfg;
-  uint16_t tx_size;
-  uint8_t* p_tx_pkt;
-  uint8_t* p_rx_pkt;
-  bool cong;
-  btif_hl_soc_cb_t* p_scb;
-  int channel_id;
-} btif_hl_mdl_cb_t;
-
-typedef struct {
-  int channel_id;
-  int mdep_cfg_idx;
-  bool in_use;
-  btif_hl_chan_cb_state_t cb_state;
-  btif_hl_pend_dch_op_t op;
-  RawAddress bd_addr;
-  bool abort_pending;
-} btif_hl_pending_chan_cb_t;
-
-typedef struct {
-  btif_hl_mdl_cb_t mdl[BTA_HL_NUM_MDLS_PER_MCL];
-  bool in_use;
-  bool is_connected;
-  uint16_t req_ctrl_psm;
-  uint16_t ctrl_psm;
-  uint16_t data_psm;
-  RawAddress bd_addr;
-  uint16_t cch_mtu;
-  tBTA_SEC sec_mask;
-  tBTA_HL_MCL_HANDLE mcl_handle;
-  btif_hl_pending_chan_cb_t pcb;
-  bool valid_sdp_idx;
-  uint8_t sdp_idx;
-  tBTA_HL_SDP sdp;
-  btif_hl_cch_op_t cch_oper;
-  alarm_t* cch_timer;
-} btif_hl_mcl_cb_t;
-
-typedef struct {
-  bool active;
-  uint16_t mdl_id;
-  uint8_t mdep_cfg_idx;
-  RawAddress bd_addr;
-  int channel_id;
-} btif_hl_delete_mdl_t;
-
-typedef struct {
-  btif_hl_mcl_cb_t mcb[BTA_HL_NUM_MCLS]; /* application Control Blocks */
-  bool in_use;                           /* this CB is in use*/
-  bool reg_pending;
-  uint8_t app_id;
-
-  tBTA_HL_SUP_FEATURE sup_feature;
-  tBTA_HL_DCH_CFG channel_type[BTA_HL_NUM_MDEPS];
-  tBTA_HL_SDP_INFO_IND sdp_info_ind;
-  btif_hl_cch_filter_t filter;
-
-  btif_hl_mdl_cfg_t mdl_cfg[BTA_HL_NUM_MDL_CFGS];
-  int mdl_cfg_channel_id[BTA_HL_NUM_MDL_CFGS];
-
-  btif_hl_delete_mdl_t delete_mdl;
-  tBTA_HL_DEVICE_TYPE dev_type;
-  tBTA_HL_APP_HANDLE app_handle;
-  uint16_t sec_mask; /* Security mask for BTM_SetSecurityLevel() */
-  char srv_name[BTA_SERVICE_NAME_LEN +
-                1]; /* service name to be used in the SDP; null terminated*/
-  char srv_desp[BTA_SERVICE_DESP_LEN + 1]; /* service description to be used in
-                                              the SDP; null terminated */
-  char provider_name[BTA_PROVIDER_NAME_LEN + 1]; /* provide name to be used in
-                                                    the SDP; null terminated */
-  char
-      application_name[BTIF_HL_APPLICATION_NAME_LEN + 1]; /* applicaiton name */
-} btif_hl_app_cb_t;
-
-typedef struct {
-  bool in_use;
-  uint8_t app_idx;
-} btif_hl_pending_reg_cb_t;
-
-/* BTIF-HL control block  */
-typedef struct {
-  btif_hl_app_cb_t acb[BTA_HL_NUM_APPS]; /* HL Control Blocks */
-  tBTA_HL_CTRL_CBACK* p_ctrl_cback; /* pointer to control callback function */
-  uint8_t next_app_id;
-  uint16_t next_channel_id;
-  btif_hl_state_t state;
-} btif_hl_cb_t;
-
-typedef uint8_t btif_hl_evt_t;
-
-typedef struct {
-  int app_id;
-  RawAddress bd_addr;
-  int mdep_cfg_index;
-  int channel_id;
-  btif_hl_chan_cb_state_t cb_state;
-  int fd;
-} btif_hl_send_chan_state_cb_t;
-
-typedef struct { uint8_t app_idx; } btif_hl_reg_t;
-
-typedef btif_hl_reg_t btif_hl_unreg_t;
-typedef btif_hl_reg_t btif_hl_update_mdl_t;
-
-typedef union {
-  btif_hl_send_chan_state_cb_t chan_cb;
-  btif_hl_reg_t reg;
-  btif_hl_unreg_t unreg;
-  btif_hl_update_mdl_t update_mdl;
-} btif_hl_evt_cb_t;
-
-/*******************************************************************************
- *  Functions
- ******************************************************************************/
-
-#define BTIF_HL_GET_CB_PTR() &(btif_hl_cb)
-#define BTIF_HL_GET_APP_CB_PTR(app_idx) &(btif_hl_cb.acb[(app_idx)])
-#define BTIF_HL_GET_MCL_CB_PTR(app_idx, mcl_idx) \
-  &(btif_hl_cb.acb[(app_idx)].mcb[(mcl_idx)])
-#define BTIF_HL_GET_MDL_CB_PTR(app_idx, mcl_idx, mdl_idx) \
-  &(btif_hl_cb.acb[(app_idx)].mcb[(mcl_idx)].mdl[mdl_idx])
-#define BTIF_HL_GET_PCB_PTR(app_idx, mcl_idx) \
-  &(btif_hl_cb.acb[app_idx].mcb[mcl_idx].pcb)
-#define BTIF_HL_GET_MDL_CFG_PTR(app_idx, item_idx) \
-  &(btif_hl_cb.acb[(app_idx)].mdl_cfg[(item_idx)])
-#define BTIF_HL_GET_MDL_CFG_CHANNEL_ID_PTR(app_idx, item_idx) \
-  &(btif_hl_cb.acb[(app_idx)].mdl_cfg_channel_id[(item_idx)])
-
-extern btif_hl_cb_t btif_hl_cb;
-extern btif_hl_cb_t* p_btif_hl_cb;
-
-extern bool btif_hl_find_mcl_idx(uint8_t app_idx, const RawAddress& p_bd_addr,
-                                 uint8_t* p_mcl_idx);
-extern bool btif_hl_find_app_idx(uint8_t app_id, uint8_t* p_app_idx);
-extern bool btif_hl_find_avail_mcl_idx(uint8_t app_idx, uint8_t* p_mcl_idx);
-extern bool btif_hl_find_avail_mdl_idx(uint8_t app_idx, uint8_t mcl_idx,
-                                       uint8_t* p_mdl_idx);
-extern bool btif_hl_find_mcl_idx_using_handle(tBTA_HL_MCL_HANDLE mcl_handle,
-                                              uint8_t* p_app_idx,
-                                              uint8_t* p_mcl_idx);
-extern bool btif_hl_save_mdl_cfg(uint8_t app_id, uint8_t item_idx,
-                                 tBTA_HL_MDL_CFG* p_mdl_cfg);
-extern bool btif_hl_delete_mdl_cfg(uint8_t app_id, uint8_t item_idx);
-extern bool btif_hl_find_mdl_idx_using_handle(tBTA_HL_MDL_HANDLE mdl_handle,
-                                              uint8_t* p_app_idx,
-                                              uint8_t* p_mcl_idx,
-                                              uint8_t* p_mdl_idx);
-extern void btif_hl_abort_pending_chan_setup(uint8_t app_idx, uint8_t mcl_idx);
-extern bool btif_hl_proc_pending_op(uint8_t app_idx, uint8_t mcl_idx);
-extern bool btif_hl_load_mdl_config(uint8_t app_id, uint8_t buffer_size,
-                                    tBTA_HL_MDL_CFG* p_mdl_buf);
-
-#endif
diff --git a/btif/include/btif_keystore.h b/btif/include/btif_keystore.h
index 4762350..cc06a98 100644
--- a/btif/include/btif_keystore.h
+++ b/btif/include/btif_keystore.h
@@ -59,6 +59,14 @@
    */
   std::string Decrypt(const std::string& input_filename);
 
+  /**
+   * Check for existence of keystore key.
+   *
+   * This key can be cleared if a user manually wipes bluetooth storage data
+   * b/133214365
+   */
+  bool DoesKeyExist();
+
  private:
   std::unique_ptr<keystore::KeystoreClient> keystore_client_;
   std::mutex api_mutex_;
diff --git a/btif/include/btif_storage.h b/btif/include/btif_storage.h
index 07d29c8..1c1163d 100644
--- a/btif/include/btif_storage.h
+++ b/btif/include/btif_storage.h
@@ -99,6 +99,32 @@
 
 /*******************************************************************************
  *
+ * Function         btif_storage_get_io_caps
+ *
+ * Description      BTIF storage API - Fetches the local Input/Output
+ *                  capabilities of the device.
+ *
+ * Returns          Returns local IO Capability of device. If not stored,
+ *                  returns BTM_LOCAL_IO_CAPS.
+ *
+ ******************************************************************************/
+uint8_t btif_storage_get_local_io_caps();
+
+/*******************************************************************************
+ *
+ * Function         btif_storage_get_io_caps_ble
+ *
+ * Description      BTIF storage API - Fetches the local Input/Output
+ *                  capabilities of the BLE device.
+ *
+ * Returns          Returns local IO Capability of BLE device. If not stored,
+ *                  returns BTM_LOCAL_IO_CAPS_BLE.
+ *
+ ******************************************************************************/
+uint8_t btif_storage_get_local_io_caps_ble();
+
+/*******************************************************************************
+ *
  * Function         btif_storage_add_remote_device
  *
  * Description      BTIF storage API - Adds a newly discovered device to
@@ -125,7 +151,7 @@
  *
  ******************************************************************************/
 bt_status_t btif_storage_add_bonded_device(RawAddress* remote_bd_addr,
-                                           LINK_KEY link_key, uint8_t key_type,
+                                           LinkKey link_key, uint8_t key_type,
                                            uint8_t pin_length);
 
 /*******************************************************************************
@@ -201,11 +227,14 @@
 /** Deletes the bonded hearing aid device info from NVRAM */
 void btif_storage_remove_hearing_aid(const RawAddress& address);
 
-/** Add the hearing aid device to white list */
-void btif_storage_add_hearing_aid_to_white_list(const RawAddress& address);
+/** Set/Unset the hearing aid device HEARING_AID_IS_WHITE_LISTED flag. */
+void btif_storage_set_hearing_aid_white_list(const RawAddress& address,
+                                             bool add_to_whitelist);
 
-/** Remove the hearing aid device from white list */
-void btif_storage_remove_hearing_aid_white_list(const RawAddress& address);
+/** Get the hearing aid device properties. */
+bool btif_storage_get_hearing_aid_prop(
+    const RawAddress& address, uint8_t* capabilities, uint64_t* hi_sync_id,
+    uint16_t* render_delay, uint16_t* preparation_delay, uint16_t* codecs);
 
 /*******************************************************************************
  *
@@ -220,6 +249,8 @@
  ******************************************************************************/
 bool btif_storage_is_restricted_device(const RawAddress* remote_bd_addr);
 
+int btif_storage_get_num_bonded_devices(void);
+
 bt_status_t btif_storage_add_ble_bonding_key(RawAddress* remote_bd_addr,
                                              const uint8_t* key,
                                              uint8_t key_type,
@@ -229,13 +260,13 @@
                                              uint8_t* key_value,
                                              int key_length);
 
-bt_status_t btif_storage_add_ble_local_key(char* key, uint8_t key_type,
-                                           uint8_t key_length);
+bt_status_t btif_storage_add_ble_local_key(const Octet16& key,
+                                           uint8_t key_type);
 bt_status_t btif_storage_remove_ble_bonding_keys(
     const RawAddress* remote_bd_addr);
 bt_status_t btif_storage_remove_ble_local_keys(void);
-bt_status_t btif_storage_get_ble_local_key(uint8_t key_type, char* key_value,
-                                           int key_len);
+bt_status_t btif_storage_get_ble_local_key(uint8_t key_type,
+                                           Octet16* key_value);
 
 bt_status_t btif_storage_get_remote_addr_type(const RawAddress* remote_bd_addr,
                                               int* addr_type);
diff --git a/btif/src/bluetooth.cc b/btif/src/bluetooth.cc
index 6e86ce7..9dd4908 100644
--- a/btif/src/bluetooth.cc
+++ b/btif/src/bluetooth.cc
@@ -40,20 +40,20 @@
 #include <hardware/bt_hearing_aid.h>
 #include <hardware/bt_hf_client.h>
 #include <hardware/bt_hh.h>
-#include <hardware/bt_hl.h>
 #include <hardware/bt_mce.h>
 #include <hardware/bt_pan.h>
 #include <hardware/bt_rc.h>
 #include <hardware/bt_sdp.h>
 #include <hardware/bt_sock.h>
 
-#include "avrcp_service.h"
 #include "bt_utils.h"
 #include "bta/include/bta_hearing_aid_api.h"
 #include "bta/include/bta_hf_client_api.h"
+#include "btif/avrcp/avrcp_service.h"
 #include "btif_a2dp.h"
 #include "btif_api.h"
 #include "btif_av.h"
+#include "btif_bqr.h"
 #include "btif_config.h"
 #include "btif_debug.h"
 #include "btif_debug_btsnoop.h"
@@ -62,18 +62,17 @@
 #include "btif_storage.h"
 #include "btsnoop.h"
 #include "btsnoop_mem.h"
+#include "common/address_obfuscator.h"
+#include "common/metrics.h"
 #include "device/include/interop.h"
 #include "osi/include/alarm.h"
 #include "osi/include/allocation_tracker.h"
 #include "osi/include/log.h"
-#include "osi/include/metrics.h"
 #include "osi/include/osi.h"
 #include "osi/include/wakelock.h"
+#include "stack/gatt/connection_manager.h"
 #include "stack_manager.h"
 
-/* Test interface includes */
-#include "mca_api.h"
-
 using bluetooth::hearing_aid::HearingAidInterface;
 
 /*******************************************************************************
@@ -82,6 +81,7 @@
 
 bt_callbacks_t* bt_hal_cbacks = NULL;
 bool restricted_mode = false;
+bool single_user_mode = false;
 
 /*******************************************************************************
  *  Externs
@@ -100,8 +100,6 @@
 extern const bthh_interface_t* btif_hh_get_interface();
 /* hid device profile */
 extern const bthd_interface_t* btif_hd_get_interface();
-/* health device profile */
-extern const bthl_interface_t* btif_hl_get_interface();
 /*pan*/
 extern const btpan_interface_t* btif_pan_get_interface();
 /*map client*/
@@ -117,9 +115,6 @@
 /*Hearing Aid client*/
 extern HearingAidInterface* btif_hearing_aid_get_interface();
 
-/* List all test interface here */
-extern const btmcap_test_interface_t* stack_mcap_get_interface();
-
 /*******************************************************************************
  *  Functions
  ******************************************************************************/
@@ -138,8 +133,10 @@
  *
  ****************************************************************************/
 
-static int init(bt_callbacks_t* callbacks) {
-  LOG_INFO(LOG_TAG, "%s", __func__);
+static int init(bt_callbacks_t* callbacks, bool start_restricted,
+                bool is_single_user_mode) {
+  LOG_INFO(LOG_TAG, "%s: start restricted = %d ; single user = %d", __func__,
+           start_restricted, is_single_user_mode);
 
   if (interface_ready()) return BT_STATUS_DONE;
 
@@ -148,16 +145,14 @@
 #endif
 
   bt_hal_cbacks = callbacks;
+  restricted_mode = start_restricted;
+  single_user_mode = is_single_user_mode;
   stack_manager_get_interface()->init_stack();
   btif_debug_init();
   return BT_STATUS_SUCCESS;
 }
 
-static int enable(bool start_restricted) {
-  LOG_INFO(LOG_TAG, "%s: start restricted = %d", __func__, start_restricted);
-
-  restricted_mode = start_restricted;
-
+static int enable() {
   if (!interface_ready()) return BT_STATUS_NOT_READY;
 
   stack_manager_get_interface()->start_up_stack_async();
@@ -174,6 +169,7 @@
 static void cleanup(void) { stack_manager_get_interface()->clean_up_stack(); }
 
 bool is_restricted_mode() { return restricted_mode; }
+bool is_single_user_mode() { return single_user_mode; }
 
 static int get_adapter_properties(void) {
   /* sanity check */
@@ -323,13 +319,15 @@
   osi_allocator_debug_dump(fd);
   alarm_debug_dump(fd);
   HearingAid::DebugDump(fd);
+  connection_manager::dump(fd);
+  bluetooth::bqr::DebugDump(fd);
 #if (BTSNOOP_MEM == TRUE)
   btif_debug_btsnoop_dump(fd);
 #endif
 }
 
 static void dumpMetrics(std::string* output) {
-  system_bt_osi::BluetoothMetricsLogger::GetInstance()->WriteString(output);
+  bluetooth::common::BluetoothMetricsLogger::GetInstance()->WriteString(output);
 }
 
 static const void* get_profile_interface(const char* profile_id) {
@@ -363,9 +361,6 @@
   if (is_profile(profile_id, BT_PROFILE_HIDDEV_ID))
     return btif_hd_get_interface();
 
-  if (is_profile(profile_id, BT_PROFILE_HEALTH_ID))
-    return btif_hl_get_interface();
-
   if (is_profile(profile_id, BT_PROFILE_SDP_CLIENT_ID))
     return btif_sdp_get_interface();
 
@@ -378,9 +373,6 @@
   if (is_profile(profile_id, BT_PROFILE_AV_RC_CTRL_ID))
     return btif_rc_ctrl_get_interface();
 
-  if (is_profile(profile_id, BT_TEST_INTERFACE_MCAP_ID))
-    return stack_mcap_get_interface();
-
   if (is_profile(profile_id, BT_PROFILE_HEARING_AID_ID))
     return btif_hearing_aid_get_interface();
   return NULL;
@@ -451,6 +443,11 @@
   return bluetooth::avrcp::AvrcpService::GetServiceInterface();
 }
 
+static std::string obfuscate_address(const RawAddress& address) {
+  return bluetooth::common::AddressObfuscator::GetInstance()->Obfuscate(
+      address);
+}
+
 EXPORT_SYMBOL bt_interface_t bluetoothInterface = {
     sizeof(bluetoothInterface),
     init,
@@ -486,4 +483,5 @@
     interop_database_clear,
     interop_database_add,
     get_avrcp_service,
+    obfuscate_address,
 };
diff --git a/btif/src/btif_a2dp.cc b/btif/src/btif_a2dp.cc
index 86485d4..e2d6132 100644
--- a/btif/src/btif_a2dp.cc
+++ b/btif/src/btif_a2dp.cc
@@ -22,6 +22,7 @@
 #include <stdbool.h>
 
 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
+#include "audio_hal_interface/a2dp_encoding.h"
 #include "bt_common.h"
 #include "bta_av_api.h"
 #include "btif_a2dp.h"
@@ -45,69 +46,65 @@
   }
 }
 
-bool btif_a2dp_on_started(const RawAddress& peer_addr,
-                          tBTA_AV_START* p_av_start, bool pending_start) {
-  bool ack = false;
-
-  LOG_INFO(LOG_TAG,
-           "%s: ## ON A2DP STARTED ## peer %s pending_start:%s p_av_start:%p",
-           __func__, peer_addr.ToString().c_str(),
-           logbool(pending_start).c_str(), p_av_start);
+bool btif_a2dp_on_started(const RawAddress& peer_addr, tBTA_AV_START* p_av_start) {
+  LOG(INFO) << __func__ << ": ## ON A2DP STARTED ## peer " << peer_addr << " p_av_start:" << p_av_start;
 
   if (p_av_start == NULL) {
-    /* ack back a local start request */
-
-    if (!btif_av_is_a2dp_offload_enabled()) {
-      btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
-      return true;
-    } else if (bluetooth::headset::IsCallIdle()) {
-      btif_av_stream_start_offload();
+    tA2DP_CTRL_ACK status = A2DP_CTRL_ACK_SUCCESS;
+    if (!bluetooth::headset::IsCallIdle()) {
+      LOG(ERROR) << __func__ << ": peer " << peer_addr << " call in progress, do not start A2DP stream";
+      status = A2DP_CTRL_ACK_INCALL_FAILURE;
+    }
+    /* just ack back a local start request, do not start the media encoder since
+     * this is not for BTA_AV_START_EVT. */
+    if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+      bluetooth::audio::a2dp::ack_stream_started(status);
+    } else if (btif_av_is_a2dp_offload_enabled()) {
+      btif_a2dp_audio_on_started(status);
     } else {
-      LOG_ERROR(LOG_TAG, "%s: peer %s call in progress, do not start offload",
-                __func__, peer_addr.ToString().c_str());
-      btif_a2dp_audio_on_started(A2DP_CTRL_ACK_INCALL_FAILURE);
+      btif_a2dp_command_ack(status);
     }
     return true;
   }
 
-  LOG_INFO(LOG_TAG,
-           "%s: peer %s pending_start:%s status:%d suspending:%s initiator:%s",
-           __func__, peer_addr.ToString().c_str(),
-           logbool(pending_start).c_str(), p_av_start->status,
-           logbool(p_av_start->suspending).c_str(),
-           logbool(p_av_start->initiator).c_str());
+  LOG(INFO) << __func__ << ": peer " << peer_addr << " status:" << +p_av_start->status
+            << " suspending:" << logbool(p_av_start->suspending) << " initiator:" << logbool(p_av_start->initiator);
 
   if (p_av_start->status == BTA_AV_SUCCESS) {
-    if (!p_av_start->suspending) {
-      if (p_av_start->initiator) {
-        if (pending_start) {
-          if (btif_av_is_a2dp_offload_enabled()) {
-            btif_av_stream_start_offload();
-          } else {
-            btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
-          }
-          ack = true;
-        }
-      } else {
-        // We were started remotely
-        if (btif_av_is_a2dp_offload_enabled()) {
-          btif_av_stream_start_offload();
-        }
-      }
-
-      /* media task is autostarted upon a2dp audiopath connection */
+    if (p_av_start->suspending) {
+      LOG(WARNING) << __func__ << ": peer " << peer_addr << " A2DP is suspending and ignores the started event";
+      return false;
     }
-  } else if (pending_start) {
-    LOG_ERROR(LOG_TAG, "%s: peer %s A2DP start request failed: status = %d",
-              __func__, peer_addr.ToString().c_str(), p_av_start->status);
     if (btif_av_is_a2dp_offload_enabled()) {
+      btif_av_stream_start_offload();
+    } else if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+      if (btif_av_get_peer_sep() == AVDT_TSEP_SNK) {
+        /* Start the media encoder to do the SW audio stream */
+        btif_a2dp_source_start_audio_req();
+      }
+      if (p_av_start->initiator) {
+        bluetooth::audio::a2dp::ack_stream_started(A2DP_CTRL_ACK_SUCCESS);
+        return true;
+      }
+    } else {
+      if (p_av_start->initiator) {
+        btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+        return true;
+      }
+      /* media task is auto-started upon UIPC connection of a2dp audiopath */
+    }
+  } else if (p_av_start->initiator) {
+    LOG(ERROR) << __func__ << ": peer " << peer_addr << " A2DP start request failed: status = " << +p_av_start->status;
+    if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+      bluetooth::audio::a2dp::ack_stream_started(A2DP_CTRL_ACK_FAILURE);
+    } else if (btif_av_is_a2dp_offload_enabled()) {
       btif_a2dp_audio_on_started(p_av_start->status);
     } else {
       btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
     }
-    ack = true;
+    return true;
   }
-  return ack;
+  return false;
 }
 
 void btif_a2dp_on_stopped(tBTA_AV_SUSPEND* p_av_suspend) {
@@ -118,7 +115,8 @@
     btif_a2dp_sink_on_stopped(p_av_suspend);
     return;
   }
-  if (!btif_av_is_a2dp_offload_enabled()) {
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled() ||
+      !btif_av_is_a2dp_offload_enabled()) {
     btif_a2dp_source_on_stopped(p_av_suspend);
   } else if (p_av_suspend != NULL) {
     btif_a2dp_audio_on_stopped(p_av_suspend->status);
@@ -128,13 +126,14 @@
 void btif_a2dp_on_suspended(tBTA_AV_SUSPEND* p_av_suspend) {
   LOG_INFO(LOG_TAG, "%s: ## ON A2DP SUSPENDED ## p_av_suspend=%p", __func__,
            p_av_suspend);
-  if (!btif_av_is_a2dp_offload_enabled()) {
-    if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
-      btif_a2dp_sink_on_suspended(p_av_suspend);
-    } else {
-      btif_a2dp_source_on_suspended(p_av_suspend);
-    }
-  } else {
+  if (btif_av_get_peer_sep() == AVDT_TSEP_SRC) {
+    btif_a2dp_sink_on_suspended(p_av_suspend);
+    return;
+  }
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled() ||
+      !btif_av_is_a2dp_offload_enabled()) {
+    btif_a2dp_source_on_suspended(p_av_suspend);
+  } else if (p_av_suspend != NULL) {
     btif_a2dp_audio_on_suspended(p_av_suspend->status);
   }
 }
@@ -161,7 +160,6 @@
       break;
   }
   if (btif_av_is_a2dp_offload_enabled()) {
-    btif_a2dp_audio_on_started(status);
     if (ack != BTA_AV_SUCCESS && btif_av_stream_started_ready()) {
       // Offload request will return with failure from btif_av sm if
       // suspend is triggered for remote start. Disconnect only if SoC
@@ -170,8 +168,12 @@
                 peer_addr.ToString().c_str());
       btif_av_src_disconnect_sink(peer_addr);
     }
+  }
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bluetooth::audio::a2dp::ack_stream_started(ack);
   } else {
     btif_a2dp_command_ack(ack);
+    btif_a2dp_audio_on_started(status);
   }
 }
 
diff --git a/btif/src/btif_a2dp_audio_interface.cc b/btif/src/btif_a2dp_audio_interface.cc
index 7343bbe..7e46818 100644
--- a/btif/src/btif_a2dp_audio_interface.cc
+++ b/btif/src/btif_a2dp_audio_interface.cc
@@ -40,11 +40,13 @@
 #include "btif_av.h"
 #include "btif_av_co.h"
 #include "btif_hf.h"
-#include "osi/include/metrics.h"
+#include "common/metrics.h"
+#include "common/time_util.h"
 #include "osi/include/osi.h"
+#include "stack/include/btu.h"
 
-using system_bt_osi::A2dpSessionMetrics;
-using system_bt_osi::BluetoothMetricsLogger;
+using bluetooth::common::A2dpSessionMetrics;
+using bluetooth::common::BluetoothMetricsLogger;
 
 using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioOffload;
 using android::hardware::bluetooth::a2dp::V1_0::IBluetoothAudioHost;
@@ -107,11 +109,11 @@
   }
   void LogAudioStart() {
     std::lock_guard<std::recursive_mutex> lock(lock_);
-    audio_start_time_ms_ = time_get_os_boottime_ms();
+    audio_start_time_ms_ = bluetooth::common::time_get_os_boottime_ms();
   }
   void LogAudioStop() {
     std::lock_guard<std::recursive_mutex> lock(lock_);
-    audio_stop_time_ms_ = time_get_os_boottime_ms();
+    audio_stop_time_ms_ = bluetooth::common::time_get_os_boottime_ms();
   }
   void LogAudioStopMetricsAndReset() {
     std::lock_guard<std::recursive_mutex> lock(lock_);
@@ -163,8 +165,8 @@
       const wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
     LOG_ERROR(LOG_TAG, "%s", __func__);
     // Restart the session on the correct thread
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&btif_a2dp_audio_interface_restart_session));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&btif_a2dp_audio_interface_restart_session));
   }
 };
 sp<BluetoothAudioDeathRecipient> bluetoothAudioDeathRecipient =
@@ -299,7 +301,7 @@
 void btif_a2dp_audio_interface_start_session() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
   a2dp_offload_audio_stats.Reset();
   btif_a2dp_audio_interface_init();
   CHECK(btAudio != nullptr);
@@ -313,7 +315,7 @@
   LOG_INFO(LOG_TAG, "%s", __func__);
   a2dp_offload_audio_stats.LogAudioStopMetricsAndReset();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
   a2dp_offload_audio_stats.Reset();
   if (btAudio == nullptr) return;
   auto ret = btAudio->endSession();
@@ -339,6 +341,9 @@
   LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
   if (btAudio != nullptr) {
     if (a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
+      if (status != A2DP_CTRL_ACK_PENDING) {
+        a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
+      }
       LOG_INFO(LOG_TAG, "%s: calling method onStarted", __func__);
       auto hal_status = mapToStatus(status);
       btAudio->streamStarted(hal_status);
@@ -353,6 +358,9 @@
   LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
   if (btAudio != nullptr) {
     if (a2dp_cmd_pending == A2DP_CTRL_CMD_SUSPEND) {
+      if (status != A2DP_CTRL_ACK_PENDING) {
+        a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
+      }
       LOG_INFO(LOG_TAG, "calling method onSuspended");
       auto hal_status = mapToStatus(status);
       btAudio->streamSuspended(hal_status);
@@ -366,6 +374,7 @@
 void btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status) {
   LOG_INFO(LOG_TAG, "%s: status = %d", __func__, status);
   if (btAudio != nullptr && a2dp_cmd_pending == A2DP_CTRL_CMD_START) {
+    a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
     LOG_INFO(LOG_TAG, "%s: Remote disconnected when start under progress",
              __func__);
     btAudio->streamStarted(mapToStatus(A2DP_CTRL_ACK_DISCONNECT_IN_PROGRESS));
@@ -418,7 +427,6 @@
 uint8_t btif_a2dp_audio_process_request(uint8_t cmd) {
   LOG_INFO(LOG_TAG, "%s: cmd: %s", __func__,
            audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
-  a2dp_cmd_pending = cmd;
   uint8_t status;
   switch (cmd) {
     case A2DP_CTRL_CMD_START:
@@ -461,7 +469,7 @@
       APPL_TRACE_WARNING("%s: A2DP command %s while AV stream is not ready",
                          __func__,
                          audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd));
-      return A2DP_CTRL_ACK_FAILURE;
+      status = A2DP_CTRL_ACK_FAILURE;
       break;
 
     case A2DP_CTRL_CMD_STOP:
@@ -472,7 +480,7 @@
         break;
       }
       btif_av_stream_stop(RawAddress::kEmpty);
-      return A2DP_CTRL_ACK_SUCCESS;
+      status = A2DP_CTRL_ACK_SUCCESS;
       break;
 
     case A2DP_CTRL_CMD_SUSPEND:
@@ -502,5 +510,10 @@
   }
   LOG_INFO(LOG_TAG, "a2dp-ctrl-cmd : %s DONE returning status %d",
            audio_a2dp_hw_dump_ctrl_event((tA2DP_CTRL_CMD)cmd), status);
+  if (status == A2DP_CTRL_ACK_PENDING) {
+    a2dp_cmd_pending = cmd;
+  } else {
+    a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
+  }
   return status;
 }
diff --git a/btif/src/btif_a2dp_audio_interface_linux.cc b/btif/src/btif_a2dp_audio_interface_linux.cc
new file mode 100644
index 0000000..b5a0e19
--- /dev/null
+++ b/btif/src/btif_a2dp_audio_interface_linux.cc
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2018 Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "btif_a2dp_audio_interface.h"
+
+#include <base/logging.h>
+
+void btif_a2dp_audio_on_started(tBTA_AV_STATUS status) {
+  LOG(FATAL) << "Unimplemented yet";
+}
+void btif_a2dp_audio_on_stopped(tBTA_AV_STATUS status) {
+  LOG(FATAL) << "Unimplemented yet";
+}
+void btif_a2dp_audio_on_suspended(tBTA_AV_STATUS status) {
+  LOG(FATAL) << "Unimplemented yet";
+}
+void btif_a2dp_audio_interface_start_session(void) {
+  LOG(FATAL) << "Unimplemented yet";
+}
+void btif_a2dp_audio_interface_end_session(void) {
+  LOG(FATAL) << "Unimplemented yet";
+}
diff --git a/btif/src/btif_a2dp_control.cc b/btif/src/btif_a2dp_control.cc
index fb62480..26b7f02 100644
--- a/btif/src/btif_a2dp_control.cc
+++ b/btif/src/btif_a2dp_control.cc
@@ -48,7 +48,7 @@
 
 /* We can have max one command pending */
 static tA2DP_CTRL_CMD a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
-std::unique_ptr<tUIPC_STATE> a2dp_uipc;
+std::unique_ptr<tUIPC_STATE> a2dp_uipc = nullptr;
 
 void btif_a2dp_control_init(void) {
   a2dp_uipc = UIPC_Init();
@@ -57,7 +57,9 @@
 
 void btif_a2dp_control_cleanup(void) {
   /* This calls blocks until UIPC is fully closed */
-  UIPC_Close(*a2dp_uipc, UIPC_CH_ID_ALL);
+  if (a2dp_uipc != nullptr) {
+    UIPC_Close(*a2dp_uipc, UIPC_CH_ID_ALL);
+  }
 }
 
 static void btif_a2dp_recv_ctrl_data(void) {
@@ -419,7 +421,9 @@
   a2dp_cmd_pending = A2DP_CTRL_CMD_NONE;
 
   /* Acknowledge start request */
-  UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
+  if (a2dp_uipc != nullptr) {
+    UIPC_Send(*a2dp_uipc, UIPC_CH_ID_AV_CTRL, 0, &ack, sizeof(ack));
+  }
 }
 
 void btif_a2dp_control_log_bytes_read(uint32_t bytes_read) {
diff --git a/btif/src/btif_a2dp_sink.cc b/btif/src/btif_a2dp_sink.cc
index c17b33a..bb1bc49 100644
--- a/btif/src/btif_a2dp_sink.cc
+++ b/btif/src/btif_a2dp_sink.cc
@@ -20,8 +20,12 @@
 #define LOG_TAG "bt_btif_a2dp_sink"
 
 #include <atomic>
+#include <cstdio>
 #include <cstring>
 #include <mutex>
+#include <string>
+
+#include <base/bind.h>
 
 #include "bt_common.h"
 #include "btif_a2dp.h"
@@ -30,11 +34,12 @@
 #include "btif_av_co.h"
 #include "btif_avrcp_audio_track.h"
 #include "btif_util.h"
+#include "common/message_loop_thread.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "osi/include/thread.h"
 
+using bluetooth::common::MessageLoopThread;
 using LockGuard = std::lock_guard<std::mutex>;
 
 /**
@@ -73,47 +78,77 @@
 } tBTIF_MEDIA_SINK_FOCUS_UPDATE;
 
 /* BTIF A2DP Sink control block */
-typedef struct {
-  thread_t* worker_thread;
-  fixed_queue_t* cmd_msg_queue;
+class BtifA2dpSinkControlBlock {
+ public:
+  explicit BtifA2dpSinkControlBlock(const std::string& thread_name)
+      : worker_thread(thread_name),
+        rx_audio_queue(nullptr),
+        rx_flush(false),
+        decode_alarm(nullptr),
+        sample_rate(0),
+        channel_count(0),
+        rx_focus_state(BTIF_A2DP_SINK_FOCUS_NOT_GRANTED),
+        audio_track(nullptr),
+        decoder_interface(nullptr) {}
+
+  void Reset() {
+    if (audio_track != nullptr) {
+      BtifAvrcpAudioTrackStop(audio_track);
+      BtifAvrcpAudioTrackDelete(audio_track);
+    }
+    audio_track = nullptr;
+    fixed_queue_free(rx_audio_queue, nullptr);
+    rx_audio_queue = nullptr;
+    alarm_free(decode_alarm);
+    decode_alarm = nullptr;
+    rx_flush = false;
+    rx_focus_state = BTIF_A2DP_SINK_FOCUS_NOT_GRANTED;
+    sample_rate = 0;
+    channel_count = 0;
+    decoder_interface = nullptr;
+  }
+
+  MessageLoopThread worker_thread;
   fixed_queue_t* rx_audio_queue;
   bool rx_flush; /* discards any incoming data when true */
   alarm_t* decode_alarm;
   tA2DP_SAMPLE_RATE sample_rate;
+  tA2DP_BITS_PER_SAMPLE bits_per_sample;
   tA2DP_CHANNEL_COUNT channel_count;
   btif_a2dp_sink_focus_state_t rx_focus_state; /* audio focus state */
   void* audio_track;
   const tA2DP_DECODER_INTERFACE* decoder_interface;
-} tBTIF_A2DP_SINK_CB;
+};
 
 // Mutex for below data structures.
 static std::mutex g_mutex;
 
-static tBTIF_A2DP_SINK_CB btif_a2dp_sink_cb;
+static BtifA2dpSinkControlBlock btif_a2dp_sink_cb("bt_a2dp_sink_worker_thread");
 
 static std::atomic<int> btif_a2dp_sink_state{BTIF_A2DP_SINK_STATE_OFF};
 
-static void btif_a2dp_sink_init_delayed(void* context);
-static void btif_a2dp_sink_startup_delayed(void* context);
-static void btif_a2dp_sink_start_session_delayed(void* context);
-static void btif_a2dp_sink_end_session_delayed(void* context);
-static void btif_a2dp_sink_shutdown_delayed(void* context);
-static void btif_a2dp_sink_cleanup_delayed(void* context);
-static void btif_a2dp_sink_command_ready(fixed_queue_t* queue, void* context);
-static void btif_a2dp_sink_audio_handle_stop_decoding(void);
+static void btif_a2dp_sink_init_delayed();
+static void btif_a2dp_sink_startup_delayed();
+static void btif_a2dp_sink_start_session_delayed(
+    std::promise<void> peer_ready_promise);
+static void btif_a2dp_sink_end_session_delayed();
+static void btif_a2dp_sink_shutdown_delayed();
+static void btif_a2dp_sink_cleanup_delayed();
+static void btif_a2dp_sink_command_ready(BT_HDR* p_msg);
+static void btif_a2dp_sink_audio_handle_stop_decoding();
 static void btif_decode_alarm_cb(void* context);
-static void btif_a2dp_sink_audio_handle_start_decoding(void);
-static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context);
-static void btif_a2dp_sink_audio_rx_flush_req(void);
+static void btif_a2dp_sink_audio_handle_start_decoding();
+static void btif_a2dp_sink_avk_handle_timer();
+static void btif_a2dp_sink_audio_rx_flush_req();
 /* Handle incoming media packets A2DP SINK streaming */
 static void btif_a2dp_sink_handle_inc_media(BT_HDR* p_msg);
 static void btif_a2dp_sink_decoder_update_event(
     tBTIF_MEDIA_SINK_DECODER_UPDATE* p_buf);
-static void btif_a2dp_sink_clear_track_event(void);
+static void btif_a2dp_sink_clear_track_event();
 static void btif_a2dp_sink_set_focus_state_event(
     btif_a2dp_sink_focus_state_t state);
-static void btif_a2dp_sink_audio_rx_flush_event(void);
-static void btif_a2dp_sink_clear_track_event_req(void);
+static void btif_a2dp_sink_audio_rx_flush_event();
+static void btif_a2dp_sink_clear_track_event_req();
 
 UNUSED_ATTR static const char* dump_media_event(uint16_t event) {
   switch (event) {
@@ -127,7 +162,7 @@
   return "UNKNOWN A2DP SINK EVENT";
 }
 
-bool btif_a2dp_sink_init(void) {
+bool btif_a2dp_sink_init() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
 
@@ -136,72 +171,75 @@
     return false;
   }
 
-  memset(&btif_a2dp_sink_cb, 0, sizeof(btif_a2dp_sink_cb));
+  btif_a2dp_sink_cb.Reset();
   btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_STARTING_UP;
 
   /* Start A2DP Sink media task */
-  btif_a2dp_sink_cb.worker_thread = thread_new("btif_a2dp_sink_worker_thread");
-  if (btif_a2dp_sink_cb.worker_thread == NULL) {
+  btif_a2dp_sink_cb.worker_thread.StartUp();
+  if (!btif_a2dp_sink_cb.worker_thread.IsRunning()) {
     LOG_ERROR(LOG_TAG, "%s: unable to start up media thread", __func__);
     btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF;
     return false;
   }
 
-  btif_a2dp_sink_cb.rx_focus_state = BTIF_A2DP_SINK_FOCUS_NOT_GRANTED;
-  btif_a2dp_sink_cb.audio_track = NULL;
   btif_a2dp_sink_cb.rx_audio_queue = fixed_queue_new(SIZE_MAX);
 
-  btif_a2dp_sink_cb.cmd_msg_queue = fixed_queue_new(SIZE_MAX);
-  fixed_queue_register_dequeue(
-      btif_a2dp_sink_cb.cmd_msg_queue,
-      thread_get_reactor(btif_a2dp_sink_cb.worker_thread),
-      btif_a2dp_sink_command_ready, NULL);
-
   /* Schedule the rest of the operations */
-  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_init_delayed,
-              NULL);
-
+  if (!btif_a2dp_sink_cb.worker_thread.EnableRealTimeScheduling()) {
+    LOG(FATAL) << __func__
+               << ": Failed to increase A2DP decoder thread priority";
+  }
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_init_delayed));
   return true;
 }
 
-static void btif_a2dp_sink_init_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_init_delayed() {
   LOG_INFO(LOG_TAG, "%s", __func__);
-  raise_priority_a2dp(TASK_HIGH_MEDIA);
   btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_RUNNING;
 }
 
-bool btif_a2dp_sink_startup(void) {
+bool btif_a2dp_sink_startup() {
   LOG_INFO(LOG_TAG, "%s", __func__);
-  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_startup_delayed,
-              NULL);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_startup_delayed));
   return true;
 }
 
-static void btif_a2dp_sink_startup_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_startup_delayed() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
   // Nothing to do
 }
 
-bool btif_a2dp_sink_start_session(const RawAddress& peer_address) {
-  LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
-           peer_address.ToString().c_str());
-  thread_post(btif_a2dp_sink_cb.worker_thread,
-              btif_a2dp_sink_start_session_delayed, NULL);
-  return true;
+bool btif_a2dp_sink_start_session(const RawAddress& peer_address,
+                                  std::promise<void> peer_ready_promise) {
+  LOG(INFO) << __func__ << ": peer_address=" << peer_address;
+  if (btif_a2dp_sink_cb.worker_thread.DoInThread(
+          FROM_HERE, base::BindOnce(btif_a2dp_sink_start_session_delayed,
+                                    std::move(peer_ready_promise)))) {
+    return true;
+  } else {
+    // cannot set promise but triggers crash
+    LOG(FATAL) << __func__ << ": peer_address=" << peer_address
+               << " fails to context switch";
+    return false;
+  }
 }
 
-static void btif_a2dp_sink_start_session_delayed(UNUSED_ATTR void* context) {
-  LOG_INFO(LOG_TAG, "%s", __func__);
+static void btif_a2dp_sink_start_session_delayed(
+    std::promise<void> peer_ready_promise) {
+  LOG(INFO) << __func__;
   LockGuard lock(g_mutex);
+  peer_ready_promise.set_value();
   // Nothing to do
 }
 
 bool btif_a2dp_sink_restart_session(const RawAddress& old_peer_address,
-                                    const RawAddress& new_peer_address) {
-  LOG_INFO(LOG_TAG, "%s: old_peer_address=%s new_peer_address=%s", __func__,
-           old_peer_address.ToString().c_str(),
-           new_peer_address.ToString().c_str());
+                                    const RawAddress& new_peer_address,
+                                    std::promise<void> peer_ready_promise) {
+  LOG(INFO) << __func__ << ": old_peer_address=" << old_peer_address
+            << " new_peer_address=" << new_peer_address;
 
   CHECK(!new_peer_address.IsEmpty());
 
@@ -210,15 +248,17 @@
   }
 
   if (!bta_av_co_set_active_peer(new_peer_address)) {
-    LOG_ERROR(LOG_TAG, "%s: Cannot stream audio: cannot set active peer to %s",
-              __func__, new_peer_address.ToString().c_str());
+    LOG(ERROR) << __func__
+               << ": Cannot stream audio: cannot set active peer to "
+               << new_peer_address;
+    peer_ready_promise.set_value();
     return false;
   }
 
   if (old_peer_address.IsEmpty()) {
     btif_a2dp_sink_startup();
   }
-  btif_a2dp_sink_start_session(new_peer_address);
+  btif_a2dp_sink_start_session(new_peer_address, std::move(peer_ready_promise));
 
   return true;
 }
@@ -226,35 +266,33 @@
 bool btif_a2dp_sink_end_session(const RawAddress& peer_address) {
   LOG_INFO(LOG_TAG, "%s: peer_address=%s", __func__,
            peer_address.ToString().c_str());
-  thread_post(btif_a2dp_sink_cb.worker_thread,
-              btif_a2dp_sink_end_session_delayed, NULL);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_end_session_delayed));
   return true;
 }
 
-static void btif_a2dp_sink_end_session_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_end_session_delayed() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
   // Nothing to do
 }
 
-void btif_a2dp_sink_shutdown(void) {
+void btif_a2dp_sink_shutdown() {
   LOG_INFO(LOG_TAG, "%s", __func__);
-  thread_post(btif_a2dp_sink_cb.worker_thread, btif_a2dp_sink_shutdown_delayed,
-              NULL);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_shutdown_delayed));
 }
 
-static void btif_a2dp_sink_shutdown_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_shutdown_delayed() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
   // Nothing to do
 }
 
-void btif_a2dp_sink_cleanup(void) {
+void btif_a2dp_sink_cleanup() {
   LOG_INFO(LOG_TAG, "%s", __func__);
 
   alarm_t* decode_alarm;
-  fixed_queue_t* cmd_msg_queue;
-  thread_t* worker_thread;
 
   // Make sure the sink is shutdown
   btif_a2dp_sink_shutdown();
@@ -269,47 +307,43 @@
     btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_SHUTTING_DOWN;
 
     decode_alarm = btif_a2dp_sink_cb.decode_alarm;
-    btif_a2dp_sink_cb.decode_alarm = NULL;
-
-    cmd_msg_queue = btif_a2dp_sink_cb.cmd_msg_queue;
-    btif_a2dp_sink_cb.cmd_msg_queue = NULL;
-
-    worker_thread = btif_a2dp_sink_cb.worker_thread;
-    btif_a2dp_sink_cb.worker_thread = NULL;
+    btif_a2dp_sink_cb.decode_alarm = nullptr;
   }
 
   // Stop the timer
   alarm_free(decode_alarm);
 
   // Exit the thread
-  fixed_queue_free(cmd_msg_queue, NULL);
-  thread_post(worker_thread, btif_a2dp_sink_cleanup_delayed, NULL);
-  thread_free(worker_thread);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_cleanup_delayed));
+  btif_a2dp_sink_cb.worker_thread.ShutDown();
 }
 
-static void btif_a2dp_sink_cleanup_delayed(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_cleanup_delayed() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
 
-  fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, NULL);
-  btif_a2dp_sink_cb.rx_audio_queue = NULL;
+  fixed_queue_free(btif_a2dp_sink_cb.rx_audio_queue, nullptr);
+  btif_a2dp_sink_cb.rx_audio_queue = nullptr;
   btif_a2dp_sink_state = BTIF_A2DP_SINK_STATE_OFF;
 }
 
-tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate(void) {
+tA2DP_SAMPLE_RATE btif_a2dp_sink_get_sample_rate() {
   LockGuard lock(g_mutex);
   return btif_a2dp_sink_cb.sample_rate;
 }
 
-tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count(void) {
+tA2DP_BITS_PER_SAMPLE btif_a2dp_sink_get_bits_per_sample() {
+  LockGuard lock(g_mutex);
+  return btif_a2dp_sink_cb.bits_per_sample;
+}
+
+tA2DP_CHANNEL_COUNT btif_a2dp_sink_get_channel_count() {
   LockGuard lock(g_mutex);
   return btif_a2dp_sink_cb.channel_count;
 }
 
-static void btif_a2dp_sink_command_ready(fixed_queue_t* queue,
-                                         UNUSED_ATTR void* context) {
-  BT_HDR* p_msg = (BT_HDR*)fixed_queue_dequeue(queue);
-
+static void btif_a2dp_sink_command_ready(BT_HDR* p_msg) {
   LOG_VERBOSE(LOG_TAG, "%s: event %d %s", __func__, p_msg->event,
               dump_media_event(p_msg->event));
 
@@ -352,10 +386,11 @@
   memcpy(p_buf->codec_info, p_codec_info, AVDT_CODEC_SIZE);
   p_buf->hdr.event = BTIF_MEDIA_SINK_DECODER_UPDATE;
 
-  fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, (BT_HDR*)p_buf));
 }
 
-void btif_a2dp_sink_on_idle(void) {
+void btif_a2dp_sink_on_idle() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   if (btif_a2dp_sink_state == BTIF_A2DP_SINK_STATE_OFF) return;
   btif_a2dp_sink_audio_handle_stop_decoding();
@@ -374,7 +409,7 @@
   btif_a2dp_sink_audio_handle_stop_decoding();
 }
 
-static void btif_a2dp_sink_audio_handle_stop_decoding(void) {
+static void btif_a2dp_sink_audio_handle_stop_decoding() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   alarm_t* old_alarm;
   {
@@ -382,7 +417,7 @@
     btif_a2dp_sink_cb.rx_flush = true;
     btif_a2dp_sink_audio_rx_flush_req();
     old_alarm = btif_a2dp_sink_cb.decode_alarm;
-    btif_a2dp_sink_cb.decode_alarm = NULL;
+    btif_a2dp_sink_cb.decode_alarm = nullptr;
   }
 
   // Drop the lock here, btif_decode_alarm_cb may in the process of being called
@@ -401,13 +436,11 @@
 
 static void btif_decode_alarm_cb(UNUSED_ATTR void* context) {
   LockGuard lock(g_mutex);
-  if (btif_a2dp_sink_cb.worker_thread != NULL) {
-    thread_post(btif_a2dp_sink_cb.worker_thread,
-                btif_a2dp_sink_avk_handle_timer, NULL);
-  }
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_avk_handle_timer));
 }
 
-static void btif_a2dp_sink_clear_track_event(void) {
+static void btif_a2dp_sink_clear_track_event() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
 
@@ -415,13 +448,13 @@
   BtifAvrcpAudioTrackStop(btif_a2dp_sink_cb.audio_track);
   BtifAvrcpAudioTrackDelete(btif_a2dp_sink_cb.audio_track);
 #endif
-  btif_a2dp_sink_cb.audio_track = NULL;
+  btif_a2dp_sink_cb.audio_track = nullptr;
 }
 
 // Must be called while locked.
-static void btif_a2dp_sink_audio_handle_start_decoding(void) {
+static void btif_a2dp_sink_audio_handle_start_decoding() {
   LOG_INFO(LOG_TAG, "%s", __func__);
-  if (btif_a2dp_sink_cb.decode_alarm != NULL)
+  if (btif_a2dp_sink_cb.decode_alarm != nullptr)
     return;  // Already started decoding
 
 #ifndef OS_GENERIC
@@ -429,12 +462,12 @@
 #endif
 
   btif_a2dp_sink_cb.decode_alarm = alarm_new_periodic("btif.a2dp_sink_decode");
-  if (btif_a2dp_sink_cb.decode_alarm == NULL) {
+  if (btif_a2dp_sink_cb.decode_alarm == nullptr) {
     LOG_ERROR(LOG_TAG, "%s: unable to allocate decode alarm", __func__);
     return;
   }
   alarm_set(btif_a2dp_sink_cb.decode_alarm, BTIF_SINK_MEDIA_TIME_TICK_MS,
-            btif_decode_alarm_cb, NULL);
+            btif_decode_alarm_cb, nullptr);
 }
 
 static void btif_a2dp_sink_on_decode_complete(uint8_t* data, uint32_t len) {
@@ -452,13 +485,13 @@
     return;
   }
 
-  CHECK(btif_a2dp_sink_cb.decoder_interface);
+  CHECK(btif_a2dp_sink_cb.decoder_interface != nullptr);
   if (!btif_a2dp_sink_cb.decoder_interface->decode_packet(p_msg)) {
     LOG_ERROR(LOG_TAG, "%s: decoding failed", __func__);
   }
 }
 
-static void btif_a2dp_sink_avk_handle_timer(UNUSED_ATTR void* context) {
+static void btif_a2dp_sink_avk_handle_timer() {
   LockGuard lock(g_mutex);
 
   BT_HDR* p_msg;
@@ -503,7 +536,7 @@
   btif_a2dp_sink_cb.rx_flush = enable;
 }
 
-static void btif_a2dp_sink_audio_rx_flush_event(void) {
+static void btif_a2dp_sink_audio_rx_flush_event() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   LockGuard lock(g_mutex);
   // Flush all received encoded audio buffers
@@ -524,6 +557,11 @@
     LOG_ERROR(LOG_TAG, "%s: cannot get the track frequency", __func__);
     return;
   }
+  int bits_per_sample = A2DP_GetTrackBitsPerSample(p_buf->codec_info);
+  if (bits_per_sample == -1) {
+    LOG_ERROR(LOG_TAG, "%s: cannot get the bits per sample", __func__);
+    return;
+  }
   int channel_count = A2DP_GetTrackChannelCount(p_buf->codec_info);
   if (channel_count == -1) {
     LOG_ERROR(LOG_TAG, "%s: cannot get the channel count", __func__);
@@ -535,13 +573,14 @@
     return;
   }
   btif_a2dp_sink_cb.sample_rate = sample_rate;
+  btif_a2dp_sink_cb.bits_per_sample = bits_per_sample;
   btif_a2dp_sink_cb.channel_count = channel_count;
 
   btif_a2dp_sink_cb.rx_flush = false;
   APPL_TRACE_DEBUG("%s: reset to Sink role", __func__);
 
   btif_a2dp_sink_cb.decoder_interface = bta_av_co_get_decoder_interface();
-  if (btif_a2dp_sink_cb.decoder_interface == NULL) {
+  if (btif_a2dp_sink_cb.decoder_interface == nullptr) {
     LOG_ERROR(LOG_TAG, "%s: cannot stream audio: no source decoder interface",
               __func__);
     return;
@@ -556,11 +595,11 @@
   APPL_TRACE_DEBUG("%s: create audio track", __func__);
   btif_a2dp_sink_cb.audio_track =
 #ifndef OS_GENERIC
-      BtifAvrcpAudioTrackCreate(sample_rate, channel_type);
+      BtifAvrcpAudioTrackCreate(sample_rate, bits_per_sample, channel_type);
 #else
       NULL;
 #endif
-  if (btif_a2dp_sink_cb.audio_track == NULL) {
+  if (btif_a2dp_sink_cb.audio_track == nullptr) {
     LOG_ERROR(LOG_TAG, "%s: track creation failed", __func__);
     return;
   }
@@ -595,7 +634,7 @@
   return fixed_queue_length(btif_a2dp_sink_cb.rx_audio_queue);
 }
 
-void btif_a2dp_sink_audio_rx_flush_req(void) {
+void btif_a2dp_sink_audio_rx_flush_req() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   if (fixed_queue_is_empty(btif_a2dp_sink_cb.rx_audio_queue)) {
     /* Queue is already empty */
@@ -604,7 +643,8 @@
 
   BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR)));
   p_buf->event = BTIF_MEDIA_SINK_AUDIO_RX_FLUSH;
-  fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, p_buf));
 }
 
 void btif_a2dp_sink_debug_dump(UNUSED_ATTR int fd) {
@@ -618,7 +658,8 @@
           osi_malloc(sizeof(tBTIF_MEDIA_SINK_FOCUS_UPDATE)));
   p_buf->focus_state = state;
   p_buf->hdr.event = BTIF_MEDIA_SINK_SET_FOCUS_STATE;
-  fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, (BT_HDR*)p_buf));
 }
 
 static void btif_a2dp_sink_set_focus_state_event(
@@ -646,10 +687,11 @@
 #endif
 }
 
-static void btif_a2dp_sink_clear_track_event_req(void) {
+static void btif_a2dp_sink_clear_track_event_req() {
   LOG_INFO(LOG_TAG, "%s", __func__);
   BT_HDR* p_buf = reinterpret_cast<BT_HDR*>(osi_malloc(sizeof(BT_HDR)));
 
   p_buf->event = BTIF_MEDIA_SINK_CLEAR_TRACK;
-  fixed_queue_enqueue(btif_a2dp_sink_cb.cmd_msg_queue, p_buf);
+  btif_a2dp_sink_cb.worker_thread.DoInThread(
+      FROM_HERE, base::BindOnce(btif_a2dp_sink_command_ready, p_buf));
 }
diff --git a/btif/src/btif_a2dp_source.cc b/btif/src/btif_a2dp_source.cc
index 78e5a4e..9951ce1 100644
--- a/btif/src/btif_a2dp_source.cc
+++ b/btif/src/btif_a2dp_source.cc
@@ -30,6 +30,7 @@
 #include <algorithm>
 
 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
+#include "audio_hal_interface/a2dp_encoding.h"
 #include "bt_common.h"
 #include "bta_av_ci.h"
 #include "btif_a2dp.h"
@@ -39,19 +40,19 @@
 #include "btif_av.h"
 #include "btif_av_co.h"
 #include "btif_util.h"
+#include "common/message_loop_thread.h"
+#include "common/metrics.h"
+#include "common/repeating_timer.h"
+#include "common/time_util.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/log.h"
-#include "osi/include/metrics.h"
 #include "osi/include/osi.h"
-#include "osi/include/thread.h"
-#include "osi/include/time.h"
+#include "osi/include/wakelock.h"
 #include "uipc.h"
 
-#include <condition_variable>
-#include <mutex>
-
-using system_bt_osi::BluetoothMetricsLogger;
-using system_bt_osi::A2dpSessionMetrics;
+using bluetooth::common::A2dpSessionMetrics;
+using bluetooth::common::BluetoothMetricsLogger;
+using bluetooth::common::RepeatingTimer;
 
 extern std::unique_ptr<tUIPC_STATE> a2dp_uipc;
 
@@ -165,95 +166,6 @@
   int codec_index = -1;
 };
 
-class BtWorkerThread {
- public:
-  BtWorkerThread(const std::string& thread_name)
-      : thread_name_(thread_name),
-        message_loop_(nullptr),
-        run_loop_(nullptr),
-        message_loop_thread_(nullptr),
-        started_(false) {}
-
-  void StartUp() {
-    if (message_loop_thread_ != nullptr) {
-      return;  // Already started up
-    }
-    message_loop_thread_ = thread_new(thread_name_.c_str());
-    CHECK(message_loop_thread_ != nullptr);
-    started_ = false;
-    thread_post(message_loop_thread_, &BtWorkerThread::RunThread, this);
-    {
-      // Block until run_loop_ is allocated and ready to run
-      std::unique_lock<std::mutex> start_lock(start_up_mutex_);
-      while (!started_) {
-        start_up_cv_.wait(start_lock);
-      }
-    }
-  }
-
-  bool DoInThread(const tracked_objects::Location& from_here,
-                  const base::Closure& task) {
-    if ((message_loop_ == nullptr) || !message_loop_->task_runner().get()) {
-      LOG_ERROR(
-          LOG_TAG,
-          "%s: Dropping message for thread %s: message loop is not initialized",
-          __func__, thread_name_.c_str());
-      return false;
-    }
-    if (!message_loop_->task_runner()->PostTask(from_here, task)) {
-      LOG_ERROR(LOG_TAG,
-                "%s: Posting task to message loop for thread %s failed",
-                __func__, thread_name_.c_str());
-      return false;
-    }
-    return true;
-  }
-
-  void ShutDown() {
-    if ((run_loop_ != nullptr) && (message_loop_ != nullptr)) {
-      message_loop_->task_runner()->PostTask(FROM_HERE,
-                                             run_loop_->QuitClosure());
-    }
-    thread_free(message_loop_thread_);
-    message_loop_thread_ = nullptr;
-  }
-
- private:
-  static void RunThread(void* context) {
-    auto wt = static_cast<BtWorkerThread*>(context);
-    wt->Run();
-  }
-
-  void Run() {
-    LOG_INFO(LOG_TAG, "%s: message loop for thread %s started", __func__,
-             thread_name_.c_str());
-    message_loop_ = new base::MessageLoop();
-    run_loop_ = new base::RunLoop();
-    {
-      std::unique_lock<std::mutex> start_lock(start_up_mutex_);
-      started_ = true;
-      start_up_cv_.notify_all();
-    }
-    // Blocking util ShutDown() is called
-    run_loop_->Run();
-    delete message_loop_;
-    message_loop_ = nullptr;
-    delete run_loop_;
-    run_loop_ = nullptr;
-    LOG_INFO(LOG_TAG, "%s: message loop for thread %s finished", __func__,
-             thread_name_.c_str());
-  }
-
-  std::string thread_name_;
-  base::MessageLoop* message_loop_;
-  base::RunLoop* run_loop_;
-  thread_t* message_loop_thread_;
-  // For start-up
-  bool started_;
-  std::mutex start_up_mutex_;
-  std::condition_variable start_up_cv_;
-};
-
 class BtifA2dpSource {
  public:
   enum RunState {
@@ -266,7 +178,6 @@
   BtifA2dpSource()
       : tx_audio_queue(nullptr),
         tx_flush(false),
-        media_alarm(nullptr),
         encoder_interface(nullptr),
         encoder_interval_ms(0),
         state_(kStateOff) {}
@@ -275,8 +186,8 @@
     fixed_queue_free(tx_audio_queue, nullptr);
     tx_audio_queue = nullptr;
     tx_flush = false;
-    alarm_free(media_alarm);
-    media_alarm = nullptr;
+    media_alarm.CancelAndWait();
+    wakelock_release();
     encoder_interface = nullptr;
     encoder_interval_ms = 0;
     stats.Reset();
@@ -302,9 +213,9 @@
 
   fixed_queue_t* tx_audio_queue;
   bool tx_flush; /* Discards any outgoing data when true */
-  alarm_t* media_alarm;
+  RepeatingTimer media_alarm;
   const tA2DP_ENCODER_INTERFACE* encoder_interface;
-  period_ms_t encoder_interval_ms; /* Local copy of the encoder interval */
+  uint64_t encoder_interval_ms; /* Local copy of the encoder interval */
   BtifMediaStats stats;
   BtifMediaStats accumulated_stats;
 
@@ -312,13 +223,14 @@
   BtifA2dpSource::RunState state_;
 };
 
-static BtWorkerThread btif_a2dp_source_thread("btif_a2dp_source_thread");
+static bluetooth::common::MessageLoopThread btif_a2dp_source_thread(
+    "bt_a2dp_source_worker_thread");
 static BtifA2dpSource btif_a2dp_source_cb;
 
 static void btif_a2dp_source_init_delayed(void);
 static void btif_a2dp_source_startup_delayed(void);
 static void btif_a2dp_source_start_session_delayed(
-    const RawAddress& peer_address);
+    const RawAddress& peer_address, std::promise<void> start_session_promise);
 static void btif_a2dp_source_end_session_delayed(
     const RawAddress& peer_address);
 static void btif_a2dp_source_shutdown_delayed(void);
@@ -338,7 +250,6 @@
 static void btif_a2dp_source_audio_feeding_update_event(
     const btav_a2dp_codec_config_t& codec_audio_config);
 static bool btif_a2dp_source_audio_tx_flush_req(void);
-static void btif_a2dp_source_alarm_cb(void* context);
 static void btif_a2dp_source_audio_handle_timer(void);
 static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len);
 static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n,
@@ -439,52 +350,72 @@
   return true;
 }
 
-static void btif_a2dp_source_startup_delayed(void) {
+static void btif_a2dp_source_startup_delayed() {
   LOG_INFO(LOG_TAG, "%s: state=%s", __func__,
            btif_a2dp_source_cb.StateStr().c_str());
-
-  raise_priority_a2dp(TASK_HIGH_MEDIA);
-  btif_a2dp_control_init();
+  if (!btif_a2dp_source_thread.EnableRealTimeScheduling()) {
+    LOG(FATAL) << __func__ << ": unable to enable real time scheduling";
+  }
+  if (!bluetooth::audio::a2dp::init(&btif_a2dp_source_thread)) {
+    if (btif_av_is_a2dp_offload_enabled()) {
+      LOG(WARNING) << __func__ << ": Using BluetoothA2dp HAL";
+    } else {
+      LOG(WARNING) << __func__ << ": Using legacy HAL";
+      btif_a2dp_control_init();
+    }
+  }
   btif_a2dp_source_cb.SetState(BtifA2dpSource::kStateRunning);
 }
 
-bool btif_a2dp_source_start_session(const RawAddress& peer_address) {
-  LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
-           peer_address.ToString().c_str(),
-           btif_a2dp_source_cb.StateStr().c_str());
+bool btif_a2dp_source_start_session(const RawAddress& peer_address,
+                                    std::promise<void> peer_ready_promise) {
+  LOG(INFO) << __func__ << ": peer_address=" << peer_address
+            << " state=" << btif_a2dp_source_cb.StateStr();
   btif_a2dp_source_setup_codec(peer_address);
-  btif_a2dp_source_thread.DoInThread(
-      FROM_HERE,
-      base::Bind(&btif_a2dp_source_start_session_delayed, peer_address));
-  return true;
+  if (btif_a2dp_source_thread.DoInThread(
+          FROM_HERE,
+          base::BindOnce(&btif_a2dp_source_start_session_delayed, peer_address,
+                         std::move(peer_ready_promise)))) {
+    return true;
+  } else {
+    // cannot set promise but triggers crash
+    LOG(FATAL) << __func__ << ": peer_address=" << peer_address
+               << " state=" << btif_a2dp_source_cb.StateStr()
+               << " fails to context switch";
+    return false;
+  }
 }
 
 static void btif_a2dp_source_start_session_delayed(
-    const RawAddress& peer_address) {
-  LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
-           peer_address.ToString().c_str(),
-           btif_a2dp_source_cb.StateStr().c_str());
+    const RawAddress& peer_address, std::promise<void> peer_ready_promise) {
+  LOG(INFO) << __func__ << ": peer_address=" << peer_address
+            << " state=" << btif_a2dp_source_cb.StateStr();
   if (btif_a2dp_source_cb.State() != BtifA2dpSource::kStateRunning) {
-    LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
+    LOG(ERROR) << __func__ << ": A2DP Source media task is not running";
+    peer_ready_promise.set_value();
     return;
   }
-  if (btif_av_is_a2dp_offload_enabled()) {
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bluetooth::audio::a2dp::start_session();
+    BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
+        bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+  } else if (btif_av_is_a2dp_offload_enabled()) {
     btif_a2dp_audio_interface_start_session();
   } else {
     BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-        system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+        bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
   }
+  peer_ready_promise.set_value();
 }
 
 bool btif_a2dp_source_restart_session(const RawAddress& old_peer_address,
-                                      const RawAddress& new_peer_address) {
-  bool is_streaming = alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
-  LOG_INFO(LOG_TAG,
-           "%s: old_peer_address=%s new_peer_address=%s is_streaming=%s "
-           "state=%s",
-           __func__, old_peer_address.ToString().c_str(),
-           new_peer_address.ToString().c_str(), logbool(is_streaming).c_str(),
-           btif_a2dp_source_cb.StateStr().c_str());
+                                      const RawAddress& new_peer_address,
+                                      std::promise<void> peer_ready_promise) {
+  bool is_streaming = btif_a2dp_source_cb.media_alarm.IsScheduled();
+  LOG(INFO) << __func__ << ": old_peer_address=" << old_peer_address
+            << " new_peer_address=" << new_peer_address
+            << " is_streaming=" << logbool(is_streaming)
+            << " state=" << btif_a2dp_source_cb.StateStr();
 
   CHECK(!new_peer_address.IsEmpty());
 
@@ -503,7 +434,8 @@
 
   // Start the session.
   // If audio was streaming before, start audio streaming as well.
-  btif_a2dp_source_start_session(new_peer_address);
+  btif_a2dp_source_start_session(new_peer_address,
+                                 std::move(peer_ready_promise));
   if (is_streaming) {
     btif_a2dp_source_start_audio_req();
   }
@@ -525,18 +457,21 @@
   LOG_INFO(LOG_TAG, "%s: peer_address=%s state=%s", __func__,
            peer_address.ToString().c_str(),
            btif_a2dp_source_cb.StateStr().c_str());
-  if (!btif_av_is_a2dp_offload_enabled()) {
-    BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-        system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
-  }
   if ((btif_a2dp_source_cb.State() == BtifA2dpSource::kStateRunning) ||
       (btif_a2dp_source_cb.State() == BtifA2dpSource::kStateShuttingDown)) {
     btif_av_stream_stop(peer_address);
   } else {
     LOG_ERROR(LOG_TAG, "%s: A2DP Source media task is not running", __func__);
   }
-  if (btif_av_is_a2dp_offload_enabled()) {
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bluetooth::audio::a2dp::end_session();
+    BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+        bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
+  } else if (btif_av_is_a2dp_offload_enabled()) {
     btif_a2dp_audio_interface_end_session();
+  } else {
+    BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
+        bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
   }
 }
 
@@ -561,12 +496,16 @@
            btif_a2dp_source_cb.StateStr().c_str());
 
   // Stop the timer
-  alarm_free(btif_a2dp_source_cb.media_alarm);
-  btif_a2dp_source_cb.media_alarm = nullptr;
+  btif_a2dp_source_cb.media_alarm.CancelAndWait();
+  wakelock_release();
 
-  btif_a2dp_control_cleanup();
-  if (btif_av_is_a2dp_offload_enabled())
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bluetooth::audio::a2dp::cleanup();
+  } else if (btif_av_is_a2dp_offload_enabled()) {
     btif_a2dp_audio_interface_end_session();
+  } else {
+    btif_a2dp_control_cleanup();
+  }
   fixed_queue_free(btif_a2dp_source_cb.tx_audio_queue, nullptr);
   btif_a2dp_source_cb.tx_audio_queue = nullptr;
 
@@ -602,7 +541,7 @@
 }
 
 bool btif_a2dp_source_is_streaming(void) {
-  return alarm_is_scheduled(btif_a2dp_source_cb.media_alarm);
+  return btif_a2dp_source_cb.media_alarm.IsScheduled();
 }
 
 static void btif_a2dp_source_setup_codec(const RawAddress& peer_address) {
@@ -655,6 +594,10 @@
   // Save a local copy of the encoder_interval_ms
   btif_a2dp_source_cb.encoder_interval_ms =
       btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms();
+
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bluetooth::audio::a2dp::setup_codec();
+  }
 }
 
 void btif_a2dp_source_start_audio_req(void) {
@@ -737,12 +680,19 @@
       if (p_av_suspend->initiator) {
         LOG_WARN(LOG_TAG, "%s: A2DP stop request failed: status=%d", __func__,
                  p_av_suspend->status);
-        btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+        if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+          bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE);
+        } else {
+          btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+        }
       }
       return;
     }
   }
-
+  if (btif_av_is_a2dp_offload_enabled()) {
+    bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS);
+    return;
+  }
   /* ensure tx frames are immediately suspended */
   btif_a2dp_source_cb.tx_flush = true;
 
@@ -764,10 +714,17 @@
     if (p_av_suspend->initiator) {
       LOG_WARN(LOG_TAG, "%s: A2DP suspend request failed: status=%d", __func__,
                p_av_suspend->status);
-      btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+      if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+        bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_FAILURE);
+      } else {
+        btif_a2dp_command_ack(A2DP_CTRL_ACK_FAILURE);
+      }
     }
   }
-
+  if (btif_av_is_a2dp_offload_enabled()) {
+    bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS);
+    return;
+  }
   /* once stream is fully stopped we will ack back */
 
   /* ensure tx frames are immediately flushed */
@@ -787,7 +744,7 @@
 static void btif_a2dp_source_audio_tx_start_event(void) {
   LOG_INFO(LOG_TAG, "%s: media_alarm is %srunning, streaming %s state=%s",
            __func__,
-           alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
+           btif_a2dp_source_cb.media_alarm.IsScheduled() ? "" : "not ",
            btif_a2dp_source_is_streaming() ? "true" : "false",
            btif_a2dp_source_cb.StateStr().c_str());
 
@@ -800,22 +757,20 @@
   APPL_TRACE_EVENT(
       "%s: starting timer %" PRIu64 " ms", __func__,
       btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms());
-  alarm_free(btif_a2dp_source_cb.media_alarm);
-  btif_a2dp_source_cb.media_alarm =
-      alarm_new_periodic("btif.a2dp_source_media_alarm");
-  if (btif_a2dp_source_cb.media_alarm == nullptr) {
-    LOG_ERROR(LOG_TAG, "%s: unable to allocate media alarm", __func__);
-    return;
-  }
 
-  alarm_set(btif_a2dp_source_cb.media_alarm,
-            btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms(),
-            btif_a2dp_source_alarm_cb, nullptr);
+  wakelock_acquire();
+  btif_a2dp_source_cb.media_alarm.SchedulePeriodic(
+      btif_a2dp_source_thread.GetWeakPtr(), FROM_HERE,
+      base::Bind(&btif_a2dp_source_audio_handle_timer),
+      base::TimeDelta::FromMilliseconds(
+          btif_a2dp_source_cb.encoder_interface->get_encoder_interval_ms()));
 
   btif_a2dp_source_cb.stats.Reset();
-  // Assign session_start_us to 1 when time_get_os_boottime_us() is 0 to
-  // indicate btif_a2dp_source_start_audio_req() has been called
-  btif_a2dp_source_cb.stats.session_start_us = time_get_os_boottime_us();
+  // Assign session_start_us to 1 when
+  // bluetooth::common::time_get_os_boottime_us() is 0 to indicate
+  // btif_a2dp_source_start_audio_req() has been called
+  btif_a2dp_source_cb.stats.session_start_us =
+      bluetooth::common::time_get_os_boottime_us();
   if (btif_a2dp_source_cb.stats.session_start_us == 0) {
     btif_a2dp_source_cb.stats.session_start_us = 1;
   }
@@ -829,13 +784,14 @@
 static void btif_a2dp_source_audio_tx_stop_event(void) {
   LOG_INFO(LOG_TAG, "%s: media_alarm is %srunning, streaming %s state=%s",
            __func__,
-           alarm_is_scheduled(btif_a2dp_source_cb.media_alarm) ? "" : "not ",
+           btif_a2dp_source_cb.media_alarm.IsScheduled() ? "" : "not ",
            btif_a2dp_source_is_streaming() ? "true" : "false",
            btif_a2dp_source_cb.StateStr().c_str());
 
   if (btif_av_is_a2dp_offload_enabled()) return;
 
-  btif_a2dp_source_cb.stats.session_end_us = time_get_os_boottime_us();
+  btif_a2dp_source_cb.stats.session_end_us =
+      bluetooth::common::time_get_os_boottime_us();
   btif_a2dp_source_update_metrics();
   btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
                                     &btif_a2dp_source_cb.accumulated_stats);
@@ -844,29 +800,38 @@
   uint16_t event;
 
   // Keep track of audio data still left in the pipe
-  btif_a2dp_control_log_bytes_read(
-      UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, &event, p_buf, sizeof(p_buf)));
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    btif_a2dp_control_log_bytes_read(
+        bluetooth::audio::a2dp::read(p_buf, sizeof(p_buf)));
+  } else if (a2dp_uipc != nullptr) {
+    btif_a2dp_control_log_bytes_read(UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO,
+                                               &event, p_buf, sizeof(p_buf)));
+  }
 
   /* Stop the timer first */
-  alarm_free(btif_a2dp_source_cb.media_alarm);
-  btif_a2dp_source_cb.media_alarm = nullptr;
+  btif_a2dp_source_cb.media_alarm.CancelAndWait();
+  wakelock_release();
 
-  UIPC_Close(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO);
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bluetooth::audio::a2dp::ack_stream_suspended(A2DP_CTRL_ACK_SUCCESS);
+  } else if (a2dp_uipc != nullptr) {
+    UIPC_Close(*a2dp_uipc, 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
-   * un-blocked on wait for acknowledgment for the sent command.
-   * This resolves a corner cases AVDTP SUSPEND collision
-   * when the DUT and the remote device issue SUSPEND simultaneously
-   * and due to the processing of the SUSPEND request from the remote,
-   * the media path is torn down. If the A2DP HAL happens to wait
-   * for ACK for the initiated SUSPEND, it would never receive it casuing
-   * a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
-   * to get the ACK for any pending command in such cases.
-   */
+    /*
+     * Try to send acknowldegment once the media stream is
+     * stopped. This will make sure that the A2DP HAL layer is
+     * un-blocked on wait for acknowledgment for the sent command.
+     * This resolves a corner cases AVDTP SUSPEND collision
+     * when the DUT and the remote device issue SUSPEND simultaneously
+     * and due to the processing of the SUSPEND request from the remote,
+     * the media path is torn down. If the A2DP HAL happens to wait
+     * for ACK for the initiated SUSPEND, it would never receive it casuing
+     * a block/wait. Due to this acknowledgement, the A2DP HAL is guranteed
+     * to get the ACK for any pending command in such cases.
+     */
 
-  btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+    btif_a2dp_command_ack(A2DP_CTRL_ACK_SUCCESS);
+  }
 
   /* audio engine stopped, reset tx suspended flag */
   btif_a2dp_source_cb.tx_flush = false;
@@ -876,18 +841,13 @@
     btif_a2dp_source_cb.encoder_interface->feeding_reset();
 }
 
-static void btif_a2dp_source_alarm_cb(UNUSED_ATTR void* context) {
-  btif_a2dp_source_thread.DoInThread(
-      FROM_HERE, base::Bind(&btif_a2dp_source_audio_handle_timer));
-}
-
 static void btif_a2dp_source_audio_handle_timer(void) {
   if (btif_av_is_a2dp_offload_enabled()) return;
 
-  uint64_t timestamp_us = time_get_os_boottime_us();
+  uint64_t timestamp_us = bluetooth::common::time_get_os_boottime_us();
   log_tstamps_us("A2DP Source tx timer", timestamp_us);
 
-  if (!alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
+  if (!btif_a2dp_source_cb.media_alarm.IsScheduled()) {
     LOG_ERROR(LOG_TAG, "%s: ERROR Media task Scheduled after Suspend",
               __func__);
     return;
@@ -912,8 +872,13 @@
 
 static uint32_t btif_a2dp_source_read_callback(uint8_t* p_buf, uint32_t len) {
   uint16_t event;
-  uint32_t bytes_read =
-      UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, &event, p_buf, len);
+  uint32_t bytes_read = 0;
+
+  if (bluetooth::audio::a2dp::is_hal_2_0_enabled()) {
+    bytes_read = bluetooth::audio::a2dp::read(p_buf, len);
+  } else if (a2dp_uipc != nullptr) {
+    bytes_read = UIPC_Read(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, &event, p_buf, len);
+  }
 
   if (bytes_read < len) {
     LOG_WARN(LOG_TAG, "%s: UNDERFLOW: ONLY READ %d BYTES OUT OF %d", __func__,
@@ -922,7 +887,10 @@
         (len - bytes_read);
     btif_a2dp_source_cb.stats.media_read_total_underflow_count++;
     btif_a2dp_source_cb.stats.media_read_last_underflow_us =
-        time_get_os_boottime_us();
+        bluetooth::common::time_get_os_boottime_us();
+    bluetooth::common::LogA2dpAudioUnderrunEvent(
+        btif_av_source_active_peer(), btif_a2dp_source_cb.encoder_interval_ms,
+        len - bytes_read);
   }
 
   return bytes_read;
@@ -930,11 +898,11 @@
 
 static bool btif_a2dp_source_enqueue_callback(BT_HDR* p_buf, size_t frames_n,
                                               uint32_t bytes_read) {
-  uint64_t now_us = time_get_os_boottime_us();
+  uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
   btif_a2dp_control_log_bytes_read(bytes_read);
 
   /* Check if timer was stopped (media task stopped) */
-  if (!alarm_is_scheduled(btif_a2dp_source_cb.media_alarm)) {
+  if (!btif_a2dp_source_cb.media_alarm.IsScheduled()) {
     osi_free(p_buf);
     return false;
   }
@@ -968,10 +936,23 @@
     size_t drop_n = fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
     btif_a2dp_source_cb.stats.tx_queue_max_dropped_messages = std::max(
         drop_n, btif_a2dp_source_cb.stats.tx_queue_max_dropped_messages);
+    int num_dropped_encoded_bytes = 0;
+    int num_dropped_encoded_frames = 0;
     while (fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue)) {
       btif_a2dp_source_cb.stats.tx_queue_total_dropped_messages++;
-      osi_free(fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue));
+      void* p_data =
+          fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue);
+      if (p_data != nullptr) {
+        auto p_dropped_buf = static_cast<BT_HDR*>(p_data);
+        num_dropped_encoded_bytes += p_dropped_buf->len;
+        num_dropped_encoded_frames += p_dropped_buf->layer_specific;
+        osi_free(p_data);
+      }
     }
+    bluetooth::common::LogA2dpAudioOverrunEvent(
+        btif_av_source_active_peer(), drop_n,
+        btif_a2dp_source_cb.encoder_interval_ms, num_dropped_encoded_frames,
+        num_dropped_encoded_bytes);
 
     // Request additional debug info if we had to flush buffers
     RawAddress peer_bda = btif_av_source_active_peer();
@@ -1022,10 +1003,12 @@
   btif_a2dp_source_cb.stats.tx_queue_total_flushed_messages +=
       fixed_queue_length(btif_a2dp_source_cb.tx_audio_queue);
   btif_a2dp_source_cb.stats.tx_queue_last_flushed_us =
-      time_get_os_boottime_us();
+      bluetooth::common::time_get_os_boottime_us();
   fixed_queue_flush(btif_a2dp_source_cb.tx_audio_queue, osi_free);
 
-  UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, nullptr);
+  if (!bluetooth::audio::a2dp::is_hal_2_0_enabled() && a2dp_uipc != nullptr) {
+    UIPC_Ioctl(*a2dp_uipc, UIPC_CH_ID_AV_AUDIO, UIPC_REQ_RX_FLUSH, nullptr);
+  }
 }
 
 static bool btif_a2dp_source_audio_tx_flush_req(void) {
@@ -1038,7 +1021,7 @@
 }
 
 BT_HDR* btif_a2dp_source_audio_readbuf(void) {
-  uint64_t now_us = time_get_os_boottime_us();
+  uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
   BT_HDR* p_buf =
       (BT_HDR*)fixed_queue_try_dequeue(btif_a2dp_source_cb.tx_audio_queue);
 
@@ -1105,7 +1088,7 @@
 void btif_a2dp_source_debug_dump(int fd) {
   btif_a2dp_source_accumulate_stats(&btif_a2dp_source_cb.stats,
                                     &btif_a2dp_source_cb.accumulated_stats);
-  uint64_t now_us = time_get_os_boottime_us();
+  uint64_t now_us = bluetooth::common::time_get_os_boottime_us();
   BtifMediaStats* accumulated_stats = &btif_a2dp_source_cb.accumulated_stats;
   SchedulingStats* enqueue_stats = &accumulated_stats->tx_queue_enqueue_stats;
   SchedulingStats* dequeue_stats = &accumulated_stats->tx_queue_dequeue_stats;
@@ -1277,7 +1260,7 @@
   // mark the metric duration as invalid (-1) in this case
   if (stats.session_start_us != 0) {
     int64_t session_end_us = stats.session_end_us == 0
-                                 ? time_get_os_boottime_us()
+                                 ? bluetooth::common::time_get_os_boottime_us()
                                  : stats.session_end_us;
     if (static_cast<uint64_t>(session_end_us) > stats.session_start_us) {
       metrics.audio_duration_ms =
@@ -1326,6 +1309,9 @@
               result->status);
     return;
   }
+  bluetooth::common::LogReadRssiResult(
+      result->rem_bda, bluetooth::common::kUnknownConnectionHandle,
+      result->hci_status, result->rssi);
 
   LOG_WARN(LOG_TAG, "%s: device: %s, rssi: %d", __func__,
            result->rem_bda.ToString().c_str(), result->rssi);
@@ -1345,6 +1331,9 @@
               __func__, result->status);
     return;
   }
+  bluetooth::common::LogReadFailedContactCounterResult(
+      result->rem_bda, bluetooth::common::kUnknownConnectionHandle,
+      result->hci_status, result->failed_contact_counter);
 
   LOG_WARN(LOG_TAG, "%s: device: %s, Failed Contact Counter: %u", __func__,
            result->rem_bda.ToString().c_str(), result->failed_contact_counter);
@@ -1381,6 +1370,9 @@
               result->status);
     return;
   }
+  bluetooth::common::LogReadTxPowerLevelResult(
+      result->rem_bda, bluetooth::common::kUnknownConnectionHandle,
+      result->hci_status, result->tx_power);
 
   LOG_WARN(LOG_TAG, "%s: device: %s, Tx Power: %d", __func__,
            result->rem_bda.ToString().c_str(), result->tx_power);
diff --git a/btif/src/btif_av.cc b/btif/src/btif_av.cc
index 8d416c1..24e32ec 100644
--- a/btif/src/btif_av.cc
+++ b/btif/src/btif_av.cc
@@ -31,10 +31,10 @@
 #include <hardware/bt_rc.h>
 
 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
+#include "audio_hal_interface/a2dp_encoding.h"
 #include "bt_common.h"
 #include "bt_utils.h"
 #include "bta/include/bta_api.h"
-#include "bta/include/bta_closure_api.h"
 #include "btif/include/btif_a2dp_source.h"
 #include "btif_a2dp.h"
 #include "btif_a2dp_audio_interface.h"
@@ -43,9 +43,9 @@
 #include "btif_av_co.h"
 #include "btif_profile_queue.h"
 #include "btif_rc.h"
-#include "btif_state_machine.h"
 #include "btif_util.h"
 #include "btu.h"
+#include "common/state_machine.h"
 #include "osi/include/allocator.h"
 #include "osi/include/osi.h"
 #include "osi/include/properties.h"
@@ -115,7 +115,7 @@
 // different than Open state. Suspend flags are needed however to prevent
 // media task from trying to restart stream during remote Suspend or while
 // we are in the process of a local Suspend.
-class BtifAvStateMachine : public BtifStateMachine {
+class BtifAvStateMachine : public bluetooth::common::StateMachine {
  public:
   enum {
     kStateIdle,     // AVDTP disconnected
@@ -219,7 +219,7 @@
     kFlagPendingStart = 0x4,
     kFlagPendingStop = 0x8,
   };
-  static constexpr period_ms_t kTimeoutAvOpenOnRcMs = 2 * 1000;  // 2s
+  static constexpr uint64_t kTimeoutAvOpenOnRcMs = 2 * 1000;  // 2s
 
   BtifAvPeer(const RawAddress& peer_address, uint8_t peer_sep,
              tBTA_AV_HNDL bta_handle, uint8_t peer_id);
@@ -277,6 +277,9 @@
 
   bool IsConnected() const;
   bool IsStreaming() const;
+  bool IsInSilenceMode() const { return is_silenced_; };
+
+  void SetSilence(bool silence) { is_silenced_ = silence; };
 
   /**
    * Check whether any of the flags specified by the bitlags mask is set.
@@ -325,6 +328,7 @@
   tBTA_AV_EDR edr_;
   uint8_t flags_;
   bool self_initiated_connection_;
+  bool is_silenced_;
 };
 
 class BtifAvSource {
@@ -386,38 +390,93 @@
   const RawAddress& ActivePeer() const { return active_peer_; }
 
   /**
+   * Check whether peer is silenced
+   *
+   * @param peer_address the peer to check
+   * @return true on silence mode enabled, otherwise false
+   */
+  bool IsPeerSilenced(const RawAddress& peer_address) {
+    if (peer_address.IsEmpty()) {
+      return false;
+    }
+    BtifAvPeer* peer = FindPeer(peer_address);
+    if (peer == nullptr) {
+      BTIF_TRACE_WARNING("%s: peer is null", __func__);
+      return false;
+    }
+    if (!peer->IsConnected()) {
+      BTIF_TRACE_WARNING("%s: peer is not connected", __func__);
+      return false;
+    }
+    return peer->IsInSilenceMode();
+  }
+
+  /**
+   * Set peer silence mode
+   *
+   * @param peer_address the peer to set
+   * @param silence true on enable silence mode, false on disable
+   * @return true on success, otherwise false
+   */
+  bool SetSilencePeer(const RawAddress& peer_address, const bool silence) {
+    if (peer_address.IsEmpty()) {
+      return false;
+    }
+    LOG_INFO(LOG_TAG, "%s: peer: %s", __PRETTY_FUNCTION__,
+             peer_address.ToString().c_str());
+    BtifAvPeer* peer = FindPeer(peer_address);
+    if (peer == nullptr) {
+      BTIF_TRACE_WARNING("%s: peer is null", __func__);
+      return false;
+    }
+    if (!peer->IsConnected()) {
+      BTIF_TRACE_WARNING("%s: peer is not connected", __func__);
+      return false;
+    }
+    peer->SetSilence(silence);
+    return true;
+  }
+
+  /**
    * Set the active peer.
    *
    * @param peer_address the active peer address or RawAddress::kEmpty to
    * reset the active peer
    * @return true on success, otherwise false
    */
-  bool SetActivePeer(const RawAddress& peer_address) {
-    LOG_INFO(LOG_TAG, "%s: peer: %s", __PRETTY_FUNCTION__,
-             peer_address.ToString().c_str());
+  bool SetActivePeer(const RawAddress& peer_address,
+                     std::promise<void> peer_ready_promise) {
+    LOG(INFO) << __PRETTY_FUNCTION__ << ": peer: " << peer_address;
 
-    if (active_peer_ == peer_address) return true;  // Nothing has changed
+    if (active_peer_ == peer_address) {
+      peer_ready_promise.set_value();
+      return true;  // Nothing has changed
+    }
     if (peer_address.IsEmpty()) {
       BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the Audio source",
                        __func__);
       if (!bta_av_co_set_active_peer(peer_address)) {
-        BTIF_TRACE_WARNING("%s: unable to set active peer to empty in BtaAvCo",
-                           __func__);
+        LOG(WARNING) << __func__
+                     << ": unable to set active peer to empty in BtaAvCo";
       }
       btif_a2dp_source_end_session(active_peer_);
       btif_a2dp_source_shutdown();
       active_peer_ = peer_address;
+      peer_ready_promise.set_value();
       return true;
     }
 
     BtifAvPeer* peer = FindPeer(peer_address);
     if (peer != nullptr && !peer->IsConnected()) {
-      BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
-                       peer->PeerAddress().ToString().c_str());
+      LOG(ERROR) << __func__ << ": Error setting " << peer->PeerAddress()
+                 << " as active Source peer";
+      peer_ready_promise.set_value();
       return false;
     }
 
-    if (!btif_a2dp_source_restart_session(active_peer_, peer_address)) {
+    if (!btif_a2dp_source_restart_session(active_peer_, peer_address,
+                                          std::move(peer_ready_promise))) {
+      // cannot set promise but need to be handled within restart_session
       return false;
     }
     active_peer_ = peer_address;
@@ -432,7 +491,8 @@
    */
   void UpdateCodecConfig(
       const RawAddress& peer_address,
-      const std::vector<btav_a2dp_codec_config_t>& codec_preferences) {
+      const std::vector<btav_a2dp_codec_config_t>& codec_preferences,
+      std::promise<void> peer_ready_promise) {
     // Restart the session if the codec for the active peer is updated
     bool restart_session =
         ((active_peer_ == peer_address) && !active_peer_.IsEmpty());
@@ -446,7 +506,10 @@
       btif_a2dp_source_encoder_user_config_update_req(peer_address, cp);
     }
     if (restart_session) {
-      btif_a2dp_source_start_session(active_peer_);
+      btif_a2dp_source_start_session(active_peer_,
+                                     std::move(peer_ready_promise));
+    } else {
+      peer_ready_promise.set_value();
     }
   }
 
@@ -464,6 +527,7 @@
   bool a2dp_offload_enabled_;
   int max_connected_peers_;
   std::map<RawAddress, BtifAvPeer*> peers_;
+  std::set<RawAddress> silenced_peers_;
   RawAddress active_peer_;
   std::map<uint8_t, tBTA_AV_HNDL> peer_id2bta_handle_;
 };
@@ -529,32 +593,39 @@
    * reset the active peer
    * @return true on success, otherwise false
    */
-  bool SetActivePeer(const RawAddress& peer_address) {
-    LOG_INFO(LOG_TAG, "%s: peer: %s", __PRETTY_FUNCTION__,
-             peer_address.ToString().c_str());
+  bool SetActivePeer(const RawAddress& peer_address,
+                     std::promise<void> peer_ready_promise) {
+    LOG(INFO) << __PRETTY_FUNCTION__ << ": peer: " << peer_address;
 
-    if (active_peer_ == peer_address) return true;  // Nothing has changed
+    if (active_peer_ == peer_address) {
+      peer_ready_promise.set_value();
+      return true;  // Nothing has changed
+    }
     if (peer_address.IsEmpty()) {
       BTIF_TRACE_EVENT("%s: peer address is empty, shutdown the Audio sink",
                        __func__);
       if (!bta_av_co_set_active_peer(peer_address)) {
-        BTIF_TRACE_WARNING("%s: unable to set active peer to empty in BtaAvCo",
-                           __func__);
+        LOG(WARNING) << __func__
+                     << ": unable to set active peer to empty in BtaAvCo";
       }
       btif_a2dp_sink_end_session(active_peer_);
       btif_a2dp_sink_shutdown();
       active_peer_ = peer_address;
+      peer_ready_promise.set_value();
       return true;
     }
 
     BtifAvPeer* peer = FindPeer(peer_address);
     if (peer != nullptr && !peer->IsConnected()) {
-      BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
-                       peer->PeerAddress().ToString().c_str());
+      LOG(ERROR) << __func__ << ": Error setting " << peer->PeerAddress()
+                 << " as active Sink peer";
+      peer_ready_promise.set_value();
       return false;
     }
 
-    if (!btif_a2dp_sink_restart_session(active_peer_, peer_address)) {
+    if (!btif_a2dp_sink_restart_session(active_peer_, peer_address,
+                                        std::move(peer_ready_promise))) {
+      // cannot set promise but need to be handled within restart_session
       return false;
     }
     active_peer_ = peer_address;
@@ -830,6 +901,7 @@
 bt_status_t BtifAvPeer::Init() {
   alarm_free(av_open_on_rc_timer_);
   av_open_on_rc_timer_ = alarm_new("btif_av_peer.av_open_on_rc_timer");
+  is_silenced_ = false;
 
   state_machine_.Start();
   return BT_STATUS_SUCCESS;
@@ -908,11 +980,13 @@
 
   btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SOURCE);
 
-  do_in_bta_thread(
+  std::promise<void> peer_ready_promise;
+  do_in_main_thread(
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&BtifAvSource::SetActivePeer),
-                 base::Unretained(&btif_av_source), RawAddress::kEmpty));
-  do_in_bta_thread(FROM_HERE, base::Bind(&btif_a2dp_source_cleanup));
+      base::BindOnce(base::IgnoreResult(&BtifAvSource::SetActivePeer),
+                     base::Unretained(&btif_av_source), RawAddress::kEmpty,
+                     std::move(peer_ready_promise)));
+  do_in_main_thread(FROM_HERE, base::Bind(&btif_a2dp_source_cleanup));
 
   btif_disable_service(BTA_A2DP_SOURCE_SERVICE_ID);
   CleanupAllPeers();
@@ -1093,11 +1167,13 @@
 
   btif_queue_cleanup(UUID_SERVCLASS_AUDIO_SINK);
 
-  do_in_bta_thread(
+  std::promise<void> peer_ready_promise;
+  do_in_main_thread(
       FROM_HERE,
-      base::Bind(base::IgnoreResult(&BtifAvSink::SetActivePeer),
-                 base::Unretained(&btif_av_sink), RawAddress::kEmpty));
-  do_in_bta_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_cleanup));
+      base::BindOnce(base::IgnoreResult(&BtifAvSink::SetActivePeer),
+                     base::Unretained(&btif_av_sink), RawAddress::kEmpty,
+                     std::move(peer_ready_promise)));
+  do_in_main_thread(FROM_HERE, base::Bind(&btif_a2dp_sink_cleanup));
 
   btif_disable_service(BTA_A2DP_SINK_SERVICE_ID);
   CleanupAllPeers();
@@ -1168,6 +1244,9 @@
   peer = new BtifAvPeer(peer_address, AVDT_TSEP_SRC, bta_handle, peer_id);
   peers_.insert(std::make_pair(peer_address, peer));
   peer->Init();
+  if (active_peer_.IsEmpty()) {
+    active_peer_ = peer_address;
+  }
   return peer;
 }
 
@@ -1266,20 +1345,23 @@
   // Reset the active peer if this was the active peer and
   // the Idle state was reentered
   if (peer_.IsActivePeer() && peer_.CanBeDeleted()) {
+    std::promise<void> peer_ready_promise;
     if (peer_.IsSink()) {
-      btif_av_source.SetActivePeer(RawAddress::kEmpty);
+      btif_av_source.SetActivePeer(RawAddress::kEmpty,
+                                   std::move(peer_ready_promise));
     } else if (peer_.IsSource()) {
-      btif_av_sink.SetActivePeer(RawAddress::kEmpty);
+      btif_av_sink.SetActivePeer(RawAddress::kEmpty,
+                                 std::move(peer_ready_promise));
     }
   }
 
   // Delete peers that are re-entering the Idle state
   if (peer_.IsSink()) {
-    do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSource::DeleteIdlePeers,
-                                           base::Unretained(&btif_av_source)));
+    do_in_main_thread(FROM_HERE, base::Bind(&BtifAvSource::DeleteIdlePeers,
+                                            base::Unretained(&btif_av_source)));
   } else if (peer_.IsSource()) {
-    do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSink::DeleteIdlePeers,
-                                           base::Unretained(&btif_av_sink)));
+    do_in_main_thread(FROM_HERE, base::Bind(&BtifAvSink::DeleteIdlePeers,
+                                            base::Unretained(&btif_av_sink)));
   }
 }
 
@@ -1694,7 +1776,9 @@
   // For A2DP Source, the setting of the Active device is done by the
   // ActiveDeviceManager in Java.
   if (peer_.IsSource() && btif_av_sink.ActivePeer().IsEmpty()) {
-    if (!btif_av_sink.SetActivePeer(peer_.PeerAddress())) {
+    std::promise<void> peer_ready_promise;
+    if (!btif_av_sink.SetActivePeer(peer_.PeerAddress(),
+                                    std::move(peer_ready_promise))) {
       BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
                        peer_.PeerAddress().ToString().c_str());
     }
@@ -1759,17 +1843,13 @@
       bool should_suspend = false;
       if (peer_.IsSink() && !peer_.CheckFlags(BtifAvPeer::kFlagPendingStart |
                                               BtifAvPeer::kFlagRemoteSuspend)) {
-        BTIF_TRACE_WARNING("%s: Peer %s : trigger Suspend as remote initiated",
-                           __PRETTY_FUNCTION__,
-                           peer_.PeerAddress().ToString().c_str());
+        LOG(WARNING) << __PRETTY_FUNCTION__ << ": Peer " << peer_.PeerAddress()
+                     << " : trigger Suspend as remote initiated";
         should_suspend = true;
       }
 
-      // If peer is A2DP Source, we do not want to ACK commands on UIPC
-      if (peer_.IsSink() &&
-          btif_a2dp_on_started(
-              peer_.PeerAddress(), &p_av->start,
-              peer_.CheckFlags(BtifAvPeer::kFlagPendingStart))) {
+      // If peer is A2DP Source, do ACK commands to audio HAL and start media task
+      if (peer_.IsSink() && btif_a2dp_on_started(peer_.PeerAddress(), &p_av->start)) {
         // Only clear pending flag after acknowledgement
         peer_.ClearFlags(BtifAvPeer::kFlagPendingStart);
       }
@@ -1782,12 +1862,6 @@
         btif_a2dp_sink_set_rx_flush(false);
       }
 
-      // Change state to Started, send acknowledgement if start is pending
-      if (peer_.IsSink() && peer_.CheckFlags(BtifAvPeer::kFlagPendingStart)) {
-        btif_a2dp_on_started(peer_.PeerAddress(), nullptr, true);
-        // Pending start flag will be cleared when exit current state
-      }
-
       if (should_suspend) {
         btif_av_source_dispatch_sm_event(peer_.PeerAddress(),
                                          BTIF_AV_SUSPEND_STREAM_REQ_EVT);
@@ -1921,8 +1995,7 @@
                BtifAvEvent::EventName(event).c_str(),
                peer_.FlagsToString().c_str());
       // We were started remotely, just ACK back the local request
-      if (peer_.IsSink())
-        btif_a2dp_on_started(peer_.PeerAddress(), nullptr, true);
+      if (peer_.IsSink()) btif_a2dp_on_started(peer_.PeerAddress(), nullptr);
       break;
 
     // FIXME -- use suspend = true always to work around issue with BTA AV
@@ -2476,16 +2549,16 @@
   BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
   BTIF_TRACE_EVENT("%s: event=%s", __func__, btif_av_event.ToString().c_str());
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&btif_av_handle_bta_av_event,
-                              AVDT_TSEP_SNK /* peer_sep */, btif_av_event));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&btif_av_handle_bta_av_event,
+                               AVDT_TSEP_SNK /* peer_sep */, btif_av_event));
 }
 
 static void bta_av_sink_callback(tBTA_AV_EVT event, tBTA_AV* p_data) {
   BtifAvEvent btif_av_event(event, p_data, sizeof(tBTA_AV));
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&btif_av_handle_bta_av_event,
-                              AVDT_TSEP_SRC /* peer_sep */, btif_av_event));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&btif_av_handle_bta_av_event,
+                               AVDT_TSEP_SRC /* peer_sep */, btif_av_event));
 }
 
 // TODO: All processing should be done on the JNI thread
@@ -2527,10 +2600,11 @@
       config_req.peer_address = p_data->avk_config.bd_addr;
       BtifAvEvent btif_av_event(BTIF_AV_SINK_CONFIG_REQ_EVT, &config_req,
                                 sizeof(config_req));
-      do_in_bta_thread(FROM_HERE, base::Bind(&btif_av_handle_event,
-                                             AVDT_TSEP_SRC,  // peer_sep
-                                             config_req.peer_address,
-                                             kBtaHandleUnknown, btif_av_event));
+      do_in_main_thread(FROM_HERE,
+                        base::Bind(&btif_av_handle_event,
+                                   AVDT_TSEP_SRC,  // peer_sep
+                                   config_req.peer_address, kBtaHandleUnknown,
+                                   btif_av_event));
       break;
     }
     default:
@@ -2586,22 +2660,35 @@
   return BT_STATUS_SUCCESS;
 }
 
+static void set_source_silence_peer_int(const RawAddress& peer_address,
+                                        bool silence) {
+  BTIF_TRACE_EVENT("%s: peer_address=%s, silence=%s", __func__,
+                   peer_address.ToString().c_str(), silence ? "true" : "false");
+  if (!btif_av_source.SetSilencePeer(peer_address, silence)) {
+    BTIF_TRACE_ERROR("%s: Error setting silence state to %s", __func__,
+                     peer_address.ToString().c_str());
+  }
+}
+
 // Set the active peer
 static void set_active_peer_int(uint8_t peer_sep,
-                                const RawAddress& peer_address) {
+                                const RawAddress& peer_address,
+                                std::promise<void> peer_ready_promise) {
   BTIF_TRACE_EVENT("%s: peer_sep=%s (%d) peer_address=%s", __func__,
                    (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink", peer_sep,
                    peer_address.ToString().c_str());
   BtifAvPeer* peer = nullptr;
   if (peer_sep == AVDT_TSEP_SNK) {
-    if (!btif_av_source.SetActivePeer(peer_address)) {
+    if (!btif_av_source.SetActivePeer(peer_address,
+                                      std::move(peer_ready_promise))) {
       BTIF_TRACE_ERROR("%s: Error setting %s as active Sink peer", __func__,
                        peer_address.ToString().c_str());
     }
     return;
   }
   if (peer_sep == AVDT_TSEP_SRC) {
-    if (!btif_av_sink.SetActivePeer(peer_address)) {
+    if (!btif_av_sink.SetActivePeer(peer_address,
+                                    std::move(peer_ready_promise))) {
       BTIF_TRACE_ERROR("%s: Error setting %s as active Source peer", __func__,
                        peer_address.ToString().c_str());
     }
@@ -2612,6 +2699,7 @@
                    (peer_sep == AVDT_TSEP_SRC) ? "Source" : "Sink",
                    peer_address.ToString().c_str(),
                    (peer == nullptr) ? "found" : "connected");
+  peer_ready_promise.set_value();
 }
 
 static bt_status_t src_connect_sink(const RawAddress& peer_address) {
@@ -2650,7 +2738,7 @@
 
   BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address,
                             sizeof(peer_address));
-  return do_in_bta_thread(
+  return do_in_main_thread(
       FROM_HERE, base::Bind(&btif_av_handle_event,
                             AVDT_TSEP_SNK,  // peer_sep
                             peer_address, kBtaHandleUnknown, btif_av_event));
@@ -2666,23 +2754,44 @@
 
   BtifAvEvent btif_av_event(BTIF_AV_DISCONNECT_REQ_EVT, &peer_address,
                             sizeof(peer_address));
-  return do_in_bta_thread(
+  return do_in_main_thread(
       FROM_HERE, base::Bind(&btif_av_handle_event,
                             AVDT_TSEP_SRC,  // peer_sep
                             peer_address, kBtaHandleUnknown, btif_av_event));
 }
 
+static bt_status_t src_set_silence_sink(const RawAddress& peer_address,
+                                        bool silence) {
+  BTIF_TRACE_EVENT("%s: Peer %s", __func__, peer_address.ToString().c_str());
+  if (!btif_av_source.Enabled()) {
+    BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+    return BT_STATUS_NOT_READY;
+  }
+
+  return do_in_main_thread(FROM_HERE, base::Bind(&set_source_silence_peer_int,
+                                                 peer_address, silence));
+}
+
 static bt_status_t src_set_active_sink(const RawAddress& peer_address) {
   BTIF_TRACE_EVENT("%s: Peer %s", __func__, peer_address.ToString().c_str());
 
   if (!btif_av_source.Enabled()) {
-    BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+    LOG(WARNING) << __func__ << ": BTIF AV Source is not enabled";
     return BT_STATUS_NOT_READY;
   }
 
-  return do_in_bta_thread(FROM_HERE, base::Bind(&set_active_peer_int,
-                                                AVDT_TSEP_SNK,  // peer_sep
-                                                peer_address));
+  std::promise<void> peer_ready_promise;
+  std::future<void> peer_ready_future = peer_ready_promise.get_future();
+  bt_status_t status = do_in_main_thread(
+      FROM_HERE, base::BindOnce(&set_active_peer_int,
+                                AVDT_TSEP_SNK,  // peer_sep
+                                peer_address, std::move(peer_ready_promise)));
+  if (status == BT_STATUS_SUCCESS) {
+    peer_ready_future.wait();
+  } else {
+    LOG(WARNING) << __func__ << ": BTIF AV Source fails to change peer";
+  }
+  return status;
 }
 
 static bt_status_t codec_config_src(
@@ -2691,26 +2800,35 @@
   BTIF_TRACE_EVENT("%s", __func__);
 
   if (!btif_av_source.Enabled()) {
-    BTIF_TRACE_WARNING("%s: BTIF AV Source is not enabled", __func__);
+    LOG(WARNING) << __func__ << ": BTIF AV Source is not enabled";
     return BT_STATUS_NOT_READY;
   }
 
-  return do_in_bta_thread(
-      FROM_HERE, base::Bind(&BtifAvSource::UpdateCodecConfig,
-                            base::Unretained(&btif_av_source), peer_address,
-                            codec_preferences));
+  std::promise<void> peer_ready_promise;
+  std::future<void> peer_ready_future = peer_ready_promise.get_future();
+  bt_status_t status = do_in_main_thread(
+      FROM_HERE,
+      base::BindOnce(&BtifAvSource::UpdateCodecConfig,
+                     base::Unretained(&btif_av_source), peer_address,
+                     codec_preferences, std::move(peer_ready_promise)));
+  if (status == BT_STATUS_SUCCESS) {
+    peer_ready_future.wait();
+  } else {
+    LOG(WARNING) << __func__ << ": BTIF AV Source fails to config codec";
+  }
+  return status;
 }
 
 static void cleanup_src(void) {
   BTIF_TRACE_EVENT("%s", __func__);
-  do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSource::Cleanup,
-                                         base::Unretained(&btif_av_source)));
+  do_in_main_thread(FROM_HERE, base::Bind(&BtifAvSource::Cleanup,
+                                          base::Unretained(&btif_av_source)));
 }
 
 static void cleanup_sink(void) {
   BTIF_TRACE_EVENT("%s", __func__);
-  do_in_bta_thread(FROM_HERE, base::Bind(&BtifAvSink::Cleanup,
-                                         base::Unretained(&btif_av_sink)));
+  do_in_main_thread(FROM_HERE, base::Bind(&BtifAvSink::Cleanup,
+                                          base::Unretained(&btif_av_sink)));
 }
 
 static const btav_source_interface_t bt_av_src_interface = {
@@ -2718,6 +2836,7 @@
     init_src,
     src_connect_sink,
     src_disconnect_sink,
+    src_set_silence_sink,
     src_set_active_sink,
     codec_config_src,
     cleanup_src,
@@ -2838,10 +2957,10 @@
                    peer_address.ToString().c_str(),
                    btif_av_event.ToString().c_str());
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&btif_av_handle_event,
-                              AVDT_TSEP_SNK,  // peer_sep
-                              peer_address, kBtaHandleUnknown, btif_av_event));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&btif_av_handle_event,
+                               AVDT_TSEP_SNK,  // peer_sep
+                               peer_address, kBtaHandleUnknown, btif_av_event));
 }
 
 static void btif_av_sink_dispatch_sm_event(const RawAddress& peer_address,
@@ -2851,10 +2970,10 @@
                    peer_address.ToString().c_str(),
                    btif_av_event.ToString().c_str());
 
-  do_in_bta_thread(FROM_HERE,
-                   base::Bind(&btif_av_handle_event,
-                              AVDT_TSEP_SRC,  // peer_sep
-                              peer_address, kBtaHandleUnknown, btif_av_event));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(&btif_av_handle_event,
+                               AVDT_TSEP_SRC,  // peer_sep
+                               peer_address, kBtaHandleUnknown, btif_av_event));
 }
 
 bt_status_t btif_av_source_execute_service(bool enable) {
@@ -2968,49 +3087,6 @@
   peer->ClearFlags(BtifAvPeer::kFlagRemoteSuspend);
 }
 
-void btif_av_avrcp_event_open(const RawAddress& peer_address) {
-  // TODO: We need a better demultipexing mechanism whether the remote device
-  // is an A2DP Source or a Sink.
-  if (btif_av_source.Enabled()) {
-    BtifAvPeer* peer =
-        btif_av_source.FindOrCreatePeer(peer_address, kBtaHandleUnknown);
-    if (peer != nullptr) {
-      btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
-      return;
-    }
-  } else if (btif_av_sink.Enabled()) {
-    BtifAvPeer* peer =
-        btif_av_sink.FindOrCreatePeer(peer_address, kBtaHandleUnknown);
-    if (peer != nullptr) {
-      btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_OPEN_EVT);
-      return;
-    }
-  }
-  BTIF_TRACE_ERROR("%s: event ignored: cannot find or create peer state for %s",
-                   __func__, peer_address.ToString().c_str());
-}
-
-void btif_av_avrcp_event_close(const RawAddress& peer_address) {
-  // TODO: We need a better demultipexing mechanism whether the remote device
-  // is an A2DP Source or a Sink.
-  if (btif_av_source.Enabled()) {
-    btif_av_source_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_CLOSE_EVT);
-  } else if (btif_av_sink.Enabled()) {
-    btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_CLOSE_EVT);
-  }
-}
-
-void btif_av_avrcp_event_remote_play(const RawAddress& peer_address) {
-  // TODO: We need a better demultipexing mechanism whether the remote device
-  // is an A2DP Source or a Sink.
-  if (btif_av_source.Enabled()) {
-    btif_av_source_dispatch_sm_event(peer_address,
-                                     BTIF_AV_AVRCP_REMOTE_PLAY_EVT);
-  } else if (btif_av_sink.Enabled()) {
-    btif_av_sink_dispatch_sm_event(peer_address, BTIF_AV_AVRCP_REMOTE_PLAY_EVT);
-  }
-}
-
 bool btif_av_is_peer_edr(const RawAddress& peer_address) {
   BtifAvPeer* peer = btif_av_find_peer(peer_address);
   if (peer == nullptr) {
@@ -3133,6 +3209,7 @@
 
 void btif_av_set_audio_delay(uint16_t delay) {
   btif_a2dp_control_set_audio_delay(delay);
+  bluetooth::audio::a2dp::set_remote_delay(delay);
 }
 
 void btif_av_reset_audio_delay(void) { btif_a2dp_control_reset_audio_delay(); }
@@ -3140,3 +3217,7 @@
 bool btif_av_is_a2dp_offload_enabled() {
   return btif_av_source.A2dpOffloadEnabled();
 }
+
+bool btif_av_is_peer_silenced(const RawAddress& peer_address) {
+  return btif_av_source.IsPeerSilenced(peer_address);
+}
diff --git a/btif/src/btif_avrcp_audio_track.cc b/btif/src/btif_avrcp_audio_track.cc
index 76da406..4f3cd35 100644
--- a/btif/src/btif_avrcp_audio_track.cc
+++ b/btif/src/btif_avrcp_audio_track.cc
@@ -35,11 +35,26 @@
 char outputFilename[50] = "/data/misc/bluedroid/output_sample.pcm";
 #endif
 
-void* BtifAvrcpAudioTrackCreate(int trackFreq, int channelType) {
-  LOG_VERBOSE(LOG_TAG, "%s Track.cpp: btCreateTrack freq %d  channel %d ",
-              __func__, trackFreq, channelType);
+void* BtifAvrcpAudioTrackCreate(int trackFreq, int bits_per_sample,
+                                int channelType) {
+  audio_format_t format;
+  switch (bits_per_sample) {
+    default:
+    case 16:
+      format = AUDIO_FORMAT_PCM_16_BIT;
+      break;
+    case 24:
+      format = AUDIO_FORMAT_PCM_24_BIT_PACKED;
+      break;
+    case 32:
+      format = AUDIO_FORMAT_PCM_32_BIT;
+      break;
+  }
+  LOG_VERBOSE(LOG_TAG,
+              "%s Track.cpp: btCreateTrack freq %d format 0x%x channel %d ",
+              __func__, trackFreq, format, channelType);
   sp<android::AudioTrack> track = new android::AudioTrack(
-      AUDIO_STREAM_MUSIC, trackFreq, AUDIO_FORMAT_PCM_16_BIT, channelType,
+      AUDIO_STREAM_MUSIC, trackFreq, format, channelType,
       (size_t)0 /*frameCount*/, (audio_output_flags_t)AUDIO_OUTPUT_FLAG_FAST,
       NULL /*callback_t*/, NULL /*void* user*/, 0 /*notificationFrames*/,
       AUDIO_SESSION_ALLOCATE, android::AudioTrack::TRANSFER_SYNC);
diff --git a/btif/src/btif_avrcp_audio_track_linux.cc b/btif/src/btif_avrcp_audio_track_linux.cc
new file mode 100644
index 0000000..ea35212
--- /dev/null
+++ b/btif/src/btif_avrcp_audio_track_linux.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "btif_avrcp_audio_track.h"
+
+void* BtifAvrcpAudioTrackCreate(int trackFreq, int bits_per_sample,
+                                int channelType) {
+  return nullptr;
+}
+
+void BtifAvrcpAudioTrackStart(void* handle) {}
+
+void BtifAvrcpAudioTrackStop(void* handle) {}
+
+void BtifAvrcpAudioTrackDelete(void* handle) {}
+
+void BtifAvrcpAudioTrackPause(void* handle) {}
+
+void BtifAvrcpSetAudioTrackGain(void* handle, float gain) {}
+
+int BtifAvrcpAudioTrackWriteData(void* handle, void* audioBuffer,
+                                 int bufferlen) {
+  return 0;
+}
diff --git a/btif/src/btif_ble_advertiser.cc b/btif/src/btif_ble_advertiser.cc
index e24bcde..dcbe080 100644
--- a/btif/src/btif_ble_advertiser.cc
+++ b/btif/src/btif_ble_advertiser.cc
@@ -25,8 +25,8 @@
 #include <vector>
 
 #include "ble_advertiser.h"
-#include "bta_closure_api.h"
 #include "btif_common.h"
+#include "stack/include/btu.h"
 
 using base::Bind;
 using base::Owned;
@@ -40,7 +40,7 @@
   explicit OwnedArrayWrapper(T* o) : ptr_(o) {}
   ~OwnedArrayWrapper() { delete[] ptr_; }
   T* get() const { return ptr_; }
-  OwnedArrayWrapper(OwnedArrayWrapper&& other) {
+  OwnedArrayWrapper(OwnedArrayWrapper&& other) noexcept {
     ptr_ = other.ptr_;
     other.ptr_ = NULL;
   }
@@ -93,7 +93,7 @@
   }
 
   void RegisterAdvertiser(IdStatusCallback cb) override {
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE, Bind(&BleAdvertisingManager::RegisterAdvertiser,
                         BleAdvertisingManager::Get(),
                         Bind(&BleAdvertiserInterfaceImpl::RegisterAdvertiserCb,
@@ -101,7 +101,7 @@
   }
 
   void Unregister(uint8_t advertiser_id) override {
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(
             [](uint8_t advertiser_id) {
@@ -116,10 +116,10 @@
 
   void GetOwnAddress(uint8_t advertiser_id, GetAddressCallback cb) override {
     if (!BleAdvertisingManager::IsInitialized()) return;
-    do_in_bta_thread(FROM_HERE,
-                     Bind(&BleAdvertisingManager::GetOwnAddress,
-                          BleAdvertisingManager::Get(), advertiser_id,
-                          jni_thread_wrapper(FROM_HERE, cb)));
+    do_in_main_thread(FROM_HERE,
+                      Bind(&BleAdvertisingManager::GetOwnAddress,
+                           BleAdvertisingManager::Get(), advertiser_id,
+                           jni_thread_wrapper(FROM_HERE, cb)));
   }
 
   void SetParameters(uint8_t advertiser_id, AdvertiseParameters params,
@@ -130,16 +130,16 @@
     tBTM_BLE_ADV_PARAMS* p_params = new tBTM_BLE_ADV_PARAMS;
     parseParams(p_params, params);
 
-    do_in_bta_thread(FROM_HERE, Bind(&BleAdvertisingManager::SetParameters,
-                                     BleAdvertisingManager::Get(),
-                                     advertiser_id, base::Owned(p_params),
-                                     jni_thread_wrapper(FROM_HERE, cb)));
+    do_in_main_thread(FROM_HERE, Bind(&BleAdvertisingManager::SetParameters,
+                                      BleAdvertisingManager::Get(),
+                                      advertiser_id, base::Owned(p_params),
+                                      jni_thread_wrapper(FROM_HERE, cb)));
   }
 
   void SetData(int advertiser_id, bool set_scan_rsp, vector<uint8_t> data,
                StatusCallback cb) override {
     if (!BleAdvertisingManager::IsInitialized()) return;
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(&BleAdvertisingManager::SetData, BleAdvertisingManager::Get(),
              advertiser_id, set_scan_rsp, std::move(data),
@@ -153,7 +153,7 @@
             << " ,enable: " << enable;
 
     if (!BleAdvertisingManager::IsInitialized()) return;
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(&BleAdvertisingManager::Enable, BleAdvertisingManager::Get(),
              advertiser_id, enable, jni_thread_wrapper(FROM_HERE, cb), duration,
@@ -171,7 +171,7 @@
     tBTM_BLE_ADV_PARAMS* p_params = new tBTM_BLE_ADV_PARAMS;
     parseParams(p_params, params);
 
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(&BleAdvertisingManager::StartAdvertising,
              BleAdvertisingManager::Get(), advertiser_id,
@@ -197,7 +197,7 @@
     tBLE_PERIODIC_ADV_PARAMS* p_periodic_params = new tBLE_PERIODIC_ADV_PARAMS;
     parsePeriodicParams(p_periodic_params, periodic_params);
 
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(&BleAdvertisingManager::StartAdvertisingSet,
              BleAdvertisingManager::Get(), jni_thread_wrapper(FROM_HERE, cb),
@@ -216,7 +216,7 @@
     tBLE_PERIODIC_ADV_PARAMS* p_periodic_params = new tBLE_PERIODIC_ADV_PARAMS;
     parsePeriodicParams(p_periodic_params, periodic_params);
 
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(&BleAdvertisingManager::SetPeriodicAdvertisingParameters,
              BleAdvertisingManager::Get(), advertiser_id,
@@ -229,10 +229,10 @@
     VLOG(1) << __func__ << " advertiser_id: " << +advertiser_id;
 
     if (!BleAdvertisingManager::IsInitialized()) return;
-    do_in_bta_thread(FROM_HERE,
-                     Bind(&BleAdvertisingManager::SetPeriodicAdvertisingData,
-                          BleAdvertisingManager::Get(), advertiser_id,
-                          std::move(data), jni_thread_wrapper(FROM_HERE, cb)));
+    do_in_main_thread(FROM_HERE,
+                      Bind(&BleAdvertisingManager::SetPeriodicAdvertisingData,
+                           BleAdvertisingManager::Get(), advertiser_id,
+                           std::move(data), jni_thread_wrapper(FROM_HERE, cb)));
   }
 
   void SetPeriodicAdvertisingEnable(int advertiser_id, bool enable,
@@ -241,10 +241,10 @@
             << " ,enable: " << enable;
 
     if (!BleAdvertisingManager::IsInitialized()) return;
-    do_in_bta_thread(FROM_HERE,
-                     Bind(&BleAdvertisingManager::SetPeriodicAdvertisingEnable,
-                          BleAdvertisingManager::Get(), advertiser_id, enable,
-                          jni_thread_wrapper(FROM_HERE, cb)));
+    do_in_main_thread(FROM_HERE,
+                      Bind(&BleAdvertisingManager::SetPeriodicAdvertisingEnable,
+                           BleAdvertisingManager::Get(), advertiser_id, enable,
+                           jni_thread_wrapper(FROM_HERE, cb)));
   }
 };
 
diff --git a/btif/src/btif_ble_scanner.cc b/btif/src/btif_ble_scanner.cc
index 2587c8d..fa6fd4c 100644
--- a/btif/src/btif_ble_scanner.cc
+++ b/btif/src/btif_ble_scanner.cc
@@ -35,7 +35,6 @@
 
 #include "advertise_data_parser.h"
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bta_gatt_api.h"
 #include "btif_config.h"
 #include "btif_dm.h"
@@ -43,6 +42,7 @@
 #include "btif_gatt_util.h"
 #include "btif_storage.h"
 #include "osi/include/log.h"
+#include "stack/include/btu.h"
 #include "vendor_api.h"
 
 using base::Bind;
@@ -70,7 +70,7 @@
 std::queue<RawAddress> remote_bdaddr_cache_ordered;
 const size_t remote_bdaddr_cache_max_size = 1024;
 
-void btif_gattc_add_remote_bdaddr(const RawAddress& p_bda, uint8_t addr_type) {
+void btif_address_cache_add(const RawAddress& p_bda, uint8_t addr_type) {
   // Remove the oldest entries
   while (remote_bdaddr_cache.size() >= remote_bdaddr_cache_max_size) {
     const RawAddress& raw_address = remote_bdaddr_cache_ordered.front();
@@ -81,11 +81,11 @@
   remote_bdaddr_cache_ordered.push(p_bda);
 }
 
-bool btif_gattc_find_bdaddr(const RawAddress& p_bda) {
+bool btif_address_cache_find(const RawAddress& p_bda) {
   return (remote_bdaddr_cache.find(p_bda) != remote_bdaddr_cache.end());
 }
 
-void btif_gattc_init_dev_cb(void) {
+void btif_address_cache_init(void) {
   remote_bdaddr_cache.clear();
   remote_bdaddr_cache_ordered = {};
 }
@@ -121,8 +121,8 @@
   }
 
   if ((addr_type != BLE_ADDR_RANDOM) || (p_eir_remote_name)) {
-    if (!btif_gattc_find_bdaddr(bd_addr)) {
-      btif_gattc_add_remote_bdaddr(bd_addr, addr_type);
+    if (!btif_address_cache_find(bd_addr)) {
+      btif_address_cache_add(bd_addr, addr_type);
 
       if (p_eir_remote_name) {
         if (remote_name_len > BD_NAME_LEN + 1 ||
@@ -206,31 +206,31 @@
   ~BleScannerInterfaceImpl(){};
 
   void RegisterScanner(RegisterCallback cb) override {
-    do_in_bta_thread(FROM_HERE,
-                     Bind(
-                         [](RegisterCallback cb) {
-                           BTA_GATTC_AppRegister(
-                               bta_cback,
-                               jni_thread_wrapper(FROM_HERE, std::move(cb)));
-                         },
-                         std::move(cb)));
+    do_in_main_thread(FROM_HERE,
+                      Bind(
+                          [](RegisterCallback cb) {
+                            BTA_GATTC_AppRegister(
+                                bta_cback,
+                                jni_thread_wrapper(FROM_HERE, std::move(cb)));
+                          },
+                          std::move(cb)));
   }
 
   void Unregister(int scanner_id) override {
-    do_in_bta_thread(FROM_HERE, Bind(&BTA_GATTC_AppDeregister, scanner_id));
+    do_in_main_thread(FROM_HERE, Bind(&BTA_GATTC_AppDeregister, scanner_id));
   }
 
   void Scan(bool start) override {
     do_in_jni_thread(Bind(
         [](bool start) {
           if (!start) {
-            do_in_bta_thread(FROM_HERE,
-                             Bind(&BTA_DmBleObserve, false, 0, nullptr));
+            do_in_main_thread(FROM_HERE,
+                              Bind(&BTA_DmBleObserve, false, 0, nullptr));
             return;
           }
 
-          btif_gattc_init_dev_cb();
-          do_in_bta_thread(
+          btif_address_cache_init();
+          do_in_main_thread(
               FROM_HERE, Bind(&BTA_DmBleObserve, true, 0, bta_scan_results_cb));
         },
         start));
@@ -243,22 +243,22 @@
     BTIF_TRACE_DEBUG("%s", __func__);
 
     if (filt_param && filt_param->dely_mode == 1) {
-      do_in_bta_thread(
+      do_in_main_thread(
           FROM_HERE, base::Bind(BTM_BleTrackAdvertiser, bta_track_adv_event_cb,
                                 client_if));
     }
 
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&BTM_BleAdvFilterParamSetup, action, filt_index,
-                                base::Passed(&filt_param),
-                                jni_thread_wrapper(FROM_HERE, std::move(cb))));
+    do_in_main_thread(
+        FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, action, filt_index,
+                              base::Passed(&filt_param),
+                              jni_thread_wrapper(FROM_HERE, std::move(cb))));
   }
 
   void ScanFilterAdd(int filter_index, std::vector<ApcfCommand> filters,
                      FilterConfigCallback cb) override {
     BTIF_TRACE_DEBUG("%s: %d", __func__, filter_index);
 
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         base::Bind(
             &BTM_LE_PF_set, filter_index, std::move(filters),
@@ -270,24 +270,24 @@
 
   void ScanFilterClear(int filter_index, FilterConfigCallback cb) override {
     BTIF_TRACE_DEBUG("%s: filter_index: %d", __func__, filter_index);
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&BTM_LE_PF_clear, filter_index,
-                                jni_thread_wrapper(
-                                    FROM_HERE, Bind(cb, BTM_BLE_PF_TYPE_ALL))));
+    do_in_main_thread(
+        FROM_HERE, base::Bind(&BTM_LE_PF_clear, filter_index,
+                              jni_thread_wrapper(
+                                  FROM_HERE, Bind(cb, BTM_BLE_PF_TYPE_ALL))));
   }
 
   void ScanFilterEnable(bool enable, EnableCallback cb) override {
     BTIF_TRACE_DEBUG("%s: enable: %d", __func__, enable);
 
     uint8_t action = enable ? 1 : 0;
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&BTM_BleEnableDisableFilterFeature, action,
-                                jni_thread_wrapper(FROM_HERE, std::move(cb))));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&BTM_BleEnableDisableFilterFeature, action,
+                                 jni_thread_wrapper(FROM_HERE, std::move(cb))));
   }
 
   void SetScanParameters(int scan_interval, int scan_window,
                          Callback cb) override {
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE, base::Bind(&BTM_BleSetScanParams, scan_interval, scan_window,
                               BTM_BLE_SCAN_MODE_ACTI,
                               jni_thread_wrapper(FROM_HERE, std::move(cb))));
@@ -297,7 +297,7 @@
                               int batch_scan_trunc_max,
                               int batch_scan_notify_threshold,
                               Callback cb) override {
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         base::Bind(&BTM_BleSetStorageConfig, (uint8_t)batch_scan_full_max,
                    (uint8_t)batch_scan_trunc_max,
@@ -308,21 +308,21 @@
 
   void BatchscanEnable(int scan_mode, int scan_interval, int scan_window,
                        int addr_type, int discard_rule, Callback cb) override {
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE, base::Bind(&BTM_BleEnableBatchScan, scan_mode, scan_interval,
                               scan_window, discard_rule, addr_type,
                               jni_thread_wrapper(FROM_HERE, cb)));
   }
 
   void BatchscanDisable(Callback cb) override {
-    do_in_bta_thread(FROM_HERE, base::Bind(&BTM_BleDisableBatchScan,
-                                           jni_thread_wrapper(FROM_HERE, cb)));
+    do_in_main_thread(FROM_HERE, base::Bind(&BTM_BleDisableBatchScan,
+                                            jni_thread_wrapper(FROM_HERE, cb)));
   }
 
   void BatchscanReadReports(int client_if, int scan_mode) override {
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(&BTM_BleReadScanReports, (uint8_t)scan_mode,
-                                Bind(bta_batch_scan_reports_cb, client_if)));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(&BTM_BleReadScanReports, (uint8_t)scan_mode,
+                                 Bind(bta_batch_scan_reports_cb, client_if)));
   }
 
   void StartSync(uint8_t sid, RawAddress address, uint16_t skip,
diff --git a/btif/src/btif_bqr.cc b/btif/src/btif_bqr.cc
new file mode 100644
index 0000000..17253c5
--- /dev/null
+++ b/btif/src/btif_bqr.cc
@@ -0,0 +1,326 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <statslog.h>
+
+#include "btif_bqr.h"
+#include "btif_dm.h"
+#include "common/leaky_bonded_queue.h"
+#include "osi/include/properties.h"
+#include "stack/btm/btm_int.h"
+
+namespace bluetooth {
+namespace bqr {
+
+using bluetooth::common::LeakyBondedQueue;
+using std::chrono::system_clock;
+
+// The instance of BQR event queue
+static std::unique_ptr<LeakyBondedQueue<BqrVseSubEvt>> kpBqrEventQueue(
+    new LeakyBondedQueue<BqrVseSubEvt>(kBqrEventQueueSize));
+
+bool BqrVseSubEvt::ParseBqrEvt(uint8_t length, uint8_t* p_param_buf) {
+  if (length < kBqrParamTotalLen) {
+    LOG(FATAL) << __func__
+               << ": Parameter total length: " << std::to_string(length)
+               << " is abnormal. It shall be not shorter than: "
+               << std::to_string(kBqrParamTotalLen);
+    return false;
+  }
+
+  STREAM_TO_UINT8(quality_report_id_, p_param_buf);
+  STREAM_TO_UINT8(packet_types_, p_param_buf);
+  STREAM_TO_UINT16(connection_handle_, p_param_buf);
+  STREAM_TO_UINT8(connection_role_, p_param_buf);
+  STREAM_TO_UINT8(tx_power_level_, p_param_buf);
+  STREAM_TO_INT8(rssi_, p_param_buf);
+  STREAM_TO_UINT8(snr_, p_param_buf);
+  STREAM_TO_UINT8(unused_afh_channel_count_, p_param_buf);
+  STREAM_TO_UINT8(afh_select_unideal_channel_count_, p_param_buf);
+  STREAM_TO_UINT16(lsto_, p_param_buf);
+  STREAM_TO_UINT32(connection_piconet_clock_, p_param_buf);
+  STREAM_TO_UINT32(retransmission_count_, p_param_buf);
+  STREAM_TO_UINT32(no_rx_count_, p_param_buf);
+  STREAM_TO_UINT32(nak_count_, p_param_buf);
+  STREAM_TO_UINT32(last_tx_ack_timestamp_, p_param_buf);
+  STREAM_TO_UINT32(flow_off_count_, p_param_buf);
+  STREAM_TO_UINT32(last_flow_on_timestamp_, p_param_buf);
+  STREAM_TO_UINT32(buffer_overflow_bytes_, p_param_buf);
+  STREAM_TO_UINT32(buffer_underflow_bytes_, p_param_buf);
+
+  const auto now = system_clock::to_time_t(system_clock::now());
+  localtime_r(&now, &tm_timestamp_);
+
+  return true;
+}
+
+std::string BqrVseSubEvt::ToString() const {
+  std::stringstream ss_return_string;
+  ss_return_string << QualityReportIdToString(quality_report_id_)
+                   << ", Handle: " << loghex(connection_handle_) << ", "
+                   << PacketTypeToString(packet_types_) << ", "
+                   << ((connection_role_ == 0) ? "Master" : "Slave ")
+                   << ", PwLv: " << loghex(tx_power_level_)
+                   << ", RSSI: " << std::to_string(rssi_)
+                   << ", SNR: " << std::to_string(snr_) << ", UnusedCh: "
+                   << std::to_string(unused_afh_channel_count_)
+                   << ", UnidealCh: "
+                   << std::to_string(afh_select_unideal_channel_count_)
+                   << ", ReTx: " << std::to_string(retransmission_count_)
+                   << ", NoRX: " << std::to_string(no_rx_count_)
+                   << ", NAK: " << std::to_string(nak_count_)
+                   << ", FlowOff: " << std::to_string(flow_off_count_)
+                   << ", OverFlow: " << std::to_string(buffer_overflow_bytes_)
+                   << ", UndFlow: " << std::to_string(buffer_underflow_bytes_);
+  return ss_return_string.str();
+}
+
+std::string QualityReportIdToString(uint8_t quality_report_id) {
+  switch (quality_report_id) {
+    case QUALITY_REPORT_ID_MONITOR_MODE:
+      return "Monitoring ";
+    case QUALITY_REPORT_ID_APPROACH_LSTO:
+      return "Appro LSTO ";
+    case QUALITY_REPORT_ID_A2DP_AUDIO_CHOPPY:
+      return "A2DP Choppy";
+    case QUALITY_REPORT_ID_SCO_VOICE_CHOPPY:
+      return "SCO Choppy ";
+    default:
+      return "Invalid    ";
+  }
+}
+
+std::string PacketTypeToString(uint8_t packet_type) {
+  switch (packet_type) {
+    case PACKET_TYPE_ID:
+      return "ID";
+    case PACKET_TYPE_NULL:
+      return "NULL";
+    case PACKET_TYPE_POLL:
+      return "POLL";
+    case PACKET_TYPE_FHS:
+      return "FHS";
+    case PACKET_TYPE_HV1:
+      return "HV1";
+    case PACKET_TYPE_HV2:
+      return "HV2";
+    case PACKET_TYPE_HV3:
+      return "HV3";
+    case PACKET_TYPE_DV:
+      return "DV";
+    case PACKET_TYPE_EV3:
+      return "EV3";
+    case PACKET_TYPE_EV4:
+      return "EV4";
+    case PACKET_TYPE_EV5:
+      return "EV5";
+    case PACKET_TYPE_2EV3:
+      return "2EV3";
+    case PACKET_TYPE_2EV5:
+      return "2EV5";
+    case PACKET_TYPE_3EV3:
+      return "3EV3";
+    case PACKET_TYPE_3EV5:
+      return "3EV5";
+    case PACKET_TYPE_DM1:
+      return "DM1";
+    case PACKET_TYPE_DH1:
+      return "DH1";
+    case PACKET_TYPE_DM3:
+      return "DM3";
+    case PACKET_TYPE_DH3:
+      return "DH3";
+    case PACKET_TYPE_DM5:
+      return "DM5";
+    case PACKET_TYPE_DH5:
+      return "DH5";
+    case PACKET_TYPE_AUX1:
+      return "AUX1";
+    case PACKET_TYPE_2DH1:
+      return "2DH1";
+    case PACKET_TYPE_2DH3:
+      return "2DH3";
+    case PACKET_TYPE_2DH5:
+      return "2DH5";
+    case PACKET_TYPE_3DH1:
+      return "3DH1";
+    case PACKET_TYPE_3DH3:
+      return "3DH3";
+    case PACKET_TYPE_3DH5:
+      return "3DH5";
+    default:
+      return "UnKnown ";
+  }
+}
+
+void AddBqrEventToQueue(uint8_t length, uint8_t* p_stream) {
+  std::unique_ptr<BqrVseSubEvt> p_bqr_event = std::make_unique<BqrVseSubEvt>();
+  if (!p_bqr_event->ParseBqrEvt(length, p_stream)) {
+    LOG(WARNING) << __func__ << ": Fail to parse BQR sub event.";
+    return;
+  }
+
+  LOG(WARNING) << *p_bqr_event;
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_QUALITY_REPORT_REPORTED,
+      p_bqr_event->quality_report_id_, p_bqr_event->packet_types_,
+      p_bqr_event->connection_handle_, p_bqr_event->connection_role_,
+      p_bqr_event->tx_power_level_, p_bqr_event->rssi_, p_bqr_event->snr_,
+      p_bqr_event->unused_afh_channel_count_,
+      p_bqr_event->afh_select_unideal_channel_count_, p_bqr_event->lsto_,
+      p_bqr_event->connection_piconet_clock_,
+      p_bqr_event->retransmission_count_, p_bqr_event->no_rx_count_,
+      p_bqr_event->nak_count_, p_bqr_event->last_tx_ack_timestamp_,
+      p_bqr_event->flow_off_count_, p_bqr_event->last_flow_on_timestamp_,
+      p_bqr_event->buffer_overflow_bytes_,
+      p_bqr_event->buffer_underflow_bytes_);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed to log BQR event to statsd, error "
+                 << ret;
+  }
+  kpBqrEventQueue->Enqueue(p_bqr_event.release());
+}
+
+void ConfigureBqrCmpl(uint32_t current_evt_mask) {
+  LOG(INFO) << __func__ << ": current_evt_mask: " << loghex(current_evt_mask);
+  // (Un)Register for VSE of Bluetooth Quality Report sub event
+  tBTM_STATUS btm_status = BTM_BT_Quality_Report_VSE_Register(
+      current_evt_mask > kQualityEventMaskAllOff, AddBqrEventToQueue);
+
+  if (btm_status != BTM_SUCCESS) {
+    LOG(ERROR) << __func__ << ": Fail to (un)register VSE of BQR sub event."
+               << " status: " << btm_status;
+  }
+}
+
+void EnableBtQualityReport(bool is_enable) {
+  LOG(INFO) << __func__ << ": is_enable: " << logbool(is_enable);
+
+  char bqr_prop_evtmask[PROPERTY_VALUE_MAX] = {0};
+  char bqr_prop_interval_ms[PROPERTY_VALUE_MAX] = {0};
+  osi_property_get(kpPropertyEventMask, bqr_prop_evtmask, "");
+  osi_property_get(kpPropertyMinReportIntervalMs, bqr_prop_interval_ms, "");
+
+  if (strlen(bqr_prop_evtmask) == 0 || strlen(bqr_prop_interval_ms) == 0) {
+    LOG(WARNING) << __func__ << ": Bluetooth Quality Report is disabled."
+                 << " bqr_prop_evtmask: " << bqr_prop_evtmask
+                 << ", bqr_prop_interval_ms: " << bqr_prop_interval_ms;
+    return;
+  }
+
+  BqrConfiguration bqr_config = {};
+
+  if (is_enable) {
+    bqr_config.report_action = REPORT_ACTION_ADD;
+    bqr_config.quality_event_mask =
+        static_cast<uint32_t>(atoi(bqr_prop_evtmask));
+    bqr_config.minimum_report_interval_ms =
+        static_cast<uint16_t>(atoi(bqr_prop_interval_ms));
+  } else {
+    bqr_config.report_action = REPORT_ACTION_CLEAR;
+    bqr_config.quality_event_mask = kQualityEventMaskAllOff;
+    bqr_config.minimum_report_interval_ms = kMinReportIntervalNoLimit;
+  }
+
+  LOG(INFO) << __func__
+            << ": Event Mask: " << loghex(bqr_config.quality_event_mask)
+            << ", Interval: " << bqr_config.minimum_report_interval_ms;
+  ConfigureBqr(bqr_config);
+}
+
+void BqrVscCompleteCallback(tBTM_VSC_CMPL* p_vsc_cmpl_params) {
+  if (p_vsc_cmpl_params->param_len < 1) {
+    LOG(ERROR) << __func__ << ": The length of returned parameters is less than 1";
+    return;
+  }
+
+  uint8_t* p_event_param_buf = p_vsc_cmpl_params->p_param_buf;
+  uint8_t status = 0xff;
+  // [Return Parameter]         | [Size]   | [Purpose]
+  // Status                     | 1 octet  | Command complete status
+  // Current_Quality_Event_Mask | 4 octets | Indicates current bit mask setting
+  STREAM_TO_UINT8(status, p_event_param_buf);
+  if (status != HCI_SUCCESS) {
+    LOG(ERROR) << __func__ << ": Fail to configure BQR. status: " << loghex(status);
+    return;
+  }
+
+  if (p_vsc_cmpl_params->param_len != 5) {
+    LOG(FATAL) << __func__
+               << ": The length of returned parameters is not equal to 5: "
+               << std::to_string(p_vsc_cmpl_params->param_len);
+    return;
+  }
+
+  uint32_t current_quality_event_mask = kQualityEventMaskAllOff;
+  STREAM_TO_UINT32(current_quality_event_mask, p_event_param_buf);
+
+  LOG(INFO) << __func__
+            << ", current event mask: " << loghex(current_quality_event_mask);
+  ConfigureBqrCmpl(current_quality_event_mask);
+}
+
+void ConfigureBqr(const BqrConfiguration& bqr_config) {
+  if (bqr_config.report_action > REPORT_ACTION_CLEAR ||
+      bqr_config.quality_event_mask > kQualityEventMaskAll ||
+      bqr_config.minimum_report_interval_ms > kMinReportIntervalMaxMs) {
+    LOG(FATAL) << __func__ << ": Invalid Parameter"
+               << ", Action: " << bqr_config.report_action
+               << ", Mask: " << loghex(bqr_config.quality_event_mask)
+               << ", Interval: " << bqr_config.minimum_report_interval_ms;
+    return;
+  }
+
+  LOG(INFO) << __func__ << ": Action: " << bqr_config.report_action
+            << ", Mask: " << loghex(bqr_config.quality_event_mask)
+            << ", Interval: " << bqr_config.minimum_report_interval_ms;
+
+  uint8_t param[sizeof(BqrConfiguration)];
+  uint8_t* p_param = param;
+  UINT8_TO_STREAM(p_param, bqr_config.report_action);
+  UINT32_TO_STREAM(p_param, bqr_config.quality_event_mask);
+  UINT16_TO_STREAM(p_param, bqr_config.minimum_report_interval_ms);
+
+  BTM_VendorSpecificCommand(HCI_CONTROLLER_BQR_OPCODE_OCF, p_param - param,
+                            param, BqrVscCompleteCallback);
+}
+
+void DebugDump(int fd) {
+  dprintf(fd, "\nBT Quality Report Events: \n");
+
+  if (kpBqrEventQueue->Empty()) {
+    dprintf(fd, "Event queue is empty.\n");
+    return;
+  }
+
+  while (!kpBqrEventQueue->Empty()) {
+    std::unique_ptr<BqrVseSubEvt> p_event(kpBqrEventQueue->Dequeue());
+
+    bool warning = (p_event->rssi_ < kCriWarnRssi ||
+                    p_event->unused_afh_channel_count_ > kCriWarnUnusedCh);
+
+    std::stringstream ss_timestamp;
+    ss_timestamp << std::put_time(&p_event->tm_timestamp_, "%m-%d %H:%M:%S");
+
+    dprintf(fd, "%c  %s %s\n", warning ? '*' : ' ', ss_timestamp.str().c_str(),
+            p_event->ToString().c_str());
+  }
+
+  dprintf(fd, "\n");
+}
+
+}  // namespace bqr
+}  // namespace bluetooth
diff --git a/btif/src/btif_config.cc b/btif/src/btif_config.cc
index 7c361ae..ed24d7d 100644
--- a/btif/src/btif_config.cc
+++ b/btif/src/btif_config.cc
@@ -40,6 +40,7 @@
 #include "btif_config_transcode.h"
 #include "btif_keystore.h"
 #include "btif_util.h"
+#include "common/address_obfuscator.h"
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
 #include "osi/include/compat.h"
@@ -59,9 +60,14 @@
 
 constexpr int kBufferSize = 400 * 10;  // initial file is ~400B
 
-static bool use_key_attestation() { return getuid() == AID_BLUETOOTH; }
+static bool use_key_attestation() {
+  return getuid() == AID_BLUETOOTH && is_single_user_mode();
+}
 
+#define BT_CONFIG_METRICS_SECTION "Metrics"
+#define BT_CONFIG_METRICS_SALT_256BIT "Salt256Bit"
 using bluetooth::BtifKeystore;
+using bluetooth::common::AddressObfuscator;
 
 // TODO(armansito): Find a better way than searching by a hardcoded path.
 #if defined(OS_GENERIC)
@@ -76,7 +82,7 @@
 static const char* CONFIG_LEGACY_FILE_PATH =
     "/data/misc/bluedroid/bt_config.xml";
 #endif  // defined(OS_GENERIC)
-static const period_ms_t CONFIG_SETTLE_PERIOD_MS = 3000;
+static const uint64_t CONFIG_SETTLE_PERIOD_MS = 3000;
 
 static void timer_config_save_cb(void* data);
 static void btif_config_write(uint16_t event, char* p_param);
@@ -132,7 +138,41 @@
   return true;
 }
 
-static std::mutex config_lock;  // protects operations on |config|.
+/**
+ * Read metrics salt from config file, if salt is invalid or does not exist,
+ * generate new one and save it to config
+ */
+static void read_or_set_metrics_salt() {
+  AddressObfuscator::Octet32 metrics_salt = {};
+  size_t metrics_salt_length = metrics_salt.size();
+  if (!btif_config_get_bin(BT_CONFIG_METRICS_SECTION,
+                           BT_CONFIG_METRICS_SALT_256BIT, metrics_salt.data(),
+                           &metrics_salt_length)) {
+    LOG(WARNING) << __func__ << ": Failed to read metrics salt from config";
+    // Invalidate salt
+    metrics_salt.fill(0);
+  }
+  if (metrics_salt_length != metrics_salt.size()) {
+    LOG(ERROR) << __func__ << ": Metrics salt length incorrect, "
+               << metrics_salt_length << " instead of " << metrics_salt.size();
+    // Invalidate salt
+    metrics_salt.fill(0);
+  }
+  if (!AddressObfuscator::IsSaltValid(metrics_salt)) {
+    LOG(INFO) << __func__ << ": Metrics salt is not invalid, creating new one";
+    if (RAND_bytes(metrics_salt.data(), metrics_salt.size()) != 1) {
+      LOG(FATAL) << __func__ << "Failed to generate salt for metrics";
+    }
+    if (!btif_config_set_bin(BT_CONFIG_METRICS_SECTION,
+                             BT_CONFIG_METRICS_SALT_256BIT, metrics_salt.data(),
+                             metrics_salt.size())) {
+      LOG(FATAL) << __func__ << "Failed to write metrics salt to config";
+    }
+  }
+  AddressObfuscator::GetInstance()->Initialize(metrics_salt);
+}
+
+static std::recursive_mutex config_lock;  // protects operations on |config|.
 static std::unique_ptr<config_t> config;
 static alarm_t* config_timer;
 
@@ -141,9 +181,11 @@
 // Module lifecycle functions
 
 static future_t* init(void) {
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
 
-  if (is_factory_reset()) delete_config_files();
+  if (is_factory_reset() ||
+      (use_key_attestation() && !btif_keystore.DoesKeyExist()))
+    delete_config_files();
 
   std::string file_source;
 
@@ -197,6 +239,9 @@
                       btif_config_time_created);
   }
 
+  // Read or set metrics 256 bit hashing salt
+  read_or_set_metrics_salt();
+
   // TODO(sharvil): use a non-wake alarm for this once we have
   // API support for it. There's no need to wake the system to
   // write back to disk.
@@ -259,7 +304,7 @@
   alarm_free(config_timer);
   config_timer = NULL;
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   config.reset();
   return future_new_immediate(FUTURE_SUCCESS);
 }
@@ -274,14 +319,14 @@
   CHECK(config != NULL);
   CHECK(section != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   return config_has_section(*config, section);
 }
 
 bool btif_config_exist(const std::string& section, const std::string& key) {
   CHECK(config != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   return config_has_key(*config, section, key);
 }
 
@@ -290,7 +335,7 @@
   CHECK(config != NULL);
   CHECK(value != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   bool ret = config_has_key(*config, section, key);
   if (ret) *value = config_get_int(*config, section, key, *value);
 
@@ -301,7 +346,7 @@
                          int value) {
   CHECK(config != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   config_set_int(config.get(), section, key, value);
 
   return true;
@@ -312,7 +357,7 @@
   CHECK(config != NULL);
   CHECK(value != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   bool ret = config_has_key(*config, section, key);
   if (ret) *value = config_get_uint64(*config, section, key, *value);
 
@@ -323,7 +368,7 @@
                             uint64_t value) {
   CHECK(config != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   config_set_uint64(config.get(), section, key, value);
 
   return true;
@@ -336,7 +381,7 @@
   CHECK(size_bytes != NULL);
 
   {
-    std::unique_lock<std::mutex> lock(config_lock);
+    std::unique_lock<std::recursive_mutex> lock(config_lock);
     const std::string* stored_value =
         config_get_string(*config, section, key, NULL);
     if (!stored_value) return false;
@@ -351,7 +396,7 @@
                          const std::string& value) {
   CHECK(config != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   config_set_string(config.get(), section, key, value);
   return true;
 }
@@ -362,16 +407,26 @@
   CHECK(value != NULL);
   CHECK(length != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   const std::string* value_str = config_get_string(*config, section, key, NULL);
 
-  if (!value_str) return false;
+  if (!value_str) {
+    VLOG(1) << __func__ << ": cannot find string for section " << section
+            << ", key " << key;
+    return false;
+  }
 
   size_t value_len = value_str->length();
-  if ((value_len % 2) != 0 || *length < (value_len / 2)) return false;
+  if ((value_len % 2) != 0 || *length < (value_len / 2)) {
+    LOG(WARNING) << ": value size not divisible by 2, size is " << value_len;
+    return false;
+  }
 
   for (size_t i = 0; i < value_len; ++i)
-    if (!isxdigit(value_str->c_str()[i])) return false;
+    if (!isxdigit(value_str->c_str()[i])) {
+      LOG(WARNING) << ": value is not hex digit";
+      return false;
+    }
 
   const char* ptr = value_str->c_str();
   for (*length = 0; *ptr; ptr += 2, *length += 1)
@@ -384,7 +439,7 @@
                                   const std::string& key) {
   CHECK(config != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   const std::string* value_str = config_get_string(*config, section, key, NULL);
   if (!value_str) return 0;
 
@@ -400,6 +455,12 @@
 
   if (length > 0) CHECK(value != NULL);
 
+  size_t max_value = ((size_t)-1);
+  if (((max_value - 1) / 2) < length) {
+    LOG(ERROR) << __func__ << ": length too long";
+    return false;
+  }
+
   char* str = (char*)osi_calloc(length * 2 + 1);
 
   for (size_t i = 0; i < length; ++i) {
@@ -408,7 +469,7 @@
   }
 
   {
-    std::unique_lock<std::mutex> lock(config_lock);
+    std::unique_lock<std::recursive_mutex> lock(config_lock);
     config_set_string(config.get(), section, key, str);
   }
 
@@ -421,7 +482,7 @@
 bool btif_config_remove(const std::string& section, const std::string& key) {
   CHECK(config != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   return config_remove_key(config.get(), section, key);
 }
 
@@ -446,7 +507,7 @@
 
   alarm_cancel(config_timer);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
 
   config = config_new_empty();
 
@@ -474,7 +535,7 @@
   CHECK(config != NULL);
   CHECK(config_timer != NULL);
 
-  std::unique_lock<std::mutex> lock(config_lock);
+  std::unique_lock<std::recursive_mutex> lock(config_lock);
   rename(CONFIG_FILE_PATH, CONFIG_BACKUP_PATH);
   rename(CONFIG_FILE_CHECKSUM_PATH, CONFIG_BACKUP_CHECKSUM_PATH);
   std::unique_ptr<config_t> config_paired = config_new_clone(*config);
@@ -595,7 +656,7 @@
   uint8_t hash[SHA256_DIGEST_LENGTH];
   SHA256_CTX sha256;
   SHA256_Init(&sha256);
-  std::array<unsigned char, kBufferSize> buffer;
+  std::array<std::byte, kBufferSize> buffer;
   int bytes_read = 0;
   while ((bytes_read = fread(buffer.data(), 1, buffer.size(), fp))) {
     SHA256_Update(&sha256, buffer.data(), bytes_read);
diff --git a/btif/src/btif_core.cc b/btif/src/btif_core.cc
index 582ae47..aa77979 100644
--- a/btif/src/btif_core.cc
+++ b/btif/src/btif_core.cc
@@ -46,7 +46,6 @@
 #include "bt_common.h"
 #include "bt_utils.h"
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bte.h"
 #include "btif_api.h"
 #include "btif_av.h"
@@ -58,17 +57,18 @@
 #include "btif_uid.h"
 #include "btif_util.h"
 #include "btu.h"
+#include "common/message_loop_thread.h"
 #include "device/include/controller.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/future.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 #include "osi/include/properties.h"
-#include "osi/include/thread.h"
 #include "stack_manager.h"
 
 using base::PlatformThread;
 using bluetooth::Uuid;
+using bluetooth::common::MessageLoopThread;
 
 /*******************************************************************************
  *  Constants & Macros
@@ -128,12 +128,9 @@
  */
 static uint8_t btif_dut_mode = 0;
 
-static thread_t* bt_jni_workqueue_thread;
-static const char* BT_JNI_WORKQUEUE_NAME = "bt_jni_workqueue";
-static uid_set_t* uid_set = NULL;
-base::MessageLoop* message_loop_ = NULL;
-base::RunLoop* jni_run_loop = NULL;
-static base::PlatformThreadId btif_thread_id_ = -1;
+static MessageLoopThread jni_thread("bt_jni_thread");
+static base::AtExitManager* exit_manager;
+static uid_set_t* uid_set;
 
 /*******************************************************************************
  *  Static functions
@@ -223,36 +220,24 @@
  * This function posts a task into the btif message loop, that executes it in
  * the JNI message loop.
  **/
-bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here,
-                             const base::Closure& task) {
-  if (!message_loop_) {
-    BTIF_TRACE_WARNING("%s: Dropped message, message_loop not initialized yet!",
-                       __func__);
+bt_status_t do_in_jni_thread(const base::Location& from_here,
+                             base::OnceClosure task) {
+  if (!jni_thread.DoInThread(from_here, std::move(task))) {
+    LOG(ERROR) << __func__ << ": Post task to task runner failed!";
     return BT_STATUS_FAIL;
   }
-
-  scoped_refptr<base::SingleThreadTaskRunner> task_runner =
-      message_loop_->task_runner();
-  if (!task_runner.get()) {
-    BTIF_TRACE_WARNING("%s: task runner is dead", __func__);
-    return BT_STATUS_FAIL;
-  }
-
-  if (task_runner->PostTask(from_here, task)) return BT_STATUS_SUCCESS;
-
-  BTIF_TRACE_ERROR("%s: Post task to task runner failed!", __func__);
-  return BT_STATUS_FAIL;
+  return BT_STATUS_SUCCESS;
 }
 
-bt_status_t do_in_jni_thread(const base::Closure& task) {
-  return do_in_jni_thread(FROM_HERE, task);
+bt_status_t do_in_jni_thread(base::OnceClosure task) {
+  return do_in_jni_thread(FROM_HERE, std::move(task));
 }
 
 bool is_on_jni_thread() {
-  return btif_thread_id_ == PlatformThread::CurrentId();
+  return jni_thread.GetThreadId() == PlatformThread::CurrentId();
 }
 
-base::MessageLoop* get_jni_message_loop() { return message_loop_; }
+base::MessageLoop* get_jni_message_loop() { return jni_thread.message_loop(); }
 
 /*******************************************************************************
  *
@@ -260,11 +245,11 @@
  *
  * Description      checks if BTIF is currently in DUT mode
  *
- * Returns          1 if test mode, otherwize 0
+ * Returns          true if test mode, otherwise false
  *
  ******************************************************************************/
 
-uint8_t btif_is_dut_mode(void) { return (btif_dut_mode == 1); }
+bool btif_is_dut_mode() { return btif_dut_mode == 1; }
 
 /*******************************************************************************
  *
@@ -327,38 +312,6 @@
   do_in_jni_thread(base::Bind(&bt_jni_msg_ready, p_msg));
 }
 
-void btif_thread_post(thread_fn func, void* context) {
-  do_in_jni_thread(base::Bind(func, context));
-}
-
-void run_message_loop(UNUSED_ATTR void* context) {
-  LOG_INFO(LOG_TAG, "%s entered", __func__);
-  btif_thread_id_ = PlatformThread::CurrentId();
-
-  // TODO(jpawlowski): exit_manager should be defined in main(), but there is no
-  // main method.
-  // It is therefore defined in bt_jni_workqueue_thread, and will be deleted
-  // when we free it.
-  base::AtExitManager exit_manager;
-
-  message_loop_ = new base::MessageLoop(base::MessageLoop::Type::TYPE_DEFAULT);
-
-  // Associate this workqueue thread with JNI.
-  message_loop_->task_runner()->PostTask(FROM_HERE,
-                                         base::Bind(&btif_jni_associate));
-
-  jni_run_loop = new base::RunLoop();
-  jni_run_loop->Run();
-
-  delete message_loop_;
-  message_loop_ = NULL;
-
-  delete jni_run_loop;
-  jni_run_loop = NULL;
-
-  btif_thread_id_ = -1;
-  LOG_INFO(LOG_TAG, "%s finished", __func__);
-}
 /*******************************************************************************
  *
  * Function         btif_init_bluetooth
@@ -370,27 +323,12 @@
  ******************************************************************************/
 bt_status_t btif_init_bluetooth() {
   LOG_INFO(LOG_TAG, "%s entered", __func__);
-
+  exit_manager = new base::AtExitManager();
   bte_main_boot_entry();
-
-  bt_jni_workqueue_thread = thread_new(BT_JNI_WORKQUEUE_NAME);
-  if (bt_jni_workqueue_thread == NULL) {
-    LOG_ERROR(LOG_TAG, "%s Unable to create thread %s", __func__,
-              BT_JNI_WORKQUEUE_NAME);
-    goto error_exit;
-  }
-
-  thread_post(bt_jni_workqueue_thread, run_message_loop, nullptr);
-
+  jni_thread.StartUp();
+  jni_thread.DoInThread(FROM_HERE, base::Bind(btif_jni_associate));
   LOG_INFO(LOG_TAG, "%s finished", __func__);
   return BT_STATUS_SUCCESS;
-
-error_exit:;
-  thread_free(bt_jni_workqueue_thread);
-
-  bt_jni_workqueue_thread = NULL;
-
-  return BT_STATUS_FAIL;
 }
 
 /*******************************************************************************
@@ -475,10 +413,10 @@
  * Returns          void
  *
  ******************************************************************************/
-bt_status_t btif_disable_bluetooth(void) {
+bt_status_t btif_disable_bluetooth() {
   LOG_INFO(LOG_TAG, "%s entered", __func__);
 
-  do_in_bta_thread(FROM_HERE, base::Bind(&btm_ble_multi_adv_cleanup));
+  do_in_main_thread(FROM_HERE, base::Bind(&btm_ble_multi_adv_cleanup));
   // TODO(jpawlowski): this should do whole BTA_VendorCleanup(), but it would
   // kill the stack now.
 
@@ -505,7 +443,7 @@
  *
  ******************************************************************************/
 
-void btif_disable_bluetooth_evt(void) {
+void btif_disable_bluetooth_evt() {
   LOG_INFO(LOG_TAG, "%s entered", __func__);
 
   bte_main_disable();
@@ -526,29 +464,18 @@
  *
  ******************************************************************************/
 
-bt_status_t btif_cleanup_bluetooth(void) {
+bt_status_t btif_cleanup_bluetooth() {
   LOG_INFO(LOG_TAG, "%s entered", __func__);
-
-  do_in_bta_thread(FROM_HERE, base::Bind(&BTA_VendorCleanup));
-
+  do_in_main_thread(FROM_HERE, base::Bind(&BTA_VendorCleanup));
   btif_dm_cleanup();
-  btif_jni_disassociate();
+  jni_thread.DoInThread(FROM_HERE, base::BindOnce(btif_jni_disassociate));
   btif_queue_release();
-
-  if (jni_run_loop && message_loop_) {
-    message_loop_->task_runner()->PostTask(FROM_HERE,
-                                           jni_run_loop->QuitClosure());
-  }
-
-  thread_free(bt_jni_workqueue_thread);
-  bt_jni_workqueue_thread = NULL;
-
+  jni_thread.ShutDown();
   bte_main_cleanup();
-
+  delete exit_manager;
+  exit_manager = nullptr;
   btif_dut_mode = 0;
-
   LOG_INFO(LOG_TAG, "%s finished", __func__);
-
   return BT_STATUS_SUCCESS;
 }
 
@@ -620,7 +547,8 @@
  ****************************************************************************/
 
 static bt_status_t btif_in_get_adapter_properties(void) {
-  bt_property_t properties[6];
+  const static uint32_t NUM_ADAPTER_PROPERTIES = 8;
+  bt_property_t properties[NUM_ADAPTER_PROPERTIES];
   uint32_t num_props = 0;
 
   RawAddress addr;
@@ -630,6 +558,8 @@
   RawAddress bonded_devices[BTM_SEC_MAX_DEVICE_RECORDS];
   Uuid local_uuids[BT_MAX_NUM_UUIDS];
   bt_status_t status;
+  bt_io_cap_t local_bt_io_cap;
+  bt_io_cap_t local_bt_io_cap_ble;
 
   /* RawAddress */
   BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_BDADDR,
@@ -674,6 +604,18 @@
   btif_storage_get_adapter_property(&properties[num_props]);
   num_props++;
 
+  /* LOCAL IO Capabilities */
+  BTIF_STORAGE_FILL_PROPERTY(&properties[num_props], BT_PROPERTY_LOCAL_IO_CAPS,
+                             sizeof(bt_io_cap_t), &local_bt_io_cap);
+  btif_storage_get_adapter_property(&properties[num_props]);
+  num_props++;
+
+  BTIF_STORAGE_FILL_PROPERTY(&properties[num_props],
+                             BT_PROPERTY_LOCAL_IO_CAPS_BLE, sizeof(bt_io_cap_t),
+                             &local_bt_io_cap_ble);
+  btif_storage_get_adapter_property(&properties[num_props]);
+  num_props++;
+
   HAL_CBACK(bt_hal_cbacks, adapter_properties_cb, BT_STATUS_SUCCESS, num_props,
             properties);
 
@@ -1024,6 +966,13 @@
        * BTA events */
       status = BT_STATUS_FAIL;
       break;
+    case BT_PROPERTY_LOCAL_IO_CAPS:
+    case BT_PROPERTY_LOCAL_IO_CAPS_BLE: {
+      // Changing IO Capability of stack at run-time is not currently supported.
+      // This call changes the stored value which will affect the stack next
+      // time it starts up.
+      storage_req_id = BTIF_CORE_STORAGE_ADAPTER_WRITE;
+    } break;
     default:
       BTIF_TRACE_ERROR("btif_get_adapter_property : invalid type %d",
                        property->type);
diff --git a/btif/src/btif_debug_btsnoop.cc b/btif/src/btif_debug_btsnoop.cc
index 1dcb835..45fcade 100644
--- a/btif/src/btif_debug_btsnoop.cc
+++ b/btif/src/btif_debug_btsnoop.cc
@@ -27,7 +27,6 @@
 #include "hci/include/btsnoop_mem.h"
 #include "internal_include/bt_target.h"
 #include "osi/include/ringbuffer.h"
-#include "osi/include/time.h"
 
 #define REDUCE_HCI_TYPE_TO_SIGNIFICANT_BITS(type) ((type) >> 8)
 
@@ -123,9 +122,9 @@
 
     case BT_EVT_TO_LM_HCI_SCO:
     case BT_EVT_TO_BTU_HCI_SCO:
-    // We're not logging SCO packets at this time since they are not currently
-    // used.
-    // FALLTHROUGH
+      // We're not logging SCO packets at this time since they are not currently
+      // used.
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     default:
       return 0;
   }
diff --git a/btif/src/btif_debug_conn.cc b/btif/src/btif_debug_conn.cc
index 6b4d96f..dc36c45 100644
--- a/btif/src/btif_debug_conn.cc
+++ b/btif/src/btif_debug_conn.cc
@@ -21,7 +21,7 @@
 #include <time.h>
 
 #include "btif/include/btif_debug_conn.h"
-#include "osi/include/time.h"
+#include "common/time_util.h"
 
 #define NUM_CONNECTION_EVENTS 16
 #define TEMP_BUFFER_SIZE 30
@@ -69,7 +69,7 @@
   next_event();
 
   conn_event_t* evt = &connection_events[current_event];
-  evt->ts = time_gettimeofday_us();
+  evt->ts = bluetooth::common::time_gettimeofday_us();
   evt->state = state;
   evt->disconnect_reason = disconnect_reason;
   evt->bda = bda;
diff --git a/btif/src/btif_dm.cc b/btif/src/btif_dm.cc
index 364d042..2a84aa9 100644
--- a/btif/src/btif_dm.cc
+++ b/btif/src/btif_dm.cc
@@ -47,10 +47,10 @@
 
 #include "advertise_data_parser.h"
 #include "bt_common.h"
-#include "bta_closure_api.h"
 #include "bta_gatt_api.h"
 #include "btif_api.h"
 #include "btif_av.h"
+#include "btif_bqr.h"
 #include "btif_config.h"
 #include "btif_dm.h"
 #include "btif_hd.h"
@@ -60,12 +60,12 @@
 #include "btif_storage.h"
 #include "btif_util.h"
 #include "btu.h"
+#include "common/metrics.h"
 #include "device/include/controller.h"
 #include "device/include/interop.h"
 #include "internal_include/stack_config.h"
 #include "osi/include/allocator.h"
 #include "osi/include/log.h"
-#include "osi/include/metrics.h"
 #include "osi/include/osi.h"
 #include "osi/include/properties.h"
 #include "stack/btm/btm_int.h"
@@ -97,8 +97,9 @@
 #define BTIF_DM_MAX_SDP_ATTEMPTS_AFTER_PAIRING 2
 
 #define NUM_TIMEOUT_RETRIES 5
-
+#ifndef PROPERTY_PRODUCT_MODEL
 #define PROPERTY_PRODUCT_MODEL "ro.product.model"
+#endif
 #define DEFAULT_LOCAL_NAME_MAX 31
 #if (DEFAULT_LOCAL_NAME_MAX > BTM_MAX_LOC_BD_NAME_LEN)
 #error "default btif local name size exceeds stack supported length"
@@ -125,15 +126,17 @@
   btif_dm_ble_cb_t ble;
 } btif_dm_pairing_cb_t;
 
+// TODO(jpawlowski): unify ?
+// btif_dm_local_key_id_t == tBTM_BLE_LOCAL_ID_KEYS == tBTA_BLE_LOCAL_ID_KEYS
 typedef struct {
-  uint8_t ir[BT_OCTET16_LEN];
-  uint8_t irk[BT_OCTET16_LEN];
-  uint8_t dhk[BT_OCTET16_LEN];
+  Octet16 ir;
+  Octet16 irk;
+  Octet16 dhk;
 } btif_dm_local_key_id_t;
 
 typedef struct {
   bool is_er_rcvd;
-  uint8_t er[BT_OCTET16_LEN];
+  Octet16 er;
   bool is_id_keys_rcvd;
   btif_dm_local_key_id_t id_keys; /* ID kyes */
 
@@ -505,6 +508,11 @@
   auto tmp = bd_addr;
   HAL_CBACK(bt_hal_cbacks, bond_state_changed_cb, status, &tmp, state);
 
+  int dev_type;
+  if (!btif_get_device_type(bd_addr, &dev_type)) {
+    dev_type = BT_DEVICE_TYPE_BREDR;
+  }
+
   if (state == BT_BOND_STATE_BONDING ||
       (state == BT_BOND_STATE_BONDED && pairing_cb.sdp_attempts > 0)) {
     // Save state for the device is bonding or SDP.
@@ -1157,7 +1165,7 @@
           btif_dm_cb_create_bond(bd_addr, BTA_TRANSPORT_UNKNOWN);
           return;
         }
-      /* Fall-through */
+        FALLTHROUGH_INTENDED; /* FALLTHROUGH */
       case HCI_ERR_CONNECTION_TOUT:
         status = BT_STATUS_RMT_DEV_DOWN;
         break;
@@ -1340,7 +1348,7 @@
     } break;
 
     case BTA_DM_INQ_CMPL_EVT: {
-      do_in_bta_thread(
+      do_in_main_thread(
           FROM_HERE,
           base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
                      nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
@@ -1362,7 +1370,7 @@
       if (!btif_dm_inquiry_in_progress) {
         btgatt_filt_param_setup_t adv_filt_param;
         memset(&adv_filt_param, 0, sizeof(btgatt_filt_param_setup_t));
-        do_in_bta_thread(
+        do_in_main_thread(
             FROM_HERE,
             base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
                        nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
@@ -1432,7 +1440,8 @@
                  bd_addr.ToString().c_str());
         pairing_cb.sdp_attempts = 0;
 
-        // Both SDP and bonding are done, clear pairing control block
+        // Both SDP and bonding are done, clear pairing control block in case
+        // it is not already cleared
         pairing_cb = {};
 
         // Send one empty UUID to Java to unblock pairing intent when SDP failed
@@ -1622,7 +1631,7 @@
       ** and bonded_devices_info_cb
       */
       btif_storage_load_bonded_devices();
-
+      bluetooth::bqr::EnableBtQualityReport(true);
       btif_enable_bluetooth_evt(p_data->enable.status);
     } break;
 
@@ -1636,6 +1645,7 @@
           btif_in_execute_service_request(i, false);
         }
       }
+      bluetooth::bqr::EnableBtQualityReport(false);
       btif_disable_bluetooth_evt();
       break;
 
@@ -1814,25 +1824,22 @@
     case BTA_DM_BLE_LOCAL_IR_EVT:
       BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_IR_EVT. ");
       ble_local_key_cb.is_id_keys_rcvd = true;
-      memcpy(&ble_local_key_cb.id_keys.irk[0], &p_data->ble_id_keys.irk[0],
-             sizeof(BT_OCTET16));
-      memcpy(&ble_local_key_cb.id_keys.ir[0], &p_data->ble_id_keys.ir[0],
-             sizeof(BT_OCTET16));
-      memcpy(&ble_local_key_cb.id_keys.dhk[0], &p_data->ble_id_keys.dhk[0],
-             sizeof(BT_OCTET16));
-      btif_storage_add_ble_local_key((char*)&ble_local_key_cb.id_keys.irk[0],
-                                     BTIF_DM_LE_LOCAL_KEY_IRK, BT_OCTET16_LEN);
-      btif_storage_add_ble_local_key((char*)&ble_local_key_cb.id_keys.ir[0],
-                                     BTIF_DM_LE_LOCAL_KEY_IR, BT_OCTET16_LEN);
-      btif_storage_add_ble_local_key((char*)&ble_local_key_cb.id_keys.dhk[0],
-                                     BTIF_DM_LE_LOCAL_KEY_DHK, BT_OCTET16_LEN);
+      ble_local_key_cb.id_keys.irk = p_data->ble_id_keys.irk;
+      ble_local_key_cb.id_keys.ir = p_data->ble_id_keys.ir;
+      ble_local_key_cb.id_keys.dhk = p_data->ble_id_keys.dhk;
+      btif_storage_add_ble_local_key(ble_local_key_cb.id_keys.irk,
+                                     BTIF_DM_LE_LOCAL_KEY_IRK);
+      btif_storage_add_ble_local_key(ble_local_key_cb.id_keys.ir,
+                                     BTIF_DM_LE_LOCAL_KEY_IR);
+      btif_storage_add_ble_local_key(ble_local_key_cb.id_keys.dhk,
+                                     BTIF_DM_LE_LOCAL_KEY_DHK);
       break;
     case BTA_DM_BLE_LOCAL_ER_EVT:
       BTIF_TRACE_DEBUG("BTA_DM_BLE_LOCAL_ER_EVT. ");
       ble_local_key_cb.is_er_rcvd = true;
-      memcpy(&ble_local_key_cb.er[0], &p_data->ble_er[0], sizeof(BT_OCTET16));
-      btif_storage_add_ble_local_key((char*)&ble_local_key_cb.er[0],
-                                     BTIF_DM_LE_LOCAL_KEY_ER, BT_OCTET16_LEN);
+      ble_local_key_cb.er = p_data->ble_er;
+      btif_storage_add_ble_local_key(ble_local_key_cb.er,
+                                     BTIF_DM_LE_LOCAL_KEY_ER);
       break;
 
     case BTA_DM_BLE_AUTH_CMPL_EVT:
@@ -2156,7 +2163,7 @@
   BTIF_TRACE_EVENT("%s", __func__);
 
   /* Cleanup anything remaining on index 0 */
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE,
       base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_DELETE, 0,
                  nullptr, base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
@@ -2169,7 +2176,7 @@
   adv_filt_param->list_logic_type = BTA_DM_BLE_PF_LIST_LOGIC_OR;
   adv_filt_param->rssi_low_thres = LOWEST_RSSI_VALUE;
   adv_filt_param->rssi_high_thres = LOWEST_RSSI_VALUE;
-  do_in_bta_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(&BTM_BleAdvFilterParamSetup, BTM_BLE_SCAN_COND_ADD,
                             0, base::Passed(&adv_filt_param),
                             base::Bind(&bte_scan_filt_param_cfg_evt, 0)));
@@ -2462,6 +2469,20 @@
       prop->len = sizeof(DEV_CLASS);
     } break;
 
+    // While fetching IO_CAP* values for the local device, we maintain backward
+    // compatibility by using the value from #define macros BTM_LOCAL_IO_CAPS,
+    // BTM_LOCAL_IO_CAPS_BLE if the values have never been explicitly set.
+
+    case BT_PROPERTY_LOCAL_IO_CAPS: {
+      *(bt_io_cap_t*)prop->val = (bt_io_cap_t)BTM_LOCAL_IO_CAPS;
+      prop->len = sizeof(bt_io_cap_t);
+    } break;
+
+    case BT_PROPERTY_LOCAL_IO_CAPS_BLE: {
+      *(bt_io_cap_t*)prop->val = (bt_io_cap_t)BTM_LOCAL_IO_CAPS_BLE;
+      prop->len = sizeof(bt_io_cap_t);
+    } break;
+
     default:
       prop->len = 0;
       return BT_STATUS_FAIL;
@@ -2658,7 +2679,7 @@
   }
 }
 
-void btif_dm_proc_loc_oob(bool valid, BT_OCTET16 c, BT_OCTET16 r) {
+void btif_dm_proc_loc_oob(bool valid, const Octet16& c, const Octet16& r) {
   FILE* fp;
   const char* path_a = "/data/misc/bluedroid/LOCAL/a.key";
   const char* path_b = "/data/misc/bluedroid/LOCAL/b.key";
@@ -2667,8 +2688,8 @@
   BTIF_TRACE_DEBUG("%s: valid=%d", __func__, valid);
   if (is_empty_128bit(oob_cb.oob_data.c192) && valid) {
     BTIF_TRACE_DEBUG("save local OOB data in memory");
-    memcpy(oob_cb.oob_data.c192, c, BT_OCTET16_LEN);
-    memcpy(oob_cb.oob_data.r192, r, BT_OCTET16_LEN);
+    memcpy(oob_cb.oob_data.c192, c.data(), OCTET16_LEN);
+    memcpy(oob_cb.oob_data.r192, r.data(), OCTET16_LEN);
     osi_property_get("service.brcm.bt.oob", prop_oob, "3");
     BTIF_TRACE_DEBUG("%s: prop_oob = %s", __func__, prop_oob);
     if (prop_oob[0] == '1')
@@ -2683,8 +2704,8 @@
       } else {
         BTIF_TRACE_DEBUG("%s: save local OOB data into file %s", __func__,
                          path);
-        fwrite(c, 1, BT_OCTET16_LEN, fp);
-        fwrite(r, 1, BT_OCTET16_LEN, fp);
+        fwrite(c.data(), 1, OCTET16_LEN, fp);
+        fwrite(r.data(), 1, OCTET16_LEN, fp);
         fclose(fp);
       }
     }
@@ -2754,8 +2775,8 @@
   return true;
 }
 
-bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, BT_OCTET16 p_c,
-                          BT_OCTET16 p_r) {
+bool btif_dm_proc_rmt_oob(const RawAddress& bd_addr, Octet16* p_c,
+                          Octet16* p_r) {
   const char* path_a = "/data/misc/bluedroid/LOCAL/a.key";
   const char* path_b = "/data/misc/bluedroid/LOCAL/b.key";
   const char* path = NULL;
@@ -2778,8 +2799,8 @@
   }
 
   BTIF_TRACE_DEBUG("%s: read OOB data from %s", __func__, path);
-  fread(p_c, 1, BT_OCTET16_LEN, fp);
-  fread(p_r, 1, BT_OCTET16_LEN, fp);
+  fread(p_c->data(), 1, OCTET16_LEN, fp);
+  fread(p_r->data(), 1, OCTET16_LEN, fp);
   fclose(fp);
 
   RawAddress bt_bd_addr = bd_addr;
@@ -2854,7 +2875,6 @@
       state = BT_BOND_STATE_NONE;
     } else {
       btif_dm_save_ble_bonding_keys(bdaddr);
-      BTA_GATTC_Refresh(bd_addr);
       btif_dm_get_remote_services_by_transport(&bd_addr, GATT_TRANSPORT_LE);
     }
   } else {
@@ -2863,10 +2883,23 @@
       case BTA_DM_AUTH_SMP_PAIR_AUTH_FAIL:
       case BTA_DM_AUTH_SMP_CONFIRM_VALUE_FAIL:
       case BTA_DM_AUTH_SMP_UNKNOWN_ERR:
-      case BTA_DM_AUTH_SMP_CONN_TOUT:
         btif_dm_remove_ble_bonding_keys();
         status = BT_STATUS_AUTH_FAILURE;
         break;
+
+      case BTA_DM_AUTH_SMP_CONN_TOUT: {
+        if (btm_sec_is_a_bonded_dev(bd_addr)) {
+          LOG(INFO) << __func__ << " Bonded device addr=" << bd_addr
+                    << " timed out - will not remove the keys";
+          // Don't send state change to upper layers - otherwise Java think we
+          // unbonded, and will disconnect HID profile.
+          return;
+        }
+
+        btif_dm_remove_ble_bonding_keys();
+        status = BT_STATUS_AUTH_FAILURE;
+        break;
+      }
       case BTA_DM_AUTH_SMP_PAIR_NOT_SUPPORT:
         status = BT_STATUS_AUTH_REJECTED;
         break;
@@ -2886,41 +2919,37 @@
 void btif_dm_load_ble_local_keys(void) {
   memset(&ble_local_key_cb, 0, sizeof(btif_dm_local_key_cb_t));
 
-  if (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_ER,
-                                     (char*)&ble_local_key_cb.er[0],
-                                     BT_OCTET16_LEN) == BT_STATUS_SUCCESS) {
+  if (btif_storage_get_ble_local_key(
+          BTIF_DM_LE_LOCAL_KEY_ER, &ble_local_key_cb.er) == BT_STATUS_SUCCESS) {
     ble_local_key_cb.is_er_rcvd = true;
     BTIF_TRACE_DEBUG("%s BLE ER key loaded", __func__);
   }
 
   if ((btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IR,
-                                      (char*)&ble_local_key_cb.id_keys.ir[0],
-                                      BT_OCTET16_LEN) == BT_STATUS_SUCCESS) &&
+                                      &ble_local_key_cb.id_keys.ir) ==
+       BT_STATUS_SUCCESS) &&
       (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_IRK,
-                                      (char*)&ble_local_key_cb.id_keys.irk[0],
-                                      BT_OCTET16_LEN) == BT_STATUS_SUCCESS) &&
+                                      &ble_local_key_cb.id_keys.irk) ==
+       BT_STATUS_SUCCESS) &&
       (btif_storage_get_ble_local_key(BTIF_DM_LE_LOCAL_KEY_DHK,
-                                      (char*)&ble_local_key_cb.id_keys.dhk[0],
-                                      BT_OCTET16_LEN) == BT_STATUS_SUCCESS)) {
+                                      &ble_local_key_cb.id_keys.dhk) ==
+       BT_STATUS_SUCCESS)) {
     ble_local_key_cb.is_id_keys_rcvd = true;
     BTIF_TRACE_DEBUG("%s BLE ID keys loaded", __func__);
   }
 }
 void btif_dm_get_ble_local_keys(tBTA_DM_BLE_LOCAL_KEY_MASK* p_key_mask,
-                                BT_OCTET16 er,
+                                Octet16* p_er,
                                 tBTA_BLE_LOCAL_ID_KEYS* p_id_keys) {
   if (ble_local_key_cb.is_er_rcvd) {
-    memcpy(&er[0], &ble_local_key_cb.er[0], sizeof(BT_OCTET16));
+    *p_er = ble_local_key_cb.er;
     *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ER;
   }
 
   if (ble_local_key_cb.is_id_keys_rcvd) {
-    memcpy(&p_id_keys->ir[0], &ble_local_key_cb.id_keys.ir[0],
-           sizeof(BT_OCTET16));
-    memcpy(&p_id_keys->irk[0], &ble_local_key_cb.id_keys.irk[0],
-           sizeof(BT_OCTET16));
-    memcpy(&p_id_keys->dhk[0], &ble_local_key_cb.id_keys.dhk[0],
-           sizeof(BT_OCTET16));
+    p_id_keys->ir = ble_local_key_cb.id_keys.ir;
+    p_id_keys->irk = ble_local_key_cb.id_keys.irk;
+    p_id_keys->dhk = ble_local_key_cb.id_keys.dhk;
     *p_key_mask |= BTA_BLE_LOCAL_KEY_TYPE_ID;
   }
   BTIF_TRACE_DEBUG("%s  *p_key_mask=0x%02x", __func__, *p_key_mask);
@@ -3242,26 +3271,26 @@
   int type;
   btif_get_device_type(bd_addr, &type);
 
-  system_bt_osi::device_type_t device_type;
+  bluetooth::common::device_type_t device_type;
   switch (type) {
     case BT_DEVICE_TYPE_BREDR:
-      device_type = system_bt_osi::DEVICE_TYPE_BREDR;
+      device_type = bluetooth::common::DEVICE_TYPE_BREDR;
       break;
     case BT_DEVICE_TYPE_BLE:
-      device_type = system_bt_osi::DEVICE_TYPE_LE;
+      device_type = bluetooth::common::DEVICE_TYPE_LE;
       break;
     case BT_DEVICE_TYPE_DUMO:
-      device_type = system_bt_osi::DEVICE_TYPE_DUMO;
+      device_type = bluetooth::common::DEVICE_TYPE_DUMO;
       break;
     default:
-      device_type = system_bt_osi::DEVICE_TYPE_UNKNOWN;
+      device_type = bluetooth::common::DEVICE_TYPE_UNKNOWN;
       break;
   }
 
   uint32_t cod = get_cod(&bd_addr);
   uint64_t ts =
       event->timestamp.tv_sec * 1000 + event->timestamp.tv_nsec / 1000000;
-  system_bt_osi::BluetoothMetricsLogger::GetInstance()->LogPairEvent(
+  bluetooth::common::BluetoothMetricsLogger::GetInstance()->LogPairEvent(
       0, ts, cod, device_type);
 }
 
diff --git a/btif/src/btif_gatt_client.cc b/btif/src/btif_gatt_client.cc
index 0e06bbb..14433d3 100644
--- a/btif/src/btif_gatt_client.cc
+++ b/btif/src/btif_gatt_client.cc
@@ -41,7 +41,6 @@
 #include <hardware/bt_gatt.h>
 
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bta_gatt_api.h"
 #include "btif_config.h"
 #include "btif_dm.h"
@@ -49,6 +48,7 @@
 #include "btif_gatt_util.h"
 #include "btif_storage.h"
 #include "osi/include/log.h"
+#include "stack/include/btu.h"
 #include "vendor_api.h"
 
 using base::Bind;
@@ -163,6 +163,9 @@
       /* Ignore for now */
       break;
 
+    case BTA_GATTC_SEARCH_RES_EVT:
+      break;
+
     case BTA_GATTC_CANCEL_OPEN_EVT:
       break;
 
@@ -276,7 +279,6 @@
         return;
       }
     }
-    BTA_DmBleStartAutoConn();
   }
 
   // Determine transport
@@ -562,8 +564,8 @@
                                          uint8_t tx_phy, uint8_t rx_phy,
                                          uint16_t phy_options) {
   CHECK_BTGATT_INIT();
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
   return BT_STATUS_SUCCESS;
 }
 
@@ -571,8 +573,8 @@
     const RawAddress& bd_addr,
     base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
   CHECK_BTGATT_INIT();
-  do_in_bta_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
-                                   jni_thread_wrapper(FROM_HERE, cb)));
+  do_in_main_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
+                                    jni_thread_wrapper(FROM_HERE, cb)));
   return BT_STATUS_SUCCESS;
 }
 
diff --git a/btif/src/btif_gatt_server.cc b/btif/src/btif_gatt_server.cc
index b7fdc8c..6dc5eb7 100644
--- a/btif/src/btif_gatt_server.cc
+++ b/btif/src/btif_gatt_server.cc
@@ -40,7 +40,6 @@
 
 #include "bt_common.h"
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bta_gatt_api.h"
 #include "btif_config.h"
 #include "btif_dm.h"
@@ -48,6 +47,7 @@
 #include "btif_gatt_util.h"
 #include "btif_storage.h"
 #include "osi/include/log.h"
+#include "stack/include/btu.h"
 
 using base::Bind;
 using base::Owned;
@@ -291,9 +291,6 @@
     BTA_DmAddBleDevice(address, addr_type, device_type);
   }
 
-  // Mark background connections
-  if (!is_direct) BTA_DmBleStartAutoConn();
-
   // Determine transport
   if (transport_param != GATT_TRANSPORT_AUTO) {
     transport = transport_param;
@@ -425,8 +422,8 @@
                                                 uint8_t tx_phy, uint8_t rx_phy,
                                                 uint16_t phy_options) {
   CHECK_BTGATT_INIT();
-  do_in_bta_thread(FROM_HERE,
-                   Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
+  do_in_main_thread(FROM_HERE,
+                    Bind(&BTM_BleSetPhy, bd_addr, tx_phy, rx_phy, phy_options));
   return BT_STATUS_SUCCESS;
 }
 
@@ -434,8 +431,8 @@
     const RawAddress& bd_addr,
     base::Callback<void(uint8_t tx_phy, uint8_t rx_phy, uint8_t status)> cb) {
   CHECK_BTGATT_INIT();
-  do_in_bta_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
-                                   jni_thread_wrapper(FROM_HERE, cb)));
+  do_in_main_thread(FROM_HERE, Bind(&BTM_BleReadPhy, bd_addr,
+                                    jni_thread_wrapper(FROM_HERE, cb)));
   return BT_STATUS_SUCCESS;
 }
 
diff --git a/btif/src/btif_gatt_test.cc b/btif/src/btif_gatt_test.cc
index 1297d50..1c0af35 100644
--- a/btif/src/btif_gatt_test.cc
+++ b/btif/src/btif_gatt_test.cc
@@ -219,24 +219,18 @@
 
     case 0x04: /* Discover */
     {
-      tGATT_DISC_PARAM param;
-      memset(&param, 0, sizeof(tGATT_DISC_PARAM));
-
       if (params->u1 >= GATT_DISC_MAX) {
         LOG_ERROR(LOG_TAG, "%s: DISCOVER - Invalid type (%d)!", __func__,
                   params->u1);
         return (bt_status_t)0;
       }
 
-      param.s_handle = params->u2;
-      param.e_handle = params->u3;
-      param.service = *params->uuid1;
-
       LOG_DEBUG(LOG_TAG,
                 "%s: DISCOVER (%s), conn_id=%d, uuid=%s, handles=0x%04x-0x%04x",
                 __func__, disc_name[params->u1], test_cb.conn_id,
-                param.service.ToString().c_str(), params->u2, params->u3);
-      GATTC_Discover(test_cb.conn_id, params->u1, &param);
+                params->uuid1->ToString().c_str(), params->u2, params->u3);
+      GATTC_Discover(test_cb.conn_id, params->u1, params->u2, params->u3,
+                     *params->uuid1);
       break;
     }
 
diff --git a/btif/src/btif_hd.cc b/btif/src/btif_hd.cc
index 6d83167..d580a19 100644
--- a/btif/src/btif_hd.cc
+++ b/btif/src/btif_hd.cc
@@ -201,10 +201,8 @@
 
     case BTA_HD_OPEN_EVT: {
       RawAddress* addr = (RawAddress*)&p_data->conn.bda;
-      BTIF_TRACE_WARNING(
-          "BTA_HD_OPEN_EVT, address (%02x:%02x:%02x:%02x:%02x:%02x)",
-          addr->address[0], addr->address[1], addr->address[2],
-          addr->address[3], addr->address[4], addr->address[5]);
+      BTIF_TRACE_WARNING("BTA_HD_OPEN_EVT, address=%s",
+                         addr->ToString().c_str());
       /* Check if the connection is from hid host and not hid device */
       if (check_cod_hid(addr)) {
         /* Incoming connection from hid device, reject it */
diff --git a/btif/src/btif_hearing_aid.cc b/btif/src/btif_hearing_aid.cc
index 74db790..943017e 100644
--- a/btif/src/btif_hearing_aid.cc
+++ b/btif/src/btif_hearing_aid.cc
@@ -18,10 +18,10 @@
 
 /* Hearing Aid Profile Interface */
 
-#include "bta_closure_api.h"
 #include "bta_hearing_aid_api.h"
 #include "btif_common.h"
 #include "btif_storage.h"
+#include "stack/include/btu.h"
 
 #include <base/bind.h>
 #include <base/location.h>
@@ -37,11 +37,12 @@
 
 // template specialization
 template <>
-base::Callback<void()> jni_thread_wrapper(
-    const tracked_objects::Location& from_here, base::Callback<void()> cb) {
+base::Callback<void()> jni_thread_wrapper(const base::Location& from_here,
+                                          base::Callback<void()> cb) {
   return base::Bind(
-      [](const tracked_objects::Location& from_here,
-         base::Callback<void()> cb) { do_in_jni_thread(from_here, cb); },
+      [](const base::Location& from_here, base::Callback<void()> cb) {
+        do_in_jni_thread(from_here, cb);
+      },
       from_here, std::move(cb));
 }
 
@@ -54,10 +55,10 @@
       public HearingAidCallbacks {
   ~HearingAidInterfaceImpl() = default;
 
-  void Init(HearingAidCallbacks* callbacks) {
+  void Init(HearingAidCallbacks* callbacks) override {
     DVLOG(2) << __func__;
     this->callbacks = callbacks;
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
         Bind(&HearingAid::Initialize, this,
              jni_thread_wrapper(FROM_HERE,
@@ -83,56 +84,49 @@
 
   void Connect(const RawAddress& address) override {
     DVLOG(2) << __func__ << " address: " << address;
-    do_in_bta_thread(FROM_HERE, Bind(&HearingAid::Connect,
-                                     Unretained(HearingAid::Get()), address));
+    do_in_main_thread(FROM_HERE, Bind(&HearingAid::Connect,
+                                      Unretained(HearingAid::Get()), address));
   }
 
   void Disconnect(const RawAddress& address) override {
     DVLOG(2) << __func__ << " address: " << address;
-    do_in_bta_thread(FROM_HERE, Bind(&HearingAid::Disconnect,
-                                     Unretained(HearingAid::Get()), address));
-    do_in_jni_thread(
-        FROM_HERE, Bind(&btif_storage_remove_hearing_aid_white_list, address));
+    do_in_main_thread(FROM_HERE, Bind(&HearingAid::Disconnect,
+                                      Unretained(HearingAid::Get()), address));
+    do_in_jni_thread(FROM_HERE, Bind(&btif_storage_set_hearing_aid_white_list,
+                                     address, false));
   }
 
   void AddToWhiteList(const RawAddress& address) override {
-    DVLOG(2) << __func__ << " address: " << address;
-    do_in_bta_thread(FROM_HERE, Bind(&HearingAid::AddToWhiteList,
-                                     Unretained(HearingAid::Get()), address));
-    do_in_jni_thread(
-        FROM_HERE, Bind(&btif_storage_add_hearing_aid_to_white_list, address));
-  }
-
-  void RemoveFromWhiteList(const RawAddress& address) override {
-    DVLOG(2) << __func__ << " address: " << address;
-    do_in_bta_thread(FROM_HERE, Bind(&HearingAid::RemoveFromWhiteList,
-                                     Unretained(HearingAid::Get()), address));
-    do_in_jni_thread(
-        FROM_HERE, Bind(&btif_storage_remove_hearing_aid_white_list, address));
+    VLOG(2) << __func__ << " address: " << address;
+    do_in_main_thread(FROM_HERE, Bind(&HearingAid::AddToWhiteList,
+                                      Unretained(HearingAid::Get()), address));
+    do_in_jni_thread(FROM_HERE, Bind(&btif_storage_set_hearing_aid_white_list,
+                                     address, true));
   }
 
   void SetVolume(int8_t volume) override {
     DVLOG(2) << __func__ << " volume: " << +volume;
-    do_in_bta_thread(FROM_HERE, Bind(&HearingAid::SetVolume,
-                                     Unretained(HearingAid::Get()), volume));
+    do_in_main_thread(FROM_HERE, Bind(&HearingAid::SetVolume,
+                                      Unretained(HearingAid::Get()), volume));
   }
 
   void RemoveDevice(const RawAddress& address) override {
     DVLOG(2) << __func__ << " address: " << address;
 
     // RemoveDevice can be called on devices that don't have HA enabled
-    if (HearingAid::IsInitialized()) {
-      do_in_bta_thread(FROM_HERE, Bind(&HearingAid::Disconnect,
-                                       Unretained(HearingAid::Get()), address));
+    if (HearingAid::IsHearingAidRunning()) {
+      do_in_main_thread(FROM_HERE,
+                        Bind(&HearingAid::Disconnect,
+                             Unretained(HearingAid::Get()), address));
     }
 
     do_in_jni_thread(FROM_HERE,
                      Bind(&btif_storage_remove_hearing_aid, address));
   }
 
-  void Cleanup(void) {
+  void Cleanup(void) override {
     DVLOG(2) << __func__;
-    do_in_bta_thread(FROM_HERE, Bind(&HearingAid::CleanUp));
+    do_in_main_thread(FROM_HERE, Bind(&HearingAid::CleanUp));
   }
 
  private:
diff --git a/btif/src/btif_hf.cc b/btif/src/btif_hf.cc
index 24656c2..04ad011 100644
--- a/btif/src/btif_hf.cc
+++ b/btif/src/btif_hf.cc
@@ -36,6 +36,7 @@
 #include <hardware/bluetooth_headset_callbacks.h>
 #include <hardware/bluetooth_headset_interface.h>
 #include <hardware/bt_hf.h>
+#include <log/log.h>
 
 #include "bta/include/utl.h"
 #include "bta_ag_api.h"
@@ -43,7 +44,7 @@
 #include "btif_hf.h"
 #include "btif_profile_queue.h"
 #include "btif_util.h"
-#include "osi/include/metrics.h"
+#include "common/metrics.h"
 
 namespace bluetooth {
 namespace headset {
@@ -118,16 +119,6 @@
 
 static btif_hf_cb_t btif_hf_cb[BTA_AG_MAX_NUM_CLIENTS];
 
-/* By default, even though codec negotiation is enabled, we will not use WBS as
- * the default
- * codec unless this variable is set to true.
- */
-#ifndef BTIF_HF_WBS_PREFERRED
-#define BTIF_HF_WBS_PREFERRED false
-#endif
-
-static bool btif_conf_hf_force_wbs = BTIF_HF_WBS_PREFERRED;
-
 static const char* dump_hf_call_state(bthf_call_state_t call_state) {
   switch (call_state) {
     CASE_RETURN_STR(BTHF_CALL_STATE_IDLE)
@@ -341,7 +332,7 @@
         btif_hf_cb[idx].state = BTHF_CONNECTION_STATE_CONNECTED;
         btif_hf_cb[idx].peer_feat = 0;
         clear_phone_state_multihf(&btif_hf_cb[idx]);
-        system_bt_osi::BluetoothMetricsLogger::GetInstance()
+        bluetooth::common::BluetoothMetricsLogger::GetInstance()
             ->LogHeadsetProfileRfcConnection(p_data->open.service_id);
         bt_hf_callbacks->ConnectionStateCallback(
             btif_hf_cb[idx].state, &btif_hf_cb[idx].connected_bda);
@@ -421,7 +412,7 @@
     case BTA_AG_AT_BLDN_EVT:
     case BTA_AG_AT_D_EVT:
       bt_hf_callbacks->DialCallCallback(
-          (event == BTA_AG_AT_D_EVT) ? p_data->val.str : nullptr,
+          (event == BTA_AG_AT_D_EVT) ? p_data->val.str : (char*)"",
           &btif_hf_cb[idx].connected_bda);
       break;
 
@@ -511,7 +502,7 @@
       we should set the BTA AG Codec to mSBC. This would trigger a +BCS to mSBC
       at the time
       of SCO connection establishment */
-      if ((btif_conf_hf_force_wbs) && (p_data->val.num & BTA_AG_CODEC_MSBC)) {
+      if (p_data->val.num & BTA_AG_CODEC_MSBC) {
         BTIF_TRACE_EVENT("%s: btif_hf override-Preferred Codec to MSBC",
                          __func__);
         BTA_AgSetCodec(btif_hf_cb[idx].handle, BTA_AG_CODEC_MSBC);
@@ -709,7 +700,7 @@
   bt_status_t PhoneStateChange(int num_active, int num_held,
                                bthf_call_state_t call_setup_state,
                                const char* number, bthf_call_addrtype_t type,
-                               RawAddress* bd_addr) override;
+                               const char* name, RawAddress* bd_addr) override;
 
   void Cleanup() override;
   bt_status_t SetScoAllowed(bool value) override;
@@ -1052,7 +1043,8 @@
 
 bt_status_t HeadsetInterface::PhoneStateChange(
     int num_active, int num_held, bthf_call_state_t call_setup_state,
-    const char* number, bthf_call_addrtype_t type, RawAddress* bd_addr) {
+    const char* number, bthf_call_addrtype_t type, const char* name,
+    RawAddress* bd_addr) {
   CHECK_BTHF_INIT();
   if (!bd_addr) {
     BTIF_TRACE_WARNING("%s: bd_addr is null", __func__);
@@ -1184,22 +1176,53 @@
           }
         }
         if (number) {
-          int xx = 0;
-          if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+'))
-            xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"+%s\"", number);
-          else
-            xx = snprintf(ag_res.str, sizeof(ag_res.str), "\"%s\"", number);
-          ag_res.num = type;
-          // 5 = [,][3_digit_type][null_terminator]
-          if (xx > static_cast<int>(sizeof(ag_res.str) - 5)) {
-            android_errorWriteLog(0x534e4554, "79431031");
-            xx = sizeof(ag_res.str) - 5;
-            // Null terminating the string
-            memset(&ag_res.str[xx], 0, 5);
+          std::ostringstream call_number_stream;
+          if ((type == BTHF_CALL_ADDRTYPE_INTERNATIONAL) && (*number != '+')) {
+            call_number_stream << "\"+";
+          } else {
+            call_number_stream << "\"";
           }
 
-          if (res == BTA_AG_CALL_WAIT_RES)
-            snprintf(&ag_res.str[xx], sizeof(ag_res.str) - xx, ",%d", type);
+          std::string name_str;
+          if (name) {
+            name_str.append(name);
+          }
+          std::string number_str(number);
+          // 13 = ["][+]["][,][3_digit_type][,,,]["]["][null_terminator]
+          int overflow_size =
+              13 + static_cast<int>(number_str.length() + name_str.length()) -
+              static_cast<int>(sizeof(ag_res.str));
+          if (overflow_size > 0) {
+            android_errorWriteLog(0x534e4554, "79431031");
+            int extra_overflow_size =
+                overflow_size - static_cast<int>(name_str.length());
+            if (extra_overflow_size > 0) {
+              number_str.resize(number_str.length() - extra_overflow_size);
+              name_str.clear();
+            } else {
+              name_str.resize(name_str.length() - overflow_size);
+            }
+          }
+          call_number_stream << number_str << "\"";
+
+          // Store caller id string and append type info.
+          // Make sure type info is valid, otherwise add 129 as default type
+          ag_res.num = static_cast<uint16_t>(type);
+          if ((ag_res.num < BTA_AG_CLIP_TYPE_MIN) ||
+              (ag_res.num > BTA_AG_CLIP_TYPE_MAX)) {
+            if (ag_res.num != BTA_AG_CLIP_TYPE_VOIP) {
+              ag_res.num = BTA_AG_CLIP_TYPE_DEFAULT;
+            }
+          }
+
+          if (res == BTA_AG_CALL_WAIT_RES || name_str.empty()) {
+            call_number_stream << "," << std::to_string(ag_res.num);
+          } else {
+            call_number_stream << "," << std::to_string(ag_res.num) << ",,,\""
+                               << name_str << "\"";
+          }
+          snprintf(ag_res.str, sizeof(ag_res.str), "%s",
+                   call_number_stream.str().c_str());
         }
         break;
       case BTHF_CALL_STATE_DIALING:
diff --git a/btif/src/btif_hf_client.cc b/btif/src/btif_hf_client.cc
index 7c65bf7..e84291d 100644
--- a/btif/src/btif_hf_client.cc
+++ b/btif/src/btif_hf_client.cc
@@ -949,7 +949,7 @@
                 (bthf_client_call_state_t)p_data->clcc.status,
                 p_data->clcc.mpty ? BTHF_CLIENT_CALL_MPTY_TYPE_MULTI
                                   : BTHF_CLIENT_CALL_MPTY_TYPE_SINGLE,
-                p_data->clcc.number_present ? p_data->clcc.number : NULL);
+                p_data->clcc.number_present ? p_data->clcc.number : "");
       break;
 
     case BTA_HF_CLIENT_CNUM_EVT:
diff --git a/btif/src/btif_hh.cc b/btif/src/btif_hh.cc
index c5a9021..650923a 100644
--- a/btif/src/btif_hh.cc
+++ b/btif/src/btif_hh.cc
@@ -543,6 +543,14 @@
     p_dev->local_vup = true;
     BTA_HhSendCtrl(p_dev->dev_handle, BTA_HH_CTRL_VIRTUAL_CABLE_UNPLUG);
     return BT_STATUS_SUCCESS;
+  } else if ((p_dev != NULL) &&
+             (p_dev->dev_status == BTHH_CONN_STATE_CONNECTED)) {
+    BTIF_TRACE_ERROR("%s: Virtual unplug not suported, disconnecting device");
+    /* start the timer */
+    btif_hh_start_vup_timer(bd_addr);
+    p_dev->local_vup = true;
+    BTA_HhClose(p_dev->dev_handle);
+    return BT_STATUS_SUCCESS;
   } else {
     BTIF_TRACE_ERROR("%s: Error, device %s not opened, status = %d", __func__,
                      bd_addr->ToString().c_str(), btif_hh_cb.status);
@@ -682,6 +690,21 @@
   }
 }
 
+/*******************************************************************************
+ *
+ *
+ * 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_t reportId, uint16_t bufferSize) {
+  BTA_HhGetReport(p_dev->dev_handle, r_type, reportId, bufferSize);
+}
+
 /*****************************************************************************
  *   Section name (Group of functions)
  ****************************************************************************/
diff --git a/btif/src/btif_keystore.cc b/btif/src/btif_keystore.cc
index fe9d3dd..0af03e1 100644
--- a/btif/src/btif_keystore.cc
+++ b/btif/src/btif_keystore.cc
@@ -98,4 +98,8 @@
                                        &software_enforced_characteristics);
 }
 
+bool BtifKeystore::DoesKeyExist() {
+  return keystore_client_->doesKeyExist(kKeyStore);
+}
+
 }  // namespace bluetooth
diff --git a/btif/src/btif_pan.cc b/btif/src/btif_pan.cc
index 9828c4b..fe10b49 100644
--- a/btif/src/btif_pan.cc
+++ b/btif/src/btif_pan.cc
@@ -54,7 +54,6 @@
 
 #include "bt_common.h"
 #include "bta_api.h"
-#include "bta_closure_api.h"
 #include "bta_pan_api.h"
 #include "btif_common.h"
 #include "btif_pan_internal.h"
@@ -65,6 +64,7 @@
 #include "device/include/controller.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
+#include "stack/include/btu.h"
 
 #define FORWARD_IGNORE 1
 #define FORWARD_SUCCESS 0
@@ -369,8 +369,8 @@
   btpan_cb.flow = enable;
   if (enable) {
     btsock_thread_add_fd(pan_pth, btpan_cb.tap_fd, 0, SOCK_THREAD_FD_RD, 0);
-    do_in_bta_thread(FROM_HERE,
-                     base::Bind(btu_exec_tap_fd_read, btpan_cb.tap_fd));
+    do_in_main_thread(FROM_HERE,
+                      base::Bind(btu_exec_tap_fd_read, btpan_cb.tap_fd));
   }
 }
 
@@ -773,6 +773,6 @@
     btpan_tap_close(fd);
     btif_pan_close_all_conns();
   } else if (flags & SOCK_THREAD_FD_RD) {
-    do_in_bta_thread(FROM_HERE, base::Bind(btu_exec_tap_fd_read, fd));
+    do_in_main_thread(FROM_HERE, base::Bind(btu_exec_tap_fd_read, fd));
   }
 }
diff --git a/btif/src/btif_profile_queue.cc b/btif/src/btif_profile_queue.cc
index 10acade..41275f1 100644
--- a/btif/src/btif_profile_queue.cc
+++ b/btif/src/btif_profile_queue.cc
@@ -29,6 +29,7 @@
 #include "btif_profile_queue.h"
 
 #include <base/bind.h>
+#include <base/callback.h>
 #include <base/logging.h>
 #include <base/strings/stringprintf.h>
 #include <string.h>
@@ -210,7 +211,6 @@
   LOG_INFO(LOG_TAG, "%s", __func__);
   if (do_in_jni_thread(FROM_HERE, base::Bind(&queue_int_release)) !=
       BT_STATUS_SUCCESS) {
-    // Scheduling failed - the thread to schedule on is probably dead
-    queue_int_release();
+    LOG(FATAL) << __func__ << ": Failed to schedule on JNI thread";
   }
 }
diff --git a/btif/src/btif_rc.cc b/btif/src/btif_rc.cc
index c226b5f..9919a7b 100644
--- a/btif/src/btif_rc.cc
+++ b/btif/src/btif_rc.cc
@@ -216,7 +216,7 @@
 
 rc_device_t device;
 
-static void sleep_ms(period_ms_t timeout_ms);
+static void sleep_ms(uint64_t timeout_ms);
 
 /* Response status code - Unknown Error - this is changed to "reserved" */
 #define BTIF_STS_GEN_ERROR 0x06
@@ -272,7 +272,6 @@
                                            uint8_t label,
                                            btif_rc_device_cb_t* p_dev);
 static void rc_ctrl_procedure_complete(btif_rc_device_cb_t* p_dev);
-static void rc_stop_play_status_timer(btif_rc_device_cb_t* p_dev);
 static void register_for_event_notification(btif_rc_supported_event_t* p_event,
                                             btif_rc_device_cb_t* p_dev);
 static void handle_get_capability_response(tBTA_AV_META_MSG* pmeta_msg,
@@ -338,7 +337,6 @@
                                       uint8_t label,
                                       btif_rc_device_cb_t* p_dev);
 
-static void rc_start_play_status_timer(btif_rc_device_cb_t* p_dev);
 static bool absolute_volume_disabled(void);
 
 /*****************************************************************************
@@ -466,11 +464,12 @@
     rc_features |= BTRC_FEAT_ABSOLUTE_VOLUME;
   }
 
-  if ((p_dev->rc_features & BTA_AV_FEAT_METADATA) &&
-      (p_dev->rc_features & BTA_AV_FEAT_VENDOR) &&
-      (p_dev->rc_features_processed != true)) {
+  if (p_dev->rc_features & BTA_AV_FEAT_METADATA) {
     rc_features |= BTRC_FEAT_METADATA;
+  }
 
+  if ((p_dev->rc_features & BTA_AV_FEAT_VENDOR) &&
+      (p_dev->rc_features_processed != true)) {
     /* Mark rc features processed to avoid repeating
      * the AVRCP procedure every time on receiving this
      * update.
@@ -687,7 +686,6 @@
   memset(&p_dev->rc_app_settings, 0, sizeof(btif_rc_player_app_settings_t));
   p_dev->rc_features_processed = false;
   p_dev->rc_procedure_complete = false;
-  rc_stop_play_status_timer(p_dev);
   /* Check and clear the notification event list */
   if (p_dev->rc_supported_event_list != NULL) {
     list_clear(p_dev->rc_supported_event_list);
@@ -1367,8 +1365,6 @@
 static uint8_t fill_attribute_id_array(
     uint8_t cmd_attribute_number, btrc_media_attr_t* cmd_attribute_id_array,
     size_t out_array_size, btrc_media_attr_t* out_attribute_id_array) {
-  /* Reset attribute array */
-  memset(out_attribute_id_array, 0, out_array_size);
   /* Default case for cmd_attribute_number == 0xFF, No attribute */
   uint8_t out_attribute_number = 0;
   if (cmd_attribute_number == 0) {
@@ -1440,7 +1436,7 @@
                            AVRC_STS_BAD_CMD, pavrc_cmd->cmd.opcode);
     } break;
     case AVRC_PDU_GET_ELEMENT_ATTR: {
-      btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+      btrc_media_attr_t element_attrs[BTRC_MAX_ELEM_ATTR_SIZE] = {};
       uint8_t num_attr = fill_attribute_id_array(
           pavrc_cmd->get_elem_attrs.num_attr,
           (btrc_media_attr_t*)pavrc_cmd->get_elem_attrs.attrs,
@@ -1487,7 +1483,7 @@
     } break;
 
     case AVRC_PDU_GET_FOLDER_ITEMS: {
-      uint32_t attr_ids[BTRC_MAX_ELEM_ATTR_SIZE];
+      uint32_t attr_ids[BTRC_MAX_ELEM_ATTR_SIZE] = {0};
       uint8_t num_attr;
       num_attr = pavrc_cmd->get_items.attr_count;
 
@@ -1578,7 +1574,7 @@
     } break;
 
     case AVRC_PDU_GET_ITEM_ATTRIBUTES: {
-      btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE];
+      btrc_media_attr_t item_attrs[BTRC_MAX_ELEM_ATTR_SIZE] = {};
       uint8_t num_attr = fill_attribute_id_array(
           pavrc_cmd->get_attrs.attr_count,
           (btrc_media_attr_t*)pavrc_cmd->get_attrs.p_attr_list,
@@ -2047,7 +2043,7 @@
         } break;
 
         case AVRC_ITEM_MEDIA: {
-          tAVRC_ATTR_ENTRY attr_vals[BTRC_MAX_ELEM_ATTR_SIZE];
+          tAVRC_ATTR_ENTRY attr_vals[BTRC_MAX_ELEM_ATTR_SIZE] = {};
 
           memcpy(item.u.media.uid, cur_item->media.uid, sizeof(tAVRC_UID));
           item.u.media.type = cur_item->media.type;
@@ -2926,77 +2922,6 @@
 
 /***************************************************************************
  *
- * Function         btif_rc_play_status_timeout_handler
- *
- * Description      RC play status timeout handler (Runs in BTIF context).
- * Returns          None
- *
- **************************************************************************/
-static void btif_rc_play_status_timeout_handler(UNUSED_ATTR uint16_t event,
-                                                char* p_data) {
-  btif_rc_handle_t* rc_handle = (btif_rc_handle_t*)p_data;
-  btif_rc_device_cb_t* p_dev = btif_rc_get_device_by_handle(rc_handle->handle);
-  if (p_dev == NULL) {
-    BTIF_TRACE_ERROR("%s timeout handler but no device found for handle %d",
-                     __func__, rc_handle->handle);
-    return;
-  }
-  get_play_status_cmd(p_dev);
-  rc_start_play_status_timer(p_dev);
-}
-
-/***************************************************************************
- *
- * Function         btif_rc_play_status_timer_timeout
- *
- * Description      RC play status timeout callback.
- *                  This is called from BTU context and switches to BTIF
- *                  context to handle the timeout events
- * Returns          None
- *
- **************************************************************************/
-static void btif_rc_play_status_timer_timeout(void* data) {
-  btif_rc_handle_t rc_handle;
-  rc_handle.handle = PTR_TO_UINT(data);
-  BTIF_TRACE_DEBUG("%s called with handle: %d", __func__, rc_handle);
-  btif_transfer_context(btif_rc_play_status_timeout_handler, 0,
-                        (char*)(&rc_handle), sizeof(btif_rc_handle_t), NULL);
-}
-
-/***************************************************************************
- *
- * Function         rc_start_play_status_timer
- *
- * Description      Helper function to start the timer to fetch play status.
- * Returns          None
- *
- **************************************************************************/
-static void rc_start_play_status_timer(btif_rc_device_cb_t* p_dev) {
-  /* Start the Play status timer only if it is not started */
-  if (!alarm_is_scheduled(p_dev->rc_play_status_timer)) {
-    if (p_dev->rc_play_status_timer == NULL) {
-      p_dev->rc_play_status_timer = alarm_new("p_dev->rc_play_status_timer");
-    }
-    alarm_set_on_mloop(
-        p_dev->rc_play_status_timer, BTIF_TIMEOUT_RC_INTERIM_RSP_MS,
-        btif_rc_play_status_timer_timeout, UINT_TO_PTR(p_dev->rc_handle));
-  }
-}
-
-/***************************************************************************
- *
- * Function         rc_stop_play_status_timer
- *
- * Description      Helper function to stop the play status timer.
- * Returns          None
- *
- **************************************************************************/
-void rc_stop_play_status_timer(btif_rc_device_cb_t* p_dev) {
-  alarm_cancel(p_dev->rc_play_status_timer);
-}
-
-/***************************************************************************
- *
  * Function         register_for_event_notification
  *
  * Description      Helper function registering notification events
@@ -3013,9 +2938,12 @@
     BTIF_TRACE_ERROR("%s: no more transaction labels: %d", __func__, status);
     return;
   }
-
-  status = register_notification_cmd(p_transaction->lbl, p_event->event_id, 0,
-                                     p_dev);
+  // interval is only valid for AVRC_EVT_PLAY_POS_CHANGED
+  uint32_t interval = 0;
+  if (p_event->event_id == AVRC_EVT_PLAY_POS_CHANGED) {
+    interval = 2000;
+  }
+  status = register_notification_cmd(p_transaction->lbl, p_event->event_id, interval, p_dev);
   if (status != BT_STATUS_SUCCESS) {
     BTIF_TRACE_ERROR("%s: Error in Notification registration: %d", __func__,
                      status);
@@ -3123,7 +3051,9 @@
       /* Skip registering for Play position change notification */
       if ((p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_STATUS_CHANGE) ||
           (p_rsp->param.event_id[xx] == AVRC_EVT_TRACK_CHANGE) ||
+          (p_rsp->param.event_id[xx] == AVRC_EVT_PLAY_POS_CHANGED) ||
           (p_rsp->param.event_id[xx] == AVRC_EVT_APP_SETTING_CHANGE) ||
+          (p_rsp->param.event_id[xx] == AVRC_EVT_NOW_PLAYING_CHANGE) ||
           (p_rsp->param.event_id[xx] == AVRC_EVT_ADDR_PLAYER_CHANGE) ||
           (p_rsp->param.event_id[xx] == AVRC_EVT_UIDS_CHANGE)) {
         p_event = (btif_rc_supported_event_t*)osi_malloc(
@@ -3133,6 +3063,15 @@
         list_append(p_dev->rc_supported_event_list, p_event);
       }
     }
+
+    // On occasion a remote device can intermittently send a poorly configured
+    // packet with 0 capabilities. This check ensures the stack does not crash.
+    // Typically the remote device will send a proper packet in the future and
+    // continue operation.
+    if (list_is_empty(p_dev->rc_supported_event_list)) {
+      return;
+    }
+
     p_event =
         (btif_rc_supported_event_t*)list_front(p_dev->rc_supported_event_list);
     if (p_event != NULL) {
@@ -3200,14 +3139,7 @@
     BTIF_TRACE_DEBUG("%s: Interim response: 0x%2X ", __func__, p_rsp->event_id);
     switch (p_rsp->event_id) {
       case AVRC_EVT_PLAY_STATUS_CHANGE:
-        /* Start timer to get play status periodically
-         * if the play state is playing.
-         */
-        if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING ||
-            p_rsp->param.play_status == AVRC_PLAYSTATE_REV_SEEK ||
-            p_rsp->param.play_status == AVRC_PLAYSTATE_FWD_SEEK) {
-          rc_start_play_status_timer(p_dev);
-        }
+        get_play_status_cmd(p_dev);
         do_in_jni_thread(
             FROM_HERE,
             base::Bind(bt_rc_ctrl_callbacks->play_status_changed_cb,
@@ -3224,6 +3156,7 @@
            * Attributes will be fetched after the AVRCP procedure
            */
           BE_STREAM_TO_UINT64(p_dev->rc_playing_uid, p_data);
+          get_play_status_cmd(p_dev);
         }
         break;
 
@@ -3231,6 +3164,10 @@
         break;
 
       case AVRC_EVT_NOW_PLAYING_CHANGE:
+        do_in_jni_thread(
+            FROM_HERE,
+            base::Bind(bt_rc_ctrl_callbacks->now_playing_contents_changed_cb,
+                       p_dev->rc_addr));
         break;
 
       case AVRC_EVT_AVAL_PLAYERS_CHANGE:
@@ -3238,16 +3175,21 @@
 
       case AVRC_EVT_ADDR_PLAYER_CHANGE:
         do_in_jni_thread(
-            FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->set_addressed_player_cb,
-                                  p_dev->rc_addr, BTRC_STS_ADDR_PLAY_CHGD));
+            FROM_HERE,
+            base::Bind(bt_rc_ctrl_callbacks->addressed_player_changed_cb,
+                       p_dev->rc_addr, p_rsp->param.addr_player.player_id));
         break;
 
+      case AVRC_EVT_PLAY_POS_CHANGED:
+        do_in_jni_thread(FROM_HERE, base::Bind(bt_rc_ctrl_callbacks->play_position_changed_cb, p_dev->rc_addr, 0,
+                                               p_rsp->param.play_pos));
+
+        break;
       case AVRC_EVT_UIDS_CHANGE:
         break;
 
       case AVRC_EVT_TRACK_REACHED_END:
       case AVRC_EVT_TRACK_REACHED_START:
-      case AVRC_EVT_PLAY_POS_CHANGED:
       case AVRC_EVT_BATTERY_STATUS_CHANGE:
       case AVRC_EVT_SYSTEM_STATUS_CHANGE:
       default:
@@ -3310,11 +3252,8 @@
          * if the play state is playing.
          */
         if (p_rsp->param.play_status == AVRC_PLAYSTATE_PLAYING) {
-          rc_start_play_status_timer(p_dev);
           get_element_attribute_cmd(AVRC_MAX_NUM_MEDIA_ATTR_ID, attr_list,
                                     p_dev);
-        } else {
-          rc_stop_play_status_timer(p_dev);
         }
         do_in_jni_thread(
             FROM_HERE,
@@ -3357,12 +3296,15 @@
       case AVRC_EVT_ADDR_PLAYER_CHANGE:
         break;
 
+      case AVRC_EVT_PLAY_POS_CHANGED:
+        // handle on interim
+        break;
+
       case AVRC_EVT_UIDS_CHANGE:
         break;
 
       case AVRC_EVT_TRACK_REACHED_END:
       case AVRC_EVT_TRACK_REACHED_START:
-      case AVRC_EVT_PLAY_POS_CHANGED:
       case AVRC_EVT_BATTERY_STATUS_CHANGE:
       case AVRC_EVT_SYSTEM_STATUS_CHANGE:
       default:
@@ -5417,7 +5359,7 @@
  *
  *      Returns        void
  ******************************************************************************/
-static void sleep_ms(period_ms_t timeout_ms) {
+static void sleep_ms(uint64_t timeout_ms) {
   struct timespec delay;
   delay.tv_sec = timeout_ms / 1000;
   delay.tv_nsec = 1000 * 1000 * (timeout_ms % 1000);
diff --git a/btif/src/btif_sdp_server.cc b/btif/src/btif_sdp_server.cc
index 4738da4..ef1b02f 100644
--- a/btif/src/btif_sdp_server.cc
+++ b/btif/src/btif_sdp_server.cc
@@ -28,6 +28,7 @@
 
 #define LOG_TAG "bt_btif_sdp_server"
 
+#include <log/log.h>
 #include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
@@ -71,6 +72,7 @@
  *****************************************************************************/
 static int add_maps_sdp(const bluetooth_sdp_mas_record* rec);
 static int add_mapc_sdp(const bluetooth_sdp_mns_record* rec);
+static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec);
 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec);
 static int add_opps_sdp(const bluetooth_sdp_ops_record* rec);
 static int add_saps_sdp(const bluetooth_sdp_sap_record* rec);
@@ -338,7 +340,8 @@
         handle = add_saps_sdp(&record->sap);
         break;
       case SDP_TYPE_PBAP_PCE:
-      //        break; not yet supported
+        handle = add_pbapc_sdp(&record->pce);
+        break;
       default:
         BTIF_TRACE_DEBUG("Record type %d is not supported", record->hdr.type);
         break;
@@ -532,6 +535,49 @@
   return sdp_handle;
 }
 
+/* Create a PBAP Client SDP record based on information stored in a
+ * bluetooth_sdp_pce_record */
+static int add_pbapc_sdp(const bluetooth_sdp_pce_record* rec) {
+  uint16_t service = UUID_SERVCLASS_PBAP_PCE;
+  uint16_t browse = UUID_SERVCLASS_PUBLIC_BROWSE_GROUP;
+  bool status = true;
+  uint32_t sdp_handle = 0;
+
+  APPL_TRACE_DEBUG("%s(): service name %s", __func__, rec->hdr.service_name);
+  sdp_handle = SDP_CreateRecord();
+  if (sdp_handle == 0) {
+    APPL_TRACE_ERROR("%s(): Unable to register PBAP Client Service", __func__);
+    return sdp_handle;
+  }
+
+  status &= SDP_AddServiceClassIdList(sdp_handle, 1, &service);
+
+  /* Add a name entry */
+  status &= SDP_AddAttribute(sdp_handle, (uint16_t)ATTR_ID_SERVICE_NAME,
+                             (uint8_t)TEXT_STR_DESC_TYPE,
+                             (uint32_t)(rec->hdr.service_name_length + 1),
+                             (uint8_t*)rec->hdr.service_name);
+
+  /* Add in the Bluetooth Profile Descriptor List */
+  status &= SDP_AddProfileDescriptorList(sdp_handle, service,
+                                         rec->hdr.profile_version);
+
+  /* Make the service browseable */
+  status &=
+      SDP_AddUuidSequence(sdp_handle, ATTR_ID_BROWSE_GROUP_LIST, 1, &browse);
+
+  if (!status) {
+    SDP_DeleteRecord(sdp_handle);
+    sdp_handle = 0;
+    APPL_TRACE_ERROR("%s() FAILED", __func__);
+    return sdp_handle;
+  }
+  bta_sys_add_uuid(service); /* UUID_SERVCLASS_PBAP_PCE */
+  APPL_TRACE_DEBUG("%s():  SDP Registered (handle 0x%08x)", __func__,
+                   sdp_handle);
+  return sdp_handle;
+}
+
 /* Create a PBAP Server SDP record based on information stored in a
  * bluetooth_sdp_pse_record */
 static int add_pbaps_sdp(const bluetooth_sdp_pse_record* rec) {
diff --git a/btif/src/btif_sock.cc b/btif/src/btif_sock.cc
index 90121b1..0c4f6f6 100644
--- a/btif/src/btif_sock.cc
+++ b/btif/src/btif_sock.cc
@@ -22,6 +22,7 @@
 
 #include <base/logging.h>
 
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
 
@@ -34,6 +35,7 @@
 #include "btif_sock_thread.h"
 #include "btif_uid.h"
 #include "btif_util.h"
+#include "common/metrics.h"
 #include "device/include/controller.h"
 #include "osi/include/thread.h"
 
@@ -138,6 +140,11 @@
   bt_status_t status = BT_STATUS_FAIL;
   int original_channel = channel;
 
+  bluetooth::common::LogSocketConnectionState(
+      RawAddress::kEmpty, 0, type,
+      android::bluetooth::SocketConnectionstateEnum::
+          SOCKET_CONNECTION_STATE_LISTENING,
+      0, 0, app_uid, channel, android::bluetooth::SOCKET_ROLE_LISTEN);
   switch (type) {
     case BTSOCK_RFCOMM:
       status = btsock_rfc_listen(service_name, service_uuid, channel, sock_fd,
@@ -174,6 +181,13 @@
       status = BT_STATUS_UNSUPPORTED;
       break;
   }
+  if (status != BT_STATUS_SUCCESS) {
+    bluetooth::common::LogSocketConnectionState(
+        RawAddress::kEmpty, 0, type,
+        android::bluetooth::SocketConnectionstateEnum::
+            SOCKET_CONNECTION_STATE_DISCONNECTED,
+        0, 0, app_uid, channel, android::bluetooth::SOCKET_ROLE_LISTEN);
+  }
   return status;
 }
 
@@ -186,6 +200,11 @@
   *sock_fd = INVALID_FD;
   bt_status_t status = BT_STATUS_FAIL;
 
+  bluetooth::common::LogSocketConnectionState(
+      *bd_addr, 0, type,
+      android::bluetooth::SocketConnectionstateEnum::
+          SOCKET_CONNECTION_STATE_CONNECTING,
+      0, 0, app_uid, channel, android::bluetooth::SOCKET_ROLE_CONNECTION);
   switch (type) {
     case BTSOCK_RFCOMM:
       status =
@@ -213,6 +232,13 @@
       status = BT_STATUS_UNSUPPORTED;
       break;
   }
+  if (status != BT_STATUS_SUCCESS) {
+    bluetooth::common::LogSocketConnectionState(
+        *bd_addr, 0, type,
+        android::bluetooth::SocketConnectionstateEnum::
+            SOCKET_CONNECTION_STATE_DISCONNECTED,
+        0, 0, app_uid, channel, android::bluetooth::SOCKET_ROLE_CONNECTION);
+  }
   return status;
 }
 
@@ -237,7 +263,8 @@
       btsock_l2cap_signaled(fd, flags, user_id);
       break;
     default:
-      CHECK(false && "Invalid socket type");
+      LOG(FATAL) << "Invalid socket type! type=" << type << " fd=" << fd
+                 << " flags=" << flags << " user_id=" << user_id;
       break;
   }
 }
diff --git a/btif/src/btif_sock_l2cap.cc b/btif/src/btif_sock_l2cap.cc
index 43f2372..1f85c73 100644
--- a/btif/src/btif_sock_l2cap.cc
+++ b/btif/src/btif_sock_l2cap.cc
@@ -28,6 +28,7 @@
 
 #include <mutex>
 
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
 #include <hardware/bt_sock.h>
 
 #include "osi/include/allocator.h"
@@ -46,6 +47,7 @@
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/metrics.h"
 #include "hcimsgs.h"
 #include "l2c_api.h"
 #include "l2c_int.h"
@@ -84,6 +86,10 @@
   bool is_le_coc;                 // is le connection oriented channel?
   uint16_t rx_mtu;
   uint16_t tx_mtu;
+  // Cumulative number of bytes transmitted on this socket
+  int64_t tx_bytes;
+  // Cumulative number of bytes received on this socket
+  int64_t rx_bytes;
 } l2cap_socket;
 
 static void btsock_l2cap_server_listen(l2cap_socket* sock);
@@ -215,6 +221,14 @@
   if (!t) /* prever double-frees */
     return;
 
+  // Whenever a socket is freed, the connection must be dropped
+  bluetooth::common::LogSocketConnectionState(
+      sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTED, sock->tx_bytes,
+      sock->rx_bytes, sock->app_uid, sock->channel,
+      sock->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                   : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   if (sock->next) sock->next->prev = sock->prev;
 
   if (sock->prev)
@@ -309,6 +323,8 @@
   sock->prev = NULL;
   if (socks) socks->prev = sock;
   sock->id = (socks ? socks->id : 0) + 1;
+  sock->tx_bytes = 0;
+  sock->rx_bytes = 0;
   socks = sock;
   /* paranoia cap on: verify no ID duplicates due to overflow and fix as needed
    */
@@ -396,6 +412,14 @@
   DVLOG(2) << __func__ << ": sock->handle: " << sock->handle
            << ", id: " << sock->id;
 
+  bluetooth::common::LogSocketConnectionState(
+      sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SocketConnectionstateEnum::
+          SOCKET_CONNECTION_STATE_LISTENING,
+      0, 0, sock->app_uid, sock->channel,
+      sock->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                   : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   if (!sock->server_psm_sent) {
     if (!send_app_psm_or_chan_l(sock)) {
       // closed
@@ -448,6 +472,14 @@
   accept_rs->id = sock->id;
   sock->id = new_listen_id;
 
+  bluetooth::common::LogSocketConnectionState(
+      accept_rs->addr, accept_rs->id,
+      accept_rs->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SOCKET_CONNECTION_STATE_CONNECTED, 0, 0,
+      accept_rs->app_uid, accept_rs->channel,
+      accept_rs->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                        : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   // start monitor the socket
   btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
                        SOCK_THREAD_FD_EXCEPTION, sock->id);
@@ -489,6 +521,14 @@
   *(p_open->p_p_cback) = (void*)btsock_l2cap_cbk;
   *(p_open->p_user_data) = UINT_TO_PTR(accept_rs->id);
 
+  bluetooth::common::LogSocketConnectionState(
+      accept_rs->addr, accept_rs->id,
+      accept_rs->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SOCKET_CONNECTION_STATE_CONNECTED, 0, 0,
+      accept_rs->app_uid, accept_rs->channel,
+      accept_rs->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                        : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   // start monitor the socket
   btsock_thread_add_fd(pth, sock->our_fd, BTSOCK_L2CAP,
                        SOCK_THREAD_FD_EXCEPTION, sock->id);
@@ -518,6 +558,13 @@
     return;
   }
 
+  bluetooth::common::LogSocketConnectionState(
+      sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SOCKET_CONNECTION_STATE_CONNECTED, 0, 0,
+      sock->app_uid, sock->channel,
+      sock->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                   : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   // start monitoring the socketpair to get call back when app writing data
   DVLOG(2) << " connect signal sent, slot id: " << sock->id
            << ", chan: " << sock->channel << ", server: " << sock->server;
@@ -542,6 +589,13 @@
     return;
   }
 
+  bluetooth::common::LogSocketConnectionState(
+      sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SOCKET_CONNECTION_STATE_CONNECTED, 0, 0,
+      sock->app_uid, sock->channel,
+      sock->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                   : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   // start monitoring the socketpair to get call back when app writing data
   DVLOG(2) << " connect signal sent, slot id: " << sock->id
            << ", chan: " << sock->channel << ", server: " << sock->server;
@@ -564,17 +618,20 @@
 
   sock->tx_mtu = le_open->tx_mtu;
   if (sock->fixed_chan && le_open->status == BTA_JV_SUCCESS) {
-    if (!sock->server)
+    if (!sock->server) {
       on_cl_l2cap_le_connect_l(le_open, sock);
-    else
+    } else {
       on_srv_l2cap_le_connect_l(le_open, sock);
+    }
   } else if (!sock->fixed_chan && psm_open->status == BTA_JV_SUCCESS) {
-    if (!sock->server)
+    if (!sock->server) {
       on_cl_l2cap_psm_connect_l(psm_open, sock);
-    else
+    } else {
       on_srv_l2cap_psm_connect_l(psm_open, sock);
-  } else
+    }
+  } else {
     btsock_l2cap_free_l(sock);
+  }
 }
 
 static void on_l2cap_close(tBTA_JV_L2CAP_CLOSE* p_close, uint32_t id) {
@@ -584,6 +641,13 @@
   sock = btsock_l2cap_find_by_id_l(id);
   if (!sock) return;
 
+  bluetooth::common::LogSocketConnectionState(
+      sock->addr, sock->id, sock->is_le_coc ? BTSOCK_L2CAP_LE : BTSOCK_L2CAP,
+      android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTING, 0, 0,
+      sock->app_uid, sock->channel,
+      sock->server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                   : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   DVLOG(2) << __func__ << ": slot id: " << sock->id << ", fd: " << sock->our_fd
            << (sock->fixed_chan ? ", fixed_chan:" : ", PSM: ") << sock->channel
            << ", server:" << sock->server;
@@ -624,6 +688,7 @@
                          sock->id);
   }
 
+  sock->tx_bytes += len;
   uid_set_add_tx(uid_set, app_uid, len);
 }
 
@@ -677,6 +742,7 @@
     }
   }
 
+  sock->rx_bytes += bytes_read;
   uid_set_add_rx(uid_set, app_uid, bytes_read);
 }
 
diff --git a/btif/src/btif_sock_rfc.cc b/btif/src/btif_sock_rfc.cc
index 4b490a0..3c9e26e 100644
--- a/btif/src/btif_sock_rfc.cc
+++ b/btif/src/btif_sock_rfc.cc
@@ -30,6 +30,7 @@
 
 #include <mutex>
 
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
 #include <hardware/bluetooth.h>
 #include <hardware/bt_sock.h>
 
@@ -47,6 +48,7 @@
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/metrics.h"
 #include "hcimsgs.h"
 #include "osi/include/compat.h"
 #include "osi/include/list.h"
@@ -97,6 +99,10 @@
   int rfc_port_handle;
   int role;
   list_t* incoming_queue;
+  // Cumulative number of bytes transmitted on this socket
+  int64_t tx_bytes;
+  // Cumulative number of bytes received on this socket
+  int64_t rx_bytes;
 } rfc_slot_t;
 
 static rfc_slot_t rfc_slots[MAX_RFC_CHANNEL];
@@ -225,11 +231,15 @@
   } else {
     memset(slot->service_name, 0, sizeof(slot->service_name));
   }
-  if (addr) slot->addr = *addr;
-
+  if (addr) {
+    slot->addr = *addr;
+  } else {
+    slot->addr = RawAddress::kEmpty;
+  }
   slot->id = rfc_slot_id;
   slot->f.server = server;
-
+  slot->tx_bytes = 0;
+  slot->rx_bytes = 0;
   return slot;
 }
 
@@ -411,6 +421,12 @@
   if (slot->fd != INVALID_FD) {
     shutdown(slot->fd, SHUT_RDWR);
     close(slot->fd);
+    bluetooth::common::LogSocketConnectionState(
+        slot->addr, slot->id, BTSOCK_RFCOMM,
+        android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTED,
+        slot->tx_bytes, slot->rx_bytes, slot->app_uid, slot->scn,
+        slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                       : android::bluetooth::SOCKET_ROLE_CONNECTION);
     slot->fd = INVALID_FD;
   }
 
@@ -436,6 +452,8 @@
   memset(&slot->f, 0, sizeof(slot->f));
   slot->id = 0;
   slot->scn_notified = false;
+  slot->tx_bytes = 0;
+  slot->rx_bytes = 0;
 }
 
 static bool send_app_scn(rfc_slot_t* slot) {
@@ -484,6 +502,13 @@
 
   if (p_start->status == BTA_JV_SUCCESS) {
     slot->rfc_handle = p_start->handle;
+    bluetooth::common::LogSocketConnectionState(
+        slot->addr, slot->id, BTSOCK_RFCOMM,
+        android::bluetooth::SocketConnectionstateEnum::
+            SOCKET_CONNECTION_STATE_LISTENING,
+        0, 0, slot->app_uid, slot->scn,
+        slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                       : android::bluetooth::SOCKET_ROLE_CONNECTION);
   } else {
     cleanup_rfc_slot(slot);
   }
@@ -500,6 +525,13 @@
       srv_rs, &p_open->rem_bda, p_open->handle, p_open->new_listen_handle);
   if (!accept_rs) return 0;
 
+  bluetooth::common::LogSocketConnectionState(
+      accept_rs->addr, accept_rs->id, BTSOCK_RFCOMM,
+      android::bluetooth::SOCKET_CONNECTION_STATE_CONNECTED, 0, 0,
+      accept_rs->app_uid, accept_rs->scn,
+      accept_rs->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                          : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   // Start monitoring the socket.
   btsock_thread_add_fd(pth, srv_rs->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_EXCEPTION,
                        srv_rs->id);
@@ -525,6 +557,13 @@
   slot->rfc_port_handle = BTA_JvRfcommGetPortHdl(p_open->handle);
   slot->addr = p_open->rem_bda;
 
+  bluetooth::common::LogSocketConnectionState(
+      slot->addr, slot->id, BTSOCK_RFCOMM,
+      android::bluetooth::SOCKET_CONNECTION_STATE_CONNECTED, 0, 0,
+      slot->app_uid, slot->scn,
+      slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                     : android::bluetooth::SOCKET_ROLE_CONNECTION);
+
   if (send_app_connect_signal(slot->fd, &slot->addr, slot->scn, 0, -1)) {
     slot->f.connected = true;
   } else {
@@ -539,7 +578,15 @@
 
   // rfc_handle already closed when receiving rfcomm close event from stack.
   rfc_slot_t* slot = find_rfc_slot_by_id(id);
-  if (slot) cleanup_rfc_slot(slot);
+  if (slot) {
+    bluetooth::common::LogSocketConnectionState(
+        slot->addr, slot->id, BTSOCK_RFCOMM,
+        android::bluetooth::SOCKET_CONNECTION_STATE_DISCONNECTING, 0, 0,
+        slot->app_uid, slot->scn,
+        slot->f.server ? android::bluetooth::SOCKET_ROLE_LISTEN
+                       : android::bluetooth::SOCKET_ROLE_CONNECTION);
+    cleanup_rfc_slot(slot);
+  }
 }
 
 static void on_rfc_write_done(tBTA_JV_RFCOMM_WRITE* p, uint32_t id) {
@@ -559,6 +606,7 @@
       btsock_thread_add_fd(pth, slot->fd, BTSOCK_RFCOMM, SOCK_THREAD_FD_RD,
                            slot->id);
     }
+    slot->tx_bytes += p->len;
   }
 
   uid_set_add_tx(uid_set, app_uid, p->len);
@@ -877,6 +925,7 @@
     list_append(slot->incoming_queue, p_buf);
   }
 
+  slot->rx_bytes += bytes_rx;
   uid_set_add_rx(uid_set, app_uid, bytes_rx);
 
   return ret;  // Return 0 to disable data flow.
diff --git a/btif/src/btif_storage.cc b/btif/src/btif_storage.cc
index ef2e191..2427493 100644
--- a/btif/src/btif_storage.cc
+++ b/btif/src/btif_storage.cc
@@ -41,7 +41,6 @@
 #include <time.h>
 
 #include "bt_common.h"
-#include "bta_closure_api.h"
 #include "bta_hd_api.h"
 #include "bta_hearing_aid_api.h"
 #include "bta_hh_api.h"
@@ -83,6 +82,8 @@
 #define BTIF_STORAGE_PATH_REMOTE_HIDINFO "HidInfo"
 #define BTIF_STORAGE_KEY_ADAPTER_NAME "Name"
 #define BTIF_STORAGE_KEY_ADAPTER_SCANMODE "ScanMode"
+#define BTIF_STORAGE_KEY_LOCAL_IO_CAPS "LocalIOCaps"
+#define BTIF_STORAGE_KEY_LOCAL_IO_CAPS_BLE "LocalIOCapsBLE"
 #define BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT "DiscoveryTimeout"
 
 /* This is a local property to add a device found */
@@ -225,6 +226,14 @@
       btif_config_set_int("Adapter", BTIF_STORAGE_KEY_ADAPTER_SCANMODE,
                           *(int*)prop->val);
       break;
+    case BT_PROPERTY_LOCAL_IO_CAPS:
+      btif_config_set_int("Adapter", BTIF_STORAGE_KEY_LOCAL_IO_CAPS,
+                          *(int*)prop->val);
+      break;
+    case BT_PROPERTY_LOCAL_IO_CAPS_BLE:
+      btif_config_set_int("Adapter", BTIF_STORAGE_KEY_LOCAL_IO_CAPS_BLE,
+                          *(int*)prop->val);
+      break;
     case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
       btif_config_set_int("Adapter", BTIF_STORAGE_KEY_ADAPTER_DISC_TIMEOUT,
                           *(int*)prop->val);
@@ -326,6 +335,18 @@
         ret = btif_config_get_int("Adapter", BTIF_STORAGE_KEY_ADAPTER_SCANMODE,
                                   (int*)prop->val);
       break;
+
+    case BT_PROPERTY_LOCAL_IO_CAPS:
+      if (prop->len >= (int)sizeof(int))
+        ret = btif_config_get_int("Adapter", BTIF_STORAGE_KEY_LOCAL_IO_CAPS,
+                                  (int*)prop->val);
+      break;
+    case BT_PROPERTY_LOCAL_IO_CAPS_BLE:
+      if (prop->len >= (int)sizeof(int))
+        ret = btif_config_get_int("Adapter", BTIF_STORAGE_KEY_LOCAL_IO_CAPS_BLE,
+                                  (int*)prop->val);
+      break;
+
     case BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT:
       if (prop->len >= (int)sizeof(int))
         ret = btif_config_get_int(
@@ -394,9 +415,9 @@
 static bt_status_t btif_in_fetch_bonded_device(const std::string& bdstr) {
   bool bt_linkkey_file_found = false;
 
-  LINK_KEY link_key;
-  size_t size = sizeof(link_key);
-  if (btif_config_get_bin(bdstr, "LinkKey", (uint8_t*)link_key, &size)) {
+  LinkKey link_key;
+  size_t size = link_key.size();
+  if (btif_config_get_bin(bdstr, "LinkKey", link_key.data(), &size)) {
     int linkkey_type;
     if (btif_config_get_int(bdstr, "LinkKeyType", &linkkey_type)) {
       bt_linkkey_file_found = true;
@@ -438,9 +459,9 @@
     if (!RawAddress::IsValidAddress(name)) continue;
 
     BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
-    LINK_KEY link_key;
+    LinkKey link_key;
     size_t size = sizeof(link_key);
-    if (btif_config_get_bin(name, "LinkKey", link_key, &size)) {
+    if (btif_config_get_bin(name, "LinkKey", link_key.data(), &size)) {
       int linkkey_type;
       if (btif_config_get_int(name, "LinkKeyType", &linkkey_type)) {
         RawAddress bd_addr;
@@ -466,8 +487,7 @@
         bt_linkkey_file_found = false;
       }
     }
-    if (!btif_in_fetch_bonded_ble_device(name.c_str(), add, p_bonded_devices) &&
-        !bt_linkkey_file_found) {
+    if (!btif_in_fetch_bonded_ble_device(name, add, p_bonded_devices) && !bt_linkkey_file_found) {
       BTIF_TRACE_DEBUG("Remote device:%s, no link key or ble key found",
                        name.c_str());
     }
@@ -545,6 +565,57 @@
   return num_uuids;
 }
 
+/**
+ * Helper function for fetching a local Input/Output capability property. If not
+ * set, it returns the default value.
+ */
+static uint8_t btif_storage_get_io_cap_property(bt_property_type_t type,
+                                                uint8_t default_value) {
+  char buf[sizeof(int)];
+
+  bt_property_t property;
+  property.type = type;
+  property.val = (void*)buf;
+  property.len = sizeof(int);
+
+  bt_status_t ret = btif_storage_get_adapter_property(&property);
+
+  return (ret == BT_STATUS_SUCCESS) ? (uint8_t)(*(int*)property.val)
+                                    : default_value;
+}
+
+/*******************************************************************************
+ *
+ * Function         btif_storage_get_io_caps
+ *
+ * Description      BTIF storage API - Fetches the local Input/Output
+ *                  capabilities of the device.
+ *
+ * Returns          Returns local IO Capability of device. If not stored,
+ *                  returns BTM_LOCAL_IO_CAPS.
+ *
+ ******************************************************************************/
+uint8_t btif_storage_get_local_io_caps() {
+  return btif_storage_get_io_cap_property(BT_PROPERTY_LOCAL_IO_CAPS,
+                                          BTM_LOCAL_IO_CAPS);
+}
+
+/*******************************************************************************
+ *
+ * Function         btif_storage_get_io_caps_ble
+ *
+ * Description      BTIF storage API - Fetches the local Input/Output
+ *                  capabilities of the BLE device.
+ *
+ * Returns          Returns local IO Capability of BLE device. If not stored,
+ *                  returns BTM_LOCAL_IO_CAPS_BLE.
+ *
+ ******************************************************************************/
+uint8_t btif_storage_get_local_io_caps_ble() {
+  return btif_storage_get_io_cap_property(BT_PROPERTY_LOCAL_IO_CAPS_BLE,
+                                          BTM_LOCAL_IO_CAPS_BLE);
+}
+
 /*******************************************************************************
  *
  * Function         btif_storage_get_adapter_property
@@ -611,6 +682,7 @@
                 Uuid::From16Bit(UUID_SERVCLASS_AG_HANDSFREE);
             num_uuids++;
           }
+            FALLTHROUGH_INTENDED; /* FALLTHROUGH */
           /* intentional fall through: Send both BFP & HSP UUIDs if HFP is
            * enabled */
           case BTA_HSP_SERVICE_ID: {
@@ -745,12 +817,13 @@
  ******************************************************************************/
 
 bt_status_t btif_storage_add_bonded_device(RawAddress* remote_bd_addr,
-                                           LINK_KEY link_key, uint8_t key_type,
+                                           LinkKey link_key, uint8_t key_type,
                                            uint8_t pin_length) {
   std::string bdstr = remote_bd_addr->ToString();
   int ret = btif_config_set_int(bdstr, "LinkKeyType", (int)key_type);
   ret &= btif_config_set_int(bdstr, "PinLength", (int)pin_length);
-  ret &= btif_config_set_bin(bdstr, "LinkKey", link_key, sizeof(LINK_KEY));
+  ret &=
+      btif_config_set_bin(bdstr, "LinkKey", link_key.data(), link_key.size());
 
   if (is_restricted_mode()) {
     BTIF_TRACE_WARNING("%s: '%s' pairing will be removed if unrestricted",
@@ -816,9 +889,8 @@
     tBTA_LE_KEY_VALUE key;
     memset(&key, 0, sizeof(key));
 
-    if (btif_storage_get_ble_bonding_key(
-            &bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key,
-            sizeof(tBTM_LE_PENC_KEYS)) == BT_STATUS_SUCCESS) {
+    if (btif_storage_get_ble_bonding_key(&bd_addr, BTIF_DM_LE_KEY_PENC, (uint8_t*)&key, sizeof(tBTM_LE_PENC_KEYS)) ==
+        BT_STATUS_SUCCESS) {
       if (is_sample_ltk(key.penc_key.ltk)) {
         bad_ltk.push_back(bd_addr);
       }
@@ -827,8 +899,7 @@
 
   for (RawAddress address : bad_ltk) {
     android_errorWriteLog(0x534e4554, "128437297");
-    LOG(ERROR) << __func__
-               << ": removing bond to device using test TLK: " << address;
+    LOG(ERROR) << __func__ << ": removing bond to device using test TLK: " << address;
 
     btif_storage_remove_bonded_device(&address);
   }
@@ -1096,8 +1167,8 @@
  *                  BT_STATUS_FAIL otherwise
  *
  ******************************************************************************/
-bt_status_t btif_storage_add_ble_local_key(char* key, uint8_t key_type,
-                                           uint8_t key_length) {
+bt_status_t btif_storage_add_ble_local_key(const Octet16& key,
+                                           uint8_t key_type) {
   const char* name;
   switch (key_type) {
     case BTIF_DM_LE_LOCAL_KEY_IR:
@@ -1115,24 +1186,17 @@
     default:
       return BT_STATUS_FAIL;
   }
-  int ret =
-      btif_config_set_bin("Adapter", name, (const uint8_t*)key, key_length);
+  int ret = btif_config_set_bin("Adapter", name, key.data(), key.size());
   btif_config_save();
   return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
-/*******************************************************************************
- *
- * Function         btif_storage_get_ble_local_key
- *
- * Description
- *
- * Returns          BT_STATUS_SUCCESS if the fetch was successful,
- *                  BT_STATUS_FAIL otherwise
- *
- ******************************************************************************/
-bt_status_t btif_storage_get_ble_local_key(uint8_t key_type, char* key_value,
-                                           int key_length) {
+/** Stores local key of |key_type| into |key_value|
+ * Returns BT_STATUS_SUCCESS if the fetch was successful, BT_STATUS_FAIL
+ * otherwise
+ */
+bt_status_t btif_storage_get_ble_local_key(uint8_t key_type,
+                                           Octet16* key_value) {
   const char* name;
   switch (key_type) {
     case BTIF_DM_LE_LOCAL_KEY_IR:
@@ -1150,8 +1214,8 @@
     default:
       return BT_STATUS_FAIL;
   }
-  size_t length = key_length;
-  int ret = btif_config_get_bin("Adapter", name, (uint8_t*)key_value, &length);
+  size_t length = key_value->size();
+  int ret = btif_config_get_bin("Adapter", name, key_value->data(), &length);
   return ret ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
@@ -1399,48 +1463,55 @@
   return BT_STATUS_SUCCESS;
 }
 
-constexpr char HEARING_AID_PSM[] = "HearingAidPsm";
+constexpr char HEARING_AID_READ_PSM_HANDLE[] = "HearingAidReadPsmHandle";
 constexpr char HEARING_AID_CAPABILITIES[] = "HearingAidCapabilities";
 constexpr char HEARING_AID_CODECS[] = "HearingAidCodecs";
 constexpr char HEARING_AID_AUDIO_CONTROL_POINT[] =
     "HearingAidAudioControlPoint";
 constexpr char HEARING_AID_VOLUME_HANDLE[] = "HearingAidVolumeHandle";
+constexpr char HEARING_AID_AUDIO_STATUS_HANDLE[] =
+    "HearingAidAudioStatusHandle";
+constexpr char HEARING_AID_AUDIO_STATUS_CCC_HANDLE[] =
+    "HearingAidAudioStatusCccHandle";
+constexpr char HEARING_AID_SERVICE_CHANGED_CCC_HANDLE[] =
+    "HearingAidServiceChangedCccHandle";
 constexpr char HEARING_AID_SYNC_ID[] = "HearingAidSyncId";
 constexpr char HEARING_AID_RENDER_DELAY[] = "HearingAidRenderDelay";
 constexpr char HEARING_AID_PREPARATION_DELAY[] = "HearingAidPreparationDelay";
 constexpr char HEARING_AID_IS_WHITE_LISTED[] = "HearingAidIsWhiteListed";
 
-void btif_storage_add_hearing_aid(const RawAddress& address, uint16_t psm,
-                                  uint8_t capabilities, uint16_t codecs,
-                                  uint16_t audio_control_point_handle,
-                                  uint16_t volume_handle, uint64_t hi_sync_id,
-                                  uint16_t render_delay,
-                                  uint16_t preparation_delay) {
+void btif_storage_add_hearing_aid(const HearingDevice& dev_info) {
   do_in_jni_thread(
       FROM_HERE,
       Bind(
-          [](const RawAddress& address, uint16_t psm, uint8_t capabilities,
-             uint16_t codecs, uint16_t audio_control_point_handle,
-             uint16_t volume_handle, uint64_t hi_sync_id, uint16_t render_delay,
-             uint16_t preparation_delay) {
-            std::string bdstr = address.ToString();
+          [](const HearingDevice& dev_info) {
+            std::string bdstr = dev_info.address.ToString();
             VLOG(2) << "saving hearing aid device: " << bdstr;
-            btif_config_set_int(bdstr, HEARING_AID_PSM, psm);
-            btif_config_set_int(bdstr, HEARING_AID_CAPABILITIES, capabilities);
-            btif_config_set_int(bdstr, HEARING_AID_CODECS, codecs);
+            btif_config_set_int(bdstr, HEARING_AID_SERVICE_CHANGED_CCC_HANDLE,
+                                dev_info.service_changed_ccc_handle);
+            btif_config_set_int(bdstr, HEARING_AID_READ_PSM_HANDLE,
+                                dev_info.read_psm_handle);
+            btif_config_set_int(bdstr, HEARING_AID_CAPABILITIES,
+                                dev_info.capabilities);
+            btif_config_set_int(bdstr, HEARING_AID_CODECS, dev_info.codecs);
             btif_config_set_int(bdstr, HEARING_AID_AUDIO_CONTROL_POINT,
-                                audio_control_point_handle);
+                                dev_info.audio_control_point_handle);
             btif_config_set_int(bdstr, HEARING_AID_VOLUME_HANDLE,
-                                volume_handle);
-            btif_config_set_uint64(bdstr, HEARING_AID_SYNC_ID, hi_sync_id);
-            btif_config_set_int(bdstr, HEARING_AID_RENDER_DELAY, render_delay);
+                                dev_info.volume_handle);
+            btif_config_set_int(bdstr, HEARING_AID_AUDIO_STATUS_HANDLE,
+                                dev_info.audio_status_handle);
+            btif_config_set_int(bdstr, HEARING_AID_AUDIO_STATUS_CCC_HANDLE,
+                                dev_info.audio_status_ccc_handle);
+            btif_config_set_uint64(bdstr, HEARING_AID_SYNC_ID,
+                                   dev_info.hi_sync_id);
+            btif_config_set_int(bdstr, HEARING_AID_RENDER_DELAY,
+                                dev_info.render_delay);
             btif_config_set_int(bdstr, HEARING_AID_PREPARATION_DELAY,
-                                preparation_delay);
+                                dev_info.preparation_delay);
             btif_config_set_int(bdstr, HEARING_AID_IS_WHITE_LISTED, true);
             btif_config_save();
           },
-          address, psm, capabilities, codecs, audio_control_point_handle,
-          volume_handle, hi_sync_id, render_delay, preparation_delay));
+          dev_info));
 }
 
 /** Loads information about bonded hearing aid devices */
@@ -1451,19 +1522,35 @@
     const std::string& name = section.name;
     if (!RawAddress::IsValidAddress(name)) continue;
 
+    int size = STORAGE_UUID_STRING_SIZE * HEARINGAID_MAX_NUM_UUIDS;
+    char uuid_str[size];
+    bool isHearingaidDevice = false;
+    if (btif_config_get_str(name, BTIF_STORAGE_PATH_REMOTE_SERVICE, uuid_str,
+                            &size)) {
+      Uuid p_uuid[HEARINGAID_MAX_NUM_UUIDS];
+      size_t num_uuids =
+          btif_split_uuids_string(uuid_str, p_uuid, HEARINGAID_MAX_NUM_UUIDS);
+      for (size_t i = 0; i < num_uuids; i++) {
+        if (p_uuid[i] == Uuid::FromString("FDF0")) {
+          isHearingaidDevice = true;
+          break;
+        }
+      }
+    }
+    if (!isHearingaidDevice) {
+      continue;
+    }
+
     BTIF_TRACE_DEBUG("Remote device:%s", name.c_str());
 
-    int value;
-    if (!btif_config_get_int(name, HEARING_AID_PSM, &value)) continue;
-    uint16_t psm = value;
-
-    if (btif_in_fetch_bonded_device(name.c_str()) != BT_STATUS_SUCCESS) {
+    if (btif_in_fetch_bonded_device(name) != BT_STATUS_SUCCESS) {
       RawAddress bd_addr;
       RawAddress::FromString(name, bd_addr);
       btif_storage_remove_hearing_aid(bd_addr);
       continue;
     }
 
+    int value;
     uint8_t capabilities = 0;
     if (btif_config_get_int(name, HEARING_AID_CAPABILITIES, &value))
       capabilities = value;
@@ -1475,10 +1562,27 @@
     if (btif_config_get_int(name, HEARING_AID_AUDIO_CONTROL_POINT, &value))
       audio_control_point_handle = value;
 
+    uint16_t audio_status_handle = 0;
+    if (btif_config_get_int(name, HEARING_AID_AUDIO_STATUS_HANDLE, &value))
+      audio_status_handle = value;
+
+    uint16_t audio_status_ccc_handle = 0;
+    if (btif_config_get_int(name, HEARING_AID_AUDIO_STATUS_CCC_HANDLE, &value))
+      audio_status_ccc_handle = value;
+
+    uint16_t service_changed_ccc_handle = 0;
+    if (btif_config_get_int(name, HEARING_AID_SERVICE_CHANGED_CCC_HANDLE,
+                            &value))
+      service_changed_ccc_handle = value;
+
     uint16_t volume_handle = 0;
     if (btif_config_get_int(name, HEARING_AID_VOLUME_HANDLE, &value))
       volume_handle = value;
 
+    uint16_t read_psm_handle = 0;
+    if (btif_config_get_int(name, HEARING_AID_READ_PSM_HANDLE, &value))
+      read_psm_handle = value;
+
     uint64_t lvalue;
     uint64_t hi_sync_id = 0;
     if (btif_config_get_uint64(name, HEARING_AID_SYNC_ID, &lvalue))
@@ -1498,41 +1602,86 @@
 
     RawAddress bd_addr;
     RawAddress::FromString(name, bd_addr);
+
     // add extracted information to BTA Hearing Aid
-    do_in_bta_thread(
+    do_in_main_thread(
         FROM_HERE,
-        Bind(&HearingAid::AddFromStorage, bd_addr, psm, capabilities, codecs,
-             audio_control_point_handle, volume_handle, hi_sync_id,
-             render_delay, preparation_delay, is_white_listed));
+        Bind(&HearingAid::AddFromStorage,
+             HearingDevice(bd_addr, capabilities, codecs,
+                           audio_control_point_handle, audio_status_handle,
+                           audio_status_ccc_handle, service_changed_ccc_handle,
+                           volume_handle, read_psm_handle, hi_sync_id,
+                           render_delay, preparation_delay),
+             is_white_listed));
   }
 }
 
 /** Deletes the bonded hearing aid device info from NVRAM */
 void btif_storage_remove_hearing_aid(const RawAddress& address) {
   std::string addrstr = address.ToString();
-
-  btif_config_remove(addrstr, HEARING_AID_PSM);
+  btif_config_remove(addrstr, HEARING_AID_READ_PSM_HANDLE);
   btif_config_remove(addrstr, HEARING_AID_CAPABILITIES);
   btif_config_remove(addrstr, HEARING_AID_CODECS);
   btif_config_remove(addrstr, HEARING_AID_AUDIO_CONTROL_POINT);
   btif_config_remove(addrstr, HEARING_AID_VOLUME_HANDLE);
+  btif_config_remove(addrstr, HEARING_AID_AUDIO_STATUS_HANDLE);
+  btif_config_remove(addrstr, HEARING_AID_AUDIO_STATUS_CCC_HANDLE);
+  btif_config_remove(addrstr, HEARING_AID_SERVICE_CHANGED_CCC_HANDLE);
   btif_config_remove(addrstr, HEARING_AID_SYNC_ID);
+  btif_config_remove(addrstr, HEARING_AID_RENDER_DELAY);
+  btif_config_remove(addrstr, HEARING_AID_PREPARATION_DELAY);
   btif_config_remove(addrstr, HEARING_AID_IS_WHITE_LISTED);
   btif_config_save();
 }
 
-/** Add the hearing aid device to white list */
-void btif_storage_add_hearing_aid_to_white_list(const RawAddress& address) {
+/** Set/Unset the hearing aid device HEARING_AID_IS_WHITE_LISTED flag. */
+void btif_storage_set_hearing_aid_white_list(const RawAddress& address,
+                                             bool add_to_whitelist) {
   std::string addrstr = address.ToString();
 
-  btif_config_set_int(addrstr, HEARING_AID_IS_WHITE_LISTED, true);
+  btif_config_set_int(addrstr, HEARING_AID_IS_WHITE_LISTED, add_to_whitelist);
+  btif_config_save();
 }
 
-/** Remove the hearing aid device from white list */
-void btif_storage_remove_hearing_aid_white_list(const RawAddress& address) {
+/** Get the hearing aid device properties. */
+bool btif_storage_get_hearing_aid_prop(
+    const RawAddress& address, uint8_t* capabilities, uint64_t* hi_sync_id,
+    uint16_t* render_delay, uint16_t* preparation_delay, uint16_t* codecs) {
   std::string addrstr = address.ToString();
 
-  btif_config_set_int(addrstr, HEARING_AID_IS_WHITE_LISTED, false);
+  int value;
+  if (btif_config_get_int(addrstr, HEARING_AID_CAPABILITIES, &value)) {
+    *capabilities = value;
+  } else {
+    return false;
+  }
+
+  if (btif_config_get_int(addrstr, HEARING_AID_CODECS, &value)) {
+    *codecs = value;
+  } else {
+    return false;
+  }
+
+  if (btif_config_get_int(addrstr, HEARING_AID_RENDER_DELAY, &value)) {
+    *render_delay = value;
+  } else {
+    return false;
+  }
+
+  if (btif_config_get_int(addrstr, HEARING_AID_PREPARATION_DELAY, &value)) {
+    *preparation_delay = value;
+  } else {
+    return false;
+  }
+
+  uint64_t lvalue;
+  if (btif_config_get_uint64(addrstr, HEARING_AID_SYNC_ID, &lvalue)) {
+    *hi_sync_id = lvalue;
+  } else {
+    return false;
+  }
+
+  return true;
 }
 
 /*******************************************************************************
@@ -1550,6 +1699,12 @@
   return btif_config_exist(remote_bd_addr->ToString(), "Restricted");
 }
 
+int btif_storage_get_num_bonded_devices(void) {
+  btif_bonded_devices_t bonded_devices;
+  btif_in_fetch_bonded_devices(&bonded_devices, 0);
+  return bonded_devices.num_devices;
+}
+
 /*******************************************************************************
  * Function         btif_storage_load_hidd
  *
diff --git a/btif/src/stack_manager.cc b/btif/src/stack_manager.cc
index e37db87..60c2c0c 100644
--- a/btif/src/stack_manager.cc
+++ b/btif/src/stack_manager.cc
@@ -26,18 +26,20 @@
 #include "btcore/include/osi_module.h"
 #include "btif_api.h"
 #include "btif_common.h"
+#include "common/message_loop_thread.h"
 #include "device/include/controller.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 #include "osi/include/semaphore.h"
-#include "osi/include/thread.h"
 
 // Temp includes
 #include "bt_utils.h"
 #include "btif_config.h"
 #include "btif_profile_queue.h"
 
-static thread_t* management_thread;
+using bluetooth::common::MessageLoopThread;
+
+static MessageLoopThread management_thread("bt_stack_manager_thread");
 
 // If initialized, any of the bluetooth API functions can be called.
 // (e.g. turning logging on and off, enabling/disabling the stack, etc)
@@ -56,40 +58,44 @@
 // Unvetted includes/imports, etc which should be removed or vetted in the
 // future
 static future_t* hack_future;
-void btif_thread_post(thread_fn func, void* context);
 // End unvetted section
 
 // Interface functions
 
-static void init_stack(void) {
+static void init_stack() {
   // This is a synchronous process. Post it to the thread though, so
   // state modification only happens there. Using the thread to perform
   // all stack operations ensures that the operations are done serially
   // and do not overlap.
   semaphore_t* semaphore = semaphore_new(0);
-  thread_post(management_thread, event_init_stack, semaphore);
+  management_thread.DoInThread(FROM_HERE,
+                               base::Bind(event_init_stack, semaphore));
   semaphore_wait(semaphore);
   semaphore_free(semaphore);
 }
 
-static void start_up_stack_async(void) {
-  thread_post(management_thread, event_start_up_stack, NULL);
+static void start_up_stack_async() {
+  management_thread.DoInThread(FROM_HERE,
+                               base::Bind(event_start_up_stack, nullptr));
 }
 
-static void shut_down_stack_async(void) {
-  thread_post(management_thread, event_shut_down_stack, NULL);
+static void shut_down_stack_async() {
+  management_thread.DoInThread(FROM_HERE,
+                               base::Bind(event_shut_down_stack, nullptr));
 }
 
-static void clean_up_stack(void) {
+static void clean_up_stack() {
   // This is a synchronous process. Post it to the thread though, so
   // state modification only happens there.
   semaphore_t* semaphore = semaphore_new(0);
-  thread_post(management_thread, event_clean_up_stack, semaphore);
+  management_thread.DoInThread(FROM_HERE,
+                               base::Bind(event_clean_up_stack, semaphore));
   semaphore_wait(semaphore);
   semaphore_free(semaphore);
+  management_thread.ShutDown();
 }
 
-static bool get_stack_is_running(void) { return stack_is_running; }
+static bool get_stack_is_running() { return stack_is_running; }
 
 // Internal functions
 
@@ -119,12 +125,12 @@
   if (semaphore) semaphore_post(semaphore);
 }
 
-static void ensure_stack_is_initialized(void) {
+static void ensure_stack_is_initialized() {
   if (!stack_is_initialized) {
     LOG_WARN(LOG_TAG, "%s found the stack was uninitialized. Initializing now.",
              __func__);
     // No semaphore needed since we are calling it directly
-    event_init_stack(NULL);
+    event_init_stack(nullptr);
   }
 }
 
@@ -148,13 +154,13 @@
   if (future_await(local_hack_future) != FUTURE_SUCCESS) {
     LOG_ERROR(LOG_TAG, "%s failed to start up the stack", __func__);
     stack_is_running = true;  // So stack shutdown actually happens
-    event_shut_down_stack(NULL);
+    event_shut_down_stack(nullptr);
     return;
   }
 
   stack_is_running = true;
   LOG_INFO(LOG_TAG, "%s finished", __func__);
-  btif_thread_post(event_signal_stack_up, NULL);
+  do_in_jni_thread(FROM_HERE, base::Bind(event_signal_stack_up, nullptr));
 }
 
 // Synchronous function to shut down the stack
@@ -178,17 +184,17 @@
                                                     // state
 
   hack_future = future_new();
-  btif_thread_post(event_signal_stack_down, NULL);
+  do_in_jni_thread(FROM_HERE, base::Bind(event_signal_stack_down, nullptr));
   future_await(hack_future);
   LOG_INFO(LOG_TAG, "%s finished", __func__);
 }
 
-static void ensure_stack_is_not_running(void) {
+static void ensure_stack_is_not_running() {
   if (stack_is_running) {
     LOG_WARN(LOG_TAG,
              "%s found the stack was still running. Bringing it down now.",
              __func__);
-    event_shut_down_stack(NULL);
+    event_shut_down_stack(nullptr);
   }
 }
 
@@ -228,19 +234,18 @@
   future_ready(stack_manager_get_hack_future(), FUTURE_SUCCESS);
 }
 
-static void ensure_manager_initialized(void) {
-  if (management_thread) return;
+static void ensure_manager_initialized() {
+  if (management_thread.IsRunning()) return;
 
-  management_thread = thread_new("stack_manager");
-  if (!management_thread) {
-    LOG_ERROR(LOG_TAG, "%s unable to create stack management thread", __func__);
+  management_thread.StartUp();
+  if (!management_thread.IsRunning()) {
+    LOG_ERROR(LOG_TAG, "%s unable to start stack management thread", __func__);
     return;
   }
 }
 
 static const stack_manager_t interface = {init_stack, start_up_stack_async,
                                           shut_down_stack_async, clean_up_stack,
-
                                           get_stack_is_running};
 
 const stack_manager_t* stack_manager_get_interface() {
diff --git a/btif/test/btif_profile_queue_test.cc b/btif/test/btif_profile_queue_test.cc
index f7bce86..486959b 100644
--- a/btif/test/btif_profile_queue_test.cc
+++ b/btif/test/btif_profile_queue_test.cc
@@ -15,12 +15,14 @@
  *  limitations under the License.
  *
  ******************************************************************************/
+#include "btif/include/btif_profile_queue.h"
+
 #include <gtest/gtest.h>
 
 #include <base/bind.h>
+#include <base/callback.h>
+#include <base/location.h>
 
-#include "base/location.h"
-#include "btif/include/btif_profile_queue.h"
 #include "stack_manager.h"
 #include "types/raw_address.h"
 
@@ -33,9 +35,9 @@
 static stack_manager_t sStackManager = {nullptr, nullptr, nullptr, nullptr,
                                         get_stack_is_running};
 const stack_manager_t* stack_manager_get_interface() { return &sStackManager; }
-bt_status_t do_in_jni_thread(const tracked_objects::Location& from_here,
-                             const base::Closure& task) {
-  task.Run();
+bt_status_t do_in_jni_thread(const base::Location& from_here,
+                             base::OnceClosure task) {
+  std::move(task).Run();
   return BT_STATUS_SUCCESS;
 }
 bool is_on_jni_thread() { return true; }
diff --git a/build/Android.bp b/build/Android.bp
index b8abb0f..cde9a36 100644
--- a/build/Android.bp
+++ b/build/Android.bp
@@ -55,9 +55,53 @@
 
 fluoride_defaults {
     name: "fluoride_defaults",
+    target: {
+        android: {
+            test_config_template: ":BluetoothTestConfigTemplate",
+        }
+    },
     defaults: ["fluoride_types_defaults"],
     header_libs: ["libbluetooth_headers"],
+    shared_libs: ["libstatslog"],
     static_libs: [
         "libbluetooth-types",
+        "libbt-platform-protos-lite",
     ],
+    cpp_std: "c++17",
+    sanitize: {
+        misc_undefined: ["bounds"],
+    },
+}
+
+// Enables code coverage for a set of source files. Must be combined with
+// "clang_coverage_bin" in order to work. See //test/gen_coverage.py for more information
+// on generating code coverage.
+cc_defaults {
+    name: "clang_file_coverage",
+    target: {
+        host: {
+            clang_cflags: [
+                "-fprofile-instr-generate",
+                "-fcoverage-mapping",
+            ],
+        },
+    },
+}
+
+// Enabled code coverage on a binary. These flags allow libraries that were
+// compiled with "clang_file_coverage" to be properly linked together in
+// order to create a binary that will create a profraw file when ran. Note
+// these flags themselves don't enable code coverage for the source files
+// compiled in the binary. See //test/gen_coverage.py for more information
+// on generating code coverage.
+cc_defaults {
+    name: "clang_coverage_bin",
+    target: {
+        host: {
+            ldflags: [
+                "-fprofile-instr-generate",
+                "-fcoverage-mapping",
+            ],
+        },
+    },
 }
diff --git a/build/BUILD.gn b/build/BUILD.gn
index f09a274..922a3f6 100644
--- a/build/BUILD.gn
+++ b/build/BUILD.gn
@@ -59,6 +59,8 @@
     # current build is done by GN or via Android.mk. This is a temporary
     # workaround until we can remove all Android-specific dependencies.
     "OS_GENERIC",
+
+    "FALLTHROUGH_INTENDED",
   ]
 }
 
diff --git a/build/secondary/third_party/aac/BUILD.gn b/build/secondary/third_party/aac/BUILD.gn
index d9e79a7..18fcf93 100644
--- a/build/secondary/third_party/aac/BUILD.gn
+++ b/build/secondary/third_party/aac/BUILD.gn
@@ -18,11 +18,15 @@
   include_dirs = [
     "libAACdec/include",
     "libAACenc/include",
+    "libArithCoding/include",
+    "libDRCdec/include",
     "libPCMutils/include",
     "libFDK/include",
     "libSYS/include",
     "libMpegTPDec/include",
     "libMpegTPEnc/include",
+    "libSACenc/include",
+    "libSACdec/include",
     "libSBRdec/include",
     "libSBRenc/include",
   ]
@@ -31,17 +35,13 @@
 #TODO(jpawlowski): this files are not build right now, but might be useful when
 # arm platform linux compilation is in use:
 #    "libAACdec/src/arm/block_arm.cpp",
-#    "libFDK/src/arm/autocorr2nd.cpp",
 #    "libFDK/src/arm/dct_arm.cpp",
 #    "libFDK/src/arm/fft_rad2_arm.cpp",
-#    "libFDK/src/arm/qmf_arm.cpp",
 #    "libFDK/src/arm/scale_arm.cpp",
-#    "libSBRdec/src/arm/env_calc_arm.cpp",
 #    "libSBRdec/src/arm/lpp_tran_arm.cpp",
-#    "libSYS/src/mips/genericStds_mips.cpp",
 #    "libFDK/src/mips/fft_rad2_mips.cpp",
 #    "libFDK/src/mips/mips_fft_twiddles.cpp",
-#    "libFDK/src/mips/scale.cpp",
+#    "libFDK/src/mips/scale_mips.cpp",
 
 static_library("libFraunhoferAAC") {
   sources = [
@@ -59,12 +59,20 @@
     "libAACdec/src/channel.cpp",
     "libAACdec/src/channelinfo.cpp",
     "libAACdec/src/conceal.cpp",
+    "libAACdec/src/FDK_delay.cpp",
     "libAACdec/src/ldfiltbank.cpp",
     "libAACdec/src/pulsedata.cpp",
     "libAACdec/src/rvlcbit.cpp",
     "libAACdec/src/rvlcconceal.cpp",
     "libAACdec/src/rvlc.cpp",
     "libAACdec/src/stereo.cpp",
+    "libAACdec/src/usacdec_ace_d4t64.cpp",
+    "libAACdec/src/usacdec_acelp.cpp",
+    "libAACdec/src/usacdec_ace_ltp.cpp",
+    "libAACdec/src/usacdec_fac.cpp",
+    "libAACdec/src/usacdec_lpc.cpp",
+    "libAACdec/src/usacdec_lpd.cpp",
+    "libAACdec/src/usacdec_rom.cpp",
     "libAACenc/src/aacenc.cpp",
     "libAACenc/src/aacenc_lib.cpp",
     "libAACenc/src/aacenc_pns.cpp",
@@ -85,6 +93,7 @@
     "libAACenc/src/line_pe.cpp",
     "libAACenc/src/metadata_compressor.cpp",
     "libAACenc/src/metadata_main.cpp",
+    "libAACenc/src/mps_main.cpp",
     "libAACenc/src/ms_stereo.cpp",
     "libAACenc/src/noisedet.cpp",
     "libAACenc/src/pnsparam.cpp",
@@ -97,18 +106,34 @@
     "libAACenc/src/spreading.cpp",
     "libAACenc/src/tonality.cpp",
     "libAACenc/src/transform.cpp",
+    "libArithCoding/src/ac_arith_coder.cpp",
+    "libDRCdec/src/drcDec_gainDecoder.cpp",
+    "libDRCdec/src/drcDec_reader.cpp",
+    "libDRCdec/src/drcDec_rom.cpp",
+    "libDRCdec/src/drcDec_selectionProcess.cpp",
+    "libDRCdec/src/drcDec_tools.cpp",
+    "libDRCdec/src/drcGainDec_init.cpp",
+    "libDRCdec/src/drcGainDec_preprocess.cpp",
+    "libDRCdec/src/drcGainDec_process.cpp",
+    "libDRCdec/src/FDK_drcDecLib.cpp",
     "libFDK/src/autocorr2nd.cpp",
     "libFDK/src/dct.cpp",
     "libFDK/src/FDK_bitbuffer.cpp",
     "libFDK/src/FDK_core.cpp",
     "libFDK/src/FDK_crc.cpp",
+    "libFDK/src/FDK_decorrelate.cpp",
     "libFDK/src/FDK_hybrid.cpp",
+    "libFDK/src/FDK_lpc.cpp",
+    "libFDK/src/FDK_matrixCalloc.cpp",
+    "libFDK/src/FDK_qmf_domain.cpp",
     "libFDK/src/FDK_tools_rom.cpp",
     "libFDK/src/FDK_trigFcts.cpp",
     "libFDK/src/fft.cpp",
     "libFDK/src/fft_rad2.cpp",
     "libFDK/src/fixpoint_math.cpp",
+    "libFDK/src/huff_nodes.cpp",
     "libFDK/src/mdct.cpp",
+    "libFDK/src/nlc_dec.cpp",
     "libFDK/src/qmf.cpp",
     "libFDK/src/scale.cpp",
     "libMpegTPDec/src/tpdec_adif.cpp",
@@ -123,15 +148,45 @@
     "libMpegTPEnc/src/tpenc_latm.cpp",
     "libMpegTPEnc/src/tpenc_lib.cpp",
     "libPCMutils/src/limiter.cpp",
-    "libPCMutils/src/pcmutils_lib.cpp",
+    "libPCMutils/src/pcmdmx_lib.cpp",
+    "libPCMutils/src/pcm_utils.cpp",
+    "libSACdec/src/sac_bitdec.cpp",
+    "libSACdec/src/sac_calcM1andM2.cpp",
+    "libSACdec/src/sac_dec_conceal.cpp",
+    "libSACdec/src/sac_dec.cpp",
+    "libSACdec/src/sac_dec_lib.cpp",
+    "libSACdec/src/sac_process.cpp",
+    "libSACdec/src/sac_qmf.cpp",
+    "libSACdec/src/sac_reshapeBBEnv.cpp",
+    "libSACdec/src/sac_rom.cpp",
+    "libSACdec/src/sac_smoothing.cpp",
+    "libSACdec/src/sac_stp.cpp",
+    "libSACdec/src/sac_tsd.cpp",
+    "libSACenc/src/sacenc_bitstream.cpp",
+    "libSACenc/src/sacenc_delay.cpp",
+    "libSACenc/src/sacenc_dmx_tdom_enh.cpp",
+    "libSACenc/src/sacenc_filter.cpp",
+    "libSACenc/src/sacenc_framewindowing.cpp",
+    "libSACenc/src/sacenc_huff_tab.cpp",
+    "libSACenc/src/sacenc_lib.cpp",
+    "libSACenc/src/sacenc_nlc_enc.cpp",
+    "libSACenc/src/sacenc_onsetdetect.cpp",
+    "libSACenc/src/sacenc_paramextract.cpp",
+    "libSACenc/src/sacenc_staticgain.cpp",
+    "libSACenc/src/sacenc_tree.cpp",
+    "libSACenc/src/sacenc_vectorfunctions.cpp",
     "libSBRdec/src/env_calc.cpp",
     "libSBRdec/src/env_dec.cpp",
     "libSBRdec/src/env_extr.cpp",
+    "libSBRdec/src/hbe.cpp",
+    "libSBRdec/src/HFgen_preFlat.cpp",
     "libSBRdec/src/huff_dec.cpp",
     "libSBRdec/src/lpp_tran.cpp",
     "libSBRdec/src/psbitdec.cpp",
     "libSBRdec/src/psdec.cpp",
-    "libSBRdec/src/psdec_hybrid.cpp",
+    "libSBRdec/src/psdec_drm.cpp",
+    "libSBRdec/src/psdecrom_drm.cpp",
+    "libSBRdec/src/pvc_dec.cpp",
     "libSBRdec/src/sbr_crc.cpp",
     "libSBRdec/src/sbr_deb.cpp",
     "libSBRdec/src/sbr_dec.cpp",
@@ -154,20 +209,13 @@
     "libSBRenc/src/resampler.cpp",
     "libSBRenc/src/sbrenc_freq_sca.cpp",
     "libSBRenc/src/sbr_encoder.cpp",
+    "libSBRenc/src/sbrenc_ram.cpp",
+    "libSBRenc/src/sbrenc_rom.cpp",
     "libSBRenc/src/sbr_misc.cpp",
-    "libSBRenc/src/sbr_ram.cpp",
-    "libSBRenc/src/sbr_rom.cpp",
     "libSBRenc/src/ton_corr.cpp",
     "libSBRenc/src/tran_det.cpp",
-    "libSYS/src/cmdl_parser.cpp",
-    "libSYS/src/conv_string.cpp",
     "libSYS/src/genericStds.cpp",
-    "libSYS/src/linux/audio_linux.cpp",
-    "libSYS/src/linux/coresup_linux.cpp",
-    "libSYS/src/linux/FDK_stackload_linux.cpp",
-    "libSYS/src/linux/genericStds_linux.cpp",
-    "libSYS/src/linux/uart_linux.cpp",
-    "libSYS/src/wav_file.cpp",
+    "libSYS/src/syslib_channelMapDescr.cpp",
   ]
 
   public_configs = [ ":libFraunhoferAAC_config" ]
diff --git a/build/secondary/third_party/libchrome/BUILD.gn b/build/secondary/third_party/libchrome/BUILD.gn
index c84b293..1b0d2f0 100644
--- a/build/secondary/third_party/libchrome/BUILD.gn
+++ b/build/secondary/third_party/libchrome/BUILD.gn
@@ -24,13 +24,14 @@
     "base/base64.h",
     "base/base_export.h",
     "base/base_switches.cc",
-    "base/bind_helpers.cc",
     "base/build_time.cc",
     "base/callback_helpers.cc",
     "base/callback_internal.cc",
     "base/command_line.cc",
     "base/cpu.cc",
+    "base/debug/activity_tracker.cc",
     "base/debug/alias.cc",
+    "base/debug/dump_without_crashing.cc",
     "base/debug/debugger.cc",
     "base/debug/debugger_posix.cc",
     "base/debug/stack_trace.cc",
@@ -38,6 +39,7 @@
     "base/debug/task_annotator.cc",
     "base/environment.cc",
     "base/files/file.cc",
+    "base/files/file_descriptor_watcher_posix.cc",
     "base/files/file_enumerator.cc",
     "base/files/file_enumerator_posix.cc",
     "base/files/file_path.cc",
@@ -58,30 +60,34 @@
     "base/json/json_string_value_serializer.cc",
     "base/json/json_writer.cc",
     "base/json/string_escape.cc",
-    "base/lazy_instance.cc",
+    "base/lazy_instance_helpers.cc",
     "base/location.cc",
     "base/logging.cc",
     "base/md5.cc",
     "base/memory/ref_counted.cc",
     "base/memory/ref_counted_memory.cc",
-    "base/memory/singleton.cc",
     "base/memory/weak_ptr.cc",
     "base/message_loop/incoming_task_queue.cc",
     "base/message_loop/message_loop.cc",
+    "base/message_loop/message_loop_current.cc",
     "base/message_loop/message_loop_task_runner.cc",
     "base/message_loop/message_pump.cc",
     "base/message_loop/message_pump_default.cc",
+    "base/message_loop/message_pump_libevent.cc",
+    "base/message_loop/watchable_io_message_pump_posix.cc",
 
     # we don't want any glib dependencies.
     #   "base/message_loop/message_pump_glib.cc",
-    "base/message_loop/message_pump_libevent.cc",
     "base/metrics/bucket_ranges.cc",
+    "base/metrics/dummy_histogram.cc",
     "base/metrics/field_trial.cc",
-    "base/metrics/metrics_hashes.cc",
-    "base/metrics/histogram_base.cc",
+    "base/metrics/field_trial_param_associator.cc",
     "base/metrics/histogram.cc",
+    "base/metrics/histogram_base.cc",
+    "base/metrics/histogram_functions.cc",
     "base/metrics/histogram_samples.cc",
     "base/metrics/histogram_snapshot_manager.cc",
+    "base/metrics/metrics_hashes.cc",
     "base/metrics/persistent_histogram_allocator.cc",
     "base/metrics/persistent_memory_allocator.cc",
     "base/metrics/persistent_sample_map.cc",
@@ -89,33 +95,37 @@
     "base/metrics/sample_vector.cc",
     "base/metrics/sparse_histogram.cc",
     "base/metrics/statistics_recorder.cc",
+    "base/native_library.cc",
+    "base/observer_list_threadsafe.cc",
+    "base/path_service.cc",
     "base/pending_task.cc",
     "base/pickle.cc",
     "base/posix/file_descriptor_shuffle.cc",
+    "base/posix/global_descriptors.cc",
     "base/posix/safe_strerror.cc",
-    "base/posix/unix_domain_socket_linux.cc",
     "base/process/internal_linux.cc",
     "base/process/kill.cc",
     "base/process/kill_posix.cc",
     "base/process/launch.cc",
     "base/process/launch_posix.cc",
+    "base/process/memory.cc",
+    "base/process/process_handle.cc",
     "base/process/process_handle_linux.cc",
     "base/process/process_handle_posix.cc",
+    "base/process/process_info_linux.cc",
     "base/process/process_iterator.cc",
     "base/process/process_iterator_linux.cc",
     "base/process/process_metrics.cc",
     "base/process/process_metrics_linux.cc",
     "base/process/process_metrics_posix.cc",
     "base/process/process_posix.cc",
-    "base/profiler/scoped_profile.cc",
-    "base/profiler/scoped_tracker.cc",
-    "base/profiler/tracked_time.cc",
     "base/rand_util.cc",
     "base/rand_util_posix.cc",
     "base/run_loop.cc",
     "base/sequence_checker_impl.cc",
     "base/sequenced_task_runner.cc",
-    "base/sha1_portable.cc",
+    "base/sequence_token.cc",
+    "base/sha1.cc",
     "base/strings/pattern.cc",
     "base/strings/safe_sprintf.cc",
     "base/strings/string16.cc",
@@ -128,11 +138,10 @@
     "base/strings/sys_string_conversions_posix.cc",
     "base/strings/utf_string_conversions.cc",
     "base/strings/utf_string_conversion_utils.cc",
-    "base/synchronization/cancellation_flag.cc",
+    "base/synchronization/atomic_flag.cc",
     "base/synchronization/condition_variable_posix.cc",
     "base/synchronization/lock.cc",
     "base/synchronization/lock_impl_posix.cc",
-    "base/synchronization/read_write_lock_posix.cc",
     "base/synchronization/waitable_event_posix.cc",
     "base/sync_socket_posix.cc",
     "base/sys_info.cc",
@@ -148,64 +157,43 @@
     "base/task_runner.cc",
     "base/third_party/icu/icu_utf.cc",
     "base/third_party/nspr/prtime.cc",
-    "base/threading/non_thread_safe_impl.cc",
     "base/threading/platform_thread_internal_posix.cc",
     "base/threading/platform_thread_linux.cc",
     "base/threading/platform_thread_posix.cc",
     "base/threading/post_task_and_reply_impl.cc",
+    "base/threading/scoped_blocking_call.cc",
+    "base/threading/sequence_local_storage_map.cc",
+    "base/threading/sequence_local_storage_slot.cc",
     "base/threading/sequenced_task_runner_handle.cc",
-    "base/threading/sequenced_worker_pool.cc",
     "base/threading/simple_thread.cc",
     "base/threading/thread.cc",
     "base/threading/thread_checker_impl.cc",
     "base/threading/thread_collision_warner.cc",
     "base/threading/thread_id_name_manager.cc",
-    "base/threading/thread_local_posix.cc",
     "base/threading/thread_local_storage.cc",
     "base/threading/thread_local_storage_posix.cc",
     "base/threading/thread_restrictions.cc",
-    "base/threading/worker_pool.cc",
-    "base/threading/worker_pool_posix.cc",
     "base/threading/thread_task_runner_handle.cc",
     "base/time/clock.cc",
     "base/time/default_clock.cc",
     "base/time/default_tick_clock.cc",
-    "base/timer/elapsed_timer.cc",
-    "base/timer/timer.cc",
     "base/time/tick_clock.cc",
     "base/time/time.cc",
-    "base/time/time_posix.cc",
-    "base/trace_event/heap_profiler_allocation_context.cc",
-    "base/trace_event/heap_profiler_allocation_context_tracker.cc",
-    "base/trace_event/heap_profiler_stack_frame_deduplicator.cc",
-    "base/trace_event/heap_profiler_type_name_deduplicator.cc",
-    "base/trace_event/malloc_dump_provider.cc",
-    "base/trace_event/memory_allocator_dump.cc",
-    "base/trace_event/memory_allocator_dump_guid.cc",
-    "base/trace_event/memory_dump_manager.cc",
-    "base/trace_event/memory_dump_session_state.cc",
-    "base/trace_event/memory_infra_background_whitelist.cc",
-    "base/trace_event/process_memory_dump.cc",
-    "base/trace_event/process_memory_maps.cc",
-    "base/trace_event/process_memory_totals.cc",
-    "base/trace_event/trace_buffer.cc",
-    "base/trace_event/trace_config.cc",
-    "base/trace_event/trace_event_argument.cc",
-    "base/trace_event/trace_event_impl.cc",
-    "base/trace_event/trace_event_memory_overhead.cc",
-    "base/trace_event/trace_event_synthetic_delay.cc",
-    "base/trace_event/trace_log.cc",
-    "base/trace_event/trace_log_constants.cc",
-    "base/trace_event/trace_sampling_thread.cc",
-    "base/tracked_objects.cc",
-    "base/tracking_info.cc",
+    "base/time/time_conversion_posix.cc",
+    "base/time/time_exploded_posix.cc",
+    "base/time/time_now_posix.cc",
+    "base/time/time_override.cc",
+    "base/timer/elapsed_timer.cc",
+    "base/timer/timer.cc",
+    "base/unguessable_token.cc",
+    "base/value_iterators.cc",
     "base/values.cc",
+    "base/version.cc",
     "base/vlog.cc",
 
     "dbus/bus.cc",
     "dbus/dbus_statistics.cc",
     "dbus/exported_object.cc",
-    "dbus/file_descriptor.cc",
     "dbus/message.cc",
     "dbus/object_manager.cc",
     "dbus/object_path.cc",
diff --git a/common/Android.bp b/common/Android.bp
new file mode 100644
index 0000000..202559d
--- /dev/null
+++ b/common/Android.bp
@@ -0,0 +1,126 @@
+cc_library_static {
+    name: "libbt-common",
+    defaults: [
+        "fluoride_defaults",
+        "clang_file_coverage",
+    ],
+    host_supported: true,
+    include_dirs: [
+        "system/bt",
+        "system/bt/stack/include",
+    ],
+    srcs: [
+        "address_obfuscator.cc",
+        "message_loop_thread.cc",
+        "metrics.cc",
+        "once_timer.cc",
+        "repeating_timer.cc",
+        "time_util.cc",
+    ],
+    shared_libs: [
+        "libcrypto",
+    ],
+    static_libs: [
+        "libbt-protos-lite",
+    ],
+}
+
+cc_test {
+    name: "bluetooth_test_common",
+    test_suites: ["device-tests"],
+    defaults: [
+        "fluoride_defaults",
+        "clang_coverage_bin",
+    ],
+    host_supported: true,
+    include_dirs: [
+        "system/bt",
+        "system/bt/stack/include",
+    ],
+    srcs : [
+        "address_obfuscator_unittest.cc",
+        "leaky_bonded_queue_unittest.cc",
+        "message_loop_thread_unittest.cc",
+        "metrics_unittest.cc",
+        "once_timer_unittest.cc",
+        "repeating_timer_unittest.cc",
+        "state_machine_unittest.cc",
+        "time_util_unittest.cc",
+        "id_generator_unittest.cc",
+    ],
+    shared_libs: [
+        "libprotobuf-cpp-lite",
+        "libcrypto",
+    ],
+    static_libs : [
+        "libgmock",
+        "libbt-common",
+        "libbt-protos-lite",
+    ],
+    sanitize: {
+        cfi: false,
+    },
+}
+
+cc_test {
+    name: "net_test_performance",
+    defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
+    include_dirs: ["system/bt"],
+    host_supported: true,
+    srcs: [
+        "test/thread_performance_test.cc",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libgmock",
+        "libosi",
+        "libbt-common"
+    ],
+}
+
+cc_benchmark {
+    name: "bluetooth_benchmark_thread_performance",
+    defaults: [
+        "fluoride_defaults",
+    ],
+    host_supported: true,
+    include_dirs: ["system/bt"],
+    srcs: [
+        "benchmark/thread_performance_benchmark.cc",
+    ],
+    shared_libs: [
+        "libcrypto",
+        "liblog",
+    ],
+    static_libs: [
+        "libosi",
+        "libbt-common"
+    ],
+}
+
+cc_benchmark {
+    name: "bluetooth_benchmark_timer_performance",
+    defaults: [
+        "fluoride_defaults",
+    ],
+    host_supported: false,
+    include_dirs: ["system/bt"],
+    srcs: [
+        "benchmark/timer_performance_benchmark.cc",
+    ],
+    shared_libs: [
+        "liblog",
+        "libcrypto",
+        "libprotobuf-cpp-lite",
+        "libcrypto",
+        "libcutils",
+    ],
+    static_libs: [
+        "libosi",
+        "libbt-common",
+        "libbt-protos-lite",
+    ],
+}
diff --git a/common/BUILD.gn b/common/BUILD.gn
new file mode 100644
index 0000000..76d70f8
--- /dev/null
+++ b/common/BUILD.gn
@@ -0,0 +1,62 @@
+#
+#  Copyright 2018 The Android Open Source Project
+#
+#  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.
+#
+
+static_library("common") {
+  sources = [
+    "message_loop_thread.cc",
+    "metrics_linux.cc",
+    "time_util.cc",
+    "timer.cc",
+  ]
+
+  include_dirs = [
+    "//",
+    "//stack/include",
+    "//linux_include",
+    "//internal_include",
+  ]
+
+  deps = [
+    "//third_party/libchrome:base",
+  ]
+}
+
+executable("bt_test_common") {
+  testonly = true
+  sources = [
+    "leaky_bonded_queue_unittest.cc",
+    "state_machine_unittest.cc",
+    "time_util_unittest.cc",
+    "timer_unittest.cc"
+  ]
+
+  include_dirs = [
+    "//",
+    "//common",
+  ]
+
+  deps = [
+    "//common",
+    "//third_party/googletest:gtest_main",
+    "//third_party/googletest:gmock_main",
+    "//third_party/libchrome:base",
+  ]
+
+  libs = [
+    "-lpthread",
+    "-lrt",
+  ]
+}
diff --git a/common/address_obfuscator.cc b/common/address_obfuscator.cc
new file mode 100644
index 0000000..5c30288
--- /dev/null
+++ b/common/address_obfuscator.cc
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "address_obfuscator.h"
+
+#include <algorithm>
+
+#include <base/logging.h>
+#include <openssl/hmac.h>
+
+#include "bt_trace.h"
+
+namespace bluetooth {
+namespace common {
+
+bool AddressObfuscator::IsSaltValid(const Octet32& salt_256bit) {
+  return !std::all_of(salt_256bit.begin(), salt_256bit.end(),
+                      [](uint8_t i) { return i == 0; });
+}
+
+void AddressObfuscator::Initialize(const Octet32& salt_256bit) {
+  std::lock_guard<std::recursive_mutex> lock(instance_mutex_);
+  salt_256bit_ = salt_256bit;
+}
+
+bool AddressObfuscator::IsInitialized() {
+  std::lock_guard<std::recursive_mutex> lock(instance_mutex_);
+  return IsSaltValid(salt_256bit_);
+}
+
+std::string AddressObfuscator::Obfuscate(const RawAddress& address) {
+  std::lock_guard<std::recursive_mutex> lock(instance_mutex_);
+  CHECK(IsInitialized());
+  std::array<uint8_t, EVP_MAX_MD_SIZE> result = {};
+  unsigned int out_len = 0;
+  CHECK(::HMAC(EVP_sha256(), salt_256bit_.data(), salt_256bit_.size(),
+               address.address, address.kLength, result.data(),
+               &out_len) != nullptr);
+  CHECK_EQ(out_len, static_cast<unsigned int>(kOctet32Length));
+  return std::string(reinterpret_cast<const char*>(result.data()), out_len);
+}
+
+}  // namespace common
+}  // namespace bluetooth
\ No newline at end of file
diff --git a/common/address_obfuscator.h b/common/address_obfuscator.h
new file mode 100644
index 0000000..b8e7dc2
--- /dev/null
+++ b/common/address_obfuscator.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <array>
+#include <mutex>
+#include <string>
+
+#include "raw_address.h"
+
+namespace bluetooth {
+namespace common {
+
+class AddressObfuscator {
+ public:
+  static constexpr unsigned int kOctet32Length = 32;
+  using Octet32 = std::array<uint8_t, kOctet32Length>;
+  static AddressObfuscator* GetInstance() {
+    static auto instance = new AddressObfuscator();
+    return instance;
+  }
+
+  /**
+   * Return true if the input salt is valid
+   * Criteria:
+   * - Salt must be non-zero
+   *
+   * @param salt_256bit
+   * @return true if the salt is valid
+   */
+  static bool IsSaltValid(const Octet32& salt_256bit);
+
+  /**
+   * Initialize this obfuscator with necessary parameters
+   *
+   * @param salt_256bit a 256 bit salt used to hash the fixed length address
+   */
+  void Initialize(const Octet32& salt_256bit);
+
+  /**
+   * Return true if Initialize() was called earlier
+   */
+  bool IsInitialized();
+
+  /**
+   * Obfuscate Bluetooth MAC address into an anonymous ID string
+   *
+   * @param address Bluetooth MAC address to be obfuscated
+   * @return the obfuscated MAC address in 256 bit
+   */
+  std::string Obfuscate(const RawAddress& address);
+
+ private:
+  AddressObfuscator() : salt_256bit_({0}) {}
+  Octet32 salt_256bit_;
+  std::recursive_mutex instance_mutex_;
+};
+
+}  // namespace common
+}  // namespace bluetooth
\ No newline at end of file
diff --git a/common/address_obfuscator_unittest.cc b/common/address_obfuscator_unittest.cc
new file mode 100644
index 0000000..d10446f
--- /dev/null
+++ b/common/address_obfuscator_unittest.cc
@@ -0,0 +1,120 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "address_obfuscator.h"
+
+#include <gtest/gtest.h>
+
+using bluetooth::common::AddressObfuscator;
+
+constexpr AddressObfuscator::Octet32 kEmptyKey = {0};
+
+constexpr AddressObfuscator::Octet32 kTestKey1 = {
+    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+    0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+};
+static RawAddress kTestData1 = {{0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff}};
+constexpr AddressObfuscator::Octet32 kTestResultRaw1 = {
+    0x9b, 0x52, 0xb9, 0xb9, 0xb9, 0x34, 0x80, 0x1d, 0x98, 0x0b, 0x10,
+    0xbe, 0x45, 0xa2, 0x6d, 0xaa, 0x99, 0xc3, 0x04, 0x10, 0x08, 0x03,
+    0xb7, 0xb4, 0xa9, 0xde, 0xcf, 0x89, 0xe1, 0x5d, 0xd4, 0xaa};
+static std::string kTestResult1(
+    reinterpret_cast<const char*>(kTestResultRaw1.data()),
+    kTestResultRaw1.size());
+
+constexpr AddressObfuscator::Octet32 kTestKey2 = {
+    0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
+    0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
+    0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20};
+
+static RawAddress kTestData2_1 = {{0x9e, 0xf5, 0x3d, 0x6c, 0x2e, 0x33}};
+constexpr AddressObfuscator::Octet32 kTestResultRaw2_1 = {
+    0xb4, 0xe2, 0xfc, 0xb9, 0x59, 0x0d, 0x1f, 0xcf, 0x68, 0x80, 0xb2,
+    0x3d, 0x08, 0x55, 0x4e, 0x64, 0xf5, 0x3b, 0x33, 0x0d, 0xb6, 0x31,
+    0x9a, 0xbc, 0x4e, 0xce, 0x61, 0xbd, 0x46, 0x66, 0x45, 0x94};
+static std::string kTestResult2_1(
+    reinterpret_cast<const char*>(kTestResultRaw2_1.data()),
+    kTestResultRaw2_1.size());
+
+static RawAddress kTestData2_2 = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+constexpr AddressObfuscator::Octet32 kTestResultRaw2_2 = {
+    0xd4, 0xd8, 0x23, 0xc0, 0x24, 0xba, 0xde, 0xe3, 0x1c, 0xad, 0x84,
+    0x8b, 0x3d, 0xc6, 0xda, 0x93, 0x88, 0xb2, 0x5c, 0x60, 0x13, 0xe5,
+    0xe2, 0x3e, 0x75, 0x5f, 0xd7, 0x15, 0x56, 0xf7, 0xaf, 0x27};
+static std::string kTestResult2_2(
+    reinterpret_cast<const char*>(kTestResultRaw2_2.data()),
+    kTestResultRaw2_2.size());
+
+static RawAddress kTestData2_3 = {{0xff, 0xff, 0xff, 0xff, 0xff, 0xff}};
+constexpr AddressObfuscator::Octet32 kTestResultRaw2_3 = {
+    0x6f, 0x7c, 0x3d, 0x23, 0xcc, 0x7a, 0xf2, 0x68, 0xee, 0xe8, 0x6c,
+    0x0f, 0xb5, 0xe0, 0x0c, 0x88, 0xf6, 0x38, 0x71, 0x44, 0x88, 0x09,
+    0x45, 0x0a, 0xa2, 0xd7, 0xf6, 0x70, 0xba, 0x8c, 0xe9, 0x79};
+static std::string kTestResult2_3(
+    reinterpret_cast<const char*>(kTestResultRaw2_3.data()),
+    kTestResultRaw2_3.size());
+
+TEST(AddressObfuscatorTest, test_invalid_key) {
+  EXPECT_FALSE(AddressObfuscator::IsSaltValid(kEmptyKey));
+}
+
+TEST(AddressObfuscatorTest, test_valid_key) {
+  EXPECT_TRUE(AddressObfuscator::IsSaltValid(kTestKey1));
+}
+
+TEST(AddressObfuscatorTest, test_initialize_negative) {
+  AddressObfuscator::GetInstance()->Initialize(kEmptyKey);
+  EXPECT_FALSE(AddressObfuscator::GetInstance()->IsInitialized());
+}
+
+TEST(AddressObfuscatorTest, test_initialize_positive) {
+  AddressObfuscator::GetInstance()->Initialize(kTestKey1);
+  EXPECT_TRUE(AddressObfuscator::GetInstance()->IsInitialized());
+}
+
+TEST(AddressObfuscatorTest, test_obfuscate_address_key1) {
+  AddressObfuscator::GetInstance()->Initialize(kTestKey1);
+  std::string result = AddressObfuscator::GetInstance()->Obfuscate(kTestData1);
+  EXPECT_EQ(result.size(), AddressObfuscator::kOctet32Length);
+  EXPECT_EQ(result, kTestResult1);
+}
+
+TEST(AddressObfuscatorTest, test_obfuscate_address_key2) {
+  AddressObfuscator::GetInstance()->Initialize(kTestKey2);
+  std::string result =
+      AddressObfuscator::GetInstance()->Obfuscate(kTestData2_1);
+  EXPECT_EQ(result.size(), AddressObfuscator::kOctet32Length);
+  EXPECT_EQ(result, kTestResult2_1);
+}
+
+TEST(AddressObfuscatorTest, test_obfuscate_address_key2_empty_adddress) {
+  AddressObfuscator::GetInstance()->Initialize(kTestKey2);
+  std::string result =
+      AddressObfuscator::GetInstance()->Obfuscate(kTestData2_2);
+  EXPECT_EQ(result.size(), AddressObfuscator::kOctet32Length);
+  EXPECT_EQ(result, kTestResult2_2);
+}
+
+TEST(AddressObfuscatorTest, test_obfuscate_address_key2_max_address) {
+  AddressObfuscator::GetInstance()->Initialize(kTestKey2);
+  std::string result =
+      AddressObfuscator::GetInstance()->Obfuscate(kTestData2_3);
+  EXPECT_EQ(result.size(), AddressObfuscator::kOctet32Length);
+  EXPECT_EQ(result, kTestResult2_3);
+}
\ No newline at end of file
diff --git a/common/benchmark/thread_performance_benchmark.cc b/common/benchmark/thread_performance_benchmark.cc
new file mode 100644
index 0000000..74f157f
--- /dev/null
+++ b/common/benchmark/thread_performance_benchmark.cc
@@ -0,0 +1,432 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/run_loop.h>
+#include <base/threading/thread.h>
+#include <benchmark/benchmark.h>
+#include <future>
+#include <memory>
+#include <thread>
+
+#include "common/message_loop_thread.h"
+#include "osi/include/fixed_queue.h"
+#include "osi/include/thread.h"
+
+using ::benchmark::State;
+using bluetooth::common::MessageLoopThread;
+
+#define NUM_MESSAGES_TO_SEND 100000
+
+volatile static int g_counter = 0;
+static std::unique_ptr<std::promise<void>> g_counter_promise = nullptr;
+
+void pthread_callback_batch(void* context) {
+  auto queue = static_cast<fixed_queue_t*>(context);
+  CHECK_NE(queue, nullptr);
+  fixed_queue_dequeue(queue);
+  g_counter++;
+  if (g_counter >= NUM_MESSAGES_TO_SEND) {
+    g_counter_promise->set_value();
+  }
+}
+
+void callback_sequential(void* context) { g_counter_promise->set_value(); }
+
+void callback_sequential_queue(fixed_queue_t* queue, void* context) {
+  CHECK_NE(queue, nullptr);
+  fixed_queue_dequeue(queue);
+  g_counter_promise->set_value();
+}
+
+void callback_batch(fixed_queue_t* queue, void* data) {
+  CHECK_NE(queue, nullptr);
+  fixed_queue_dequeue(queue);
+  g_counter++;
+  if (g_counter >= NUM_MESSAGES_TO_SEND) {
+    g_counter_promise->set_value();
+  }
+}
+
+class BM_ThreadPerformance : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    benchmark::Fixture::SetUp(st);
+    set_up_promise_ = std::make_unique<std::promise<void>>();
+    g_counter = 0;
+    bt_msg_queue_ = fixed_queue_new(SIZE_MAX);
+  }
+  void TearDown(State& st) override {
+    fixed_queue_free(bt_msg_queue_, nullptr);
+    bt_msg_queue_ = nullptr;
+    set_up_promise_.reset(nullptr);
+    g_counter_promise.reset(nullptr);
+    benchmark::Fixture::TearDown(st);
+  }
+  fixed_queue_t* bt_msg_queue_ = nullptr;
+  std::unique_ptr<std::promise<void>> set_up_promise_;
+};
+
+class BM_MessageLoop : public BM_ThreadPerformance {
+ public:
+  static void RunThread(void* context) {
+    auto test = static_cast<BM_MessageLoop*>(context);
+    test->RunMessageLoop();
+  }
+  static void* RunPThread(void* context) {
+    auto test = static_cast<BM_MessageLoop*>(context);
+    test->RunMessageLoop();
+    return nullptr;
+  }
+  void RunMessageLoop() {
+    message_loop_ = new base::MessageLoop();
+    run_loop_ = new base::RunLoop();
+    message_loop_->task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
+                                  base::Unretained(set_up_promise_.get())));
+    run_loop_->Run();
+    delete message_loop_;
+    message_loop_ = nullptr;
+    delete run_loop_;
+    run_loop_ = nullptr;
+  }
+
+ protected:
+  base::MessageLoop* message_loop_ = nullptr;
+  base::RunLoop* run_loop_ = nullptr;
+};
+
+class BM_MessageLoopOsiThread : public BM_MessageLoop {
+ protected:
+  void SetUp(State& st) override {
+    BM_MessageLoop::SetUp(st);
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = thread_new("BM_MessageLoopOnOsiThread thread");
+    thread_post(thread_, &BM_MessageLoop::RunThread, this);
+    set_up_future.wait();
+  }
+
+  void TearDown(State& st) override {
+    message_loop_->task_runner()->PostTask(FROM_HERE,
+                                           run_loop_->QuitWhenIdleClosure());
+    thread_free(thread_);
+    thread_ = nullptr;
+    BM_MessageLoop::TearDown(st);
+  }
+
+  thread_t* thread_ = nullptr;
+};
+
+BENCHMARK_F(BM_MessageLoopOsiThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      message_loop_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_MessageLoopOsiThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      message_loop_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
+      counter_future.wait();
+    }
+  }
+};
+
+class BM_MessageLoopStlThread : public BM_MessageLoop {
+ protected:
+  void SetUp(State& st) override {
+    BM_MessageLoop::SetUp(st);
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = new std::thread(&BM_MessageLoop::RunThread, this);
+    set_up_future.wait();
+  }
+
+  void TearDown(State& st) override {
+    message_loop_->task_runner()->PostTask(FROM_HERE,
+                                           run_loop_->QuitWhenIdleClosure());
+    thread_->join();
+    delete thread_;
+    thread_ = nullptr;
+    BM_MessageLoop::TearDown(st);
+  }
+
+  std::thread* thread_ = nullptr;
+};
+
+BENCHMARK_F(BM_MessageLoopStlThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      message_loop_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_MessageLoopStlThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      message_loop_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
+      counter_future.wait();
+    }
+  }
+};
+
+class BM_MessageLoopPosixThread : public BM_MessageLoop {
+ protected:
+  void SetUp(State& st) override {
+    BM_MessageLoop::SetUp(st);
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    pthread_create(&thread_, nullptr, &BM_MessageLoop::RunPThread, (void*)this);
+    set_up_future.wait();
+  }
+
+  void TearDown(State& st) override {
+    message_loop_->task_runner()->PostTask(FROM_HERE,
+                                           run_loop_->QuitWhenIdleClosure());
+    pthread_join(thread_, nullptr);
+    BM_MessageLoop::TearDown(st);
+  }
+
+  pthread_t thread_ = -1;
+};
+
+BENCHMARK_F(BM_MessageLoopPosixThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      message_loop_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_MessageLoopPosixThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      message_loop_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
+      counter_future.wait();
+    }
+  }
+};
+
+class BM_OsiReactorThread : public BM_ThreadPerformance {
+ protected:
+  void SetUp(State& st) override {
+    BM_ThreadPerformance::SetUp(st);
+    thread_ = thread_new("BM_OsiReactorThread thread");
+  }
+
+  void TearDown(State& st) override {
+    thread_free(thread_);
+    thread_ = nullptr;
+    BM_ThreadPerformance::TearDown(st);
+  }
+
+  thread_t* thread_ = nullptr;
+};
+
+BENCHMARK_F(BM_OsiReactorThread, batch_enque_dequeue_using_thread_post)
+(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      thread_post(thread_, pthread_callback_batch, bt_msg_queue_);
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_OsiReactorThread, sequential_execution_using_thread_post)
+(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      thread_post(thread_, callback_sequential, nullptr);
+      counter_future.wait();
+    }
+  }
+};
+
+BENCHMARK_F(BM_OsiReactorThread, batch_enque_dequeue_using_reactor)
+(State& state) {
+  fixed_queue_register_dequeue(bt_msg_queue_, thread_get_reactor(thread_),
+                               callback_batch, nullptr);
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_OsiReactorThread, sequential_execution_using_reactor)
+(State& state) {
+  fixed_queue_register_dequeue(bt_msg_queue_, thread_get_reactor(thread_),
+                               callback_sequential_queue, nullptr);
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      counter_future.wait();
+    }
+  }
+};
+
+class BM_MessageLooopThread : public BM_ThreadPerformance {
+ protected:
+  void SetUp(State& st) override {
+    BM_ThreadPerformance::SetUp(st);
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    message_loop_thread_ =
+        new MessageLoopThread("BM_MessageLooopThread thread");
+    message_loop_thread_->StartUp();
+    message_loop_thread_->DoInThread(
+        FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
+                                  base::Unretained(set_up_promise_.get())));
+    set_up_future.wait();
+  }
+
+  void TearDown(State& st) override {
+    message_loop_thread_->ShutDown();
+    delete message_loop_thread_;
+    message_loop_thread_ = nullptr;
+    BM_ThreadPerformance::TearDown(st);
+  }
+
+  MessageLoopThread* message_loop_thread_ = nullptr;
+};
+
+BENCHMARK_F(BM_MessageLooopThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      message_loop_thread_->DoInThread(
+          FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_MessageLooopThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      message_loop_thread_->DoInThread(
+          FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
+      counter_future.wait();
+    }
+  }
+};
+
+class BM_LibChromeThread : public BM_ThreadPerformance {
+ protected:
+  void SetUp(State& st) override {
+    BM_ThreadPerformance::SetUp(st);
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = new base::Thread("BM_LibChromeThread thread");
+    thread_->Start();
+    thread_->task_runner()->PostTask(
+        FROM_HERE, base::BindOnce(&std::promise<void>::set_value,
+                                  base::Unretained(set_up_promise_.get())));
+    set_up_future.wait();
+  }
+
+  void TearDown(State& st) override {
+    thread_->Stop();
+    delete thread_;
+    thread_ = nullptr;
+    BM_ThreadPerformance::TearDown(st);
+  }
+
+  base::Thread* thread_ = nullptr;
+};
+
+BENCHMARK_F(BM_LibChromeThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    g_counter = 0;
+    g_counter_promise = std::make_unique<std::promise<void>>();
+    std::future<void> counter_future = g_counter_promise->get_future();
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+      thread_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_batch, bt_msg_queue_, nullptr));
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_F(BM_LibChromeThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+      g_counter_promise = std::make_unique<std::promise<void>>();
+      std::future<void> counter_future = g_counter_promise->get_future();
+      thread_->task_runner()->PostTask(
+          FROM_HERE, base::BindOnce(&callback_sequential, nullptr));
+      counter_future.wait();
+    }
+  }
+};
+
+int main(int argc, char** argv) {
+  // Disable LOG() output from libchrome
+  logging::LoggingSettings log_settings;
+  log_settings.logging_dest = logging::LoggingDestination::LOG_NONE;
+  CHECK(logging::InitLogging(log_settings)) << "Failed to set up logging";
+  ::benchmark::Initialize(&argc, argv);
+  if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
+    return 1;
+  }
+  ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/common/benchmark/timer_performance_benchmark.cc b/common/benchmark/timer_performance_benchmark.cc
new file mode 100644
index 0000000..deaaad8
--- /dev/null
+++ b/common/benchmark/timer_performance_benchmark.cc
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/bind.h>
+#include <base/run_loop.h>
+#include <base/threading/thread.h>
+#include <benchmark/benchmark.h>
+#include <future>
+
+#include "common/message_loop_thread.h"
+#include "common/once_timer.h"
+#include "common/repeating_timer.h"
+#include "common/time_util.h"
+#include "osi/include/alarm.h"
+
+using ::benchmark::State;
+using bluetooth::common::MessageLoopThread;
+using bluetooth::common::OnceTimer;
+using bluetooth::common::RepeatingTimer;
+using bluetooth::common::time_get_os_boottime_us;
+
+// fake get_main_message_loop implementation for alarm
+base::MessageLoop* get_main_message_loop() { return nullptr; }
+
+namespace {
+std::unordered_map<int, int> g_map;
+std::shared_ptr<std::promise<void>> g_promise;
+uint64_t g_start_time;
+int g_scheduled_tasks;
+int g_task_length;
+int g_task_interval;
+int g_task_counter;
+
+void TimerFire(void*) { g_promise->set_value(); }
+
+void AlarmSleepAndCountDelayedTime(void*) {
+  auto end_time_us = time_get_os_boottime_us();
+  auto time_after_start_ms = (end_time_us - g_start_time) / 1000;
+  g_task_counter++;
+  g_map[time_after_start_ms - g_task_counter * g_task_interval]++;
+  std::this_thread::sleep_for(std::chrono::milliseconds(g_task_length));
+  if (g_task_counter >= g_scheduled_tasks) {
+    g_promise->set_value();
+  }
+}
+
+}  // namespace
+
+class BM_OsiAlarmTimer : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    alarm_ = alarm_new("osi_alarm_timer_test");
+    g_promise = std::make_shared<std::promise<void>>();
+  }
+
+  void TearDown(State& st) override {
+    g_promise = nullptr;
+    alarm_free(alarm_);
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  alarm_t* alarm_ = nullptr;
+};
+
+BENCHMARK_DEFINE_F(BM_OsiAlarmTimer, timer_performance_ms)(State& state) {
+  auto milliseconds = static_cast<int>(state.range(0));
+  for (auto _ : state) {
+    auto start_time_point = time_get_os_boottime_us();
+    alarm_set(alarm_, milliseconds, &TimerFire, nullptr);
+    g_promise->get_future().get();
+    auto end_time_point = time_get_os_boottime_us();
+    auto duration = end_time_point - start_time_point;
+    state.SetIterationTime(duration * 1e-6);
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_OsiAlarmTimer, timer_performance_ms)
+    ->Arg(1)
+    ->Arg(5)
+    ->Arg(10)
+    ->Arg(20)
+    ->Arg(100)
+    ->Arg(1000)
+    ->Arg(2000)
+    ->Iterations(1)
+    ->UseManualTime();
+
+class BM_AlarmTaskTimer : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    message_loop_thread_ = new MessageLoopThread("timer_benchmark");
+    message_loop_thread_->StartUp();
+    message_loop_thread_->EnableRealTimeScheduling();
+    once_timer_ = new OnceTimer();
+    repeating_timer_ = new RepeatingTimer();
+    g_promise = std::make_shared<std::promise<void>>();
+  }
+
+  void TearDown(State& st) override {
+    g_promise = nullptr;
+    delete once_timer_;
+    once_timer_ = nullptr;
+    delete repeating_timer_;
+    repeating_timer_ = nullptr;
+    message_loop_thread_->ShutDown();
+    delete message_loop_thread_;
+    message_loop_thread_ = nullptr;
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  MessageLoopThread* message_loop_thread_;
+  OnceTimer* once_timer_;
+  RepeatingTimer* repeating_timer_;
+};
+
+BENCHMARK_DEFINE_F(BM_AlarmTaskTimer, timer_performance_ms)(State& state) {
+  auto milliseconds = static_cast<int>(state.range(0));
+  for (auto _ : state) {
+    auto start_time_point = time_get_os_boottime_us();
+    once_timer_->Schedule(message_loop_thread_->GetWeakPtr(), FROM_HERE,
+                          base::BindOnce(&TimerFire, nullptr),
+                          base::TimeDelta::FromMilliseconds(milliseconds));
+    g_promise->get_future().get();
+    once_timer_->Cancel();
+    auto end_time_point = time_get_os_boottime_us();
+    auto duration = end_time_point - start_time_point;
+    state.SetIterationTime(duration * 1e-6);
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_AlarmTaskTimer, timer_performance_ms)
+    ->Arg(1)
+    ->Arg(5)
+    ->Arg(10)
+    ->Arg(20)
+    ->Arg(100)
+    ->Arg(1000)
+    ->Arg(2000)
+    ->Iterations(1)
+    ->UseManualTime();
+
+class BM_OsiPeriodicAlarmTimer : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    alarm_ = alarm_new_periodic("osi_alarm_timer_test");
+    g_map.clear();
+    g_promise = std::make_shared<std::promise<void>>();
+    g_scheduled_tasks = 0;
+    g_task_length = 0;
+    g_task_interval = 0;
+    g_task_counter = 0;
+  }
+
+  void TearDown(State& st) override {
+    g_promise = nullptr;
+    alarm_free(alarm_);
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  alarm_t* alarm_ = nullptr;
+};
+
+BENCHMARK_DEFINE_F(BM_OsiPeriodicAlarmTimer, periodic_accuracy)(State& state) {
+  for (auto _ : state) {
+    g_scheduled_tasks = state.range(0);
+    g_task_length = state.range(1);
+    g_task_interval = state.range(2);
+    g_start_time = time_get_os_boottime_us();
+    alarm_set(alarm_, g_task_interval, &AlarmSleepAndCountDelayedTime, nullptr);
+    g_promise->get_future().get();
+    alarm_cancel(alarm_);
+  }
+  for (const auto& delay : g_map) {
+    state.counters[std::to_string(delay.first)] = delay.second;
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_OsiPeriodicAlarmTimer, periodic_accuracy)
+    ->Args({2000, 1, 5})
+    ->Args({2000, 3, 5})
+    ->Args({2000, 1, 7})
+    ->Args({2000, 3, 7})
+    ->Args({2000, 1, 20})
+    ->Args({2000, 5, 20})
+    ->Args({2000, 10, 20})
+    ->Args({2000, 15, 20})
+    ->Iterations(1)
+    ->UseRealTime();
+
+class BM_AlarmTaskPeriodicTimer : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    message_loop_thread_ = new MessageLoopThread("timer_benchmark");
+    message_loop_thread_->StartUp();
+    message_loop_thread_->EnableRealTimeScheduling();
+    once_timer_ = new OnceTimer();
+    repeating_timer_ = new RepeatingTimer();
+    g_map.clear();
+    g_promise = std::make_shared<std::promise<void>>();
+    g_scheduled_tasks = 0;
+    g_task_length = 0;
+    g_task_interval = 0;
+    g_task_counter = 0;
+  }
+
+  void TearDown(State& st) override {
+    g_promise = nullptr;
+    delete once_timer_;
+    once_timer_ = nullptr;
+    delete repeating_timer_;
+    repeating_timer_ = nullptr;
+    message_loop_thread_->ShutDown();
+    delete message_loop_thread_;
+    message_loop_thread_ = nullptr;
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  MessageLoopThread* message_loop_thread_;
+  OnceTimer* once_timer_;
+  RepeatingTimer* repeating_timer_;
+};
+
+BENCHMARK_DEFINE_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy)
+(State& state) {
+  for (auto _ : state) {
+    g_scheduled_tasks = state.range(0);
+    g_task_length = state.range(1);
+    g_task_interval = state.range(2);
+    g_start_time = time_get_os_boottime_us();
+    repeating_timer_->SchedulePeriodic(
+        message_loop_thread_->GetWeakPtr(), FROM_HERE,
+        base::BindRepeating(&AlarmSleepAndCountDelayedTime, nullptr),
+        base::TimeDelta::FromMilliseconds(g_task_interval));
+    g_promise->get_future().get();
+    repeating_timer_->Cancel();
+  }
+  for (const auto& delay : g_map) {
+    state.counters[std::to_string(delay.first)] = delay.second;
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_AlarmTaskPeriodicTimer, periodic_accuracy)
+    ->Args({2000, 1, 5})
+    ->Args({2000, 3, 5})
+    ->Args({2000, 1, 7})
+    ->Args({2000, 3, 7})
+    ->Args({2000, 1, 20})
+    ->Args({2000, 5, 20})
+    ->Args({2000, 10, 20})
+    ->Args({2000, 15, 20})
+    ->Iterations(1)
+    ->UseRealTime();
+
+int main(int argc, char** argv) {
+  // Disable LOG() output from libchrome
+  logging::LoggingSettings log_settings;
+  log_settings.logging_dest = logging::LoggingDestination::LOG_NONE;
+  CHECK(logging::InitLogging(log_settings)) << "Failed to set up logging";
+  ::benchmark::Initialize(&argc, argv);
+  if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
+    return 1;
+  }
+  ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/common/id_generator.h b/common/id_generator.h
new file mode 100644
index 0000000..202d645
--- /dev/null
+++ b/common/id_generator.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <array>
+
+/* Helper class generating N unique ids, from 0 to N-1 */
+template <std::size_t N>
+class IdGenerator {
+ public:
+  static int ALL_USED;
+
+  IdGenerator() : in_use_{} {}
+
+  /* Returns next free id, or ALL_USED if no ids left */
+  int GetNext() {
+    for (std::size_t i = 0; i < N; i++) {
+      if (!in_use_[i]) {
+        in_use_[i] = true;
+        return i;
+      }
+    }
+    return ALL_USED;
+  }
+
+  /* Release given ID */
+  void Release(int id) { in_use_[id] = false; }
+
+ private:
+  std::array<bool, N> in_use_;
+};
+
+template <std::size_t N>
+int IdGenerator<N>::ALL_USED = -1;
\ No newline at end of file
diff --git a/common/id_generator_unittest.cc b/common/id_generator_unittest.cc
new file mode 100644
index 0000000..d56ee19
--- /dev/null
+++ b/common/id_generator_unittest.cc
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "common/id_generator.h"
+
+#include <gtest/gtest.h>
+
+TEST(IdGeneratorTest, sanity_test) {
+  IdGenerator<5> generator;
+  ASSERT_EQ(0, generator.GetNext());
+  ASSERT_EQ(1, generator.GetNext());
+  ASSERT_EQ(2, generator.GetNext());
+  ASSERT_EQ(3, generator.GetNext());
+  ASSERT_EQ(4, generator.GetNext());
+  ASSERT_EQ(generator.ALL_USED, generator.GetNext());
+
+  generator.Release(3);
+  ASSERT_EQ(3, generator.GetNext());
+
+  generator.Release(0);
+  generator.Release(2);
+  ASSERT_EQ(0, generator.GetNext());
+  ASSERT_EQ(2, generator.GetNext());
+}
\ No newline at end of file
diff --git a/osi/include/leaky_bonded_queue.h b/common/leaky_bonded_queue.h
similarity index 95%
rename from osi/include/leaky_bonded_queue.h
rename to common/leaky_bonded_queue.h
index 6861e8b..087b192 100644
--- a/osi/include/leaky_bonded_queue.h
+++ b/common/leaky_bonded_queue.h
@@ -21,7 +21,9 @@
 #include <mutex>
 #include <queue>
 
-namespace system_bt_osi {
+namespace bluetooth {
+
+namespace common {
 
 /*
  *   LeakyBondedQueue<T>
@@ -86,8 +88,8 @@
 };
 
 /*
-* Definitions must be in the header for template classes
-*/
+ * Definitions must be in the header for template classes
+ */
 
 template <class T>
 LeakyBondedQueue<T>::LeakyBondedQueue(size_t capacity) {
@@ -155,4 +157,6 @@
   return queue_.empty();
 }
 
-}  // namespace system_bt_osi
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/osi/test/leaky_bonded_queue_test.cc b/common/leaky_bonded_queue_unittest.cc
similarity index 97%
rename from osi/test/leaky_bonded_queue_test.cc
rename to common/leaky_bonded_queue_unittest.cc
index 116676b..fcd55cd 100644
--- a/osi/test/leaky_bonded_queue_test.cc
+++ b/common/leaky_bonded_queue_unittest.cc
@@ -20,11 +20,11 @@
 
 #include <base/logging.h>
 
-#include "osi/include/leaky_bonded_queue.h"
+#include "common/leaky_bonded_queue.h"
 
 namespace testing {
 
-using system_bt_osi::LeakyBondedQueue;
+using bluetooth::common::LeakyBondedQueue;
 
 #define ITEM_EQ(a, b)                  \
   do {                                 \
@@ -239,4 +239,4 @@
   queue->Enqueue(item2);
   delete queue;
 }
-}
+}  // namespace testing
diff --git a/common/message_loop_thread.cc b/common/message_loop_thread.cc
new file mode 100644
index 0000000..e2c2e2d
--- /dev/null
+++ b/common/message_loop_thread.cc
@@ -0,0 +1,203 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "message_loop_thread.h"
+
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <thread>
+
+#include <base/strings/stringprintf.h>
+
+namespace bluetooth {
+
+namespace common {
+
+static constexpr int kRealTimeFifoSchedulingPriority = 1;
+
+MessageLoopThread::MessageLoopThread(const std::string& thread_name)
+    : thread_name_(thread_name),
+      message_loop_(nullptr),
+      run_loop_(nullptr),
+      thread_(nullptr),
+      thread_id_(-1),
+      linux_tid_(-1),
+      weak_ptr_factory_(this),
+      shutting_down_(false) {}
+
+MessageLoopThread::~MessageLoopThread() { ShutDown(); }
+
+void MessageLoopThread::StartUp() {
+  std::promise<void> start_up_promise;
+  std::future<void> start_up_future = start_up_promise.get_future();
+  {
+    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+    if (thread_ != nullptr) {
+      LOG(WARNING) << __func__ << ": thread " << *this << " is already started";
+
+      return;
+    }
+    thread_ = new std::thread(&MessageLoopThread::RunThread, this,
+                              std::move(start_up_promise));
+  }
+  start_up_future.wait();
+}
+
+bool MessageLoopThread::DoInThread(const base::Location& from_here,
+                                   base::OnceClosure task) {
+  return DoInThreadDelayed(from_here, std::move(task), base::TimeDelta());
+}
+
+bool MessageLoopThread::DoInThreadDelayed(const base::Location& from_here,
+                                          base::OnceClosure task,
+                                          const base::TimeDelta& delay) {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  if (message_loop_ == nullptr) {
+    LOG(ERROR) << __func__ << ": message loop is null for thread " << *this
+               << ", from " << from_here.ToString();
+    return false;
+  }
+  if (!message_loop_->task_runner()->PostDelayedTask(from_here, std::move(task),
+                                                     delay)) {
+    LOG(ERROR) << __func__
+               << ": failed to post task to message loop for thread " << *this
+               << ", from " << from_here.ToString();
+    return false;
+  }
+  return true;
+}
+
+void MessageLoopThread::ShutDown() {
+  {
+    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+    if (thread_ == nullptr) {
+      LOG(INFO) << __func__ << ": thread " << *this << " is already stopped";
+      return;
+    }
+    if (message_loop_ == nullptr) {
+      LOG(INFO) << __func__ << ": message_loop_ is null. Already stopping";
+      return;
+    }
+    if (shutting_down_) {
+      LOG(INFO) << __func__ << ": waiting for thread to join";
+      return;
+    }
+    shutting_down_ = true;
+    CHECK_NE(thread_id_, base::PlatformThread::CurrentId())
+        << __func__ << " should not be called on the thread itself. "
+        << "Otherwise, deadlock may happen.";
+    if (!message_loop_->task_runner()->PostTask(
+            FROM_HERE, run_loop_->QuitWhenIdleClosure())) {
+      LOG(FATAL) << __func__
+                 << ": failed to post task to message loop for thread "
+                 << *this;
+    }
+  }
+  thread_->join();
+  {
+    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+    delete thread_;
+    thread_ = nullptr;
+    shutting_down_ = false;
+  }
+}
+
+base::PlatformThreadId MessageLoopThread::GetThreadId() const {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return thread_id_;
+}
+
+std::string MessageLoopThread::GetName() const {
+  return thread_name_;
+}
+
+std::string MessageLoopThread::ToString() const {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return base::StringPrintf("%s(%d)", thread_name_.c_str(), thread_id_);
+}
+
+bool MessageLoopThread::IsRunning() const {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return message_loop_ != nullptr;
+}
+
+// Non API method, should not be protected by API mutex
+void MessageLoopThread::RunThread(MessageLoopThread* thread,
+                                  std::promise<void> start_up_promise) {
+  thread->Run(std::move(start_up_promise));
+}
+
+base::MessageLoop* MessageLoopThread::message_loop() const {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return message_loop_;
+}
+
+bool MessageLoopThread::EnableRealTimeScheduling() {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  if (!IsRunning()) {
+    LOG(ERROR) << __func__ << ": thread " << *this << " is not running";
+    return false;
+  }
+  struct sched_param rt_params = {.sched_priority =
+                                      kRealTimeFifoSchedulingPriority};
+  int rc = sched_setscheduler(linux_tid_, SCHED_FIFO, &rt_params);
+  if (rc != 0) {
+    LOG(ERROR) << __func__ << ": unable to set SCHED_FIFO priority "
+               << kRealTimeFifoSchedulingPriority << " for linux_tid "
+               << std::to_string(linux_tid_) << ", thread " << *this
+               << ", error: " << strerror(errno);
+    return false;
+  }
+  return true;
+}
+
+base::WeakPtr<MessageLoopThread> MessageLoopThread::GetWeakPtr() {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+void MessageLoopThread::Run(std::promise<void> start_up_promise) {
+  {
+    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+    LOG(INFO) << __func__ << ": message loop starting for thread "
+              << thread_name_;
+    base::PlatformThread::SetName(thread_name_);
+    message_loop_ = new base::MessageLoop();
+    run_loop_ = new base::RunLoop();
+    thread_id_ = base::PlatformThread::CurrentId();
+    linux_tid_ = static_cast<pid_t>(syscall(SYS_gettid));
+    start_up_promise.set_value();
+  }
+
+  // Blocking until ShutDown() is called
+  run_loop_->Run();
+
+  {
+    std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+    thread_id_ = -1;
+    linux_tid_ = -1;
+    delete message_loop_;
+    message_loop_ = nullptr;
+    delete run_loop_;
+    run_loop_ = nullptr;
+    LOG(INFO) << __func__ << ": message loop finished for thread "
+              << thread_name_;
+  }
+}
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/message_loop_thread.h b/common/message_loop_thread.h
new file mode 100644
index 0000000..3984a9b
--- /dev/null
+++ b/common/message_loop_thread.h
@@ -0,0 +1,212 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <future>
+#include <memory>
+#include <string>
+#include <thread>
+
+#include <base/bind.h>
+#include <base/location.h>
+#include <base/message_loop/message_loop.h>
+#include <base/run_loop.h>
+#include <base/threading/platform_thread.h>
+
+namespace bluetooth {
+
+namespace common {
+
+/**
+ * An interface to various thread related functionality
+ */
+class MessageLoopThread final {
+ public:
+  /**
+   * Create a message loop thread with name. Thread won't be running until
+   * StartUp is called.
+   *
+   * @param thread_name name of this worker thread
+   */
+  explicit MessageLoopThread(const std::string& thread_name);
+
+  /**
+   * Destroys the message loop thread automatically when it goes out of scope
+   */
+  ~MessageLoopThread();
+
+  /**
+   * Start the underlying thread. Blocks until all thread infrastructure is
+   * setup. IsRunning() and DoInThread() should return true after this call.
+   * Blocks until the thread is successfully started.
+   *
+   * Repeated call to this method will only start this thread once
+   */
+  void StartUp();
+
+  /**
+   * Post a task to run on this thread
+   *
+   * @param from_here location where this task is originated
+   * @param task task created through base::Bind()
+   * @return true if task is successfully scheduled, false if task cannot be
+   * scheduled
+   */
+  bool DoInThread(const base::Location& from_here, base::OnceClosure task);
+
+  /**
+   * Shutdown the current thread as if it is never started. IsRunning() and
+   * DoInThread() will return false after this call. Blocks until the thread is
+   * joined and freed. This thread can be re-started again using StartUp()
+   *
+   * Repeated call to this method will only stop this thread once
+   *
+   * NOTE: Should never be called on the thread itself to avoid deadlock
+   */
+  void ShutDown();
+
+  /**
+   * Get the current thread ID returned by PlatformThread::CurrentId()
+   *
+   * On Android platform, this value should be the same as the tid logged by
+   * logcat, which is returned by gettid(). On other platform, this thread id
+   * may have different meanings. Therefore, this ID is only good for logging
+   * and thread comparison purpose
+   *
+   * @return this thread's ID
+   */
+  base::PlatformThreadId GetThreadId() const;
+
+  /**
+   * Get this thread's name set in constructor
+   *
+   * @return this thread's name set in constructor
+   */
+  std::string GetName() const;
+
+  /**
+   * Get a string representation of this thread
+   *
+   * @return a string representation of this thread
+   */
+  std::string ToString() const;
+
+  /**
+   * Check if this thread is running
+   *
+   * @return true iff this thread is running and is able to do task
+   */
+  bool IsRunning() const;
+
+  /**
+   * Attempt to make scheduling for this thread real time
+   *
+   * @return true on success, false otherwise
+   */
+  bool EnableRealTimeScheduling();
+
+  /**
+   * Return the weak pointer to this object. This can be useful when posting
+   * delayed tasks to this MessageLoopThread using Timer.
+   */
+  base::WeakPtr<MessageLoopThread> GetWeakPtr();
+
+  /**
+   * Return the message loop for this thread. Accessing raw message loop is not
+   * recommended as message loop can be freed internally.
+   *
+   * @return message loop associated with this thread, nullptr if thread is not
+   * running
+   */
+  base::MessageLoop* message_loop() const;
+
+ private:
+  /**
+   * Static method to run the thread
+   *
+   * This is used instead of a C++ lambda because of the use of std::shared_ptr
+   *
+   * @param context needs to be a pointer to an instance of MessageLoopThread
+   * @param start_up_promise a std::promise that is used to notify calling
+   * thread the completion of message loop start-up
+   */
+  static void RunThread(MessageLoopThread* context,
+                        std::promise<void> start_up_promise);
+
+  /**
+   * Post a task to run on this thread after a specified delay. If the task
+   * needs to be cancelable before it's run, use base::CancelableClosure type
+   * for task closure. For example:
+   * <code>
+   * base::CancelableClosure cancelable_task;
+   * cancelable_task.Reset(base::Bind(...)); // bind the task
+   * same_thread->DoInThreadDelayed(FROM_HERE,
+   *                                cancelable_task.callback(), delay);
+   * ...
+   * // Cancel the task closure
+   * same_thread->DoInThread(FROM_HERE,
+   *                         base::Bind(&base::CancelableClosure::Cancel,
+   *                                    base::Unretained(&cancelable_task)));
+   * </code>
+   *
+   * Warning: base::CancelableClosure objects must be created on, posted to,
+   * cancelled on, and destroyed on the same thread.
+   *
+   * @param from_here location where this task is originated
+   * @param task task created through base::Bind()
+   * @param delay delay for the task to be executed
+   * @return true if task is successfully scheduled, false if task cannot be
+   * scheduled
+   */
+  bool DoInThreadDelayed(const base::Location& from_here,
+                         base::OnceClosure task, const base::TimeDelta& delay);
+
+  friend class RepeatingTimer;  // allow Timer to use DoInThreadDelayed()
+  friend class OnceTimer;       // allow OnceTimer to use DoInThreadDelayed()
+
+  /**
+   * Actual method to run the thread, blocking until ShutDown() is called
+   *
+   * @param start_up_promise a std::promise that is used to notify calling
+   * thread the completion of message loop start-up
+   */
+  void Run(std::promise<void> start_up_promise);
+
+  mutable std::recursive_mutex api_mutex_;
+  const std::string thread_name_;
+  base::MessageLoop* message_loop_;
+  base::RunLoop* run_loop_;
+  std::thread* thread_;
+  base::PlatformThreadId thread_id_;
+  // Linux specific abstractions
+  pid_t linux_tid_;
+  base::WeakPtrFactory<MessageLoopThread> weak_ptr_factory_;
+  bool shutting_down_;
+
+  DISALLOW_COPY_AND_ASSIGN(MessageLoopThread);
+};
+
+inline std::ostream& operator<<(std::ostream& os,
+                                const bluetooth::common::MessageLoopThread& a) {
+  os << a.ToString();
+  return os;
+}
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/message_loop_thread_unittest.cc b/common/message_loop_thread_unittest.cc
new file mode 100644
index 0000000..0e8f0a4
--- /dev/null
+++ b/common/message_loop_thread_unittest.cc
@@ -0,0 +1,330 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "message_loop_thread.h"
+
+#include <condition_variable>
+#include <memory>
+#include <mutex>
+
+#include <gtest/gtest.h>
+
+#include <base/bind.h>
+#include <base/threading/platform_thread.h>
+#include <sys/capability.h>
+#include <syscall.h>
+
+using bluetooth::common::MessageLoopThread;
+
+/**
+ * Unit tests to verify MessageLoopThread. Must have CAP_SYS_NICE capability.
+ */
+class MessageLoopThreadTest : public ::testing::Test {
+ public:
+  void ShouldNotHappen() { FAIL() << "Should not happen"; }
+
+  void GetThreadId(std::promise<base::PlatformThreadId> thread_id_promise) {
+    thread_id_promise.set_value(base::PlatformThread::CurrentId());
+  }
+
+  void GetLinuxTid(std::promise<pid_t> tid_promise) {
+    tid_promise.set_value(static_cast<pid_t>(syscall(SYS_gettid)));
+  }
+
+  void GetName(std::promise<std::string> name_promise) {
+    char my_name[256];
+    pthread_getname_np(pthread_self(), my_name, sizeof(my_name));
+    name_promise.set_value(my_name);
+  }
+
+  void GetSchedulingPolicyAndPriority(int* scheduling_policy,
+                                      int* schedule_priority,
+                                      std::promise<void> execution_promise) {
+    *scheduling_policy = sched_getscheduler(0);
+    struct sched_param param = {};
+    ASSERT_EQ(sched_getparam(0, &param), 0);
+    *schedule_priority = param.sched_priority;
+    execution_promise.set_value();
+  }
+
+  void SleepAndGetName(std::promise<std::string> name_promise, int sleep_ms) {
+    std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
+    GetName(std::move(name_promise));
+  }
+
+ protected:
+  static bool CanSetCurrentThreadPriority() {
+    struct __user_cap_header_struct linux_user_header = {
+        .version = _LINUX_CAPABILITY_VERSION_3};
+    struct __user_cap_data_struct linux_user_data = {};
+    if (capget(&linux_user_header, &linux_user_data) != 0) {
+      LOG(ERROR) << "Failed to get capability for current thread, error: "
+                 << strerror(errno);
+      // Log record in XML
+      RecordProperty("MessageLoopThreadTestCannotGetCapabilityReason",
+                     strerror(errno));
+      return false;
+    }
+    return ((linux_user_data.permitted >> CAP_SYS_NICE) & 0x1) != 0;
+  }
+};
+
+TEST_F(MessageLoopThreadTest, get_weak_ptr) {
+  base::WeakPtr<MessageLoopThread> message_loop_thread_ptr;
+  {
+    MessageLoopThread message_loop_thread("test_thread");
+    message_loop_thread_ptr = message_loop_thread.GetWeakPtr();
+    ASSERT_NE(message_loop_thread_ptr, nullptr);
+  }
+  ASSERT_EQ(message_loop_thread_ptr, nullptr);
+}
+
+TEST_F(MessageLoopThreadTest, test_running_thread) {
+  MessageLoopThread message_loop_thread("test_thread");
+  message_loop_thread.StartUp();
+  ASSERT_GE(message_loop_thread.GetThreadId(), 0);
+  ASSERT_TRUE(message_loop_thread.IsRunning());
+  message_loop_thread.ShutDown();
+  ASSERT_LT(message_loop_thread.GetThreadId(), 0);
+  ASSERT_FALSE(message_loop_thread.IsRunning());
+}
+
+TEST_F(MessageLoopThreadTest, test_not_self) {
+  MessageLoopThread message_loop_thread("test_thread");
+  message_loop_thread.StartUp();
+  ASSERT_GE(message_loop_thread.GetThreadId(), 0);
+  ASSERT_NE(message_loop_thread.GetThreadId(),
+            base::PlatformThread::CurrentId());
+}
+
+TEST_F(MessageLoopThreadTest, test_shutdown_without_start) {
+  MessageLoopThread message_loop_thread("test_thread");
+  message_loop_thread.ShutDown();
+  ASSERT_LT(message_loop_thread.GetThreadId(), 0);
+}
+
+TEST_F(MessageLoopThreadTest, test_do_in_thread_before_start) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  ASSERT_FALSE(message_loop_thread.DoInThread(
+      FROM_HERE, base::Bind(&MessageLoopThreadTest::ShouldNotHappen,
+                            base::Unretained(this))));
+}
+
+TEST_F(MessageLoopThreadTest, test_do_in_thread_after_shutdown) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  message_loop_thread.ShutDown();
+  ASSERT_FALSE(message_loop_thread.DoInThread(
+      FROM_HERE, base::Bind(&MessageLoopThreadTest::ShouldNotHappen,
+                            base::Unretained(this))));
+}
+
+TEST_F(MessageLoopThreadTest, test_name) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  ASSERT_GE(message_loop_thread.GetThreadId(), 0);
+  std::promise<std::string> name_promise;
+  std::future<std::string> name_future = name_promise.get_future();
+  message_loop_thread.DoInThread(
+      FROM_HERE,
+      base::BindOnce(&MessageLoopThreadTest::GetName, base::Unretained(this),
+                     std::move(name_promise)));
+  std::string my_name = name_future.get();
+  ASSERT_EQ(name, my_name);
+  ASSERT_EQ(name, message_loop_thread.GetName());
+}
+
+TEST_F(MessageLoopThreadTest, test_thread_id) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  base::PlatformThreadId thread_id = message_loop_thread.GetThreadId();
+  ASSERT_GE(thread_id, 0);
+  std::promise<base::PlatformThreadId> thread_id_promise;
+  std::future<base::PlatformThreadId> thread_id_future =
+      thread_id_promise.get_future();
+  message_loop_thread.DoInThread(
+      FROM_HERE,
+      base::BindOnce(&MessageLoopThreadTest::GetThreadId,
+                     base::Unretained(this), std::move(thread_id_promise)));
+  base::PlatformThreadId my_thread_id = thread_id_future.get();
+  ASSERT_EQ(thread_id, my_thread_id);
+}
+
+TEST_F(MessageLoopThreadTest, test_set_realtime_priority_fail_before_start) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  ASSERT_FALSE(message_loop_thread.EnableRealTimeScheduling());
+}
+
+TEST_F(MessageLoopThreadTest, test_set_realtime_priority_success) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  bool ret = message_loop_thread.EnableRealTimeScheduling();
+  if (!ret) {
+    if (CanSetCurrentThreadPriority()) {
+      FAIL() << "Cannot set real time priority even though we have permission";
+    } else {
+      LOG(WARNING) << "Allowing EnableRealTimeScheduling to fail because we"
+                      " don't have CAP_SYS_NICE capability";
+      // Log record in XML
+      RecordProperty("MessageLoopThreadTestConditionalSuccess",
+                     "Mark test as success even though EnableRealTimeScheduling"
+                     " failed because we don't have CAP_SYS_NICE capability");
+      // Quit early since further verification is no longer needed
+      return;
+    }
+  }
+  std::promise<void> execution_promise;
+  std::future<void> execution_future = execution_promise.get_future();
+  int scheduling_policy = -1;
+  int scheduling_priority = -1;
+  message_loop_thread.DoInThread(
+      FROM_HERE,
+      base::BindOnce(&MessageLoopThreadTest::GetSchedulingPolicyAndPriority,
+                     base::Unretained(this), &scheduling_policy,
+                     &scheduling_priority, std::move(execution_promise)));
+  execution_future.wait();
+  ASSERT_EQ(scheduling_policy, SCHED_FIFO);
+  // Internal implementation verified here
+  ASSERT_EQ(scheduling_priority, 1);
+  std::promise<pid_t> tid_promise;
+  std::future<pid_t> tid_future = tid_promise.get_future();
+  message_loop_thread.DoInThread(
+      FROM_HERE,
+      base::BindOnce(&MessageLoopThreadTest::GetLinuxTid,
+                     base::Unretained(this), std::move(tid_promise)));
+  pid_t linux_tid = tid_future.get();
+  ASSERT_GT(linux_tid, 0);
+  ASSERT_EQ(sched_getscheduler(linux_tid), SCHED_FIFO);
+  struct sched_param param = {};
+  ASSERT_EQ(sched_getparam(linux_tid, &param), 0);
+  // Internal implementation verified here
+  ASSERT_EQ(param.sched_priority, 1);
+}
+
+TEST_F(MessageLoopThreadTest, test_message_loop_null_before_start) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  ASSERT_EQ(message_loop_thread.message_loop(), nullptr);
+}
+
+TEST_F(MessageLoopThreadTest, test_message_loop_not_null_start) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  ASSERT_NE(message_loop_thread.message_loop(), nullptr);
+}
+
+TEST_F(MessageLoopThreadTest, test_message_loop_null_after_stop) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  ASSERT_NE(message_loop_thread.message_loop(), nullptr);
+  message_loop_thread.ShutDown();
+  ASSERT_EQ(message_loop_thread.message_loop(), nullptr);
+}
+
+TEST_F(MessageLoopThreadTest, test_to_string_method) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  std::string thread_string_before_start = message_loop_thread.ToString();
+  ASSERT_FALSE(thread_string_before_start.empty());
+  LOG(INFO) << "Before start: " << message_loop_thread;
+  message_loop_thread.StartUp();
+  std::string thread_string_running = message_loop_thread.ToString();
+  ASSERT_FALSE(thread_string_running.empty());
+  LOG(INFO) << "Running: " << message_loop_thread;
+  // String representation should look different when thread is not running
+  ASSERT_STRNE(thread_string_running.c_str(),
+               thread_string_before_start.c_str());
+  message_loop_thread.ShutDown();
+  std::string thread_string_after_shutdown = message_loop_thread.ToString();
+  LOG(INFO) << "After shutdown: " << message_loop_thread;
+  // String representation should look the same when thread is not running
+  ASSERT_STREQ(thread_string_after_shutdown.c_str(),
+               thread_string_before_start.c_str());
+}
+
+// Verify the message loop thread will shutdown after callback finishes
+TEST_F(MessageLoopThreadTest, shut_down_while_in_callback) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  std::promise<std::string> name_promise;
+  std::future<std::string> name_future = name_promise.get_future();
+  uint32_t delay_ms = 5;
+  message_loop_thread.DoInThread(
+      FROM_HERE, base::BindOnce(&MessageLoopThreadTest::SleepAndGetName,
+                                base::Unretained(this), std::move(name_promise),
+                                delay_ms));
+  message_loop_thread.ShutDown();
+  std::string my_name = name_future.get();
+  ASSERT_EQ(name, my_name);
+}
+
+// Verify the message loop thread will shutdown after callback finishes
+TEST_F(MessageLoopThreadTest, shut_down_while_in_callback_check_lock) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  message_loop_thread.DoInThread(
+      FROM_HERE,
+      base::BindOnce([](MessageLoopThread* thread) { thread->IsRunning(); },
+                     &message_loop_thread));
+  message_loop_thread.ShutDown();
+}
+
+// Verify multiple threads try shutdown, no deadlock/crash
+TEST_F(MessageLoopThreadTest, shut_down_multi_thread) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  auto thread = std::thread(&MessageLoopThread::ShutDown, &message_loop_thread);
+  message_loop_thread.ShutDown();
+  thread.join();
+}
+
+// Verify multiple threads try startup, no deadlock/crash
+TEST_F(MessageLoopThreadTest, start_up_multi_thread) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  auto thread = std::thread(&MessageLoopThread::StartUp, &message_loop_thread);
+  thread.join();
+}
+
+// Verify multiple threads try startup/shutdown, no deadlock/crash
+TEST_F(MessageLoopThreadTest, start_up_shut_down_multi_thread) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  auto thread = std::thread(&MessageLoopThread::ShutDown, &message_loop_thread);
+  thread.join();
+}
+
+// Verify multiple threads try shutdown/startup, no deadlock/crash
+TEST_F(MessageLoopThreadTest, shut_down_start_up_multi_thread) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  message_loop_thread.ShutDown();
+  auto thread = std::thread(&MessageLoopThread::StartUp, &message_loop_thread);
+  thread.join();
+}
diff --git a/osi/src/metrics.cc b/common/metrics.cc
similarity index 60%
rename from osi/src/metrics.cc
rename to common/metrics.cc
index 73450b9..4550eeb 100644
--- a/osi/src/metrics.cc
+++ b/common/metrics.cc
@@ -15,7 +15,6 @@
  *  limitations under the License.
  *
  ******************************************************************************/
-#define LOG_TAG "bt_osi_metrics"
 
 #include <unistd.h>
 #include <algorithm>
@@ -30,17 +29,20 @@
 #include <base/base64.h>
 #include <base/logging.h>
 #include <include/hardware/bt_av.h>
+#include <statslog.h>
 
 #include "bluetooth/metrics/bluetooth.pb.h"
-#include "osi/include/leaky_bonded_queue.h"
-#include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "osi/include/time.h"
 #include "stack/include/btm_api_types.h"
 
-#include "osi/include/metrics.h"
+#include "address_obfuscator.h"
+#include "leaky_bonded_queue.h"
+#include "metrics.h"
+#include "time_util.h"
 
-namespace system_bt_osi {
+namespace bluetooth {
+
+namespace common {
 
 using bluetooth::metrics::BluetoothMetricsProto::A2DPSession;
 using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec;
@@ -52,24 +54,18 @@
     BluetoothSession_DisconnectReasonType;
 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo;
 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType;
-using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
-using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
-using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
-using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
-using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
-using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
-using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
-using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_ARRAYSIZE;
 using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_IsValid;
-using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
-/*
- * Get current OS boot time in millisecond
- */
-static int64_t time_get_os_boottime_ms(void) {
-  return time_get_os_boottime_us() / 1000;
-}
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MAX;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType_MIN;
+using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
+using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
+using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
 
 static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
                               int64_t ct_b) {
@@ -359,7 +355,7 @@
                            0);
   }
   if (timestamp_ms == 0) {
-    timestamp_ms = time_get_os_boottime_ms();
+    timestamp_ms = bluetooth::common::time_get_os_boottime_ms();
   }
   pimpl_->bluetooth_session_start_time_ms_ = timestamp_ms;
   pimpl_->bluetooth_session_ = new BluetoothSession();
@@ -374,7 +370,7 @@
     return;
   }
   if (timestamp_ms == 0) {
-    timestamp_ms = time_get_os_boottime_ms();
+    timestamp_ms = bluetooth::common::time_get_os_boottime_ms();
   }
   int64_t session_duration_sec =
       (timestamp_ms - pimpl_->bluetooth_session_start_time_ms_) / 1000;
@@ -458,11 +454,11 @@
 
 void BluetoothMetricsLogger::WriteString(std::string* serialized) {
   std::lock_guard<std::recursive_mutex> lock(pimpl_->bluetooth_log_lock_);
-  LOG_DEBUG(LOG_TAG, "%s building metrics", __func__);
+  LOG(INFO) << __func__ << ": building metrics";
   Build();
-  LOG_DEBUG(LOG_TAG, "%s serializing metrics", __func__);
+  LOG(INFO) << __func__ << ": serializing metrics";
   if (!pimpl_->bluetooth_log_->SerializeToString(serialized)) {
-    LOG_ERROR(LOG_TAG, "%s: error serializing metrics", __func__);
+    LOG(ERROR) << __func__ << ": error serializing metrics";
   }
   // Always clean up log objects
   pimpl_->bluetooth_log_->Clear();
@@ -479,8 +475,9 @@
   ssize_t ret;
   OSI_NO_INTR(ret = write(fd, protoBase64.c_str(), protoBase64.size()));
   if (ret == -1) {
-    LOG_ERROR(LOG_TAG, "%s: error writing to dumpsys fd: %s (%d)", __func__,
-              strerror(errno), errno);
+    LOG(ERROR) << __func__
+               << ": error writing to dumpsys fd: " << strerror(errno) << " ("
+               << std::to_string(errno) << ")";
   }
 }
 
@@ -493,7 +490,8 @@
     new_bt_session->clear_rfcomm_session();
     LogBluetoothSessionEnd(DISCONNECT_REASON_METRICS_DUMP, 0);
     pimpl_->bluetooth_session_ = new_bt_session;
-    pimpl_->bluetooth_session_start_time_ms_ = time_get_os_boottime_ms();
+    pimpl_->bluetooth_session_start_time_ms_ =
+        bluetooth::common::time_get_os_boottime_ms();
     pimpl_->a2dp_session_metrics_ = A2dpSessionMetrics();
   }
 }
@@ -571,4 +569,290 @@
   pimpl_->scan_event_queue_->Clear();
 }
 
-}  // namespace system_bt_osi
+void LogLinkLayerConnectionEvent(const RawAddress* address,
+                                 uint32_t connection_handle,
+                                 android::bluetooth::DirectionEnum direction,
+                                 uint16_t link_type, uint32_t hci_cmd,
+                                 uint16_t hci_event, uint16_t hci_ble_event,
+                                 uint16_t cmd_status, uint16_t reason_code) {
+  std::string obfuscated_id;
+  if (address != nullptr) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(*address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address != nullptr ? obfuscated_id.c_str() : nullptr,
+      address != nullptr ? obfuscated_id.size() : 0);
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_LINK_LAYER_CONNECTION_EVENT, bytes_field,
+      connection_handle, direction, link_type, hci_cmd, hci_event,
+      hci_ble_event, cmd_status, reason_code);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed to log status " << loghex(cmd_status)
+                 << ", reason " << loghex(reason_code) << " from cmd "
+                 << loghex(hci_cmd) << ", event " << loghex(hci_event)
+                 << ", ble_event " << loghex(hci_ble_event) << " for "
+                 << address << ", handle " << connection_handle << ", type "
+                 << loghex(link_type) << ", error " << ret;
+  }
+}
+
+void LogHciTimeoutEvent(uint32_t hci_cmd) {
+  int ret =
+      android::util::stats_write(android::util::BLUETOOTH_HCI_TIMEOUT_REPORTED,
+                                 static_cast<int64_t>(hci_cmd));
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for opcode " << loghex(hci_cmd)
+                 << ", error " << ret;
+  }
+}
+
+void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
+                          uint16_t manufacturer_name, uint16_t subversion) {
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_REMOTE_VERSION_INFO_REPORTED, handle, status,
+      version, manufacturer_name, subversion);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for handle " << handle << ", status "
+                 << loghex(status) << ", version " << loghex(version)
+                 << ", manufacturer_name " << loghex(manufacturer_name)
+                 << ", subversion " << loghex(subversion) << ", error " << ret;
+  }
+}
+
+void LogA2dpAudioUnderrunEvent(const RawAddress& address,
+                               uint64_t encoding_interval_millis,
+                               int num_missing_pcm_bytes) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_A2DP_AUDIO_UNDERRUN_REPORTED, bytes_field,
+      encoding_interval_nanos, num_missing_pcm_bytes);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address
+                 << ", encoding_interval_nanos " << encoding_interval_nanos
+                 << ", num_missing_pcm_bytes " << num_missing_pcm_bytes
+                 << ", error " << ret;
+  }
+}
+
+void LogA2dpAudioOverrunEvent(const RawAddress& address,
+                              uint64_t encoding_interval_millis,
+                              int num_dropped_buffers,
+                              int num_dropped_encoded_frames,
+                              int num_dropped_encoded_bytes) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int64_t encoding_interval_nanos = encoding_interval_millis * 1000000;
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_A2DP_AUDIO_OVERRUN_REPORTED, bytes_field,
+      encoding_interval_nanos, num_dropped_buffers, num_dropped_encoded_frames,
+      num_dropped_encoded_bytes);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed to log for " << address
+                 << ", encoding_interval_nanos " << encoding_interval_nanos
+                 << ", num_dropped_buffers " << num_dropped_buffers
+                 << ", num_dropped_encoded_frames "
+                 << num_dropped_encoded_frames << ", num_dropped_encoded_bytes "
+                 << num_dropped_encoded_bytes << ", error " << ret;
+  }
+}
+
+void LogReadRssiResult(const RawAddress& address, uint16_t handle,
+                       uint32_t cmd_status, int8_t rssi) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret =
+      android::util::stats_write(android::util::BLUETOOTH_DEVICE_RSSI_REPORTED,
+                                 bytes_field, handle, cmd_status, rssi);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
+                 << handle << ", status " << loghex(cmd_status) << ", rssi "
+                 << rssi << " dBm, error " << ret;
+  }
+}
+
+void LogReadFailedContactCounterResult(const RawAddress& address,
+                                       uint16_t handle, uint32_t cmd_status,
+                                       int32_t failed_contact_counter) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_DEVICE_FAILED_CONTACT_COUNTER_REPORTED,
+      bytes_field, handle, cmd_status, failed_contact_counter);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
+                 << handle << ", status " << loghex(cmd_status)
+                 << ", failed_contact_counter " << failed_contact_counter
+                 << " packets, error " << ret;
+  }
+}
+
+void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle,
+                               uint32_t cmd_status,
+                               int32_t transmit_power_level) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField bytes_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_DEVICE_TX_POWER_LEVEL_REPORTED, bytes_field,
+      handle, cmd_status, transmit_power_level);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle "
+                 << handle << ", status " << loghex(cmd_status)
+                 << ", transmit_power_level " << transmit_power_level
+                 << " packets, error " << ret;
+  }
+}
+
+void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
+                        android::bluetooth::DirectionEnum direction,
+                        uint8_t smp_fail_reason) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField obfuscated_id_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_SMP_PAIRING_EVENT_REPORTED, obfuscated_id_field,
+      smp_cmd, direction, smp_fail_reason);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", smp_cmd "
+                 << loghex(smp_cmd) << ", direction " << direction
+                 << ", smp_fail_reason " << loghex(smp_fail_reason)
+                 << ", error " << ret;
+  }
+}
+
+void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, uint16_t hci_event,
+                            uint16_t cmd_status, uint16_t reason_code, int64_t event_value) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField obfuscated_id_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(android::util::BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED, obfuscated_id_field,
+                                       handle, hci_cmd, hci_event, cmd_status, reason_code, event_value);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", handle " << handle << ", hci_cmd " << loghex(hci_cmd)
+                 << ", hci_event " << loghex(hci_event) << ", cmd_status " << loghex(cmd_status) << ", reason "
+                 << loghex(reason_code) << ", event_value " << event_value << ", error " << ret;
+  }
+}
+
+void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid,
+                     uint16_t attribute_id, size_t attribute_size,
+                     const char* attribute_value) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField obfuscated_id_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  android::util::BytesField attribute_field(attribute_value, attribute_size);
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_SDP_ATTRIBUTE_REPORTED, obfuscated_id_field,
+      protocol_uuid, attribute_id, attribute_field);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", protocol_uuid "
+                 << loghex(protocol_uuid) << ", attribute_id "
+                 << loghex(attribute_id) << ", error " << ret;
+  }
+}
+
+void LogSocketConnectionState(
+    const RawAddress& address, int port, int type,
+    android::bluetooth::SocketConnectionstateEnum connection_state,
+    int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
+    android::bluetooth::SocketRoleEnum socket_role) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField obfuscated_id_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_SOCKET_CONNECTION_STATE_CHANGED,
+      obfuscated_id_field, port, type, connection_state, tx_bytes, rx_bytes,
+      uid, server_port, socket_role);
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", port " << port
+                 << ", type " << type << ", state " << connection_state
+                 << ", tx_bytes " << tx_bytes << ", rx_bytes " << rx_bytes
+                 << ", uid " << uid << ", server_port " << server_port
+                 << ", socket_role " << socket_role << ", error " << ret;
+  }
+}
+
+void LogManufacturerInfo(const RawAddress& address,
+                         android::bluetooth::DeviceInfoSrcEnum source_type,
+                         const std::string& source_name,
+                         const std::string& manufacturer,
+                         const std::string& model,
+                         const std::string& hardware_version,
+                         const std::string& software_version) {
+  std::string obfuscated_id;
+  if (!address.IsEmpty()) {
+    obfuscated_id = AddressObfuscator::GetInstance()->Obfuscate(address);
+  }
+  // nullptr and size 0 represent missing value for obfuscated_id
+  android::util::BytesField obfuscated_id_field(
+      address.IsEmpty() ? nullptr : obfuscated_id.c_str(),
+      address.IsEmpty() ? 0 : obfuscated_id.size());
+  int ret = android::util::stats_write(
+      android::util::BLUETOOTH_DEVICE_INFO_REPORTED, obfuscated_id_field,
+      source_type, source_name.c_str(), manufacturer.c_str(), model.c_str(),
+      hardware_version.c_str(), software_version.c_str());
+  if (ret < 0) {
+    LOG(WARNING) << __func__ << ": failed for " << address << ", source_type "
+                 << source_type << ", source_name " << source_name
+                 << ", manufacturer " << manufacturer << ", model " << model
+                 << ", hardware_version " << hardware_version
+                 << ", software_version " << software_version << ", error "
+                 << ret;
+  }
+}
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/metrics.h b/common/metrics.h
new file mode 100644
index 0000000..8d83cac
--- /dev/null
+++ b/common/metrics.h
@@ -0,0 +1,484 @@
+/******************************************************************************
+ *
+ *  Copyright 2016 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <android/bluetooth/hci/enums.pb.h>
+#include <bta/include/bta_api.h>
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
+#include <stdint.h>
+#include <memory>
+#include <string>
+
+namespace bluetooth {
+
+namespace common {
+
+// Typedefs to hide protobuf definition to the rest of stack
+
+typedef enum {
+  DEVICE_TYPE_UNKNOWN,
+  DEVICE_TYPE_BREDR,
+  DEVICE_TYPE_LE,
+  DEVICE_TYPE_DUMO,
+} device_type_t;
+
+typedef enum {
+  WAKE_EVENT_UNKNOWN,
+  WAKE_EVENT_ACQUIRED,
+  WAKE_EVENT_RELEASED,
+} wake_event_type_t;
+
+typedef enum {
+  SCAN_TYPE_UNKNOWN,
+  SCAN_TECH_TYPE_LE,
+  SCAN_TECH_TYPE_BREDR,
+  SCAN_TECH_TYPE_BOTH,
+} scan_tech_t;
+
+typedef enum {
+  CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
+  CONNECTION_TECHNOLOGY_TYPE_LE,
+  CONNECTION_TECHNOLOGY_TYPE_BREDR,
+} connection_tech_t;
+
+typedef enum {
+  DISCONNECT_REASON_UNKNOWN,
+  DISCONNECT_REASON_METRICS_DUMP,
+  DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
+} disconnect_reason_t;
+
+/* Values of A2DP metrics that we care about
+ *
+ *    audio_duration_ms : sum of audio duration (in milliseconds).
+ *    device_class: device class of the paired device.
+ *    media_timer_min_ms : minimum scheduled time (in milliseconds)
+ *                         of the media timer.
+ *    media_timer_max_ms: maximum scheduled time (in milliseconds)
+ *                        of the media timer.
+ *    media_timer_avg_ms: average scheduled time (in milliseconds)
+ *                        of the media timer.
+ *    buffer_overruns_max_count: TODO - not clear what this is.
+ *    buffer_overruns_total : number of times the media buffer with
+ *                            audio data has overrun
+ *    buffer_underruns_average: TODO - not clear what this is.
+ *    buffer_underruns_count: number of times there was no enough
+ *                            audio data to add to the media buffer.
+ * NOTE: Negative values are invalid
+ */
+class A2dpSessionMetrics {
+ public:
+  A2dpSessionMetrics() {}
+
+  /*
+   * Update the metrics value in the current metrics object using the metrics
+   * objects supplied
+   */
+  void Update(const A2dpSessionMetrics& metrics);
+
+  /*
+   * Compare whether two metrics objects are equal
+   */
+  bool operator==(const A2dpSessionMetrics& rhs) const;
+
+  /*
+   * Initialize all values to -1 which is invalid in order to make a distinction
+   * between 0 and invalid values
+   */
+  int64_t audio_duration_ms = -1;
+  int32_t media_timer_min_ms = -1;
+  int32_t media_timer_max_ms = -1;
+  int32_t media_timer_avg_ms = -1;
+  int64_t total_scheduling_count = -1;
+  int32_t buffer_overruns_max_count = -1;
+  int32_t buffer_overruns_total = -1;
+  float buffer_underruns_average = -1;
+  int32_t buffer_underruns_count = -1;
+  int64_t codec_index = -1;
+  bool is_a2dp_offload = false;
+};
+
+class BluetoothMetricsLogger {
+ public:
+  static BluetoothMetricsLogger* GetInstance() {
+    static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger();
+    return instance;
+  }
+
+  /*
+   * Record a pairing event
+   *
+   * Parameters:
+   *    timestamp_ms: Unix epoch time in milliseconds
+   *    device_class: class of remote device
+   *    device_type: type of remote device
+   *    disconnect_reason: HCI reason for pairing disconnection.
+   *                       See: stack/include/hcidefs.h
+   */
+  void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms,
+                    uint32_t device_class, device_type_t device_type);
+
+  /*
+   * Record a wake event
+   *
+   * Parameters:
+   *    timestamp_ms: Unix epoch time in milliseconds
+   *    type: whether it was acquired or released
+   *    requestor: if provided is the service requesting the wake lock
+   *    name: the name of the wake lock held
+   */
+  void LogWakeEvent(wake_event_type_t type, const std::string& requestor,
+                    const std::string& name, uint64_t timestamp_ms);
+
+  /*
+   * Record a scan event
+   *
+   * Parameters
+   *    timestamp_ms : Unix epoch time in milliseconds
+   *    start : true if this is the beginning of the scan
+   *    initiator: a unique ID identifying the app starting the scan
+   *    type: whether the scan reports BR/EDR, LE, or both.
+   *    results: number of results to be reported.
+   */
+  void LogScanEvent(bool start, const std::string& initator, scan_tech_t type,
+                    uint32_t results, uint64_t timestamp_ms);
+
+  /*
+   * Start logging a Bluetooth session
+   *
+   * A Bluetooth session is defined a a connection between this device and
+   * another remote device which may include multiple profiles and protocols
+   *
+   * Only one Bluetooth session can exist at one time. Calling this method twice
+   * without LogBluetoothSessionEnd will result in logging a premature end of
+   * current Bluetooth session
+   *
+   * Parameters:
+   *    connection_tech_type : type of connection technology
+   *    timestamp_ms : the timestamp for session start, 0 means now
+   *
+   */
+  void LogBluetoothSessionStart(connection_tech_t connection_tech_type,
+                                uint64_t timestamp_ms);
+
+  /*
+   * Stop logging a Bluetooth session and pushes it to the log queue
+   *
+   * If no Bluetooth session exist, this method exits immediately
+   *
+   * Parameters:
+   *    disconnect_reason : A string representation of disconnect reason
+   *    timestamp_ms : the timestamp of session end, 0 means now
+   *
+   */
+  void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
+                              uint64_t timestamp_ms);
+
+  /*
+   * Log information about remote device in a current Bluetooth session
+   *
+   * If a Bluetooth session does not exist, create one with default parameter
+   * and timestamp now
+   *
+   * Parameters:
+   *    device_class : device_class defined in btm_api_types.h
+   *    device_type : type of remote device
+   */
+  void LogBluetoothSessionDeviceInfo(uint32_t device_class,
+                                     device_type_t device_type);
+
+  /*
+   * Log A2DP Audio Session Information
+   *
+   * - Repeated calls to this method will override previous metrics if in the
+   *   same Bluetooth connection
+   * - If a Bluetooth session does not exist, create one with default parameter
+   *   and timestamp now
+   *
+   * Parameters:
+   *    a2dp_session_metrics - pointer to struct holding a2dp stats
+   *
+   */
+  void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
+
+  /**
+   * Log Headset profile RFCOMM connection event
+   *
+   * @param service_id the BTA service ID for this headset connection
+   */
+  void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);
+
+  /*
+   * Writes the metrics, in base64 protobuf format, into the descriptor FD,
+   * metrics events are always cleared after dump
+   */
+  void WriteBase64(int fd);
+  void WriteBase64String(std::string* serialized);
+  void WriteString(std::string* serialized);
+
+  /*
+   * Reset the metrics logger by cleaning up its staging queues and existing
+   * protobuf objects.
+   */
+  void Reset();
+
+  /*
+   * Maximum number of log entries for each session or event
+   */
+  static const size_t kMaxNumBluetoothSession = 50;
+  static const size_t kMaxNumPairEvent = 50;
+  static const size_t kMaxNumWakeEvent = 1000;
+  static const size_t kMaxNumScanEvent = 50;
+
+ private:
+  BluetoothMetricsLogger();
+
+  /*
+   * When a Bluetooth session is on and the user initiates a metrics dump, we
+   * need to be able to upload whatever we have first. This method breaks the
+   * ongoing Bluetooth session into two sessions with the previous one labeled
+   * as "METRICS_DUMP" for the disconnect reason.
+   */
+  void CutoffSession();
+
+  /*
+   * Build the internal metrics object using information gathered
+   */
+  void Build();
+
+  /*
+   * Reset objects related to current Bluetooth session
+   */
+  void ResetSession();
+
+  /*
+   * Reset the underlining BluetoothLog object
+   */
+  void ResetLog();
+
+  /*
+   * PIMPL style implementation to hide internal dependencies
+   */
+  struct impl;
+  std::unique_ptr<impl> const pimpl_;
+};
+
+/**
+ * Unknown connection handle for metrics purpose
+ */
+static const uint32_t kUnknownConnectionHandle = 0xFFFF;
+
+/**
+ * Log link layer connection event
+ *
+ * @param address Stack wide consistent Bluetooth address of this event,
+ *                nullptr if unknown
+ * @param connection_handle connection handle of this event,
+ *                          {@link kUnknownConnectionHandle} if unknown
+ * @param direction direction of this connection
+ * @param link_type type of the link
+ * @param hci_cmd HCI command opecode associated with this event, if any
+ * @param hci_event HCI event code associated with this event, if any
+ * @param hci_ble_event HCI BLE event code associated with this event, if any
+ * @param cmd_status Command status associated with this event, if any
+ * @param reason_code Reason code associated with this event, if any
+ */
+void LogLinkLayerConnectionEvent(const RawAddress* address,
+                                 uint32_t connection_handle,
+                                 android::bluetooth::DirectionEnum direction,
+                                 uint16_t link_type, uint32_t hci_cmd,
+                                 uint16_t hci_event, uint16_t hci_ble_event,
+                                 uint16_t cmd_status, uint16_t reason_code);
+
+/**
+ * Logs when Bluetooth controller failed to reply with command status within
+ * a timeout period after receiving an HCI command from the host
+ *
+ * @param hci_cmd opcode of HCI command that caused this timeout
+ */
+void LogHciTimeoutEvent(uint32_t hci_cmd);
+
+/**
+ * Logs when we receive Bluetooth Read Remote Version Information Complete
+ * Event from the remote device, as documented by the Bluetooth Core HCI
+ * specification
+ *
+ * Reference: 5.0 Core Specification, Vol 2, Part E, Page 1118
+ *
+ * @param handle handle of associated ACL connection
+ * @param status HCI command status of this event
+ * @param version version code from read remote version complete event
+ * @param manufacturer_name manufacturer code from read remote version complete
+ *                          event
+ * @param subversion subversion code from read remote version complete event
+ */
+void LogRemoteVersionInfo(uint16_t handle, uint8_t status, uint8_t version,
+                          uint16_t manufacturer_name, uint16_t subversion);
+
+/**
+ * Log A2DP audio buffer underrun event
+ *
+ * @param address A2DP device associated with this event
+ * @param encoding_interval_millis encoding interval in milliseconds
+ * @param num_missing_pcm_bytes number of PCM bytes that cannot be read from
+ *                              the source
+ */
+void LogA2dpAudioUnderrunEvent(const RawAddress& address,
+                               uint64_t encoding_interval_millis,
+                               int num_missing_pcm_bytes);
+
+/**
+ * Log A2DP audio buffer overrun event
+ *
+ * @param address A2DP device associated with this event
+ * @param encoding_interval_millis encoding interval in milliseconds
+ * @param num_dropped_buffers number of encoded buffers dropped from Tx queue
+ * @param num_dropped_encoded_frames number of encoded frames dropped from Tx
+ *                                   queue
+ * @param num_dropped_encoded_bytes number of encoded bytes dropped from Tx
+ *                                  queue
+ */
+void LogA2dpAudioOverrunEvent(const RawAddress& address,
+                              uint64_t encoding_interval_millis,
+                              int num_dropped_buffers,
+                              int num_dropped_encoded_frames,
+                              int num_dropped_encoded_bytes);
+
+/**
+ * Log read RSSI result
+ *
+ * @param address device associated with this event
+ * @param handle connection handle of this event,
+ *               {@link kUnknownConnectionHandle} if unknown
+ * @param cmd_status command status from read RSSI command
+ * @param rssi rssi value in dBm
+ */
+void LogReadRssiResult(const RawAddress& address, uint16_t handle,
+                       uint32_t cmd_status, int8_t rssi);
+
+/**
+ * Log failed contact counter report
+ *
+ * @param address device associated with this event
+ * @param handle connection handle of this event,
+ *               {@link kUnknownConnectionHandle} if unknown
+ * @param cmd_status command status from read failed contact counter command
+ * @param failed_contact_counter Number of consecutive failed contacts for a
+ *                               connection corresponding to the Handle
+ */
+void LogReadFailedContactCounterResult(const RawAddress& address,
+                                       uint16_t handle, uint32_t cmd_status,
+                                       int32_t failed_contact_counter);
+
+/**
+ * Log transmit power level for a particular device after read
+ *
+ * @param address device associated with this event
+ * @param handle connection handle of this event,
+ *               {@link kUnknownConnectionHandle} if unknown
+ * @param cmd_status command status from read failed contact counter command
+ * @param transmit_power_level transmit power level for connection to this
+ *                             device
+ */
+void LogReadTxPowerLevelResult(const RawAddress& address, uint16_t handle,
+                               uint32_t cmd_status,
+                               int32_t transmit_power_level);
+
+/**
+ * Logs when there is an event related to Bluetooth Security Manager Protocol
+ *
+ * @param address address of associated device
+ * @param smp_cmd SMP command code associated with this event
+ * @param direction direction of this SMP command
+ * @param smp_fail_reason SMP pairing failure reason code from SMP spec
+ */
+void LogSmpPairingEvent(const RawAddress& address, uint8_t smp_cmd,
+                        android::bluetooth::DirectionEnum direction,
+                        uint8_t smp_fail_reason);
+
+/**
+ * Logs there is an event related Bluetooth classic pairing
+ *
+ * @param address address of associated device
+ * @param handle connection handle of this event,
+ *               {@link kUnknownConnectionHandle} if unknown
+ * @param hci_cmd HCI command associated with this event
+ * @param hci_event HCI event associated with this event
+ * @param cmd_status Command status associated with this event
+ * @param reason_code Reason code associated with this event
+ * @param event_value A status value related to this specific event
+ */
+void LogClassicPairingEvent(const RawAddress& address, uint16_t handle, uint32_t hci_cmd, uint16_t hci_event,
+                            uint16_t cmd_status, uint16_t reason_code, int64_t event_value);
+
+/**
+ * Logs when certain Bluetooth SDP attributes are discovered
+ *
+ * @param address address of associated device
+ * @param protocol_uuid 16 bit protocol UUID from Bluetooth Assigned Numbers
+ * @param attribute_id 16 bit attribute ID from Bluetooth Assigned Numbers
+ * @param attribute_size size of this attribute
+ * @param attribute_value pointer to the attribute data, must be larger than
+ *                        attribute_size
+ */
+void LogSdpAttribute(const RawAddress& address, uint16_t protocol_uuid,
+                     uint16_t attribute_id, size_t attribute_size,
+                     const char* attribute_value);
+
+/**
+ * Logs when there is a change in Bluetooth socket connection state
+ *
+ * @param address address of associated device, empty if this is a server port
+ * @param port port of this socket connection
+ * @param type type of socket
+ * @param connection_state socket connection state
+ * @param tx_bytes number of bytes transmitted
+ * @param rx_bytes number of bytes received
+ * @param server_port server port of this socket, if any. When both
+ *        |server_port| and |port| fields are populated, |port| must be spawned
+ *        by |server_port|
+ * @param socket_role role of this socket, server or connection
+ * @param uid socket owner's uid
+ */
+void LogSocketConnectionState(
+    const RawAddress& address, int port, int type,
+    android::bluetooth::SocketConnectionstateEnum connection_state,
+    int64_t tx_bytes, int64_t rx_bytes, int uid, int server_port,
+    android::bluetooth::SocketRoleEnum socket_role);
+
+/**
+ * Logs when a Bluetooth device's manufacturer information is learnt
+ *
+ * @param address address of associated device
+ * @param source_type where is this device info obtained from
+ * @param source_name name of the data source, internal or external
+ * @param manufacturer name of the manufacturer of this device
+ * @param model model of this device
+ * @param hardware_version hardware version of this device
+ * @param software_version software version of this device
+ */
+void LogManufacturerInfo(const RawAddress& address,
+                         android::bluetooth::DeviceInfoSrcEnum source_type,
+                         const std::string& source_name,
+                         const std::string& manufacturer,
+                         const std::string& model,
+                         const std::string& hardware_version,
+                         const std::string& software_version);
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/metrics_linux.cc b/common/metrics_linux.cc
new file mode 100644
index 0000000..bf16960
--- /dev/null
+++ b/common/metrics_linux.cc
@@ -0,0 +1,93 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "metrics.h"
+
+#include <base/logging.h>
+
+#include "leaky_bonded_queue.h"
+
+namespace bluetooth {
+
+namespace common {
+
+void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {}
+
+bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
+  LOG(FATAL) << "UNIMPLEMENTED";
+  return 0;
+}
+
+struct BluetoothMetricsLogger::impl {
+  impl(size_t max_bluetooth_session, size_t max_pair_event,
+       size_t max_wake_event, size_t max_scan_event) {}
+};
+
+BluetoothMetricsLogger::BluetoothMetricsLogger()
+    : pimpl_(new impl(kMaxNumBluetoothSession, kMaxNumPairEvent,
+                      kMaxNumWakeEvent, kMaxNumScanEvent)) {}
+
+void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
+                                          uint64_t timestamp_ms,
+                                          uint32_t device_class,
+                                          device_type_t device_type) {}
+
+void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
+                                          const std::string& requestor,
+                                          const std::string& name,
+                                          uint64_t timestamp_ms) {}
+
+void BluetoothMetricsLogger::LogScanEvent(bool start,
+                                          const std::string& initator,
+                                          scan_tech_t type, uint32_t results,
+                                          uint64_t timestamp_ms) {}
+
+void BluetoothMetricsLogger::LogBluetoothSessionStart(
+    connection_tech_t connection_tech_type, uint64_t timestamp_ms) {}
+
+void BluetoothMetricsLogger::LogBluetoothSessionEnd(
+    disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {}
+
+void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
+    uint32_t device_class, device_type_t device_type) {}
+
+void BluetoothMetricsLogger::LogA2dpSession(
+    const A2dpSessionMetrics& a2dp_session_metrics) {}
+
+void BluetoothMetricsLogger::LogHeadsetProfileRfcConnection(
+    tBTA_SERVICE_ID service_id) {}
+
+void BluetoothMetricsLogger::WriteString(std::string* serialized) {}
+
+void BluetoothMetricsLogger::WriteBase64String(std::string* serialized) {}
+
+void BluetoothMetricsLogger::WriteBase64(int fd) {}
+
+void BluetoothMetricsLogger::CutoffSession() {}
+
+void BluetoothMetricsLogger::Build() {}
+
+void BluetoothMetricsLogger::ResetSession() {}
+
+void BluetoothMetricsLogger::ResetLog() {}
+
+void BluetoothMetricsLogger::Reset() {}
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/osi/test/metrics_test.cc b/common/metrics_unittest.cc
similarity index 94%
rename from osi/test/metrics_test.cc
rename to common/metrics_unittest.cc
index bfb548f..03a427a 100644
--- a/osi/test/metrics_test.cc
+++ b/common/metrics_unittest.cc
@@ -28,13 +28,15 @@
 #include <include/hardware/bt_av.h>
 
 #include "bluetooth/metrics/bluetooth.pb.h"
-#include "osi/include/metrics.h"
-#include "osi/include/time.h"
+#include "common/metrics.h"
+#include "common/time_util.h"
 
 #define BTM_COD_MAJOR_AUDIO_TEST 0x04
 
 namespace testing {
 
+using bluetooth::common::A2dpSessionMetrics;
+using bluetooth::common::BluetoothMetricsLogger;
 using bluetooth::metrics::BluetoothMetricsProto::A2DPSession;
 using bluetooth::metrics::BluetoothMetricsProto::A2dpSourceCodec;
 using bluetooth::metrics::BluetoothMetricsProto::BluetoothLog;
@@ -45,29 +47,20 @@
     BluetoothSession_DisconnectReasonType;
 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo;
 using bluetooth::metrics::BluetoothMetricsProto::DeviceInfo_DeviceType;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
+using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
 using bluetooth::metrics::BluetoothMetricsProto::PairEvent;
 using bluetooth::metrics::BluetoothMetricsProto::RFCommSession;
 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent;
-using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
 using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanEventType;
+using bluetooth::metrics::BluetoothMetricsProto::ScanEvent_ScanTechnologyType;
 using bluetooth::metrics::BluetoothMetricsProto::WakeEvent;
 using bluetooth::metrics::BluetoothMetricsProto::WakeEvent_WakeEventType;
-using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileType;
-using bluetooth::metrics::BluetoothMetricsProto::HeadsetProfileConnectionStats;
-using system_bt_osi::BluetoothMetricsLogger;
-using system_bt_osi::A2dpSessionMetrics;
 
 namespace {
 const size_t kMaxEventGenerationLimit = 5000;
 }
 
-/*
- * Get current OS boot time in ms
- */
-static int64_t time_get_os_boottime_ms(void) {
-  return time_get_os_boottime_us() / 1000;
-}
-
 static void sleep_ms(int64_t t) {
   std::this_thread::sleep_for(std::chrono::milliseconds(t));
 }
@@ -429,7 +422,7 @@
           42, DeviceInfo_DeviceType::DeviceInfo_DeviceType_DEVICE_TYPE_BREDR)));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogPairEvent(
-      35, 12345, 42, system_bt_osi::DEVICE_TYPE_BREDR);
+      35, 12345, 42, bluetooth::common::DEVICE_TYPE_BREDR);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -441,7 +434,7 @@
                     "TEST_REQ", "TEST_NAME", 12345));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
-      system_bt_osi::WAKE_EVENT_ACQUIRED, "TEST_REQ", "TEST_NAME", 12345);
+      bluetooth::common::WAKE_EVENT_ACQUIRED, "TEST_REQ", "TEST_NAME", 12345);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -455,8 +448,8 @@
   UpdateLog();
   for (size_t i = 0; i < kMaxEventGenerationLimit; ++i) {
     BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
-        i % 2 == 0 ? system_bt_osi::WAKE_EVENT_ACQUIRED
-                   : system_bt_osi::WAKE_EVENT_RELEASED,
+        i % 2 == 0 ? bluetooth::common::WAKE_EVENT_ACQUIRED
+                   : bluetooth::common::WAKE_EVENT_RELEASED,
         "TEST_REQ", "TEST_NAME", i);
   }
   std::string msg_str;
@@ -467,12 +460,14 @@
 TEST_F(BluetoothMetricsLoggerTest, ScanEventTest) {
   scan_events_.push_back(MakeScanEvent(
       ScanEvent_ScanEventType::ScanEvent_ScanEventType_SCAN_EVENT_STOP,
-      "TEST_INITIATOR", ScanEvent_ScanTechnologyType::
-                            ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR,
+      "TEST_INITIATOR",
+      ScanEvent_ScanTechnologyType::
+          ScanEvent_ScanTechnologyType_SCAN_TECH_TYPE_BREDR,
       42, 123456));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogScanEvent(
-      false, "TEST_INITIATOR", system_bt_osi::SCAN_TECH_TYPE_BREDR, 42, 123456);
+      false, "TEST_INITIATOR", bluetooth::common::SCAN_TECH_TYPE_BREDR, 42,
+      123456);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -488,9 +483,9 @@
       nullptr, nullptr, nullptr));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_LE, 123456);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_LE, 123456);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 133456);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 133456);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -506,7 +501,8 @@
       nullptr, nullptr, nullptr));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_LE, time_get_os_boottime_ms());
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_LE,
+      bluetooth::common::time_get_os_boottime_ms());
   sleep_ms(1000);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
@@ -530,10 +526,10 @@
       nullptr, nullptr, nullptr));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_UNKNOWN, 0);
   sleep_ms(1000);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_LE, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_LE, 0);
   sleep_ms(2000);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
@@ -601,13 +597,13 @@
       info, nullptr, session));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 123456);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 123456);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
-      BTM_COD_MAJOR_AUDIO_TEST, system_bt_osi::DEVICE_TYPE_BREDR);
+      BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR);
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 133456);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 133456);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -662,9 +658,9 @@
       info, nullptr, session));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
-      BTM_COD_MAJOR_AUDIO_TEST, system_bt_osi::DEVICE_TYPE_BREDR);
+      BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR);
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
   sleep_ms(1000);
   std::string msg_str;
@@ -686,7 +682,7 @@
   sleep_ms(1000);
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
   msg_str.clear();
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -731,13 +727,13 @@
       info, nullptr, session));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
-      BTM_COD_MAJOR_AUDIO_TEST, system_bt_osi::DEVICE_TYPE_BREDR);
+      BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR);
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics1);
   sleep_ms(1000);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -762,11 +758,11 @@
       nullptr, nullptr, session));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
   sleep_ms(1000);
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
   msg_str.clear();
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -892,9 +888,9 @@
       info, nullptr, nullptr));
   UpdateLog();
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionStart(
-      system_bt_osi::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
+      bluetooth::common::CONNECTION_TECHNOLOGY_TYPE_BREDR, 0);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionDeviceInfo(
-      BTM_COD_MAJOR_AUDIO_TEST, system_bt_osi::DEVICE_TYPE_BREDR);
+      BTM_COD_MAJOR_AUDIO_TEST, bluetooth::common::DEVICE_TYPE_BREDR);
   sleep_ms(1000);
   std::string msg_str;
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
@@ -917,7 +913,7 @@
   BluetoothMetricsLogger::GetInstance()->LogA2dpSession(metrics2);
   sleep_ms(1000);
   BluetoothMetricsLogger::GetInstance()->LogBluetoothSessionEnd(
-      system_bt_osi::DISCONNECT_REASON_UNKNOWN, 0);
+      bluetooth::common::DISCONNECT_REASON_UNKNOWN, 0);
   msg_str.clear();
   BluetoothMetricsLogger::GetInstance()->WriteString(&msg_str);
   EXPECT_THAT(msg_str, StrEq(bt_log_str_));
@@ -1009,4 +1005,4 @@
   EXPECT_EQ(metrics->headset_profile_connection_stats_size(), 0);
   delete metrics;
 }
-}
+}  // namespace testing
diff --git a/common/once_timer.cc b/common/once_timer.cc
new file mode 100644
index 0000000..413dc44
--- /dev/null
+++ b/common/once_timer.cc
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "once_timer.h"
+
+#include "message_loop_thread.h"
+#include "time_util.h"
+
+namespace bluetooth {
+
+namespace common {
+
+// This runs on user thread
+OnceTimer::~OnceTimer() {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  if (message_loop_thread_ != nullptr && message_loop_thread_->IsRunning()) {
+    CancelAndWait();
+  }
+}
+
+// This runs on user thread
+bool OnceTimer::Schedule(const base::WeakPtr<MessageLoopThread>& thread,
+                         const base::Location& from_here,
+                         base::OnceClosure task, base::TimeDelta delay) {
+  uint64_t time_now_us = time_get_os_boottime_us();
+  uint64_t time_next_task_us = time_now_us + delay.InMicroseconds();
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  if (thread == nullptr) {
+    LOG(ERROR) << __func__ << ": thread must be non-null";
+    return false;
+  }
+  CancelAndWait();
+  task_ = std::move(task);
+  task_wrapper_.Reset(
+      base::BindOnce(&OnceTimer::RunTask, base::Unretained(this)));
+  message_loop_thread_ = thread;
+  delay_ = delay;
+  uint64_t time_until_next_us = time_next_task_us - time_get_os_boottime_us();
+  if (!thread->DoInThreadDelayed(
+          from_here, task_wrapper_.callback(),
+          base::TimeDelta::FromMicroseconds(time_until_next_us))) {
+    LOG(ERROR) << __func__
+               << ": failed to post task to message loop for thread " << *thread
+               << ", from " << from_here.ToString();
+    task_wrapper_.Cancel();
+    message_loop_thread_ = nullptr;
+    delay_ = {};
+    return false;
+  }
+  return true;
+}
+
+// This runs on user thread
+void OnceTimer::Cancel() {
+  std::promise<void> promise;
+  CancelHelper(std::move(promise));
+}
+
+// This runs on user thread
+void OnceTimer::CancelAndWait() {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  CancelHelper(std::move(promise));
+  future.wait();
+}
+
+// This runs on user thread
+void OnceTimer::CancelHelper(std::promise<void> promise) {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  MessageLoopThread* scheduled_thread = message_loop_thread_.get();
+  if (scheduled_thread == nullptr) {
+    promise.set_value();
+    return;
+  }
+  if (scheduled_thread->GetThreadId() == base::PlatformThread::CurrentId()) {
+    CancelClosure(std::move(promise));
+    return;
+  }
+  scheduled_thread->DoInThread(
+      FROM_HERE, base::BindOnce(&OnceTimer::CancelClosure,
+                                base::Unretained(this), std::move(promise)));
+}
+
+// This runs on message loop thread
+void OnceTimer::CancelClosure(std::promise<void> promise) {
+  message_loop_thread_ = nullptr;
+  task_wrapper_.Cancel();
+  std::move(task_);
+  delay_ = base::TimeDelta();
+  promise.set_value();
+}
+
+// This runs on user thread
+bool OnceTimer::IsScheduled() const {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return message_loop_thread_ != nullptr && message_loop_thread_->IsRunning();
+}
+
+// This runs on message loop thread
+void OnceTimer::RunTask() {
+  if (message_loop_thread_ == nullptr || !message_loop_thread_->IsRunning()) {
+    LOG(ERROR) << __func__
+               << ": message_loop_thread_ is null or is not running";
+    return;
+  }
+  CHECK_EQ(message_loop_thread_->GetThreadId(),
+           base::PlatformThread::CurrentId())
+      << ": task must run on message loop thread";
+
+  task_wrapper_.Cancel();
+  std::move(task_).Run();
+  message_loop_thread_ = nullptr;
+}
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/once_timer.h b/common/once_timer.h
new file mode 100644
index 0000000..9968be5
--- /dev/null
+++ b/common/once_timer.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/bind.h>
+#include <base/cancelable_callback.h>
+#include <base/location.h>
+#include <future>
+
+namespace bluetooth {
+
+namespace common {
+
+class MessageLoopThread;
+
+/**
+ * An alarm clock that posts a delayed task to a specified MessageLoopThread
+ * once.
+ *
+ * Warning: MessageLoopThread must be running when any task is scheduled or
+ * being executed
+ */
+class OnceTimer final {
+ public:
+  OnceTimer() {}
+  ~OnceTimer();
+
+  /**
+   * Schedule a delayed task to the MessageLoopThread. Only one task can be
+   * scheduled at a time. If another task is scheduled, it will cancel the
+   * previous task synchronously and schedule the new task; this blocks until
+   * the previous task is cancelled.
+   *
+   * @param thread thread to run the task
+   * @param from_here location where this task is originated
+   * @param task task created through base::Bind()
+   * @param delay delay for the task to be executed
+   * @return true iff task is scheduled successfully
+   */
+  bool Schedule(const base::WeakPtr<MessageLoopThread>& thread,
+                const base::Location& from_here, base::OnceClosure task,
+                base::TimeDelta delay);
+
+  /**
+   * Post an event which cancels the current task asynchronously
+   */
+  void Cancel();
+
+  /**
+   * Post an event which cancels the current task and wait for the cancellation
+   * to be completed
+   */
+  void CancelAndWait();
+
+  /**
+   * Returns true when there is a pending task scheduled on a running thread,
+   * otherwise false.
+   */
+  bool IsScheduled() const;
+
+ private:
+  base::WeakPtr<MessageLoopThread> message_loop_thread_;
+  base::CancelableOnceClosure task_wrapper_;
+  base::OnceClosure task_;
+  base::TimeDelta delay_;
+  mutable std::recursive_mutex api_mutex_;
+  void CancelHelper(std::promise<void> promise);
+  void CancelClosure(std::promise<void> promise);
+
+  void RunTask();
+
+  DISALLOW_COPY_AND_ASSIGN(OnceTimer);
+};
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/once_timer_unittest.cc b/common/once_timer_unittest.cc
new file mode 100644
index 0000000..d0fa238
--- /dev/null
+++ b/common/once_timer_unittest.cc
@@ -0,0 +1,225 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <base/logging.h>
+#include <gtest/gtest.h>
+#include <future>
+
+#include "message_loop_thread.h"
+#include "once_timer.h"
+
+using bluetooth::common::MessageLoopThread;
+using bluetooth::common::OnceTimer;
+
+// Allowed error between the expected and actual delay for DoInThreadDelayed().
+constexpr uint32_t delay_error_ms = 3;
+
+/**
+ * Unit tests to verify Task Scheduler.
+ */
+class OnceTimerTest : public ::testing::Test {
+ public:
+  void ShouldNotHappen() { FAIL() << "Should not happen"; }
+
+  void IncreaseTaskCounter(int scheduled_tasks, std::promise<void>* promise) {
+    counter_++;
+    if (counter_ == scheduled_tasks) {
+      promise->set_value();
+    }
+  }
+
+  void GetName(std::string* name, std::promise<void>* promise) {
+    char my_name[256];
+    pthread_getname_np(pthread_self(), my_name, sizeof(my_name));
+    name->append(my_name);
+    promise->set_value();
+  }
+
+  void SleepAndIncreaseCounter(std::promise<void>* promise, int sleep_ms) {
+    promise->set_value();
+    std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
+    counter_++;
+  }
+
+  void CancelTimerAndWait() { timer_->CancelAndWait(); }
+
+ protected:
+  void SetUp() override {
+    ::testing::Test::SetUp();
+    counter_ = 0;
+    timer_ = new OnceTimer();
+    promise_ = new std::promise<void>();
+  }
+
+  void TearDown() override {
+    if (promise_ != nullptr) {
+      delete promise_;
+      promise_ = nullptr;
+    }
+    if (timer_ != nullptr) {
+      delete timer_;
+      timer_ = nullptr;
+    }
+  }
+
+  int counter_;
+  OnceTimer* timer_;
+  std::promise<void>* promise_;
+};
+
+TEST_F(OnceTimerTest, initial_is_not_scheduled) {
+  ASSERT_FALSE(timer_->IsScheduled());
+}
+
+TEST_F(OnceTimerTest, schedule_task) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  auto future = promise_->get_future();
+  std::string my_name;
+  uint32_t delay_ms = 5;
+
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::BindOnce(&OnceTimerTest::GetName,
+                                  base::Unretained(this), &my_name, promise_),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+  EXPECT_TRUE(timer_->IsScheduled());
+  future.get();
+  ASSERT_EQ(name, my_name);
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
+  EXPECT_FALSE(timer_->IsScheduled());
+}
+
+TEST_F(OnceTimerTest, cancel_without_scheduling) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+
+  EXPECT_FALSE(timer_->IsScheduled());
+  timer_->CancelAndWait();
+  EXPECT_FALSE(timer_->IsScheduled());
+}
+
+TEST_F(OnceTimerTest, cancel_in_callback_no_deadlock) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::BindOnce(&OnceTimerTest::CancelTimerAndWait,
+                                  base::Unretained(this)),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+}
+
+TEST_F(OnceTimerTest, cancel_single_task) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 100000000;
+  timer_->Schedule(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
+  timer_->CancelAndWait();
+}
+
+TEST_F(OnceTimerTest, message_loop_thread_down_cancel_task) {
+  std::string name = "test_thread";
+  {
+    MessageLoopThread message_loop_thread(name);
+    message_loop_thread.StartUp();
+    uint32_t delay_ms = 100000000;
+    timer_->Schedule(
+        message_loop_thread.GetWeakPtr(), FROM_HERE,
+        base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
+        base::TimeDelta::FromMilliseconds(delay_ms));
+    std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
+  }
+}
+
+// Verify that if a task is being executed, then cancelling it is no-op
+TEST_F(OnceTimerTest, cancel_current_task_no_effect) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  auto future = promise_->get_future();
+  uint32_t delay_ms = 5;
+
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::BindOnce(&OnceTimerTest::SleepAndIncreaseCounter,
+                                  base::Unretained(this), promise_, delay_ms),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+  EXPECT_TRUE(timer_->IsScheduled());
+  future.get();
+  timer_->CancelAndWait();
+  ASSERT_EQ(counter_, 1);
+  EXPECT_FALSE(timer_->IsScheduled());
+}
+
+TEST_F(OnceTimerTest, reschedule_task_dont_invoke_new_task_early) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::DoNothing(),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms - 2));
+  timer_->Schedule(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
+      base::TimeDelta::FromMilliseconds(delay_ms + 1000));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
+}
+
+TEST_F(OnceTimerTest, reschedule_task_when_firing_dont_invoke_new_task_early) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::DoNothing(),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
+  timer_->Schedule(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindOnce(&OnceTimerTest::ShouldNotHappen, base::Unretained(this)),
+      base::TimeDelta::FromMilliseconds(delay_ms + 1000));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
+}
+
+TEST_F(OnceTimerTest, reschedule_task_when_firing_must_schedule_new_task) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+  std::string my_name;
+  auto future = promise_->get_future();
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::DoNothing(),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
+  timer_->Schedule(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                   base::BindOnce(&OnceTimerTest::GetName,
+                                  base::Unretained(this), &my_name, promise_),
+                   base::TimeDelta::FromMilliseconds(delay_ms));
+  future.get();
+  ASSERT_EQ(name, my_name);
+}
diff --git a/common/repeating_timer.cc b/common/repeating_timer.cc
new file mode 100644
index 0000000..e34dabc
--- /dev/null
+++ b/common/repeating_timer.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "repeating_timer.h"
+
+#include "message_loop_thread.h"
+#include "time_util.h"
+
+namespace bluetooth {
+
+namespace common {
+
+constexpr base::TimeDelta kMinimumPeriod = base::TimeDelta::FromMicroseconds(1);
+
+// This runs on user thread
+RepeatingTimer::~RepeatingTimer() {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  if (message_loop_thread_ != nullptr && message_loop_thread_->IsRunning()) {
+    CancelAndWait();
+  }
+}
+
+// This runs on user thread
+bool RepeatingTimer::SchedulePeriodic(
+    const base::WeakPtr<MessageLoopThread>& thread,
+    const base::Location& from_here, base::Closure task,
+    base::TimeDelta period) {
+  if (period < kMinimumPeriod) {
+    LOG(ERROR) << __func__ << ": period must be at least " << kMinimumPeriod;
+    return false;
+  }
+
+  uint64_t time_now_us = time_get_os_boottime_us();
+  uint64_t time_next_task_us = time_now_us + period.InMicroseconds();
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  if (thread == nullptr) {
+    LOG(ERROR) << __func__ << ": thread must be non-null";
+    return false;
+  }
+  CancelAndWait();
+  expected_time_next_task_us_ = time_next_task_us;
+  task_ = std::move(task);
+  task_wrapper_.Reset(
+      base::Bind(&RepeatingTimer::RunTask, base::Unretained(this)));
+  message_loop_thread_ = thread;
+  period_ = period;
+  uint64_t time_until_next_us = time_next_task_us - time_get_os_boottime_us();
+  if (!thread->DoInThreadDelayed(
+          from_here, task_wrapper_.callback(),
+          base::TimeDelta::FromMicroseconds(time_until_next_us))) {
+    LOG(ERROR) << __func__
+               << ": failed to post task to message loop for thread " << *thread
+               << ", from " << from_here.ToString();
+    expected_time_next_task_us_ = 0;
+    task_wrapper_.Cancel();
+    message_loop_thread_ = nullptr;
+    period_ = {};
+    return false;
+  }
+  return true;
+}
+
+// This runs on user thread
+void RepeatingTimer::Cancel() {
+  std::promise<void> promise;
+  CancelHelper(std::move(promise));
+}
+
+// This runs on user thread
+void RepeatingTimer::CancelAndWait() {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  CancelHelper(std::move(promise));
+  future.wait();
+}
+
+// This runs on user thread
+void RepeatingTimer::CancelHelper(std::promise<void> promise) {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  MessageLoopThread* scheduled_thread = message_loop_thread_.get();
+  if (scheduled_thread == nullptr) {
+    promise.set_value();
+    return;
+  }
+  if (scheduled_thread->GetThreadId() == base::PlatformThread::CurrentId()) {
+    CancelClosure(std::move(promise));
+    return;
+  }
+  scheduled_thread->DoInThread(
+      FROM_HERE, base::BindOnce(&RepeatingTimer::CancelClosure,
+                                base::Unretained(this), std::move(promise)));
+}
+
+// This runs on message loop thread
+void RepeatingTimer::CancelClosure(std::promise<void> promise) {
+  message_loop_thread_ = nullptr;
+  task_wrapper_.Cancel();
+  task_ = {};
+  period_ = base::TimeDelta();
+  expected_time_next_task_us_ = 0;
+  promise.set_value();
+}
+
+// This runs on user thread
+bool RepeatingTimer::IsScheduled() const {
+  std::lock_guard<std::recursive_mutex> api_lock(api_mutex_);
+  return message_loop_thread_ != nullptr && message_loop_thread_->IsRunning();
+}
+
+// This runs on message loop thread
+void RepeatingTimer::RunTask() {
+  if (message_loop_thread_ == nullptr || !message_loop_thread_->IsRunning()) {
+    LOG(ERROR) << __func__
+               << ": message_loop_thread_ is null or is not running";
+    return;
+  }
+  CHECK_EQ(message_loop_thread_->GetThreadId(),
+           base::PlatformThread::CurrentId())
+      << ": task must run on message loop thread";
+
+  int64_t period_us = period_.InMicroseconds();
+  expected_time_next_task_us_ += period_us;
+  uint64_t time_now_us = time_get_os_boottime_us();
+  int64_t remaining_time_us = expected_time_next_task_us_ - time_now_us;
+  if (remaining_time_us < 0) {
+    // if remaining_time_us is negative, schedule the task to the nearest
+    // multiple of period
+    remaining_time_us = (remaining_time_us % period_us + period_us) % period_us;
+  }
+  message_loop_thread_->DoInThreadDelayed(
+      FROM_HERE, task_wrapper_.callback(),
+      base::TimeDelta::FromMicroseconds(remaining_time_us));
+
+  uint64_t time_before_task_us = time_get_os_boottime_us();
+  task_.Run();
+  uint64_t time_after_task_us = time_get_os_boottime_us();
+  auto task_time_us =
+      static_cast<int64_t>(time_after_task_us - time_before_task_us);
+  if (task_time_us > period_.InMicroseconds()) {
+    LOG(ERROR) << __func__ << ": Periodic task execution took " << task_time_us
+               << " microseconds, longer than interval "
+               << period_.InMicroseconds() << " microseconds";
+  }
+}
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/repeating_timer.h b/common/repeating_timer.h
new file mode 100644
index 0000000..b4c5108
--- /dev/null
+++ b/common/repeating_timer.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/bind.h>
+#include <base/cancelable_callback.h>
+#include <base/location.h>
+#include <future>
+
+namespace bluetooth {
+
+namespace common {
+
+class MessageLoopThread;
+
+/**
+ * An alarm clock that posts a delayed task to a specified MessageLoopThread
+ * periodically.
+ *
+ * Warning: MessageLoopThread must be running when any task is scheduled or
+ * being executed
+ */
+class RepeatingTimer final {
+ public:
+  RepeatingTimer() : expected_time_next_task_us_(0) {}
+  ~RepeatingTimer();
+
+  /**
+   * Schedule a delayed periodic task to the MessageLoopThread. Only one task
+   * can be scheduled at a time. If another task is scheduled, it will cancel
+   * the previous task synchronously and schedule the new periodic task; this
+   * blocks until the previous task is cancelled.
+   *
+   * @param thread thread to run the task
+   * @param from_here location where this task is originated
+   * @param task task created through base::Bind()
+   * @param period period for the task to be executed
+   * @return true iff task is scheduled successfully
+   */
+  bool SchedulePeriodic(const base::WeakPtr<MessageLoopThread>& thread,
+                        const base::Location& from_here,
+                        base::RepeatingClosure task, base::TimeDelta period);
+
+  /**
+   * Post an event which cancels the current task asynchronously
+   */
+  void Cancel();
+
+  /**
+   * Post an event which cancels the current task and wait for the cancellation
+   * to be completed
+   */
+  void CancelAndWait();
+
+  /**
+   * Returns true when there is a pending task scheduled on a running thread,
+   * otherwise false.
+   */
+  bool IsScheduled() const;
+
+ private:
+  base::WeakPtr<MessageLoopThread> message_loop_thread_;
+  base::CancelableClosure task_wrapper_;
+  base::RepeatingClosure task_;
+  base::TimeDelta period_;
+  uint64_t expected_time_next_task_us_;  // Using clock boot time in time_util.h
+  mutable std::recursive_mutex api_mutex_;
+  void CancelHelper(std::promise<void> promise);
+  void CancelClosure(std::promise<void> promise);
+
+  void RunTask();
+
+  DISALLOW_COPY_AND_ASSIGN(RepeatingTimer);
+};
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/repeating_timer_unittest.cc b/common/repeating_timer_unittest.cc
new file mode 100644
index 0000000..20d8d67
--- /dev/null
+++ b/common/repeating_timer_unittest.cc
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <base/logging.h>
+#include <gtest/gtest.h>
+#include <future>
+
+#include "message_loop_thread.h"
+#include "repeating_timer.h"
+
+using bluetooth::common::MessageLoopThread;
+using bluetooth::common::RepeatingTimer;
+
+// Allowed error between the expected and actual delay for DoInThreadDelayed().
+constexpr uint32_t delay_error_ms = 3;
+
+/**
+ * Unit tests to verify Task Scheduler.
+ */
+class RepeatingTimerTest : public ::testing::Test {
+ public:
+  void ShouldNotHappen() { FAIL() << "Should not happen"; }
+
+  void IncreaseTaskCounter(int scheduled_tasks, std::promise<void>* promise) {
+    counter_++;
+    if (counter_ == scheduled_tasks) {
+      promise->set_value();
+    }
+  }
+
+  void GetName(std::string* name, std::promise<void>* promise) {
+    char my_name[256];
+    pthread_getname_np(pthread_self(), my_name, sizeof(my_name));
+    name->append(my_name);
+    promise->set_value();
+  }
+
+  void SleepAndIncreaseCounter(std::promise<void>* promise, int sleep_ms) {
+    promise->set_value();
+    std::this_thread::sleep_for(std::chrono::milliseconds(sleep_ms));
+    counter_++;
+  }
+
+  void VerifyDelayTimeAndSleep(std::chrono::steady_clock::time_point start_time,
+                               int interval_ms, int scheduled_tasks,
+                               int task_length_ms,
+                               std::promise<void>* promise) {
+    auto end_time = std::chrono::steady_clock::now();
+    auto actual_delay = std::chrono::duration_cast<std::chrono::milliseconds>(
+        end_time - start_time);
+    counter_++;
+    int64_t scheduled_delay_ms = interval_ms * counter_;
+    if (counter_ == scheduled_tasks) {
+      promise->set_value();
+    }
+    ASSERT_NEAR(scheduled_delay_ms, actual_delay.count(), delay_error_ms);
+    std::this_thread::sleep_for(std::chrono::milliseconds(task_length_ms));
+  }
+
+  void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms,
+                                  int interval_between_tasks_ms) {
+    std::string name = "test_thread";
+    MessageLoopThread message_loop_thread(name);
+    message_loop_thread.StartUp();
+    message_loop_thread.EnableRealTimeScheduling();
+    auto future = promise_->get_future();
+    auto start_time = std::chrono::steady_clock::now();
+    timer_->SchedulePeriodic(
+        message_loop_thread.GetWeakPtr(), FROM_HERE,
+        base::BindRepeating(&RepeatingTimerTest::VerifyDelayTimeAndSleep,
+                            base::Unretained(this), start_time,
+                            interval_between_tasks_ms, scheduled_tasks,
+                            task_length_ms, promise_),
+        base::TimeDelta::FromMilliseconds(interval_between_tasks_ms));
+    future.get();
+    timer_->CancelAndWait();
+  }
+
+  void CancelRepeatingTimerAndWait() { timer_->CancelAndWait(); }
+
+ protected:
+  void SetUp() override {
+    ::testing::Test::SetUp();
+    counter_ = 0;
+    timer_ = new RepeatingTimer();
+    promise_ = new std::promise<void>();
+  }
+
+  void TearDown() override {
+    if (promise_ != nullptr) {
+      delete promise_;
+      promise_ = nullptr;
+    }
+    if (timer_ != nullptr) {
+      delete timer_;
+      timer_ = nullptr;
+    }
+  }
+
+  int counter_;
+  RepeatingTimer* timer_;
+  std::promise<void>* promise_;
+};
+
+TEST_F(RepeatingTimerTest, initial_is_not_scheduled) {
+  ASSERT_FALSE(timer_->IsScheduled());
+}
+
+TEST_F(RepeatingTimerTest, cancel_without_scheduling) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+
+  EXPECT_FALSE(timer_->IsScheduled());
+  timer_->CancelAndWait();
+  EXPECT_FALSE(timer_->IsScheduled());
+}
+
+TEST_F(RepeatingTimerTest, periodic_run) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  auto future = promise_->get_future();
+  uint32_t delay_ms = 5;
+  int num_tasks = 200;
+
+  timer_->SchedulePeriodic(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindRepeating(&RepeatingTimerTest::IncreaseTaskCounter,
+                          base::Unretained(this), num_tasks, promise_),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+  future.get();
+  ASSERT_GE(counter_, num_tasks);
+  timer_->CancelAndWait();
+}
+
+TEST_F(RepeatingTimerTest, schedule_periodic_task_zero_interval) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t interval_ms = 0;
+
+  ASSERT_FALSE(timer_->SchedulePeriodic(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindRepeating(&RepeatingTimerTest::ShouldNotHappen,
+                          base::Unretained(this)),
+      base::TimeDelta::FromMilliseconds(interval_ms)));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
+}
+
+// Verify that deleting the timer without cancelling it will cancel the task
+TEST_F(RepeatingTimerTest, periodic_delete_without_cancel) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+  timer_->SchedulePeriodic(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindRepeating(&RepeatingTimerTest::ShouldNotHappen,
+                          base::Unretained(this)),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+  delete timer_;
+  timer_ = nullptr;
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_error_ms));
+}
+
+TEST_F(RepeatingTimerTest, cancel_single_task_near_fire_no_race_condition) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+  timer_->SchedulePeriodic(message_loop_thread.GetWeakPtr(), FROM_HERE,
+                           base::DoNothing(),
+                           base::TimeDelta::FromMilliseconds(delay_ms));
+  std::this_thread::sleep_for(std::chrono::milliseconds(delay_ms));
+  timer_->CancelAndWait();
+}
+
+TEST_F(RepeatingTimerTest, cancel_periodic_task) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  uint32_t delay_ms = 5;
+  int num_tasks = 5;
+  auto future = promise_->get_future();
+
+  timer_->SchedulePeriodic(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindRepeating(&RepeatingTimerTest::IncreaseTaskCounter,
+                          base::Unretained(this), num_tasks, promise_),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+  future.wait();
+  timer_->CancelAndWait();
+  std::this_thread::sleep_for(
+      std::chrono::milliseconds(delay_ms + delay_error_ms));
+  int counter = counter_;
+  std::this_thread::sleep_for(
+      std::chrono::milliseconds(delay_ms + delay_error_ms));
+  ASSERT_EQ(counter, counter_);
+}
+
+// Schedule 10 short periodic tasks with interval 1 ms between each; verify the
+// functionality
+TEST_F(RepeatingTimerTest, schedule_multiple_delayed_tasks) {
+  VerifyMultipleDelayedTasks(10, 0, 1);
+}
+
+// Schedule 10 periodic tasks with interval 2 ms between each and each takes 1
+// ms; verify the functionality
+TEST_F(RepeatingTimerTest, schedule_multiple_delayed_slow_tasks) {
+  VerifyMultipleDelayedTasks(10, 1, 2);
+}
+
+TEST_F(RepeatingTimerTest,
+       message_loop_thread_down_cancel_scheduled_periodic_task) {
+  std::string name = "test_thread";
+  MessageLoopThread message_loop_thread(name);
+  message_loop_thread.StartUp();
+  std::string my_name;
+  auto future = promise_->get_future();
+  uint32_t delay_ms = 5;
+  int num_tasks = 5;
+
+  timer_->SchedulePeriodic(
+      message_loop_thread.GetWeakPtr(), FROM_HERE,
+      base::BindRepeating(&RepeatingTimerTest::IncreaseTaskCounter,
+                          base::Unretained(this), num_tasks, promise_),
+      base::TimeDelta::FromMilliseconds(delay_ms));
+  future.wait();
+  message_loop_thread.ShutDown();
+  std::this_thread::sleep_for(
+      std::chrono::milliseconds(delay_ms + delay_error_ms));
+  int counter = counter_;
+  std::this_thread::sleep_for(
+      std::chrono::milliseconds(delay_ms + delay_error_ms));
+  ASSERT_EQ(counter, counter_);
+}
diff --git a/btif/include/btif_state_machine.h b/common/state_machine.h
similarity index 90%
rename from btif/include/btif_state_machine.h
rename to common/state_machine.h
index 49b1583..62d92d2 100644
--- a/btif/include/btif_state_machine.h
+++ b/common/state_machine.h
@@ -14,18 +14,21 @@
  * limitations under the License.
  */
 
-#ifndef BTIF_STATE_MACHINE_H
-#define BTIF_STATE_MACHINE_H
+#pragma once
 
 #include <map>
 #include <utility>
 
 #include <base/logging.h>
 
+namespace bluetooth {
+
+namespace common {
+
 /**
- * State machine used by BTIF components.
+ * State machine used by Bluetooth native stack.
  */
-class BtifStateMachine {
+class StateMachine {
  public:
   enum { kStateInvalid = -1 };
 
@@ -33,7 +36,7 @@
    * A class to represent the state in the State Machine.
    */
   class State {
-    friend class BtifStateMachine;
+    friend class StateMachine;
 
    public:
     /**
@@ -42,7 +45,7 @@
      * @param sm the State Machine to use
      * @param state_id the unique State ID. It should be a non-negative number.
      */
-    State(BtifStateMachine& sm, int state_id) : sm_(sm), state_id_(state_id) {}
+    State(StateMachine& sm, int state_id) : sm_(sm), state_id_(state_id) {}
 
     virtual ~State() = default;
 
@@ -88,20 +91,20 @@
      *
      * @param dest_state the state to transition to. It cannot be nullptr.
      */
-    void TransitionTo(BtifStateMachine::State* dest_state) {
+    void TransitionTo(StateMachine::State* dest_state) {
       sm_.TransitionTo(dest_state);
     }
 
    private:
-    BtifStateMachine& sm_;
+    StateMachine& sm_;
     int state_id_;
   };
 
-  BtifStateMachine()
+  StateMachine()
       : initial_state_(nullptr),
         previous_state_(nullptr),
         current_state_(nullptr) {}
-  ~BtifStateMachine() {
+  ~StateMachine() {
     for (auto& kv : states_) delete kv.second;
   }
 
@@ -172,7 +175,7 @@
    *
    * @param dest_state the state to transition to. It cannot be nullptr.
    */
-  void TransitionTo(BtifStateMachine::State* dest_state) {
+  void TransitionTo(StateMachine::State* dest_state) {
     if (current_state_ != nullptr) {
       current_state_->OnExit();
     }
@@ -206,4 +209,6 @@
   std::map<int, State*> states_;
 };
 
-#endif  // BTIF_STATE_MACHINE_H
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/btif/test/btif_state_machine_test.cc b/common/state_machine_unittest.cc
similarity index 92%
rename from btif/test/btif_state_machine_test.cc
rename to common/state_machine_unittest.cc
index d413a4a..896e983 100644
--- a/btif/test/btif_state_machine_test.cc
+++ b/common/state_machine_unittest.cc
@@ -18,7 +18,9 @@
 
 #include <gtest/gtest.h>
 
-#include "btif/include/btif_state_machine.h"
+#include "common/state_machine.h"
+
+using bluetooth::common::StateMachine;
 
 namespace {
 static constexpr uint32_t kInvalidEvent = 0xffffffff;
@@ -31,7 +33,7 @@
 static char dataTwo = 2;
 }  // namespace
 
-class BtifStateMachineImpl : public BtifStateMachine {
+class StateMachineImpl : public StateMachine {
  public:
   enum {
     kStateZero,
@@ -41,7 +43,7 @@
 
   class StateZero : public State {
    public:
-    StateZero(BtifStateMachine& sm)
+    StateZero(StateMachine& sm)
         : State(sm, kStateZero),
           on_enter_(false),
           on_exit_(false),
@@ -70,7 +72,7 @@
 
   class StateOne : public State {
    public:
-    StateOne(BtifStateMachine& sm)
+    StateOne(StateMachine& sm)
         : State(sm, kStateOne),
           on_enter_(false),
           on_exit_(false),
@@ -99,7 +101,7 @@
 
   class StateTwo : public State {
    public:
-    StateTwo(BtifStateMachine& sm)
+    StateTwo(StateMachine& sm)
         : State(sm, kStateTwo),
           on_enter_(false),
           on_exit_(false),
@@ -126,7 +128,7 @@
     void* data_;
   };
 
-  BtifStateMachineImpl() {
+  StateMachineImpl() {
     state_zero_ = new StateZero(*this);
     state_one_ = new StateOne(*this);
     state_two_ = new StateTwo(*this);
@@ -142,23 +144,23 @@
   StateTwo* state_two_;
 };
 
-class BtifStateMachineTest : public ::testing::Test {
+class StateMachineTest : public ::testing::Test {
  protected:
-  BtifStateMachineTest() {}
+  StateMachineTest() {}
 
   void SetUp() override { sm_.Start(); }
 
   void TearDown() override { sm_.Quit(); }
 
-  BtifStateMachineImpl sm_;
+  StateMachineImpl sm_;
 };
 
-TEST_F(BtifStateMachineTest, test_initial_state) {
+TEST_F(StateMachineTest, test_initial_state) {
   ASSERT_EQ(sm_.kStateZero, sm_.StateId());
   ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
 }
 
-TEST_F(BtifStateMachineTest, test_invalid_state) {
+TEST_F(StateMachineTest, test_invalid_state) {
   sm_.Quit();
   ASSERT_EQ(sm_.kStateInvalid, sm_.StateId());
   ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
@@ -167,7 +169,7 @@
   ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
 }
 
-TEST_F(BtifStateMachineTest, test_transition_to) {
+TEST_F(StateMachineTest, test_transition_to) {
   // Initial state: StateZero
   ASSERT_EQ(sm_.kStateZero, sm_.StateId());
   ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
@@ -195,7 +197,7 @@
   ASSERT_FALSE(sm_.state_two_->on_exit_);
 }
 
-TEST_F(BtifStateMachineTest, test_process_event) {
+TEST_F(StateMachineTest, test_process_event) {
   // Initial state: StateZero
   ASSERT_EQ(sm_.kStateZero, sm_.StateId());
   ASSERT_EQ(sm_.kStateInvalid, sm_.PreviousStateId());
diff --git a/common/test/thread_performance_test.cc b/common/test/thread_performance_test.cc
new file mode 100644
index 0000000..dc6a53f
--- /dev/null
+++ b/common/test/thread_performance_test.cc
@@ -0,0 +1,368 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/bind.h>
+#include <base/logging.h>
+#include <base/run_loop.h>
+#include <base/threading/thread.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <unistd.h>
+#include <chrono>
+#include <future>
+#include <iostream>
+#include <thread>
+
+#include "common/message_loop_thread.h"
+#include "osi/include/fixed_queue.h"
+#include "osi/include/thread.h"
+
+using bluetooth::common::MessageLoopThread;
+
+#define NUM_MESSAGES_TO_SEND 100000
+
+volatile static int g_counter = 0;
+static std::unique_ptr<std::promise<void>> g_counter_promise = nullptr;
+
+void callback_batch(fixed_queue_t* queue, void* data) {
+  if (queue != nullptr) {
+    fixed_queue_dequeue(queue);
+  }
+  g_counter++;
+  if (g_counter >= NUM_MESSAGES_TO_SEND) {
+    g_counter_promise->set_value();
+  }
+}
+
+class PerformanceTest : public testing::Test {
+ protected:
+  void SetUp() override {
+    set_up_promise_ = std::make_unique<std::promise<void>>();
+    g_counter = 0;
+    bt_msg_queue_ = fixed_queue_new(SIZE_MAX);
+  }
+  void TearDown() override {
+    fixed_queue_free(bt_msg_queue_, nullptr);
+    bt_msg_queue_ = nullptr;
+    set_up_promise_.reset(nullptr);
+    g_counter_promise.reset(nullptr);
+  }
+  fixed_queue_t* bt_msg_queue_ = nullptr;
+  std::unique_ptr<std::promise<void>> set_up_promise_ = nullptr;
+};
+
+class MessageLoopPerformanceTest : public PerformanceTest {
+ public:
+  static void RunThread(void* context) {
+    auto test = static_cast<MessageLoopPerformanceTest*>(context);
+    test->RunMessageLoop();
+  }
+  static void* RunPThread(void* context) {
+    auto test = static_cast<MessageLoopPerformanceTest*>(context);
+    test->RunMessageLoop();
+    return nullptr;
+  }
+  void RunMessageLoop() {
+    message_loop_ = new base::MessageLoop();
+    run_loop_ = new base::RunLoop();
+    message_loop_->task_runner()->PostTask(
+        FROM_HERE, base::Bind(&std::promise<void>::set_value,
+                              base::Unretained(set_up_promise_.get())));
+    run_loop_->Run();
+    delete message_loop_;
+    message_loop_ = nullptr;
+    delete run_loop_;
+    run_loop_ = nullptr;
+  }
+
+ protected:
+  base::MessageLoop* message_loop_ = nullptr;
+  base::RunLoop* run_loop_ = nullptr;
+};
+
+class OsiThreadMessageLoopPerformanceTest : public MessageLoopPerformanceTest {
+ protected:
+  void SetUp() override {
+    MessageLoopPerformanceTest::SetUp();
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = thread_new("OsiThreadMessageLoopPerformanceTest thread");
+    thread_post(thread_, &MessageLoopPerformanceTest::RunThread, this);
+    set_up_future.wait();
+  }
+
+  void TearDown() override {
+    message_loop_->task_runner()->PostTask(FROM_HERE,
+                                           run_loop_->QuitWhenIdleClosure());
+    thread_free(thread_);
+    thread_ = nullptr;
+    MessageLoopPerformanceTest::TearDown();
+  }
+
+  thread_t* thread_ = nullptr;
+};
+
+TEST_F(OsiThreadMessageLoopPerformanceTest, message_loop_speed_test) {
+  g_counter = 0;
+  g_counter_promise = std::make_unique<std::promise<void>>();
+  std::future<void> counter_future = g_counter_promise->get_future();
+  std::chrono::steady_clock::time_point start_time =
+      std::chrono::steady_clock::now();
+
+  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+    fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+    message_loop_->task_runner()->PostTask(
+        FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
+  }
+  counter_future.wait();
+
+  std::chrono::steady_clock::time_point end_time =
+      std::chrono::steady_clock::now();
+  std::chrono::milliseconds duration =
+      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
+                                                            start_time);
+
+  LOG(INFO) << "OsiThreadMessageLoopPerformanceTest, " << duration.count()
+            << " ms, " << NUM_MESSAGES_TO_SEND << " messages";
+}
+
+class StlThreadMessageLoopPerformanceTest : public MessageLoopPerformanceTest {
+ protected:
+  void SetUp() override {
+    MessageLoopPerformanceTest::SetUp();
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = new std::thread(&MessageLoopPerformanceTest::RunThread, this);
+    set_up_future.wait();
+  }
+
+  void TearDown() override {
+    message_loop_->task_runner()->PostTask(FROM_HERE,
+                                           run_loop_->QuitWhenIdleClosure());
+    thread_->join();
+    delete thread_;
+    thread_ = nullptr;
+    MessageLoopPerformanceTest::TearDown();
+  }
+
+  std::thread* thread_ = nullptr;
+};
+
+TEST_F(StlThreadMessageLoopPerformanceTest, stl_thread_speed_test) {
+  g_counter = 0;
+  g_counter_promise = std::make_unique<std::promise<void>>();
+  std::future<void> counter_future = g_counter_promise->get_future();
+  std::chrono::steady_clock::time_point start_time =
+      std::chrono::steady_clock::now();
+
+  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+    fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+    message_loop_->task_runner()->PostTask(
+        FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
+  }
+  counter_future.wait();
+
+  std::chrono::steady_clock::time_point end_time =
+      std::chrono::steady_clock::now();
+  std::chrono::milliseconds duration =
+      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
+                                                            start_time);
+
+  LOG(INFO) << "StlThreadMessageLoopPerformanceTest, " << duration.count()
+            << " ms, " << NUM_MESSAGES_TO_SEND << " messages";
+}
+
+class PosixThreadMessageLoopPerformanceTest
+    : public MessageLoopPerformanceTest {
+ protected:
+  void SetUp() override {
+    MessageLoopPerformanceTest::SetUp();
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    pthread_create(&thread_, nullptr, &MessageLoopPerformanceTest::RunPThread,
+                   (void*)this);
+    set_up_future.wait();
+  }
+
+  void TearDown() override {
+    message_loop_->task_runner()->PostTask(FROM_HERE,
+                                           run_loop_->QuitWhenIdleClosure());
+    pthread_join(thread_, nullptr);
+    MessageLoopPerformanceTest::TearDown();
+  }
+
+  pthread_t thread_ = -1;
+};
+
+TEST_F(PosixThreadMessageLoopPerformanceTest, stl_thread_speed_test) {
+  g_counter = 0;
+  g_counter_promise = std::make_unique<std::promise<void>>();
+  std::future<void> counter_future = g_counter_promise->get_future();
+
+  std::chrono::steady_clock::time_point start_time =
+      std::chrono::steady_clock::now();
+
+  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+    fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+    message_loop_->task_runner()->PostTask(
+        FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
+  }
+  counter_future.wait();
+
+  std::chrono::steady_clock::time_point end_time =
+      std::chrono::steady_clock::now();
+  std::chrono::milliseconds duration =
+      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
+                                                            start_time);
+
+  LOG(INFO) << "PosixThreadMessageLoopPerformanceTest, " << duration.count()
+            << " ms, " << NUM_MESSAGES_TO_SEND << " messages";
+}
+
+class ReactorPerformanceTest : public PerformanceTest {
+ protected:
+  void SetUp() override {
+    PerformanceTest::SetUp();
+    thread_ = thread_new("ReactorPerformanceTest thread");
+  }
+
+  void TearDown() override {
+    thread_free(thread_);
+    thread_ = nullptr;
+    PerformanceTest::TearDown();
+  }
+
+  thread_t* thread_ = nullptr;
+};
+
+TEST_F(ReactorPerformanceTest, reactor_thread_speed_test) {
+  g_counter = 0;
+  g_counter_promise = std::make_unique<std::promise<void>>();
+  std::future<void> counter_future = g_counter_promise->get_future();
+  fixed_queue_register_dequeue(bt_msg_queue_, thread_get_reactor(thread_),
+                               callback_batch, nullptr);
+
+  std::chrono::steady_clock::time_point start_time =
+      std::chrono::steady_clock::now();
+
+  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+    fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+  }
+  counter_future.wait();
+
+  std::chrono::steady_clock::time_point end_time =
+      std::chrono::steady_clock::now();
+  std::chrono::milliseconds duration =
+      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
+                                                            start_time);
+
+  LOG(INFO) << "ReactorPerformanceTest, " << duration.count() << " ms, "
+            << NUM_MESSAGES_TO_SEND << " messages";
+}
+
+class WorkerThreadPerformanceTest : public PerformanceTest {
+ protected:
+  void SetUp() override {
+    PerformanceTest::SetUp();
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    worker_thread_ =
+        new MessageLoopThread("WorkerThreadPerformanceTest thread");
+    worker_thread_->StartUp();
+    worker_thread_->DoInThread(
+        FROM_HERE, base::Bind(&std::promise<void>::set_value,
+                              base::Unretained(set_up_promise_.get())));
+    set_up_future.wait();
+  }
+
+  void TearDown() override {
+    worker_thread_->ShutDown();
+    delete worker_thread_;
+    worker_thread_ = nullptr;
+    PerformanceTest::TearDown();
+  }
+
+  MessageLoopThread* worker_thread_ = nullptr;
+};
+
+TEST_F(WorkerThreadPerformanceTest, worker_thread_speed_test) {
+  g_counter = 0;
+  g_counter_promise = std::make_unique<std::promise<void>>();
+  std::future<void> counter_future = g_counter_promise->get_future();
+
+  std::chrono::steady_clock::time_point start_time =
+      std::chrono::steady_clock::now();
+
+  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+    fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+    worker_thread_->DoInThread(
+        FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
+  }
+  counter_future.wait();
+
+  std::chrono::steady_clock::time_point end_time =
+      std::chrono::steady_clock::now();
+  std::chrono::milliseconds duration =
+      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
+                                                            start_time);
+
+  LOG(INFO) << "WorkerThreadPerformanceTest, " << duration.count() << " ms, "
+            << NUM_MESSAGES_TO_SEND << " messages";
+}
+
+class LibChromeThreadPerformanceTest : public PerformanceTest {
+ protected:
+  void SetUp() override {
+    PerformanceTest::SetUp();
+    std::future<void> set_up_future = set_up_promise_->get_future();
+    thread_ = new base::Thread("LibChromeThreadPerformanceTest thread");
+    thread_->Start();
+    thread_->task_runner()->PostTask(
+        FROM_HERE, base::Bind(&std::promise<void>::set_value,
+                              base::Unretained(set_up_promise_.get())));
+    set_up_future.wait();
+  }
+
+  void TearDown() override {
+    thread_->Stop();
+    delete thread_;
+    thread_ = nullptr;
+    PerformanceTest::TearDown();
+  }
+
+  base::Thread* thread_ = nullptr;
+};
+
+TEST_F(LibChromeThreadPerformanceTest, worker_thread_speed_test) {
+  g_counter = 0;
+  g_counter_promise = std::make_unique<std::promise<void>>();
+  std::future<void> counter_future = g_counter_promise->get_future();
+
+  std::chrono::steady_clock::time_point start_time =
+      std::chrono::steady_clock::now();
+
+  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
+    fixed_queue_enqueue(bt_msg_queue_, (void*)&g_counter);
+    thread_->task_runner()->PostTask(
+        FROM_HERE, base::Bind(&callback_batch, bt_msg_queue_, nullptr));
+  }
+  counter_future.wait();
+
+  std::chrono::steady_clock::time_point end_time =
+      std::chrono::steady_clock::now();
+  std::chrono::milliseconds duration =
+      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
+                                                            start_time);
+
+  LOG(INFO) << "LibChromeThreadPerformanceTest, " << duration.count() << " ms, "
+            << NUM_MESSAGES_TO_SEND << " messages";
+}
diff --git a/osi/src/time.cc b/common/time_util.cc
similarity index 73%
rename from osi/src/time.cc
rename to common/time_util.cc
index 1a47504..273be18 100644
--- a/osi/src/time.cc
+++ b/common/time_util.cc
@@ -16,28 +16,32 @@
  *
  ******************************************************************************/
 
-#define LOG_TAG "bt_osi_time"
-
 #include <sys/time.h>
 #include <time.h>
 
-#include "osi/include/time.h"
+#include "common/time_util.h"
 
-uint32_t time_get_os_boottime_ms(void) {
-  return (uint32_t)(time_get_os_boottime_us() / 1000);
-}
+namespace bluetooth {
 
-uint64_t time_get_os_boottime_us(void) {
-  struct timespec ts_now;
+namespace common {
+
+uint64_t time_get_os_boottime_ms() { return time_get_os_boottime_us() / 1000; }
+
+uint64_t time_get_os_boottime_us() {
+  struct timespec ts_now = {};
   clock_gettime(CLOCK_BOOTTIME, &ts_now);
 
   return ((uint64_t)ts_now.tv_sec * 1000000L) +
          ((uint64_t)ts_now.tv_nsec / 1000);
 }
 
-uint64_t time_gettimeofday_us(void) {
-  struct timeval tv;
-  gettimeofday(&tv, NULL);
+uint64_t time_gettimeofday_us() {
+  struct timeval tv = {};
+  gettimeofday(&tv, nullptr);
   return static_cast<uint64_t>(tv.tv_sec) * 1000000ULL +
          static_cast<uint64_t>(tv.tv_usec);
 }
+
+}  // namespace common
+
+}  // namespace bluetooth
\ No newline at end of file
diff --git a/common/time_util.h b/common/time_util.h
new file mode 100644
index 0000000..70a64d2
--- /dev/null
+++ b/common/time_util.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ *  Copyright 2015 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <cstdint>
+
+namespace bluetooth {
+
+namespace common {
+
+// Get the OS boot time in milliseconds.
+uint64_t time_get_os_boottime_ms();
+
+// Get the OS boot time in microseconds.
+uint64_t time_get_os_boottime_us();
+
+// Get the current wall clock time in microseconds.
+uint64_t time_gettimeofday_us();
+
+}  // namespace common
+
+}  // namespace bluetooth
diff --git a/common/time_util_unittest.cc b/common/time_util_unittest.cc
new file mode 100644
index 0000000..77e205d
--- /dev/null
+++ b/common/time_util_unittest.cc
@@ -0,0 +1,146 @@
+/******************************************************************************
+ *
+ *  Copyright 2015 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "common/time_util.h"
+
+// Generous upper bound: 10 seconds
+static const uint32_t TEST_TIME_DELTA_UPPER_BOUND_MS = 10 * 1000;
+
+//
+// Test that the return value of bluetooth::common::time_get_os_boottime_ms() is
+// not zero.
+//
+TEST(TimeTest, test_time_get_os_boottime_ms_not_zero) {
+  uint64_t t1 = bluetooth::common::time_get_os_boottime_ms();
+  ASSERT_GT(t1, uint64_t(0));
+}
+
+//
+// Test that the return value of bluetooth::common::time_get_os_boottime_us() is
+// not zero.
+//
+TEST(TimeTest, test_time_get_os_boottime_us_not_zero) {
+  uint64_t t1 = bluetooth::common::time_get_os_boottime_us();
+  ASSERT_GT(t1, uint64_t(0));
+}
+
+//
+// Test that the return value of bluetooth::common::time_get_os_boottime_ms()
+// is monotonically increasing within reasonable boundries.
+//
+TEST(TimeTest, test_time_get_os_boottime_ms_increases_upper_bound) {
+  uint64_t t1 = bluetooth::common::time_get_os_boottime_ms();
+  uint64_t t2 = bluetooth::common::time_get_os_boottime_ms();
+  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS);
+}
+
+//
+// Test that the return value of bluetooth::common::time_get_os_boottime_us()
+// is monotonically increasing within reasonable boundries.
+//
+TEST(TimeTest, test_time_get_os_boottime_us_increases_upper_bound) {
+  uint64_t t1 = bluetooth::common::time_get_os_boottime_us();
+  uint64_t t2 = bluetooth::common::time_get_os_boottime_us();
+  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
+}
+
+//
+// Test that the return value of bluetooth::common::time_get_os_boottime_ms()
+// is increasing.
+//
+TEST(TimeTest, test_time_get_os_boottime_ms_increases_lower_bound) {
+  static const uint32_t TEST_TIME_SLEEP_MS = 100;
+  struct timespec delay = {};
+
+  delay.tv_sec = TEST_TIME_SLEEP_MS / 1000;
+  delay.tv_nsec = 1000 * 1000 * (TEST_TIME_SLEEP_MS % 1000);
+
+  // Take two timestamps with sleep in-between
+  uint64_t t1 = bluetooth::common::time_get_os_boottime_ms();
+  int err = nanosleep(&delay, &delay);
+  uint64_t t2 = bluetooth::common::time_get_os_boottime_ms();
+
+  ASSERT_EQ(err, 0);
+  ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_MS);
+  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS);
+}
+
+//
+// Test that the return value of bluetooth::common::time_get_os_boottime_us()
+// is increasing.
+//
+TEST(TimeTest, test_time_get_os_boottime_us_increases_lower_bound) {
+  static const uint64_t TEST_TIME_SLEEP_US = 100 * 1000;
+  struct timespec delay = {};
+
+  delay.tv_sec = TEST_TIME_SLEEP_US / (1000 * 1000);
+  delay.tv_nsec = 1000 * (TEST_TIME_SLEEP_US % (1000 * 1000));
+
+  // Take two timestamps with sleep in-between
+  uint64_t t1 = bluetooth::common::time_get_os_boottime_us();
+  int err = nanosleep(&delay, &delay);
+  uint64_t t2 = bluetooth::common::time_get_os_boottime_us();
+
+  ASSERT_EQ(err, 0);
+  ASSERT_GT(t2, t1);
+  ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_US);
+  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
+}
+
+//
+// Test that the return value of bluetooth::common::time_gettimeofday_us() is
+// not zero.
+//
+TEST(TimeTest, test_time_gettimeofday_us_not_zero) {
+  uint64_t t1 = bluetooth::common::time_gettimeofday_us();
+  ASSERT_GT(t1, uint64_t(0));
+}
+
+//
+// Test that the return value of bluetooth::common::time_gettimeofday_us()
+// is monotonically increasing within reasonable boundaries.
+//
+TEST(TimeTest, test_time_gettimeofday_us_increases_upper_bound) {
+  uint64_t t1 = bluetooth::common::time_gettimeofday_us();
+  uint64_t t2 = bluetooth::common::time_gettimeofday_us();
+  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
+}
+
+//
+// Test that the return value of bluetooth::common::time_gettimeofday_us()
+// is increasing.
+//
+TEST(TimeTest, test_time_gettimeofday_us_increases_lower_bound) {
+  static const uint64_t TEST_TIME_SLEEP_US = 100 * 1000;
+  struct timespec delay = {};
+
+  delay.tv_sec = TEST_TIME_SLEEP_US / (1000 * 1000);
+  delay.tv_nsec = 1000 * (TEST_TIME_SLEEP_US % (1000 * 1000));
+
+  // Take two timestamps with sleep in-between
+  uint64_t t1 = bluetooth::common::time_gettimeofday_us();
+  int err = nanosleep(&delay, &delay);
+  uint64_t t2 = bluetooth::common::time_gettimeofday_us();
+
+  ASSERT_EQ(err, 0);
+  ASSERT_GT(t2, t1);
+  ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_US);
+  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
+}
diff --git a/common/utils.h b/common/utils.h
new file mode 100644
index 0000000..26e8f23
--- /dev/null
+++ b/common/utils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+// A macro to re-try a syscall when it receives EINTR
+#ifndef RUN_NO_INTR
+#define RUN_NO_INTR(fn) \
+  do {                  \
+  } while ((fn) == -1 && errno == EINTR)
+#endif
+
+// A macro to disallow the copy constructor and operator= functions
+#ifndef DISALLOW_COPY_AND_ASSIGN
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
+#endif
diff --git a/conf/Android.bp b/conf/Android.bp
new file mode 100644
index 0000000..ecf4922
--- /dev/null
+++ b/conf/Android.bp
@@ -0,0 +1,15 @@
+// Bluetooth bt_stack.conf config file
+// ========================================================
+prebuilt_etc {
+    name: "bt_stack.conf",
+    src: "bt_stack.conf",
+    sub_dir: "bluetooth",
+}
+
+// Bluetooth bt_did.conf config file
+// ========================================================
+prebuilt_etc {
+    name: "bt_did.conf",
+    src: "bt_did.conf",
+    sub_dir: "bluetooth",
+}
diff --git a/conf/Android.mk b/conf/Android.mk
deleted file mode 100644
index 6f5037c..0000000
--- a/conf/Android.mk
+++ /dev/null
@@ -1,24 +0,0 @@
-# Cannot convert to Android.bp as resource copying has not
-# yet implemented for soong as of 12/16/2016
-LOCAL_PATH := $(call my-dir)
-
-# Bluetooth bt_stack.conf config file
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := bt_stack.conf
-LOCAL_MODULE_CLASS := ETC
-LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/bluetooth
-LOCAL_MODULE_TAGS := optional
-LOCAL_SRC_FILES := $(LOCAL_MODULE)
-include $(BUILD_PREBUILT)
-
-# Bluetooth bt_did.conf config file
-# ========================================================
-include $(CLEAR_VARS)
-LOCAL_MODULE := bt_did.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/device/AndroidTest.xml b/device/AndroidTest.xml
deleted file mode 100644
index 0960fb4..0000000
--- a/device/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2017 The Android Open Source Project
-
-     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.
--->
-<configuration description="Config for net_test_device">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="net_test_device->/data/local/tmp/net_test_device" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="net_test_device" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/device/include/interop.h b/device/include/interop.h
index b31efc3..a9bf586 100644
--- a/device/include/interop.h
+++ b/device/include/interop.h
@@ -89,7 +89,11 @@
   // Disable role switch for headsets/car-kits.
   // Some car kits allow role switch but when the Phone initiates role switch,
   // the Remote device will go into bad state that will lead to LMP time out.
-  INTEROP_DISABLE_ROLE_SWITCH
+  INTEROP_DISABLE_ROLE_SWITCH,
+
+  // Set a very low initial sniff subrating for HID devices that do not
+  // set their own sniff interval.
+  INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL,
 } interop_feature_t;
 
 // Check if a given |addr| matches a known interoperability workaround as
diff --git a/device/include/interop_database.h b/device/include/interop_database.h
index ad1bb5a..d7425c9 100644
--- a/device/include/interop_database.h
+++ b/device/include/interop_database.h
@@ -137,6 +137,12 @@
 
     // Jeep Uconnect
     {{{0x00, 0x54, 0xaf, 0, 0, 0}}, 3, INTEROP_DISABLE_ROLE_SWITCH},
+
+    // deepblue2 - cannot change smoothly the volume: b/37834035
+    {{{0x0c, 0xa6, 0x94, 0, 0, 0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
+
+    // AirPods 2 - unacceptably loud volume
+    {{{0x94, 0x16, 0x25, 0, 0, 0}}, 3, INTEROP_DISABLE_ABSOLUTE_VOLUME},
 };
 
 typedef struct {
@@ -163,4 +169,8 @@
 
     // Kenwood KMM-BT518HD - no audio when A2DP codec sample rate is changed
     {"KMM-BT51*HD", 11, INTEROP_DISABLE_AVDTP_RECONFIGURE},
+
+    // Nintendo Switch Pro Controller - does not set sniff interval dynamically.
+    // Requires custom HID report command to change mode.
+    {"Pro Controller", 14, INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL},
 };
diff --git a/device/src/controller.cc b/device/src/controller.cc
index 02a3998..34c8afd 100644
--- a/device/src/controller.cc
+++ b/device/src/controller.cc
@@ -30,8 +30,15 @@
 #include "osi/include/future.h"
 #include "stack/include/btm_ble_api.h"
 
-const bt_event_mask_t BLE_EVENT_MASK = {
-    {0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x1E, 0x7f}};
+const bt_event_mask_t BLE_EVENT_MASK = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+#if (BLE_PRIVACY_SPT == TRUE)
+                                         0x1E,
+#else
+                                         /* Disable "LE Enhanced Connection
+                                            Complete" when privacy is off */
+                                         0x1C,
+#endif
+                                         0x7f}};
 
 const bt_event_mask_t CLASSIC_EVENT_MASK = {HCI_DUMO_EVENT_MASK_EXT};
 
diff --git a/device/src/interop.cc b/device/src/interop.cc
index c2ed2a8..e4bce56 100644
--- a/device/src/interop.cc
+++ b/device/src/interop.cc
@@ -128,6 +128,7 @@
     CASE_RETURN_STR(INTEROP_DISABLE_AVDTP_RECONFIGURE)
     CASE_RETURN_STR(INTEROP_DYNAMIC_ROLE_SWITCH)
     CASE_RETURN_STR(INTEROP_DISABLE_ROLE_SWITCH)
+    CASE_RETURN_STR(INTEROP_HID_HOST_LIMIT_SNIFF_INTERVAL)
   }
 
   return "UNKNOWN";
diff --git a/doc/power_management.md b/doc/power_management.md
index 2b90130..6803257 100644
--- a/doc/power_management.md
+++ b/doc/power_management.md
@@ -62,12 +62,12 @@
     action that `bta_dm_pm_set_mode` will take, the connection will be removed
     from `bta_dm_conn_srvcs` and no longer be considered for power management
     decisions.
-  - `BTA_DM_PM_SNIFF` through `BTA_DM_PM_SNIFF4` are special, in that each
+  - `BTA_DM_PM_SNIFF` through `BTA_DM_PM_SNIFF6` are special, in that each
     level specifies a set of parameters for the SNIFF mode which relate to the
     min and max intervals, the number of attempts and the timeout. The overall
     action is still the same, however -- SNIFF mode is attempted. There are
     definitions available up to SNIFF7, but actual SSR values are only defined
-    up to SNIFF4. Params are defined in `bta_dm_ssr_spec`.
+    up to SNIFF6. Params are defined in `bta_dm_ssr_spec`.
   - `BTA_DM_PM_ACTIVE` is full-on power.
   - `BTA_DM_PM_RETRY` has the same effect as `BTA_DM_PM_NO_ACTION`, except a
     timeout is possible to be set, which effectively allows a power operation to
diff --git a/doc/pts_guide.md b/doc/pts_guide.md
new file mode 100644
index 0000000..1e13b9d
--- /dev/null
+++ b/doc/pts_guide.md
@@ -0,0 +1,43 @@
+# Fluoride Bluetooth Profile Tuning Suite (PTS) Test Mode
+
+This document provides commands to enable PTS test mode for Fluoride stack. We
+need special handling for some test cases as they are not applicable for the
+Fluoride stack.
+
+## PTS Test Mode system property
+
+Profile services in packages/apps/Bluetooth uses system property
+`persist.bluetooth.pts` to check if the PTS test mode is enabled. To enable it:
+
+```sh
+adb shell setprop persist.bluetooth.pts true
+```
+
+To disable it:
+
+```sh
+adb shell setprop persist.bluetooth.pts false
+```
+
+### Current use case
+
+- In `newavrcp`, we send active player update to remote device only in PTS test
+  mode (AVRCP/TG/MPS/BV-05-C AVRCP/TG/MPS/BV-07-C).
+
+## PTS Helpers in stack config
+
+Native stack also requires some special handling, and the config is stored in
+`conf/bt_stack.conf`. To enable a flag, uncomment the corresponding line and
+push the config file to `/etc/bluetooth/` in IUT.
+
+### Current use case
+
+- `PTS_SecurePairOnly` enables secure connections only mode.
+- `PTS_DisableConnUpdates` disables LE Connection updates.
+- `PTS_DisableSDPOnLEPair` disables BR/EDR discovery after LE pairing to avoid
+  cross key derivation errors.
+- `PTS_SmpOptions` sets SMP Pair options (formatted as hex bytes) `auth, io,
+  ikey, rkey, ksize`.
+- `PTS_AvrcpTest` enables AVRCP test mode. The UID is set to 0xffffffffffffffff
+  in `TrackChangedNotificationResponse` (AVRCP/TG/NFY/BV-04-C).
+- `PTS_SmpFailureCase` enables handling for various SMP failure cases.
diff --git a/doc/supported_features.md b/doc/supported_features.md
index 60580e2..6063d91 100644
--- a/doc/supported_features.md
+++ b/doc/supported_features.md
@@ -15,6 +15,5 @@
 AVDTP              | 1.2     | Source, Initiator, Acceptor
 BNEP               | 1.0     |
 GAVDP              | 1.2     | Initiator, Acceptor
-MCAP               | 1.0     | Sink
 RFCOMM             | 1.2     |
 SPP                | 1.2     | A, B
diff --git a/embdrv/g722/BUILD.gn b/embdrv/g722/BUILD.gn
new file mode 100644
index 0000000..083e80b
--- /dev/null
+++ b/embdrv/g722/BUILD.gn
@@ -0,0 +1,22 @@
+#
+#  Copyright 2018 Google, Inc.
+#
+#  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.
+#
+
+static_library("g722") {
+  sources = [
+    "g722_decode.cc",
+    "g722_encode.cc",
+  ]
+}
diff --git a/gd/.clang-format b/gd/.clang-format
new file mode 100644
index 0000000..1f1f586
--- /dev/null
+++ b/gd/.clang-format
@@ -0,0 +1,28 @@
+#
+# Copyright 2016 The Android Open Source Project
+#
+# 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.
+#
+
+#
+# Below are some minor deviations from the default Google style to
+# accommodate for handling of the large legacy code base.
+#
+
+BasedOnStyle: Google
+CommentPragmas: NOLINT:.*
+DerivePointerAlignment: false
+ColumnLimit: 120
+AllowShortFunctionsOnASingleLine: Empty
+ConstructorInitializerAllOnOneLineOrOnePerLine: false
+BreakConstructorInitializers: BeforeColon
diff --git a/gd/Android.bp b/gd/Android.bp
new file mode 100644
index 0000000..e0b8d5d
--- /dev/null
+++ b/gd/Android.bp
@@ -0,0 +1,127 @@
+cc_defaults {
+    name: "gd_defaults",
+    target: {
+        android: {
+            test_config_template: "AndroidTestTemplate.xml",
+            cflags: [
+                "-DOS_ANDROID",
+                "-DOS_LINUX_GENERIC",
+            ],
+            shared_libs: [
+                "liblog"
+            ]
+        },
+        host: {
+            cflags: [
+                "-DOS_LINUX",
+                "-DOS_LINUX_GENERIC",
+            ]
+        }
+    },
+    cpp_std: "c++17",
+    cflags: [
+        "-DEXPORT_SYMBOL=__attribute__((visibility(\"default\")))",
+        "-fvisibility=hidden",
+        "-DLOG_NDEBUG=1",
+        "-DGOOGLE_PROTOBUF_NO_RTTI",
+    ],
+    conlyflags: [
+        "-std=c99",
+    ],
+    sanitize: {
+        misc_undefined: ["bounds"],
+    },
+}
+
+// Enables code coverage for a set of source files. Must be combined with
+// "clang_coverage_bin" in order to work. See //test/gen_coverage.py for more information
+// on generating code coverage.
+cc_defaults {
+    name: "gd_clang_file_coverage",
+    target: {
+        host: {
+            clang_cflags: [
+                "-fprofile-instr-generate",
+                "-fcoverage-mapping",
+            ],
+        },
+    },
+}
+
+// Enabled code coverage on a binary. These flags allow libraries that were
+// compiled with "clang_file_coverage" to be properly linked together in
+// order to create a binary that will create a profraw file when ran. Note
+// these flags themselves don't enable code coverage for the source files
+// compiled in the binary. See //test/gen_coverage.py for more information
+// on generating code coverage.
+cc_defaults {
+    name: "gd_clang_coverage_bin",
+    target: {
+        host: {
+            ldflags: [
+                "-fprofile-instr-generate",
+                "-fcoverage-mapping",
+            ],
+        },
+    },
+}
+
+cc_library {
+    name: "libbluetooth_gd",
+    defaults: [
+        "gd_defaults",
+        "gd_clang_file_coverage",
+    ],
+    host_supported: true,
+    target: {
+        linux: {
+            srcs: [
+                ":BluetoothOsSources_linux_generic",
+            ]
+        }
+    },
+    srcs: [
+        ":BluetoothCommonSources",
+        ":BluetoothPacketSources",
+    ]
+}
+
+cc_test {
+    name: "bluetooth_test_gd",
+    test_suites: ["device-tests"],
+    defaults: [
+        "gd_defaults",
+        "gd_clang_coverage_bin",
+    ],
+    host_supported: true,
+    target: {
+        linux: {
+            srcs: [
+                ":BluetoothOsTestSources_linux_generic",
+            ]
+        }
+    },
+    srcs: [
+        ":BluetoothCommonTestSources",
+        ":BluetoothPacketTestSources",
+    ],
+    static_libs : [
+        "libbluetooth_gd",
+    ],
+    sanitize: {
+        cfi: false,
+    },
+}
+
+cc_benchmark {
+    name: "bluetooth_benchmark_gd",
+    defaults: ["gd_defaults"],
+    host_supported: true,
+    srcs: [
+        "benchmark.cc",
+        ":BluetoothOsBenchmarkSources",
+    ],
+    static_libs : [
+            "libbluetooth_gd",
+    ],
+}
diff --git a/gd/AndroidTestTemplate.xml b/gd/AndroidTestTemplate.xml
new file mode 100644
index 0000000..601be93
--- /dev/null
+++ b/gd/AndroidTestTemplate.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright 2018 The Android Open Source Project
+
+     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.
+-->
+<configuration description="Runs {MODULE}.">
+  <option name="test-suite-tag" value="apct" />
+  <option name="test-suite-tag" value="apct-native" />
+  <target_preparer class="com.android.tradefed.targetprep.RootTargetPreparer" />
+  <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
+    <option name="cleanup" value="true" />
+    <option name="push" value="{MODULE}->/data/local/tmp/{MODULE}" />
+  </target_preparer>
+  <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
+    <option name="run-command" value="settings put global ble_scan_always_enabled 0" />
+    <option name="run-command" value="svc bluetooth disable" />
+  </target_preparer>
+  <target_preparer class="com.android.tradefed.targetprep.FolderSaver">
+    <option name="device-path" value="/data/vendor/ssrdump" />
+  </target_preparer>
+  <test class="com.android.tradefed.testtype.GTest" >
+    <option name="native-test-device-path" value="/data/local/tmp" />
+    <option name="module-name" value="{MODULE}" />
+    <option name="run-test-as" value="0" />
+  </test>
+</configuration>
diff --git a/gd/TEST_MAPPING b/gd/TEST_MAPPING
new file mode 100644
index 0000000..471210b
--- /dev/null
+++ b/gd/TEST_MAPPING
@@ -0,0 +1,8 @@
+{
+  "presubmit" : [
+    {
+      "name" : "bluetooth_test_gd",
+      "host" : true
+    }
+  ]
+}
diff --git a/tools/Android.bp b/gd/benchmark.cc
similarity index 66%
copy from tools/Android.bp
copy to gd/benchmark.cc
index 9f75ba7..2b11c89 100644
--- a/tools/Android.bp
+++ b/gd/benchmark.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2019 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,13 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+#include <benchmark/benchmark.h>
+
+int main(int argc, char** argv) {
+  ::benchmark::Initialize(&argc, argv);
+  if (::benchmark::ReportUnrecognizedArguments(argc, argv)) {
+    return 1;
+  }
+  ::benchmark::RunSpecifiedBenchmarks();
+}
diff --git a/gd/common/Android.bp b/gd/common/Android.bp
new file mode 100644
index 0000000..9d8c16d
--- /dev/null
+++ b/gd/common/Android.bp
@@ -0,0 +1,15 @@
+filegroup {
+    name: "BluetoothCommonSources",
+    srcs: [
+        "address.cc",
+        "class_of_device.cc",
+    ]
+}
+
+filegroup {
+    name: "BluetoothCommonTestSources",
+    srcs: [
+        "address_unittest.cc",
+        "class_of_device_unittest.cc",
+    ]
+}
diff --git a/gd/common/address.cc b/gd/common/address.cc
new file mode 100644
index 0000000..cd8101a
--- /dev/null
+++ b/gd/common/address.cc
@@ -0,0 +1,92 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "address.h"
+
+#include <stdint.h>
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
+namespace bluetooth {
+namespace common {
+
+static_assert(sizeof(Address) == 6, "Address must be 6 bytes long!");
+
+const Address Address::kAny{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+const Address Address::kEmpty{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+Address::Address(const uint8_t (&addr)[6]) {
+  std::copy(addr, addr + kLength, address);
+};
+
+std::string Address::ToString() const {
+  char buffer[] = "00:00:00:00:00:00";
+  std::snprintf(&buffer[0], sizeof(buffer),
+      "%02x:%02x:%02x:%02x:%02x:%02x", address[5], address[4], address[3], address[2], address[1], address[0]);
+  std::string str(buffer);
+  return str;
+}
+
+bool Address::FromString(const std::string& from, Address& to) {
+  Address new_addr;
+  if (from.length() != 17) {
+    return false;
+  }
+
+  std::istringstream stream(from);
+  std::string token;
+  int index = 0;
+  while (getline(stream, token, ':')) {
+    if (index >= 6) {
+      return false;
+    }
+
+    if (token.length() != 2) {
+      return false;
+    }
+
+    char* temp = nullptr;
+    new_addr.address[5 - index] = strtol(token.c_str(), &temp, 16);
+    if (*temp != '\0') {
+      return false;
+    }
+
+    index++;
+  }
+
+  if (index != 6) {
+    return false;
+  }
+
+  to = new_addr;
+  return true;
+}
+
+size_t Address::FromOctets(const uint8_t* from) {
+  std::copy(from, from + kLength, address);
+  return kLength;
+};
+
+bool Address::IsValidAddress(const std::string& address) {
+  Address tmp;
+  return Address::FromString(address, tmp);
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/gd/common/address.h b/gd/common/address.h
new file mode 100644
index 0000000..0036a59
--- /dev/null
+++ b/gd/common/address.h
@@ -0,0 +1,81 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <string>
+
+namespace bluetooth {
+namespace common {
+
+class Address final {
+ public:
+  static constexpr unsigned int kLength = 6;
+
+  uint8_t address[kLength];
+
+  Address() = default;
+  Address(const uint8_t (&addr)[6]);
+
+  bool operator<(const Address& rhs) const {
+    return (std::memcmp(address, rhs.address, sizeof(address)) < 0);
+  }
+  bool operator==(const Address& rhs) const {
+    return (std::memcmp(address, rhs.address, sizeof(address)) == 0);
+  }
+  bool operator>(const Address& rhs) const {
+    return (rhs < *this);
+  }
+  bool operator<=(const Address& rhs) const {
+    return !(*this > rhs);
+  }
+  bool operator>=(const Address& rhs) const {
+    return !(*this < rhs);
+  }
+  bool operator!=(const Address& rhs) const {
+    return !(*this == rhs);
+  }
+
+  bool IsEmpty() const {
+    return *this == kEmpty;
+  }
+
+  std::string ToString() const;
+
+  // Converts |string| to Address and places it in |to|. If |from| does
+  // not represent a Bluetooth address, |to| is not modified and this function
+  // returns false. Otherwise, it returns true.
+  static bool FromString(const std::string& from, Address& to);
+
+  // Copies |from| raw Bluetooth address octets to the local object.
+  // Returns the number of copied octets - should be always Address::kLength
+  size_t FromOctets(const uint8_t* from);
+
+  static bool IsValidAddress(const std::string& address);
+
+  static const Address kEmpty;  // 00:00:00:00:00:00
+  static const Address kAny;    // FF:FF:FF:FF:FF:FF
+};
+
+inline std::ostream& operator<<(std::ostream& os, const Address& a) {
+  os << a.ToString();
+  return os;
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/gd/common/address_unittest.cc b/gd/common/address_unittest.cc
new file mode 100644
index 0000000..cdecce3
--- /dev/null
+++ b/gd/common/address_unittest.cc
@@ -0,0 +1,199 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "common/address.h"
+
+using bluetooth::common::Address;
+
+static const char* test_addr = "bc:9a:78:56:34:12";
+static const char* test_addr2 = "21:43:65:87:a9:cb";
+
+TEST(AddressUnittest, test_constructor_array) {
+  Address bdaddr({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(AddressUnittest, test_is_empty) {
+  Address empty;
+  Address::FromString("00:00:00:00:00:00", empty);
+  ASSERT_TRUE(empty.IsEmpty());
+
+  Address not_empty;
+  Address::FromString("00:00:00:00:00:01", not_empty);
+  ASSERT_FALSE(not_empty.IsEmpty());
+}
+
+TEST(AddressUnittest, test_to_from_str) {
+  Address bdaddr;
+  Address::FromString(test_addr, bdaddr);
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(AddressUnittest, test_from_octets) {
+  static const uint8_t test_addr_array[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
+
+  Address bdaddr;
+  size_t expected_result = Address::kLength;
+  ASSERT_EQ(expected_result, bdaddr.FromOctets(test_addr_array));
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(AddressTest, test_equals) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 == bdaddr2);
+  EXPECT_FALSE(bdaddr1 != bdaddr2);
+  EXPECT_TRUE(bdaddr1 == bdaddr1);
+  EXPECT_FALSE(bdaddr1 != bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 == bdaddr3);
+  EXPECT_TRUE(bdaddr2 != bdaddr3);
+}
+
+TEST(AddressTest, test_less_than) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_FALSE(bdaddr1 < bdaddr2);
+  EXPECT_FALSE(bdaddr1 < bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_TRUE(bdaddr2 < bdaddr3);
+  EXPECT_FALSE(bdaddr3 < bdaddr2);
+}
+
+TEST(AddressTest, test_more_than) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_FALSE(bdaddr1 > bdaddr2);
+  EXPECT_FALSE(bdaddr1 > bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 > bdaddr3);
+  EXPECT_TRUE(bdaddr3 > bdaddr2);
+}
+
+TEST(AddressTest, test_less_than_or_equal) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 <= bdaddr2);
+  EXPECT_TRUE(bdaddr1 <= bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_TRUE(bdaddr2 <= bdaddr3);
+  EXPECT_FALSE(bdaddr3 <= bdaddr2);
+}
+
+TEST(AddressTest, test_more_than_or_equal) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 >= bdaddr2);
+  EXPECT_TRUE(bdaddr1 >= bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 >= bdaddr3);
+  EXPECT_TRUE(bdaddr3 >= bdaddr2);
+}
+
+TEST(AddressTest, test_copy) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address::FromString(test_addr, bdaddr1);
+  bdaddr2 = bdaddr1;
+
+  EXPECT_TRUE(bdaddr1 == bdaddr2);
+}
+
+TEST(AddressTest, IsValidAddress) {
+  EXPECT_FALSE(Address::IsValidAddress(""));
+  EXPECT_FALSE(Address::IsValidAddress("000000000000"));
+  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:0000"));
+  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:00:0"));
+  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:00:0;"));
+  EXPECT_TRUE(Address::IsValidAddress("00:00:00:00:00:00"));
+  EXPECT_TRUE(Address::IsValidAddress("AB:cd:00:00:00:00"));
+  EXPECT_FALSE(Address::IsValidAddress("aB:cD:eF:Gh:iJ:Kl"));
+}
+
+TEST(AddressTest, BdAddrFromString) {
+  Address addr;
+  memset(&addr, 0, sizeof(addr));
+
+  EXPECT_TRUE(Address::FromString("00:00:00:00:00:00", addr));
+  const Address result0 = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+  EXPECT_EQ(0, memcmp(&addr, &result0, sizeof(addr)));
+
+  EXPECT_TRUE(Address::FromString("ab:01:4C:d5:21:9f", addr));
+  const Address result1 = {{0x9f, 0x21, 0xd5, 0x4c, 0x01, 0xab}};
+  EXPECT_EQ(0, memcmp(&addr, &result1, sizeof(addr)));
+}
+
+TEST(AddressTest, BdAddrFromStringToStringEquivalent) {
+  std::string address = "c1:c2:c3:d1:d2:d3";
+  Address addr;
+
+  EXPECT_TRUE(Address::FromString(address, addr));
+  EXPECT_EQ(addr.ToString(), address);
+}
diff --git a/gd/common/class_of_device.cc b/gd/common/class_of_device.cc
new file mode 100644
index 0000000..8d7ff68
--- /dev/null
+++ b/gd/common/class_of_device.cc
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "class_of_device.h"
+
+#include <stdint.h>
+#include <algorithm>
+#include <sstream>
+#include <vector>
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace common {
+
+static_assert(sizeof(ClassOfDevice) == ClassOfDevice::kLength, "ClassOfDevice must be 3 bytes long!");
+
+ClassOfDevice::ClassOfDevice(const uint8_t (&class_of_device)[kLength]) {
+  std::copy(class_of_device, class_of_device + kLength, cod);
+};
+
+std::string ClassOfDevice::ToString() const {
+  char buffer[] = "000-0-00";
+  std::snprintf(&buffer[0], sizeof(buffer),
+      "%03x-%01x-%02x", (static_cast<uint16_t>(cod[2]) << 4) | cod[1] >> 4, cod[1] & 0x0f, cod[0]);
+  std::string str(buffer);
+  return str;
+
+}
+
+bool ClassOfDevice::FromString(const std::string& from, ClassOfDevice& to) {
+  ClassOfDevice new_cod;
+  if (from.length() != 8) return false;
+
+  std::istringstream stream(from);
+  std::string token;
+  int index = 0;
+  uint16_t values[3];
+
+  while (getline(stream, token, '-')) {
+    if (index >= 3) {
+      return false;
+    }
+
+    if (index == 0 && token.length() != 3) {
+      return false;
+    } else if (index == 1 && token.length() != 1) {
+      return false;
+    } else if (index == 2 && token.length() != 2) {
+      return false;
+    }
+    char* temp = nullptr;
+    values[index] = strtol(token.c_str(), &temp, 16);
+    if (*temp != '\0') {
+      return false;
+    }
+
+    index++;
+  }
+
+  if (index != 3) {
+    return false;
+  }
+
+  new_cod.cod[0] = values[2];
+  new_cod.cod[1] = values[1] | ((values[0] & 0xf) << 4);
+  new_cod.cod[2] = values[0] >> 4;
+
+  to = new_cod;
+  return true;
+}
+
+size_t ClassOfDevice::FromOctets(const uint8_t* from) {
+  std::copy(from, from + kLength, cod);
+  return kLength;
+};
+
+bool ClassOfDevice::IsValid(const std::string& cod) {
+  ClassOfDevice tmp;
+  return ClassOfDevice::FromString(cod, tmp);
+}
+}  // namespace common
+}  // namespace bluetooth
diff --git a/gd/common/class_of_device.h b/gd/common/class_of_device.h
new file mode 100644
index 0000000..983f128
--- /dev/null
+++ b/gd/common/class_of_device.h
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <string>
+
+namespace bluetooth {
+namespace common {
+
+class ClassOfDevice final {
+ public:
+  static constexpr unsigned int kLength = 3;
+
+  uint8_t cod[kLength];
+
+  ClassOfDevice() = default;
+  ClassOfDevice(const uint8_t (&class_of_device)[kLength]);
+
+  bool operator==(const ClassOfDevice& rhs) const {
+    return (std::memcmp(cod, rhs.cod, sizeof(cod)) == 0);
+  }
+
+  std::string ToString() const;
+
+  // Converts |string| to ClassOfDevice and places it in |to|. If |from| does
+  // not represent a Class of Device, |to| is not modified and this function
+  // returns false. Otherwise, it returns true.
+  static bool FromString(const std::string& from, ClassOfDevice& to);
+
+  // Copies |from| raw Class of Device octets to the local object.
+  // Returns the number of copied octets (always ClassOfDevice::kLength)
+  size_t FromOctets(const uint8_t* from);
+
+  static bool IsValid(const std::string& class_of_device);
+};
+
+inline std::ostream& operator<<(std::ostream& os, const ClassOfDevice& c) {
+  os << c.ToString();
+  return os;
+}
+
+}  // namespace common
+}  // namespace bluetooth
diff --git a/gd/common/class_of_device_unittest.cc b/gd/common/class_of_device_unittest.cc
new file mode 100644
index 0000000..abd4a59
--- /dev/null
+++ b/gd/common/class_of_device_unittest.cc
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "common/class_of_device.h"
+
+using bluetooth::common::ClassOfDevice;
+
+static const char* test_class = "efc-d-ab";
+static const uint8_t test_bytes[]{0xab, 0xcd, 0xef};
+
+TEST(ClassOfDeviceUnittest, test_constructor_array) {
+  ClassOfDevice cod(test_bytes);
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceUnittest, test_to_from_str) {
+  ClassOfDevice cod;
+  ClassOfDevice::FromString(test_class, cod);
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceUnittest, test_from_octets) {
+  ClassOfDevice cod;
+  size_t expected_result = ClassOfDevice::kLength;
+  ASSERT_EQ(expected_result, cod.FromOctets(test_bytes));
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceTest, test_copy) {
+  ClassOfDevice cod1;
+  ClassOfDevice cod2;
+  ClassOfDevice::FromString(test_class, cod1);
+  cod2 = cod1;
+
+  ASSERT_EQ(cod1.cod[0], cod2.cod[0]);
+  ASSERT_EQ(cod1.cod[1], cod2.cod[1]);
+  ASSERT_EQ(cod1.cod[2], cod2.cod[2]);
+}
+
+TEST(ClassOfDeviceTest, IsValid) {
+  EXPECT_FALSE(ClassOfDevice::IsValid(""));
+  EXPECT_FALSE(ClassOfDevice::IsValid("000000"));
+  EXPECT_FALSE(ClassOfDevice::IsValid("00-00-00"));
+  EXPECT_FALSE(ClassOfDevice::IsValid("000-0-0"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("000-0-00"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("ABc-d-00"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("aBc-D-eF"));
+}
+
+TEST(ClassOfDeviceTest, classOfDeviceFromString) {
+  ClassOfDevice cod;
+
+  EXPECT_TRUE(ClassOfDevice::FromString("000-0-00", cod));
+  const ClassOfDevice result0 = {{0x00, 0x00, 0x00}};
+  EXPECT_EQ(0, memcmp(&cod, &result0, sizeof(cod)));
+
+  EXPECT_TRUE(ClassOfDevice::FromString("ab2-1-4C", cod));
+  const ClassOfDevice result1 = {{0x4c, 0x21, 0xab}};
+  EXPECT_EQ(0, memcmp(&cod, &result1, sizeof(cod)));
+}
diff --git a/gd/os/Android.bp b/gd/os/Android.bp
new file mode 100644
index 0000000..535f144
--- /dev/null
+++ b/gd/os/Android.bp
@@ -0,0 +1,29 @@
+filegroup {
+    name: "BluetoothOsSources_linux_generic",
+    srcs: [
+        "linux_generic/alarm.cc",
+        "linux_generic/handler.cc",
+        "linux_generic/reactor.cc",
+        "linux_generic/repeating_alarm.cc",
+        "linux_generic/thread.cc",
+    ]
+}
+
+filegroup {
+    name: "BluetoothOsTestSources_linux_generic",
+    srcs: [
+        "linux_generic/alarm_unittest.cc",
+        "linux_generic/handler_unittest.cc",
+        "linux_generic/reactor_unittest.cc",
+        "linux_generic/repeating_alarm_unittest.cc",
+        "linux_generic/thread_unittest.cc",
+    ]
+}
+
+filegroup {
+    name: "BluetoothOsBenchmarkSources",
+    srcs: [
+        "alarm_benchmark.cc",
+        "thread_benchmark.cc",
+    ]
+}
diff --git a/gd/os/alarm.h b/gd/os/alarm.h
new file mode 100644
index 0000000..6c07474
--- /dev/null
+++ b/gd/os/alarm.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <mutex>
+
+#include "os/thread.h"
+#include "os/utils.h"
+
+namespace bluetooth {
+namespace os {
+
+// A single-shot alarm for reactor-based thread, implemented by Linux timerfd.
+// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
+// itself from the thread.
+class Alarm {
+ public:
+  // Create and register a single-shot alarm on given thread
+  explicit Alarm(Thread* thread);
+
+  // Unregister this alarm from the thread and release resource
+  ~Alarm();
+
+  DISALLOW_COPY_AND_ASSIGN(Alarm);
+
+  // Schedule the alarm with given delay
+  void Schedule(Closure task, std::chrono::milliseconds delay);
+
+  // Cancel the alarm. No-op if it's not armed.
+  void Cancel();
+
+ private:
+  Closure task_;
+  Thread* thread_;
+  int fd_ = 0;
+  Reactor::Reactable* token_;
+  mutable std::mutex mutex_;
+  void on_fire();
+};
+
+}  // namespace os
+
+}  // namespace bluetooth
diff --git a/gd/os/alarm_benchmark.cc b/gd/os/alarm_benchmark.cc
new file mode 100644
index 0000000..54b8a38
--- /dev/null
+++ b/gd/os/alarm_benchmark.cc
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <chrono>
+#include <future>
+#include <unordered_map>
+
+#include "benchmark/benchmark.h"
+
+#include "os/alarm.h"
+#include "os/repeating_alarm.h"
+#include "os/thread.h"
+
+using ::benchmark::State;
+using ::bluetooth::os::Alarm;
+using ::bluetooth::os::RepeatingAlarm;
+using ::bluetooth::os::Thread;
+
+class BM_ReactableAlarm : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    ::benchmark::Fixture::SetUp(st);
+    thread_ = std::make_unique<Thread>("timer_benchmark", Thread::Priority::REAL_TIME);
+    alarm_ = std::make_unique<Alarm>(thread_.get());
+    repeating_alarm_ = std::make_unique<RepeatingAlarm>(thread_.get());
+    map_.clear();
+    scheduled_tasks_ = 0;
+    task_length_ = 0;
+    task_interval_ = 0;
+    task_counter_ = 0;
+    promise_ = std::promise<void>();
+  }
+
+  void TearDown(State& st) override {
+    alarm_ = nullptr;
+    repeating_alarm_ = nullptr;
+    thread_->Stop();
+    thread_ = nullptr;
+    ::benchmark::Fixture::TearDown(st);
+  }
+
+  void AlarmSleepAndCountDelayedTime() {
+    auto end_time = std::chrono::steady_clock::now();
+    auto duration_since_start = std::chrono::duration_cast<std::chrono::milliseconds>(end_time - start_time_);
+    task_counter_++;
+    map_[duration_since_start.count() - task_counter_ * task_interval_]++;
+    std::this_thread::sleep_for(std::chrono::milliseconds(task_length_));
+    if (task_counter_ >= scheduled_tasks_) {
+      promise_.set_value();
+    }
+  }
+
+  void TimerFire() {
+    promise_.set_value();
+  }
+
+  int64_t scheduled_tasks_;
+  int64_t task_length_;
+  int64_t task_interval_;
+  int task_counter_;
+  std::unordered_map<int, int> map_;
+  std::promise<void> promise_;
+  std::chrono::time_point<std::chrono::steady_clock> start_time_;
+  std::unique_ptr<Thread> thread_;
+  std::unique_ptr<Alarm> alarm_;
+  std::unique_ptr<RepeatingAlarm> repeating_alarm_;
+};
+
+BENCHMARK_DEFINE_F(BM_ReactableAlarm, timer_performance_ms)(State& state) {
+  auto milliseconds = static_cast<int>(state.range(0));
+  for (auto _ : state) {
+    auto start_time_point = std::chrono::steady_clock::now();
+    alarm_->Schedule([this] { return TimerFire(); }, std::chrono::milliseconds(milliseconds));
+    promise_.get_future().get();
+    auto end_time_point = std::chrono::steady_clock::now();
+    auto duration = std::chrono::duration_cast<std::chrono::nanoseconds>(end_time_point - start_time_point);
+    state.SetIterationTime(static_cast<double>(duration.count()) * 1e-6);
+    alarm_->Cancel();
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactableAlarm, timer_performance_ms)
+    ->Arg(1)
+    ->Arg(5)
+    ->Arg(10)
+    ->Arg(20)
+    ->Arg(100)
+    ->Arg(1000)
+    ->Arg(2000)
+    ->Iterations(1)
+    ->UseRealTime();
+
+BENCHMARK_DEFINE_F(BM_ReactableAlarm, periodic_accuracy)(State& state) {
+  for (auto _ : state) {
+    scheduled_tasks_ = state.range(0);
+    task_length_ = state.range(1);
+    task_interval_ = state.range(2);
+    start_time_ = std::chrono::steady_clock::now();
+    repeating_alarm_->Schedule([this] { AlarmSleepAndCountDelayedTime(); }, std::chrono::milliseconds(task_interval_));
+    promise_.get_future().get();
+    repeating_alarm_->Cancel();
+  }
+  for (const auto& delay : map_) {
+    state.counters[std::to_string(delay.first)] = delay.second;
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactableAlarm, periodic_accuracy)
+    ->Args({2000, 1, 5})
+    ->Args({2000, 3, 5})
+    ->Args({2000, 1, 7})
+    ->Args({2000, 3, 7})
+    ->Args({2000, 1, 20})
+    ->Args({2000, 5, 20})
+    ->Args({2000, 10, 20})
+    ->Args({2000, 15, 20})
+    ->Iterations(1)
+    ->UseRealTime();
diff --git a/gd/os/handler.h b/gd/os/handler.h
new file mode 100644
index 0000000..dc6d510
--- /dev/null
+++ b/gd/os/handler.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <mutex>
+#include <queue>
+
+#include "os/thread.h"
+#include "os/utils.h"
+
+namespace bluetooth {
+namespace os {
+
+// A message-queue style handler for reactor-based thread to handle incoming events from different threads. When it's
+// constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister itself
+// from the thread.
+class Handler {
+ public:
+  // Create and register a handler on given thread
+  explicit Handler(Thread* thread);
+
+  // Unregister this handler from the thread and release resource. Unhandled events will be discarded and not executed.
+  ~Handler();
+
+  DISALLOW_COPY_AND_ASSIGN(Handler);
+
+  // Enqueue a closure to the queue of this handler
+  void Post(Closure closure);
+
+  // Remove all pending events from the queue of this handler
+  void Clear();
+
+ private:
+  std::queue<Closure> tasks_;
+  Thread* thread_;
+  int fd_;
+  Reactor::Reactable* reactable_;
+  mutable std::mutex mutex_;
+  void handle_next_event();
+};
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/alarm.cc b/gd/os/linux_generic/alarm.cc
new file mode 100644
index 0000000..b1ee5b0
--- /dev/null
+++ b/gd/os/linux_generic/alarm.cc
@@ -0,0 +1,83 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/alarm.h"
+
+#include <sys/timerfd.h>
+#include <cstring>
+#include <unistd.h>
+
+#include "os/log.h"
+#include "os/utils.h"
+
+#ifdef OS_ANDROID
+#define ALARM_CLOCK CLOCK_BOOTTIME_ALARM
+#else
+#define ALARM_CLOCK CLOCK_BOOTTIME
+#endif
+
+namespace bluetooth {
+namespace os {
+
+Alarm::Alarm(Thread* thread)
+  : thread_(thread),
+    fd_(timerfd_create(ALARM_CLOCK, 0)) {
+  ASSERT_LOG(fd_ != -1, "cannot create timerfd: %s", strerror(errno));
+
+  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
+}
+
+Alarm::~Alarm() {
+  thread_->GetReactor()->Unregister(token_);
+
+  int close_status;
+  RUN_NO_INTR(close_status = close(fd_));
+  ASSERT(close_status != -1);
+}
+
+void Alarm::Schedule(Closure task, std::chrono::milliseconds delay) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  long delay_ms = delay.count();
+  itimerspec timer_itimerspec{
+    {/* interval for periodic timer */},
+    {delay_ms / 1000, delay_ms % 1000 * 1000000}
+  };
+  int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
+  ASSERT(result == 0);
+
+  task_ = std::move(task);
+}
+
+void Alarm::Cancel() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  itimerspec disarm_itimerspec{/* disarm timer */};
+  int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
+  ASSERT(result == 0);
+}
+
+void Alarm::on_fire() {
+  std::unique_lock<std::mutex> lock(mutex_);
+  auto task = std::move(task_);
+  uint64_t times_invoked;
+  auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
+  lock.unlock();
+  task();
+  ASSERT(bytes_read == static_cast<ssize_t>(sizeof(uint64_t)));
+  ASSERT(times_invoked == static_cast<uint64_t>(1));
+}
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/alarm_unittest.cc b/gd/os/linux_generic/alarm_unittest.cc
new file mode 100644
index 0000000..3ffd0d9
--- /dev/null
+++ b/gd/os/linux_generic/alarm_unittest.cc
@@ -0,0 +1,89 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/alarm.h"
+
+#include <future>
+
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace os {
+namespace {
+
+class AlarmTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
+    alarm_ = new Alarm(thread_);
+  }
+
+  void TearDown() override {
+    delete alarm_;
+    delete thread_;
+  }
+  Alarm* alarm_;
+
+ private:
+  Thread* thread_;
+};
+
+TEST_F(AlarmTest, cancel_while_not_armed) {
+  alarm_->Cancel();
+}
+
+TEST_F(AlarmTest, schedule) {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  auto before = std::chrono::steady_clock::now();
+  int delay_ms = 10;
+  int delay_error_ms = 3;
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(delay_ms));
+  future.get();
+  auto after = std::chrono::steady_clock::now();
+  auto duration_ms = std::chrono::duration_cast<std::chrono::milliseconds>(after - before);
+  ASSERT_NEAR(duration_ms.count(), delay_ms, delay_error_ms);
+}
+
+TEST_F(AlarmTest, cancel_alarm) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(3));
+  alarm_->Cancel();
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(AlarmTest, cancel_alarm_from_callback) {
+  alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(AlarmTest, schedule_while_alarm_armed) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(1));
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
+  future.get();
+}
+
+TEST_F(AlarmTest, delete_while_alarm_armed) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false) << "Should not happen"; }, std::chrono::milliseconds(1));
+  delete alarm_;
+  alarm_ = nullptr;
+  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+}
+
+}  // namespace
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/handler.cc b/gd/os/linux_generic/handler.cc
new file mode 100644
index 0000000..cdb3240
--- /dev/null
+++ b/gd/os/linux_generic/handler.cc
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/handler.h"
+
+#include <sys/eventfd.h>
+#include <cstring>
+#include <unistd.h>
+
+#include "os/log.h"
+#include "os/reactor.h"
+#include "os/utils.h"
+
+#ifndef EFD_SEMAPHORE
+#define EFD_SEMAPHORE 1
+#endif
+
+namespace bluetooth {
+namespace os {
+
+Handler::Handler(Thread* thread)
+  : thread_(thread),
+    fd_(eventfd(0, EFD_SEMAPHORE | EFD_NONBLOCK)) {
+  ASSERT(fd_ != -1);
+
+  reactable_ = thread_->GetReactor()->Register(fd_, [this] { this->handle_next_event(); }, nullptr);
+}
+
+Handler::~Handler() {
+  thread_->GetReactor()->Unregister(reactable_);
+  reactable_ = nullptr;
+
+  int close_status;
+  RUN_NO_INTR(close_status = close(fd_));
+  ASSERT(close_status != -1);
+}
+
+void Handler::Post(Closure closure) {
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    tasks_.emplace(std::move(closure));
+  }
+  uint64_t val = 1;
+  auto write_result = eventfd_write(fd_, val);
+  ASSERT(write_result != -1);
+}
+
+void Handler::Clear() {
+  std::lock_guard<std::mutex> lock(mutex_);
+
+  std::queue<Closure> empty;
+  std::swap(tasks_, empty);
+
+  uint64_t val;
+  while (eventfd_read(fd_, &val) == 0) {
+  }
+}
+
+void Handler::handle_next_event() {
+  Closure closure;
+  uint64_t val = 0;
+  auto read_result = eventfd_read(fd_, &val);
+  if (read_result == -1 && errno == EAGAIN) {
+    // We were told there was an item, but it was removed before we got there
+    // (aka the queue was cleared). Not a fatal error, so just bail.
+    return;
+  }
+
+  ASSERT(read_result != -1);
+
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    closure = std::move(tasks_.front());
+    tasks_.pop();
+  }
+  closure();
+}
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/handler_unittest.cc b/gd/os/linux_generic/handler_unittest.cc
new file mode 100644
index 0000000..7e0488f
--- /dev/null
+++ b/gd/os/linux_generic/handler_unittest.cc
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/handler.h"
+
+#include <sys/eventfd.h>
+#include <thread>
+
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace os {
+namespace {
+
+class HandlerTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
+    handler_ = new Handler(thread_);
+  }
+  void TearDown() override {
+    delete handler_;
+    delete thread_;
+  }
+
+  Handler* handler_;
+  Thread* thread_;
+};
+
+TEST_F(HandlerTest, empty) {}
+
+TEST_F(HandlerTest, post_task_invoked) {
+  int val = 0;
+  Closure closure = [&val]() { val++; };
+  handler_->Post(closure);
+  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+  EXPECT_EQ(val, 1);
+}
+
+TEST_F(HandlerTest, post_task_cleared) {
+  int val = 0;
+  Closure closure = [&val]() {
+    val++;
+    std::this_thread::sleep_for(std::chrono::milliseconds(5));
+  };
+  handler_->Post(std::move(closure));
+  closure = []() {
+    ASSERT_TRUE(false);
+  };
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+  handler_->Post(std::move(closure));
+  handler_->Clear();
+  std::this_thread::sleep_for(std::chrono::milliseconds(10));
+  EXPECT_EQ(val, 1);
+}
+
+}  // namespace
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/reactor.cc b/gd/os/linux_generic/reactor.cc
new file mode 100644
index 0000000..dfc6757
--- /dev/null
+++ b/gd/os/linux_generic/reactor.cc
@@ -0,0 +1,210 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/reactor.h"
+
+#include <fcntl.h>
+#include <sys/epoll.h>
+#include <sys/eventfd.h>
+#include <unistd.h>
+#include <algorithm>
+#include <cerrno>
+#include <cstring>
+
+#include "os/log.h"
+
+namespace {
+
+// Use at most sizeof(epoll_event) * kEpollMaxEvents kernel memory
+constexpr int kEpollMaxEvents = 64;
+
+}  // namespace
+
+namespace bluetooth {
+namespace os {
+
+class Reactor::Reactable {
+ public:
+  Reactable(int fd, Closure on_read_ready, Closure on_write_ready)
+      : fd_(fd),
+        on_read_ready_(std::move(on_read_ready)),
+        on_write_ready_(std::move(on_write_ready)),
+        is_executing_(false) {}
+  const int fd_;
+  Closure on_read_ready_;
+  Closure on_write_ready_;
+  bool is_executing_;
+  std::recursive_mutex lock_;
+};
+
+Reactor::Reactor()
+  : epoll_fd_(0),
+    control_fd_(0),
+    is_running_(false),
+    reactable_removed_(false) {
+  RUN_NO_INTR(epoll_fd_ = epoll_create1(EPOLL_CLOEXEC));
+  ASSERT_LOG(epoll_fd_ != -1, "could not create epoll fd: %s", strerror(errno));
+
+  control_fd_ = eventfd(0, EFD_NONBLOCK);
+  ASSERT(control_fd_ != -1);
+
+  epoll_event control_epoll_event = {EPOLLIN, {.ptr = nullptr}};
+  int result;
+  RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, control_fd_, &control_epoll_event));
+  ASSERT(result != -1);
+}
+
+Reactor::~Reactor() {
+  int result;
+  RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, control_fd_, nullptr));
+  ASSERT(result != -1);
+
+  RUN_NO_INTR(result = close(control_fd_));
+  ASSERT(result != -1);
+
+  RUN_NO_INTR(result = close(epoll_fd_));
+  ASSERT(result != -1);
+}
+
+void Reactor::Run() {
+  bool previously_running = is_running_.exchange(true);
+  ASSERT(!previously_running);
+
+  for (;;) {
+    invalidation_list_.clear();
+    epoll_event events[kEpollMaxEvents];
+    int count;
+    RUN_NO_INTR(count = epoll_wait(epoll_fd_, events, kEpollMaxEvents, -1));
+    ASSERT(count != -1);
+
+    for (int i = 0; i < count; ++i) {
+      auto event = events[i];
+      ASSERT(event.events != 0u);
+
+      // If the ptr stored in epoll_event.data is nullptr, it means the control fd triggered
+      if (event.data.ptr == nullptr) {
+        uint64_t value;
+        eventfd_read(control_fd_, &value);
+        is_running_ = false;
+        return;
+      }
+      auto* reactable = static_cast<Reactor::Reactable*>(event.data.ptr);
+      {
+        std::unique_lock<std::mutex> lock(mutex_);
+        // See if this reactable has been removed in the meantime.
+        if (std::find(invalidation_list_.begin(), invalidation_list_.end(), reactable) != invalidation_list_.end()) {
+          continue;
+        }
+
+        std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
+        lock.unlock();
+        reactable_removed_ = false;
+        reactable->is_executing_ = true;
+        if (event.events & (EPOLLIN | EPOLLHUP | EPOLLRDHUP | EPOLLERR) && reactable->on_read_ready_ != nullptr) {
+          reactable->on_read_ready_();
+        }
+        if (!reactable_removed_ && event.events & EPOLLOUT && reactable->on_write_ready_ != nullptr) {
+          reactable->on_write_ready_();
+        }
+        reactable->is_executing_ = false;
+      }
+      if (reactable_removed_) {
+        delete reactable;
+      }
+    }
+  }
+}
+
+void Reactor::Stop() {
+  if (!is_running_) {
+    LOG_WARN("not running, will stop once it's started");
+  }
+  auto control = eventfd_write(control_fd_, 1);
+  ASSERT(control != -1)
+}
+
+Reactor::Reactable* Reactor::Register(int fd, Closure on_read_ready, Closure on_write_ready) {
+  uint32_t poll_event_type = 0;
+  if (on_read_ready != nullptr) {
+    poll_event_type |= (EPOLLIN | EPOLLRDHUP);
+  }
+  if (on_write_ready != nullptr) {
+    poll_event_type |= EPOLLOUT;
+  }
+  auto* reactable = new Reactable(fd, on_read_ready, on_write_ready);
+  epoll_event event = {
+      .events = poll_event_type,
+      {.ptr = reactable}
+  };
+  int register_fd;
+  RUN_NO_INTR(register_fd = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, fd, &event));
+  ASSERT(register_fd != -1)
+  return reactable;
+}
+
+void Reactor::Unregister(Reactor::Reactable* reactable) {
+  ASSERT(reactable != nullptr);
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    invalidation_list_.push_back(reactable);
+  }
+  {
+    int result;
+    std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
+    RUN_NO_INTR(result = epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, reactable->fd_, nullptr));
+    if (result == -1 && errno == ENOENT) {
+      LOG_INFO("reactable is invalid or unregistered");
+    } else {
+      ASSERT(result != -1);
+    }
+    // If we are unregistering during the callback event from this reactable, we delete it after the callback is executed.
+    // reactable->is_executing_ is protected by reactable->lock_, so it's thread safe.
+    if (reactable->is_executing_) {
+      reactable_removed_ = true;
+    }
+  }
+  // If we are unregistering outside of the callback event from this reactable, we delete it now
+  if (!reactable_removed_) {
+    delete reactable;
+  }
+}
+
+void Reactor::ModifyRegistration(Reactor::Reactable* reactable, Closure on_read_ready, Closure on_write_ready) {
+  ASSERT(reactable != nullptr);
+
+  uint32_t poll_event_type = 0;
+  if (on_read_ready != nullptr) {
+    poll_event_type |= (EPOLLIN | EPOLLRDHUP);
+  }
+  if (on_write_ready != nullptr) {
+    poll_event_type |= EPOLLOUT;
+  }
+  {
+    std::lock_guard<std::recursive_mutex> reactable_lock(reactable->lock_);
+    reactable->on_read_ready_ = std::move(on_read_ready);
+    reactable->on_write_ready_ = std::move(on_write_ready);
+  }
+  epoll_event event = {
+      .events = poll_event_type,
+      {.ptr = reactable}
+  };
+  int modify_fd;
+  RUN_NO_INTR(modify_fd = epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, reactable->fd_, &event));
+  ASSERT(modify_fd != -1);
+}
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/reactor_unittest.cc b/gd/os/linux_generic/reactor_unittest.cc
new file mode 100644
index 0000000..7fda234
--- /dev/null
+++ b/gd/os/linux_generic/reactor_unittest.cc
@@ -0,0 +1,280 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/reactor.h"
+
+#include <sys/eventfd.h>
+#include <chrono>
+#include <future>
+#include <thread>
+
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace os {
+namespace {
+
+constexpr int kReadReadyValue = 100;
+
+std::promise<int>* g_promise;
+
+class ReactorTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    g_promise = new std::promise<int>;
+    reactor_ = new Reactor;
+  }
+
+  void TearDown() override {
+    delete g_promise;
+    g_promise = nullptr;
+    delete reactor_;
+    reactor_ = nullptr;
+  }
+
+  Reactor* reactor_;
+};
+
+class SampleReactable {
+ public:
+  SampleReactable() : fd_(eventfd(0, EFD_NONBLOCK)) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  ~SampleReactable() {
+    close(fd_);
+  }
+
+  void OnReadReady() {}
+
+  void OnWriteReady() {}
+
+  int fd_;
+};
+
+class FakeReactable {
+ public:
+  enum EventFdValue {
+    kSetPromise = 1,
+    kRegisterSampleReactable,
+    kUnregisterSampleReactable,
+    kSampleOutputValue,
+  };
+  FakeReactable() : fd_(eventfd(0, 0)), reactor_(nullptr) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  FakeReactable(Reactor* reactor) : fd_(eventfd(0, 0)), reactor_(reactor) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  ~FakeReactable() {
+    close(fd_);
+  }
+
+  void OnReadReady() {
+    uint64_t value = 0;
+    auto read_result = eventfd_read(fd_, &value);
+    EXPECT_EQ(read_result, 0);
+    if (value == kSetPromise && g_promise != nullptr) {
+      g_promise->set_value(kReadReadyValue);
+    }
+    if (value == kRegisterSampleReactable) {
+      reactable_ = reactor_->Register(sample_reactable_.fd_, [this] { this->sample_reactable_.OnReadReady(); },
+                                      [this] { this->sample_reactable_.OnWriteReady(); });
+      g_promise->set_value(kReadReadyValue);
+    }
+    if (value == kUnregisterSampleReactable) {
+      reactor_->Unregister(reactable_);
+      g_promise->set_value(kReadReadyValue);
+    }
+  }
+
+  void OnWriteReady() {
+    auto write_result = eventfd_write(fd_, output_data_);
+    output_data_ = 0;
+    EXPECT_EQ(write_result, 0);
+  }
+
+  SampleReactable sample_reactable_;
+  Reactor::Reactable* reactable_ = nullptr;
+  int fd_;
+
+ private:
+  Reactor* reactor_;
+  uint64_t output_data_ = kSampleOutputValue;
+};
+
+TEST_F(ReactorTest, start_and_stop) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_->Stop();
+  reactor_thread.join();
+}
+
+TEST_F(ReactorTest, stop_and_start) {
+  auto reactor_thread = std::thread(&Reactor::Stop, reactor_);
+  auto another_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_thread.join();
+  another_thread.join();
+}
+
+TEST_F(ReactorTest, stop_multi_times) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  for (int i = 0; i < 5; i++) {
+    reactor_->Stop();
+  }
+  reactor_thread.join();
+}
+
+TEST_F(ReactorTest, cold_register_only) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, cold_register) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, hot_register_from_different_thread) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, hot_unregister_from_different_thread) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_->Unregister(reactable);
+  auto future = g_promise->get_future();
+
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kSetPromise);
+  EXPECT_EQ(write_result, 0);
+  future.wait_for(std::chrono::milliseconds(10));
+  g_promise->set_value(2);
+  EXPECT_EQ(future.get(), 2);
+  reactor_->Stop();
+  reactor_thread.join();
+}
+
+TEST_F(ReactorTest, hot_register_from_same_thread) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  FakeReactable fake_reactable(reactor_);
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, hot_unregister_from_same_thread) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  auto future = g_promise->get_future();
+
+  FakeReactable fake_reactable(reactor_);
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  auto write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kRegisterSampleReactable);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  delete g_promise;
+  g_promise = new std::promise<int>;
+  future = g_promise->get_future();
+  write_result = eventfd_write(fake_reactable.fd_, FakeReactable::kUnregisterSampleReactable);
+  EXPECT_EQ(write_result, 0);
+  EXPECT_EQ(future.get(), kReadReadyValue);
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, start_and_stop_multi_times) {
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  reactor_->Stop();
+  reactor_thread.join();
+  for (int i = 0; i < 5; i++) {
+    reactor_thread = std::thread(&Reactor::Run, reactor_);
+    reactor_->Stop();
+    reactor_thread.join();
+  }
+}
+
+TEST_F(ReactorTest, on_write_ready) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  uint64_t value = 0;
+  auto read_result = eventfd_read(fake_reactable.fd_, &value);
+  EXPECT_EQ(read_result, 0);
+  EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
+
+  reactor_->Stop();
+  reactor_thread.join();
+
+  reactor_->Unregister(reactable);
+}
+
+TEST_F(ReactorTest, modify_registration) {
+  FakeReactable fake_reactable;
+  auto* reactable =
+      reactor_->Register(fake_reactable.fd_, std::bind(&FakeReactable::OnReadReady, &fake_reactable), nullptr);
+  reactor_->ModifyRegistration(reactable, nullptr, std::bind(&FakeReactable::OnWriteReady, &fake_reactable));
+  auto reactor_thread = std::thread(&Reactor::Run, reactor_);
+  uint64_t value = 0;
+  auto read_result = eventfd_read(fake_reactable.fd_, &value);
+  EXPECT_EQ(read_result, 0);
+  EXPECT_EQ(value, FakeReactable::kSampleOutputValue);
+
+  reactor_->Stop();
+  reactor_thread.join();
+}
+
+}  // namespace
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/repeating_alarm.cc b/gd/os/linux_generic/repeating_alarm.cc
new file mode 100644
index 0000000..3258400
--- /dev/null
+++ b/gd/os/linux_generic/repeating_alarm.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/repeating_alarm.h"
+
+#include <sys/timerfd.h>
+#include <cstring>
+#include <unistd.h>
+
+#include "os/log.h"
+#include "os/utils.h"
+
+#ifdef OS_ANDROID
+#define ALARM_CLOCK CLOCK_BOOTTIME_ALARM
+#else
+#define ALARM_CLOCK CLOCK_BOOTTIME
+#endif
+
+namespace bluetooth {
+namespace os {
+
+RepeatingAlarm::RepeatingAlarm(Thread* thread)
+  : thread_(thread),
+    fd_(timerfd_create(ALARM_CLOCK, 0)) {
+  ASSERT(fd_ != -1);
+
+  token_ = thread_->GetReactor()->Register(fd_, [this] { on_fire(); }, nullptr);
+}
+
+RepeatingAlarm::~RepeatingAlarm() {
+  thread_->GetReactor()->Unregister(token_);
+
+  int close_status;
+  RUN_NO_INTR(close_status = close(fd_));
+  ASSERT(close_status != -1);
+}
+
+void RepeatingAlarm::Schedule(Closure task, std::chrono::milliseconds period) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  long period_ms = period.count();
+  itimerspec timer_itimerspec{
+    {period_ms / 1000, period_ms % 1000 * 1000000},
+    {period_ms / 1000, period_ms % 1000 * 1000000}
+  };
+  int result = timerfd_settime(fd_, 0, &timer_itimerspec, nullptr);
+  ASSERT(result == 0);
+
+  task_ = std::move(task);
+}
+
+void RepeatingAlarm::Cancel() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  itimerspec disarm_itimerspec{/* disarm timer */};
+  int result = timerfd_settime(fd_, 0, &disarm_itimerspec, nullptr);
+  ASSERT(result == 0);
+}
+
+void RepeatingAlarm::on_fire() {
+  std::unique_lock<std::mutex> lock(mutex_);
+  auto task = task_;
+  uint64_t times_invoked;
+  auto bytes_read = read(fd_, &times_invoked, sizeof(uint64_t));
+  lock.unlock();
+  task();
+  ASSERT(bytes_read == static_cast<ssize_t>(sizeof(uint64_t)));
+}
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/repeating_alarm_unittest.cc b/gd/os/linux_generic/repeating_alarm_unittest.cc
new file mode 100644
index 0000000..a017f66
--- /dev/null
+++ b/gd/os/linux_generic/repeating_alarm_unittest.cc
@@ -0,0 +1,122 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/repeating_alarm.h"
+
+#include <future>
+
+#include "gtest/gtest.h"
+
+namespace bluetooth {
+namespace os {
+namespace {
+
+constexpr int error_ms = 20;
+
+class RepeatingAlarmTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread_ = new Thread("test_thread", Thread::Priority::NORMAL);
+    alarm_ = new RepeatingAlarm(thread_);
+  }
+
+  void TearDown() override {
+    delete alarm_;
+    delete thread_;
+  }
+
+  void VerifyMultipleDelayedTasks(int scheduled_tasks, int task_length_ms, int interval_between_tasks_ms) {
+    std::promise<void> promise;
+    auto future = promise.get_future();
+    auto start_time = std::chrono::steady_clock::now();
+    int counter = 0;
+    alarm_->Schedule(
+        [&counter, &promise, start_time, scheduled_tasks, task_length_ms, interval_between_tasks_ms]() {
+          counter++;
+          auto time_now = std::chrono::steady_clock::now();
+          auto time_delta = time_now - start_time;
+          if (counter == scheduled_tasks) {
+            promise.set_value();
+          }
+          ASSERT_NEAR(time_delta.count(), interval_between_tasks_ms * 1000000 * counter, error_ms * 1000000);
+          std::this_thread::sleep_for(std::chrono::milliseconds(task_length_ms));
+        },
+        std::chrono::milliseconds(interval_between_tasks_ms));
+    future.get();
+    alarm_->Cancel();
+  }
+
+  RepeatingAlarm* alarm_;
+
+ private:
+  Thread* thread_;
+};
+
+TEST_F(RepeatingAlarmTest, cancel_while_not_armed) {
+  alarm_->Cancel();
+}
+
+TEST_F(RepeatingAlarmTest, schedule) {
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  auto before = std::chrono::steady_clock::now();
+  int period_ms = 10;
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(period_ms));
+  future.get();
+  alarm_->Cancel();
+  auto after = std::chrono::steady_clock::now();
+  auto duration = after - before;
+  ASSERT_NEAR(duration.count(), period_ms * 1000000, error_ms * 1000000);
+}
+
+TEST_F(RepeatingAlarmTest, cancel_alarm) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
+  alarm_->Cancel();
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(RepeatingAlarmTest, cancel_alarm_from_callback) {
+  alarm_->Schedule([this]() { this->alarm_->Cancel(); }, std::chrono::milliseconds(1));
+  std::this_thread::sleep_for(std::chrono::milliseconds(5));
+}
+
+TEST_F(RepeatingAlarmTest, schedule_while_alarm_armed) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
+  std::promise<void> promise;
+  auto future = promise.get_future();
+  alarm_->Schedule([&promise]() { promise.set_value(); }, std::chrono::milliseconds(10));
+  future.get();
+  alarm_->Cancel();
+}
+
+TEST_F(RepeatingAlarmTest, delete_while_alarm_armed) {
+  alarm_->Schedule([]() { ASSERT_TRUE(false); }, std::chrono::milliseconds(1));
+  delete alarm_;
+  alarm_ = nullptr;
+  std::this_thread::sleep_for(std::chrono::milliseconds(1));
+}
+
+TEST_F(RepeatingAlarmTest, verify_small) {
+  VerifyMultipleDelayedTasks(100, 1, 10);
+}
+
+TEST_F(RepeatingAlarmTest, verify_large) {
+  VerifyMultipleDelayedTasks(100, 3, 10);
+}
+
+}  // namespace
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/thread.cc b/gd/os/linux_generic/thread.cc
new file mode 100644
index 0000000..c2969fe
--- /dev/null
+++ b/gd/os/linux_generic/thread.cc
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/thread.h"
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <cerrno>
+#include <cstring>
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace os {
+
+namespace {
+constexpr int kRealTimeFifoSchedulingPriority = 1;
+}
+
+Thread::Thread(const std::string& name, const Priority priority)
+    : name_(name),
+      reactor_(),
+      running_thread_(&Thread::run, this, priority) {}
+
+void Thread::run(Priority priority) {
+  if (priority == Priority::REAL_TIME) {
+    struct sched_param rt_params = {.sched_priority = kRealTimeFifoSchedulingPriority};
+    auto linux_tid = static_cast<pid_t>(syscall(SYS_gettid));
+    int rc;
+    RUN_NO_INTR(rc = sched_setscheduler(linux_tid, SCHED_FIFO, &rt_params));
+    if (rc != 0) {
+      LOG_ERROR("unable to set SCHED_FIFO priority: %s", strerror(errno));
+    }
+  }
+  reactor_.Run();
+}
+
+Thread::~Thread() {
+  Stop();
+}
+
+bool Thread::Stop() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  ASSERT(std::this_thread::get_id() != running_thread_.get_id());
+
+  if (!running_thread_.joinable()) {
+    return false;
+  }
+  reactor_.Stop();
+  running_thread_.join();
+  return true;
+}
+
+bool Thread::IsSameThread() const {
+  return std::this_thread::get_id() == running_thread_.get_id();
+}
+
+Reactor* Thread::GetReactor() const {
+  return &reactor_;
+}
+
+std::string Thread::GetThreadName() const {
+  return name_;
+}
+
+std::string Thread::ToString() const {
+  return "Thread " + name_;
+}
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/linux_generic/thread_unittest.cc b/gd/os/linux_generic/thread_unittest.cc
new file mode 100644
index 0000000..1e16edc
--- /dev/null
+++ b/gd/os/linux_generic/thread_unittest.cc
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "os/thread.h"
+
+#include <sys/eventfd.h>
+
+#include "gtest/gtest.h"
+#include "os/reactor.h"
+
+namespace bluetooth {
+namespace os {
+namespace {
+
+constexpr int kCheckIsSameThread = 1;
+
+class SampleReactable {
+ public:
+  explicit SampleReactable(Thread* thread) : thread_(thread), fd_(eventfd(0, 0)), is_same_thread_checked_(false) {
+    EXPECT_NE(fd_, 0);
+  }
+
+  ~SampleReactable() {
+    close(fd_);
+  }
+
+  void OnReadReady() {
+    EXPECT_TRUE(thread_->IsSameThread());
+    is_same_thread_checked_ = true;
+    uint64_t val;
+    eventfd_read(fd_, &val);
+  }
+
+  bool IsSameThreadCheckDone() {
+    return is_same_thread_checked_;
+  }
+
+  Thread* thread_;
+  int fd_;
+  bool is_same_thread_checked_;
+};
+
+class ThreadTest : public ::testing::Test {
+ protected:
+  void SetUp() override {
+    thread = new Thread("test", Thread::Priority::NORMAL);
+  }
+
+  void TearDown() override {
+    delete thread;
+  }
+  Thread* thread = nullptr;
+};
+
+TEST_F(ThreadTest, just_stop_no_op) {
+  thread->Stop();
+}
+
+TEST_F(ThreadTest, thread_name) {
+  EXPECT_EQ(thread->GetThreadName(), "test");
+}
+
+TEST_F(ThreadTest, thread_to_string) {
+  EXPECT_NE(thread->ToString().find("test"), std::string::npos);
+}
+
+TEST_F(ThreadTest, not_same_thread) {
+  EXPECT_FALSE(thread->IsSameThread());
+}
+
+TEST_F(ThreadTest, same_thread) {
+  Reactor* reactor = thread->GetReactor();
+  SampleReactable sample_reactable(thread);
+  auto* reactable =
+      reactor->Register(sample_reactable.fd_, std::bind(&SampleReactable::OnReadReady, &sample_reactable), nullptr);
+  int fd = sample_reactable.fd_;
+  int write_result = eventfd_write(fd, kCheckIsSameThread);
+  EXPECT_EQ(write_result, 0);
+  while (!sample_reactable.IsSameThreadCheckDone()) std::this_thread::yield();
+  reactor->Unregister(reactable);
+}
+
+}  // namespace
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/log.h b/gd/os/log.h
new file mode 100644
index 0000000..291b17b
--- /dev/null
+++ b/gd/os/log.h
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 Google, Inc.
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#ifndef LOG_TAG
+#define LOG_TAG "bt"
+#endif
+
+#if defined(OS_ANDROID)
+
+#include <log/log.h>
+
+#define LOG_VERBOSE(fmt, args...) ALOGV("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_DEBUG(fmt, args...) ALOGD("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_INFO(fmt, args...) ALOGI("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_WARN(fmt, args...) ALOGW("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+#define LOG_ERROR(fmt, args...) ALOGE("%s: " fmt, __PRETTY_FUNCTION__, ##args)
+
+#else
+
+/* syslog didn't work well here since we would be redefining LOG_DEBUG. */
+#include <stdio.h>
+
+#define LOGWRAPPER(fmt, args...) \
+  fprintf(stderr, "%s - %s: " fmt "\n", LOG_TAG, __PRETTY_FUNCTION__, ##args)
+
+#define LOG_VERBOSE(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_DEBUG(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_INFO(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_WARN(...) LOGWRAPPER(__VA_ARGS__)
+#define LOG_ERROR(...) LOGWRAPPER(__VA_ARGS__)
+
+#endif /* defined(OS_ANDROID) */
+
+#define ASSERT(condition) \
+  if (!(condition)) { \
+    LOG_ERROR("%s:%d assertion '" #condition "' failed", __FILE__, __LINE__); \
+    abort(); \
+  }
+
+#define ASSERT_LOG(condition, fmt, args...) \
+  if (!(condition)) { \
+    LOG_ERROR("%s:%d assertion '" #condition "' failed - " fmt, __FILE__, __LINE__, ##args); \
+    abort(); \
+  }
+
diff --git a/gd/os/reactor.h b/gd/os/reactor.h
new file mode 100644
index 0000000..a0de131
--- /dev/null
+++ b/gd/os/reactor.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <sys/epoll.h>
+#include <atomic>
+#include <functional>
+#include <list>
+#include <mutex>
+#include <thread>
+
+#include "os/utils.h"
+
+namespace bluetooth {
+namespace os {
+
+// Format of closure to be used in the entire stack
+using Closure = std::function<void()>;
+
+// A simple implementation of reactor-style looper.
+// When a reactor is running, the main loop is polling and blocked until at least one registered reactable is ready to
+// read or write. It will invoke on_read_ready() or on_write_ready(), which is registered with the reactor. Then, it
+// blocks again until ready event.
+class Reactor {
+ public:
+  // An object used for Unregister() and ModifyRegistration()
+  class Reactable;
+
+  // Construct a reactor on the current thread
+  Reactor();
+
+  // Destruct this reactor and release its resources
+  ~Reactor();
+
+  DISALLOW_COPY_AND_ASSIGN(Reactor);
+
+  // Start the reactor. The current thread will be blocked until Stop() is invoked and handled.
+  void Run();
+
+  // Stop the reactor. Must be invoked from a different thread. Note: all registered reactables will not be unregistered
+  // by Stop(). If the reactor is not running, it will be stopped once it's started.
+  void Stop();
+
+  // Register a reactable fd to this reactor. Returns a pointer to a Reactable. Caller must use this object to
+  // unregister or modify registration. Ownership of the memory space is NOT transferred to user.
+  Reactable* Register(int fd, Closure on_read_ready, Closure on_write_ready);
+
+  // Unregister a reactable from this reactor
+  void Unregister(Reactable* reactable);
+
+  // Modify the registration for a reactable with given reactable
+  void ModifyRegistration(Reactable* reactable, Closure on_read_ready, Closure on_write_ready);
+
+ private:
+  mutable std::mutex mutex_;
+  int epoll_fd_;
+  int control_fd_;
+  std::atomic<bool> is_running_;
+  std::list<Reactable*> invalidation_list_;
+  bool reactable_removed_;
+};
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/repeating_alarm.h b/gd/os/repeating_alarm.h
new file mode 100644
index 0000000..776781a
--- /dev/null
+++ b/gd/os/repeating_alarm.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <mutex>
+
+#include "os/thread.h"
+#include "os/utils.h"
+
+namespace bluetooth {
+namespace os {
+
+// A repeating alarm for reactor-based thread, implemented by Linux timerfd.
+// When it's constructed, it will register a reactable on the specified thread; when it's destroyed, it will unregister
+// itself from the thread.
+class RepeatingAlarm {
+ public:
+  // Create and register a repeating alarm on given thread
+  explicit RepeatingAlarm(Thread* thread);
+
+  // Unregister this alarm from the thread and release resource
+  ~RepeatingAlarm();
+
+  DISALLOW_COPY_AND_ASSIGN(RepeatingAlarm);
+
+  // Schedule a repeating alarm with given period
+  void Schedule(Closure task, std::chrono::milliseconds period);
+
+  // Cancel the alarm. No-op if it's not armed.
+  void Cancel();
+
+ private:
+  Closure task_;
+  Thread* thread_;
+  int fd_ = 0;
+  Reactor::Reactable* token_;
+  mutable std::mutex mutex_;
+  void on_fire();
+};
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/thread.h b/gd/os/thread.h
new file mode 100644
index 0000000..d14d75e
--- /dev/null
+++ b/gd/os/thread.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <mutex>
+#include <string>
+#include <thread>
+
+#include "os/reactor.h"
+#include "os/utils.h"
+
+namespace bluetooth {
+namespace os {
+
+// Reactor-based looper thread implementation. The thread runs immediately after it is constructed, and stops after
+// Stop() is invoked. To assign task to this thread, user needs to register a reactable object to the underlying
+// reactor.
+class Thread {
+ public:
+  // Used by thread constructor. Suggest the priority to the kernel scheduler. Use REAL_TIME if we need (soft) real-time
+  // scheduling guarantee for this thread; use NORMAL if no real-time guarantee is needed to save CPU time slice for
+  // other threads
+  enum class Priority {
+    REAL_TIME,
+    NORMAL,
+  };
+
+  // name: thread name for POSIX systems
+  // priority: priority for kernel scheduler
+  Thread(const std::string& name, Priority priority);
+
+  // Stop and destroy this thread
+  ~Thread();
+
+  DISALLOW_COPY_AND_ASSIGN(Thread);
+
+  // Stop this thread. Must be invoked from another thread. After this thread is stopped, it cannot be started again.
+  bool Stop();
+
+  // Return true if this function is invoked from this thread
+  bool IsSameThread() const;
+
+  // Return the POSIX thread name
+  std::string GetThreadName() const;
+
+  // Return a user-friendly string representation of this thread object
+  std::string ToString() const;
+
+  // Return the pointer of underlying reactor. The ownership is NOT transferred.
+  Reactor* GetReactor() const;
+
+ private:
+  void run(Priority priority);
+  mutable std::mutex mutex_;
+  const std::string name_;
+  mutable Reactor reactor_;
+  std::thread running_thread_;
+};
+
+}  // namespace os
+}  // namespace bluetooth
diff --git a/gd/os/thread_benchmark.cc b/gd/os/thread_benchmark.cc
new file mode 100644
index 0000000..dc22b9d
--- /dev/null
+++ b/gd/os/thread_benchmark.cc
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <future>
+#include <memory>
+#include <thread>
+
+#include "benchmark/benchmark.h"
+
+#include "os/handler.h"
+#include "os/thread.h"
+
+using ::benchmark::State;
+using ::bluetooth::os::Handler;
+using ::bluetooth::os::Thread;
+
+#define NUM_MESSAGES_TO_SEND 100000
+
+class BM_ThreadPerformance : public ::benchmark::Fixture {
+ protected:
+  void SetUp(State& st) override {
+    benchmark::Fixture::SetUp(st);
+    counter_promise_ = std::promise<void>();
+    counter_ = 0;
+  }
+  void TearDown(State& st) override {
+    benchmark::Fixture::TearDown(st);
+  }
+  void callback_batch() {
+    counter_++;
+    if (counter_ >= num_messages_to_send_) {
+      counter_promise_.set_value();
+    }
+  }
+
+  void callback() {
+    counter_promise_.set_value();
+  }
+
+  int64_t num_messages_to_send_;
+  int64_t counter_;
+  std::promise<void> counter_promise_;
+};
+
+class BM_ReactorThread : public BM_ThreadPerformance {
+ protected:
+  void SetUp(State& st) override {
+    BM_ThreadPerformance::SetUp(st);
+    thread_ = std::make_unique<Thread>("BM_ReactorThread thread", Thread::Priority::NORMAL);
+    handler_ = std::make_unique<Handler>(thread_.get());
+  }
+  void TearDown(State& st) override {
+    handler_ = nullptr;
+    thread_->Stop();
+    thread_ = nullptr;
+    BM_ThreadPerformance::TearDown(st);
+  }
+  std::unique_ptr<Thread> thread_;
+  std::unique_ptr<Handler> handler_;
+};
+
+BENCHMARK_DEFINE_F(BM_ReactorThread, batch_enque_dequeue)(State& state) {
+  for (auto _ : state) {
+    num_messages_to_send_ = state.range(0);
+    counter_ = 0;
+    counter_promise_ = std::promise<void>();
+    std::future<void> counter_future = counter_promise_.get_future();
+    for (int i = 0; i < num_messages_to_send_; i++) {
+      handler_->Post([this]() { callback_batch(); });
+    }
+    counter_future.wait();
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactorThread, batch_enque_dequeue)
+    ->Arg(10)
+    ->Arg(1000)
+    ->Arg(10000)
+    ->Arg(100000)
+    ->Iterations(1)
+    ->UseRealTime();
+
+BENCHMARK_DEFINE_F(BM_ReactorThread, sequential_execution)(State& state) {
+  for (auto _ : state) {
+    num_messages_to_send_ = state.range(0);
+    for (int i = 0; i < num_messages_to_send_; i++) {
+      counter_promise_ = std::promise<void>();
+      std::future<void> counter_future = counter_promise_.get_future();
+      handler_->Post([this]() { callback(); });
+      counter_future.wait();
+    }
+  }
+};
+
+BENCHMARK_REGISTER_F(BM_ReactorThread, sequential_execution)
+    ->Arg(10)
+    ->Arg(1000)
+    ->Arg(10000)
+    ->Arg(100000)
+    ->Iterations(1)
+    ->UseRealTime();
diff --git a/gd/os/utils.h b/gd/os/utils.h
new file mode 100644
index 0000000..26e8f23
--- /dev/null
+++ b/gd/os/utils.h
@@ -0,0 +1,31 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+// A macro to re-try a syscall when it receives EINTR
+#ifndef RUN_NO_INTR
+#define RUN_NO_INTR(fn) \
+  do {                  \
+  } while ((fn) == -1 && errno == EINTR)
+#endif
+
+// A macro to disallow the copy constructor and operator= functions
+#ifndef DISALLOW_COPY_AND_ASSIGN
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+  TypeName(const TypeName&) = delete;      \
+  void operator=(const TypeName&) = delete
+#endif
diff --git a/gd/packet/Android.bp b/gd/packet/Android.bp
new file mode 100644
index 0000000..be5a3c9
--- /dev/null
+++ b/gd/packet/Android.bp
@@ -0,0 +1,20 @@
+filegroup {
+    name: "BluetoothPacketSources",
+    srcs: [
+        "bit_inserter.cc",
+        "iterator.cc",
+        "packet_view.cc",
+        "raw_builder.cc",
+        "view.cc",
+    ],
+}
+
+filegroup {
+    name: "BluetoothPacketTestSources",
+    srcs: [
+        "bit_inserter_unittest.cc",
+        "packet_builder_unittest.cc",
+        "packet_view_unittest.cc",
+        "raw_builder_unittest.cc",
+    ],
+}
diff --git a/gd/packet/base_packet_builder.h b/gd/packet/base_packet_builder.h
new file mode 100644
index 0000000..f093385
--- /dev/null
+++ b/gd/packet/base_packet_builder.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include "packet/bit_inserter.h"
+
+namespace bluetooth {
+namespace packet {
+
+// A little-endian PacketBuilder can contain a big-endian PacketBuilder,
+// so BasePacketBuilder provides a common base class.
+class BasePacketBuilder {
+ public:
+  virtual ~BasePacketBuilder() = default;
+
+  virtual size_t size() const = 0;
+
+  // Write to the vector with the given iterator.
+  virtual void Serialize(BitInserter& it) const = 0;
+
+ protected:
+  BasePacketBuilder() = default;
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/bit_inserter.cc b/gd/packet/bit_inserter.cc
new file mode 100644
index 0000000..5167806
--- /dev/null
+++ b/gd/packet/bit_inserter.cc
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/iterator.h"
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace packet {
+
+template <bool little_endian>
+Iterator<little_endian>::Iterator(std::forward_list<View> data, size_t offset) {
+  data_ = data;
+  index_ = offset;
+  length_ = 0;
+  for (auto& view : data) {
+    length_ += view.size();
+  }
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator+(int offset) {
+  auto itr(*this);
+
+  return itr += offset;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator+=(int offset) {
+  index_ += offset;
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator++(int) {
+  auto itr(*this);
+  index_++;
+  return itr;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator++() {
+  index_++;
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator-(int offset) {
+  auto itr(*this);
+
+  return itr -= offset;
+}
+
+template <bool little_endian>
+int Iterator<little_endian>::operator-(Iterator<little_endian>& itr) {
+  return index_ - itr.index_;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator-=(int offset) {
+  index_ -= offset;
+
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator--(int) {
+  auto itr(*this);
+  if (index_ != 0) index_--;
+
+  return itr;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator--() {
+  if (index_ != 0) index_--;
+
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator=(const Iterator<little_endian>& itr) {
+  data_ = itr.data_;
+  index_ = itr.index_;
+
+  return *this;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator==(const Iterator<little_endian>& itr) const {
+  return index_ == itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator!=(const Iterator<little_endian>& itr) const {
+  return !(*this == itr);
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator<(const Iterator<little_endian>& itr) const {
+  return index_ < itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator>(const Iterator<little_endian>& itr) const {
+  return index_ > itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator<=(const Iterator<little_endian>& itr) const {
+  return index_ <= itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator>=(const Iterator<little_endian>& itr) const {
+  return index_ >= itr.index_;
+}
+
+template <bool little_endian>
+uint8_t Iterator<little_endian>::operator*() const {
+  ASSERT_LOG(index_ < length_, "Index %zu out of bounds: %zu", index_, length_);
+  size_t index = index_;
+
+  for (auto view : data_) {
+    if (index < view.size()) {
+      return view[index];
+    }
+    index -= view.size();
+  }
+  ASSERT_LOG(false, "Out of fragments searching for index %zu", index_);
+  return 0;
+}
+
+template <bool little_endian>
+size_t Iterator<little_endian>::NumBytesRemaining() const {
+  if (length_ > index_) {
+    return length_ - index_;
+  } else {
+    return 0;
+  }
+}
+
+// Explicit instantiations for both types of Iterators.
+template class Iterator<true>;
+template class Iterator<false>;
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/bit_inserter.h b/gd/packet/bit_inserter.h
new file mode 100644
index 0000000..9034e38
--- /dev/null
+++ b/gd/packet/bit_inserter.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace packet {
+
+class BitInserter : public std::back_insert_iterator<std::vector<uint8_t>> {
+ public:
+  BitInserter(std::vector<uint8_t>& vector) : std::back_insert_iterator<std::vector<uint8_t>>(vector) {}
+  virtual ~BitInserter() {
+    ASSERT(num_saved_bits_ == 0);
+  }
+
+  void insert_bits(uint8_t byte, size_t num_bits) {
+    size_t total_bits = num_bits + num_saved_bits_;
+    uint16_t new_value = saved_bits_ | (static_cast<uint16_t>(byte) << num_saved_bits_);
+    if (total_bits >= 8) {
+      uint8_t new_byte = static_cast<uint8_t>(new_value);
+      std::back_insert_iterator<std::vector<uint8_t>>::operator=(new_byte);
+      total_bits -= 8;
+      new_value = new_value >> 8;
+    }
+    num_saved_bits_ = total_bits;
+    uint8_t mask = 0xff >> (8 - num_saved_bits_);
+    saved_bits_ = static_cast<uint8_t>(new_value) & mask;
+  }
+
+  void insert_byte(uint8_t byte) {
+    insert_bits(byte, 8);
+  }
+
+  bool IsByteAligned() {
+    return num_saved_bits_ == 0;
+  }
+
+ private:
+  size_t num_saved_bits_{0};
+  uint8_t saved_bits_{0};
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/bit_inserter_unittest.cc b/gd/packet/bit_inserter_unittest.cc
new file mode 100644
index 0000000..6a3b668
--- /dev/null
+++ b/gd/packet/bit_inserter_unittest.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/bit_inserter.h"
+
+#include <gtest/gtest.h>
+#include <memory>
+
+#include "os/log.h"
+
+using bluetooth::packet::BitInserter;
+using std::vector;
+
+namespace bluetooth {
+namespace packet {
+
+class BitInserterTest : public ::testing::Test {
+ public:
+  BitInserterTest() {}
+  ~BitInserterTest() = default;
+};
+
+TEST(BitInserterTest, addMoreBits) {
+  std::vector<uint8_t> bytes;
+  BitInserter it(bytes);
+
+  for (size_t i = 0; i < 9; i++) {
+    it.insert_bits(static_cast<uint8_t>(i), i);
+  }
+  it.insert_bits(static_cast<uint8_t>(0b1010), 4);
+  std::vector<uint8_t> result = {
+      0b00011101 /* 3 2 1 */,
+      0b00010101 /* 5 4 */,
+      0b11100011 /* 7 6 */,
+      0b10000000 /* 8 */,
+      0b10100000 /* filled with 1010 */};
+
+  ASSERT_EQ(result.size(), bytes.size());
+  for (size_t i = 0; i < bytes.size(); i++) {
+    ASSERT_EQ(result[i], bytes[i]);
+  }
+}
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/iterator.cc b/gd/packet/iterator.cc
new file mode 100644
index 0000000..5167806
--- /dev/null
+++ b/gd/packet/iterator.cc
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/iterator.h"
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace packet {
+
+template <bool little_endian>
+Iterator<little_endian>::Iterator(std::forward_list<View> data, size_t offset) {
+  data_ = data;
+  index_ = offset;
+  length_ = 0;
+  for (auto& view : data) {
+    length_ += view.size();
+  }
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator+(int offset) {
+  auto itr(*this);
+
+  return itr += offset;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator+=(int offset) {
+  index_ += offset;
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator++(int) {
+  auto itr(*this);
+  index_++;
+  return itr;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator++() {
+  index_++;
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator-(int offset) {
+  auto itr(*this);
+
+  return itr -= offset;
+}
+
+template <bool little_endian>
+int Iterator<little_endian>::operator-(Iterator<little_endian>& itr) {
+  return index_ - itr.index_;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator-=(int offset) {
+  index_ -= offset;
+
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator--(int) {
+  auto itr(*this);
+  if (index_ != 0) index_--;
+
+  return itr;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator--() {
+  if (index_ != 0) index_--;
+
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator=(const Iterator<little_endian>& itr) {
+  data_ = itr.data_;
+  index_ = itr.index_;
+
+  return *this;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator==(const Iterator<little_endian>& itr) const {
+  return index_ == itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator!=(const Iterator<little_endian>& itr) const {
+  return !(*this == itr);
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator<(const Iterator<little_endian>& itr) const {
+  return index_ < itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator>(const Iterator<little_endian>& itr) const {
+  return index_ > itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator<=(const Iterator<little_endian>& itr) const {
+  return index_ <= itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator>=(const Iterator<little_endian>& itr) const {
+  return index_ >= itr.index_;
+}
+
+template <bool little_endian>
+uint8_t Iterator<little_endian>::operator*() const {
+  ASSERT_LOG(index_ < length_, "Index %zu out of bounds: %zu", index_, length_);
+  size_t index = index_;
+
+  for (auto view : data_) {
+    if (index < view.size()) {
+      return view[index];
+    }
+    index -= view.size();
+  }
+  ASSERT_LOG(false, "Out of fragments searching for index %zu", index_);
+  return 0;
+}
+
+template <bool little_endian>
+size_t Iterator<little_endian>::NumBytesRemaining() const {
+  if (length_ > index_) {
+    return length_ - index_;
+  } else {
+    return 0;
+  }
+}
+
+// Explicit instantiations for both types of Iterators.
+template class Iterator<true>;
+template class Iterator<false>;
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/iterator.h b/gd/packet/iterator.h
new file mode 100644
index 0000000..56d8708
--- /dev/null
+++ b/gd/packet/iterator.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+
+#include "packet/view.h"
+
+namespace bluetooth {
+namespace packet {
+
+// Templated Iterator for endianness
+template <bool little_endian>
+class Iterator : public std::iterator<std::random_access_iterator_tag, uint8_t> {
+ public:
+  Iterator(std::forward_list<View> data, size_t offset);
+  Iterator(const Iterator& itr) = default;
+  virtual ~Iterator() = default;
+
+  // All addition and subtraction operators are unbounded.
+  Iterator operator+(int offset);
+  Iterator& operator+=(int offset);
+  Iterator operator++(int);
+  Iterator& operator++();
+
+  Iterator operator-(int offset);
+  int operator-(Iterator& itr);
+  Iterator& operator-=(int offset);
+  Iterator operator--(int);
+  Iterator& operator--();
+
+  Iterator& operator=(const Iterator& itr);
+
+  bool operator!=(const Iterator& itr) const;
+  bool operator==(const Iterator& itr) const;
+
+  bool operator<(const Iterator& itr) const;
+  bool operator>(const Iterator& itr) const;
+
+  bool operator<=(const Iterator& itr) const;
+  bool operator>=(const Iterator& itr) const;
+
+  uint8_t operator*() const;
+  uint8_t operator->() const;
+
+  size_t NumBytesRemaining() const;
+
+  // Get the next sizeof(FixedWidthPODType) bytes and return the filled type
+  template <typename FixedWidthPODType>
+  FixedWidthPODType extract() {
+    static_assert(std::is_pod<FixedWidthPODType>::value, "Iterator::extract requires an fixed type.");
+    FixedWidthPODType extracted_value;
+    uint8_t* value_ptr = (uint8_t*)&extracted_value;
+
+    for (size_t i = 0; i < sizeof(FixedWidthPODType); i++) {
+      size_t index = (little_endian ? i : sizeof(FixedWidthPODType) - i - 1);
+      value_ptr[index] = *((*this)++);
+    }
+    return extracted_value;
+  }
+
+ private:
+  std::forward_list<View> data_;
+  size_t index_;
+  size_t length_;
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/packet_builder.h b/gd/packet/packet_builder.h
new file mode 100644
index 0000000..2a27cc4
--- /dev/null
+++ b/gd/packet/packet_builder.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include "common/address.h"
+#include "common/class_of_device.h"
+#include "os/log.h"
+#include "packet/base_packet_builder.h"
+#include "packet/bit_inserter.h"
+
+namespace bluetooth {
+namespace packet {
+
+// Abstract base class that is subclassed to build specifc packets.
+// The template parameter little_endian controls the generation of insert().
+template <bool little_endian>
+class PacketBuilder : public BasePacketBuilder {
+ public:
+  PacketBuilder() = default;
+  virtual ~PacketBuilder() = default;
+
+  // Classes which need fragmentation should define a function like this:
+  // std::forward_list<DerivedBuilder>& Fragment(size_t max_size);
+
+ protected:
+  // Write sizeof(FixedWidthIntegerType) bytes using the iterator
+  template <typename FixedWidthIntegerType,
+            typename std::enable_if<std::is_integral<FixedWidthIntegerType>::value, int>::type = 0>
+  void insert(FixedWidthIntegerType value, BitInserter& it) const {
+    for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
+      if (little_endian == true) {
+        it.insert_byte(static_cast<uint8_t>(value >> (i * 8)));
+      } else {
+        it.insert_byte(static_cast<uint8_t>(value >> ((sizeof(FixedWidthIntegerType) - i - 1) * 8)));
+      }
+    }
+  }
+
+  // Write num_bits bits using the iterator
+  template <typename FixedWidthIntegerType,
+            typename std::enable_if<std::is_integral<FixedWidthIntegerType>::value, int>::type = 0>
+  void insert(FixedWidthIntegerType value, BitInserter& it, size_t num_bits) const {
+    ASSERT(num_bits <= (sizeof(FixedWidthIntegerType) * 8));
+
+    for (size_t i = 0; i < num_bits / 8; i++) {
+      if (little_endian == true) {
+        it.insert_byte(static_cast<uint8_t>(value >> (i * 8)));
+      } else {
+        it.insert_byte(static_cast<uint8_t>(value >> (((num_bits / 8) - i - 1) * 8)));
+      }
+    }
+    if (num_bits % 8) {
+      it.insert_bits(static_cast<uint8_t>(value >> ((num_bits / 8) * 8)), num_bits % 8);
+    }
+  }
+
+  // Specialized insert that allows inserting enums without casting
+  template <typename Enum, typename std::enable_if<std::is_enum_v<Enum>, int>::type = 0>
+  inline void insert(Enum value, BitInserter& it) const {
+    using enum_type = typename std::underlying_type_t<Enum>;
+    static_assert(std::is_unsigned_v<enum_type>, "Enum type is signed. Did you forget to specify the enum size?");
+    insert<enum_type>(static_cast<enum_type>(value), it);
+  }
+
+  // Write a vector of FixedWidthIntegerType using the iterator
+  template <typename FixedWidthIntegerType>
+  void insert_vector(const std::vector<FixedWidthIntegerType>& vec, BitInserter& it) const {
+    static_assert(std::is_integral<FixedWidthIntegerType>::value,
+                  "PacketBuilder::insert requires an integral type vector.");
+    for (const auto& element : vec) {
+      insert(element, it);
+    }
+  }
+
+  void insert_address(const common::Address& addr, BitInserter& it) const {
+    for (const auto& element : addr.address) {
+      insert(element, it);
+    }
+  }
+
+  void insert_class_of_device(const common::ClassOfDevice& cod, BitInserter& it) const {
+    for (const auto& element : cod.cod) {
+      insert(element, it);
+    }
+  }
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/packet_builder_unittest.cc b/gd/packet/packet_builder_unittest.cc
new file mode 100644
index 0000000..74a27e6
--- /dev/null
+++ b/gd/packet/packet_builder_unittest.cc
@@ -0,0 +1,247 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+using bluetooth::packet::BasePacketBuilder;
+using bluetooth::packet::BitInserter;
+using bluetooth::packet::PacketBuilder;
+using std::vector;
+
+namespace {
+vector<uint8_t> count_all = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> count_1 = {
+    0x00,
+    0x01,
+    0x02,
+};
+
+vector<uint8_t> count_2 = {
+    0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+vector<uint8_t> count_3 = {
+    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+}  // namespace
+
+namespace bluetooth {
+namespace packet {
+
+template <bool little_endian>
+class EndianBuilder : public PacketBuilder<little_endian> {
+ public:
+  EndianBuilder(uint8_t byte, uint16_t two_bytes, uint32_t four_bytes, uint64_t eight_bytes)
+      : byte_(byte), two_bytes_(two_bytes), four_bytes_(four_bytes), eight_bytes_(eight_bytes) {}
+  ~EndianBuilder() = default;
+
+  virtual size_t size() const override {
+    return sizeof(signature_) + sizeof(byte_) + sizeof(two_bytes_) + sizeof(four_bytes_) + sizeof(eight_bytes_);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    BitInserter it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(BitInserter& it) const override {
+    PacketBuilder<little_endian>::insert(signature_, it);
+    PacketBuilder<little_endian>::insert(byte_, it);
+    PacketBuilder<little_endian>::insert(two_bytes_, it);
+    PacketBuilder<little_endian>::insert(four_bytes_, it);
+    PacketBuilder<little_endian>::insert(eight_bytes_, it);
+  }
+
+ private:
+  uint32_t signature_{(little_endian ? 0x03020100 : 0x00010203)};
+  uint8_t byte_;
+  uint16_t two_bytes_;
+  uint32_t four_bytes_;
+  uint64_t eight_bytes_;
+};
+
+class PacketBuilderEndianTest : public ::testing::Test {
+ public:
+  PacketBuilderEndianTest() = default;
+  ~PacketBuilderEndianTest() = default;
+};
+
+TEST(PacketBuilderEndianTest, insertTest) {
+  EndianBuilder<true> little(0x04, 0x0605, 0x0a090807, 0x1211100f0e0d0c0b);
+  EndianBuilder<false> big(0x04, 0x0506, 0x0708090a, 0x0b0c0d0e0f101112);
+  ASSERT_EQ(*big.FinalPacket(), *little.FinalPacket());
+}
+
+template <typename T>
+class VectorBuilder : public PacketBuilder<true> {
+ public:
+  VectorBuilder(std::vector<uint64_t> vect) {
+    for (uint64_t element : vect) {
+      vect.push_back(static_cast<T>(element));
+    }
+  }
+  ~VectorBuilder() = default;
+
+  virtual size_t size() const override {
+    return vect_.size() * sizeof(T);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    BitInserter it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(BitInserter& it) const override {
+    PacketBuilder<true>::insert_vector(vect_, it);
+  }
+
+ private:
+  std::vector<T> vect_;
+};
+
+template <typename T>
+class InsertElementsBuilder : public PacketBuilder<true> {
+ public:
+  InsertElementsBuilder(std::vector<uint64_t> vect) {
+    for (uint64_t element : vect) {
+      vect.push_back(static_cast<T>(element));
+    }
+  }
+  virtual ~InsertElementsBuilder() = default;
+
+  virtual size_t size() const override {
+    return vect_.size() * sizeof(T);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    BitInserter it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(BitInserter& it) const override {
+    for (T elem : vect_) {
+      PacketBuilder<true>::insert(elem, it);
+    }
+  }
+
+ private:
+  std::vector<T> vect_;
+};
+
+std::vector<uint64_t> vector_data{
+    0x7060504030201000, 0x7161514131211101, 0x7262524232221202, 0x7363534333231303, 0x7464544434241404,
+    0x7565554535251505, 0x7666564636261606, 0x7767574737271707, 0x7868584838281808,
+};
+
+template <typename T>
+class VectorBuilderTest : public ::testing::Test {
+ public:
+  VectorBuilderTest() = default;
+  ~VectorBuilderTest() = default;
+
+  void SetUp() {
+    packet_1_ = std::shared_ptr<VectorBuilder<T>>(new VectorBuilder<T>(vector_data));
+    packet_2_ = std::shared_ptr<InsertElementsBuilder<T>>(new InsertElementsBuilder<T>(vector_data));
+  }
+
+  void TearDown() {
+    packet_1_.reset();
+    packet_2_.reset();
+  }
+
+  std::shared_ptr<VectorBuilder<T>> packet_1_;
+  std::shared_ptr<InsertElementsBuilder<T>> packet_2_;
+};
+
+using VectorBaseTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t>;
+TYPED_TEST_CASE(VectorBuilderTest, VectorBaseTypes);
+
+TYPED_TEST(VectorBuilderTest, insertVectorTest) {
+  ASSERT_EQ(*(this->packet_1_->FinalPacket()), *(this->packet_2_->FinalPacket()));
+}
+
+class NestedBuilder : public PacketBuilder<true> {
+ public:
+  ~NestedBuilder() = default;
+
+  virtual size_t size() const override {
+    size_t payload_size = (payload_ ? payload_->size() : 0);
+    return 1 + payload_size;
+  }
+
+  static std::unique_ptr<NestedBuilder> Create(uint8_t level) {
+    return std::unique_ptr<NestedBuilder>(new NestedBuilder(level));
+  }
+
+  static std::unique_ptr<NestedBuilder> CreateNested(std::unique_ptr<BasePacketBuilder> payload, uint8_t level) {
+    return std::unique_ptr<NestedBuilder>(new NestedBuilder(std::move(payload), level));
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    BitInserter it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(BitInserter& it) const override {
+    PacketBuilder<true>::insert(level_, it);
+    if (payload_) {
+      payload_->Serialize(it);
+    }
+  }
+
+ private:
+  std::unique_ptr<BasePacketBuilder> payload_;
+  uint8_t level_;
+
+  NestedBuilder(std::unique_ptr<BasePacketBuilder> inner, uint8_t level) : payload_(std::move(inner)), level_(level) {}
+  NestedBuilder(uint8_t level) : level_(level) {}
+};
+
+class BuilderBuilderTest : public ::testing::Test {};
+
+TEST(BuilderBuilderTest, nestingTest) {
+  std::unique_ptr<BasePacketBuilder> innermost = NestedBuilder::Create(0);
+  std::unique_ptr<BasePacketBuilder> number_1 = NestedBuilder::CreateNested(std::move(innermost), 1);
+  std::unique_ptr<BasePacketBuilder> number_2 = NestedBuilder::CreateNested(std::move(number_1), 2);
+  std::unique_ptr<BasePacketBuilder> number_3 = NestedBuilder::CreateNested(std::move(number_2), 3);
+  std::unique_ptr<BasePacketBuilder> number_4 = NestedBuilder::CreateNested(std::move(number_3), 4);
+  std::unique_ptr<NestedBuilder> number_5 = NestedBuilder::CreateNested(std::move(number_4), 5);
+
+  std::vector<uint8_t> count_down{5, 4, 3, 2, 1, 0};
+  ASSERT_EQ(*number_5->FinalPacket(), count_down);
+}
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/packet_view.cc b/gd/packet/packet_view.cc
new file mode 100644
index 0000000..94522ae
--- /dev/null
+++ b/gd/packet/packet_view.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/packet_view.h"
+
+#include <algorithm>
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace packet {
+
+template <bool little_endian>
+PacketView<little_endian>::PacketView(const std::forward_list<class View> fragments)
+    : fragments_(fragments), length_(0) {
+  for (auto fragment : fragments_) {
+    length_ += fragment.size();
+  }
+}
+
+template <bool little_endian>
+PacketView<little_endian>::PacketView(std::shared_ptr<std::vector<uint8_t>> packet)
+    : fragments_({View(packet, 0, packet->size())}), length_(packet->size()) {}
+
+template <bool little_endian>
+Iterator<little_endian> PacketView<little_endian>::begin() const {
+  return Iterator<little_endian>(this->fragments_, 0);
+}
+
+template <bool little_endian>
+Iterator<little_endian> PacketView<little_endian>::end() const {
+  return Iterator<little_endian>(this->fragments_, size());
+}
+
+template <bool little_endian>
+uint8_t PacketView<little_endian>::operator[](size_t index) const {
+  return at(index);
+}
+
+template <bool little_endian>
+uint8_t PacketView<little_endian>::at(size_t index) const {
+  ASSERT_LOG(index < length_, "Index %zu out of bounds", index);
+  for (const auto& fragment : fragments_) {
+    if (index < fragment.size()) {
+      return fragment[index];
+    }
+    index -= fragment.size();
+  }
+  ASSERT_LOG(false, "Out of fragments searching for index %zu", index);
+  return 0;
+}
+
+template <bool little_endian>
+size_t PacketView<little_endian>::size() const {
+  return length_;
+}
+
+template <bool little_endian>
+std::forward_list<View> PacketView<little_endian>::GetSubviewList(size_t begin, size_t end) const {
+  ASSERT(begin <= end);
+  ASSERT(end <= length_);
+
+  std::forward_list<View> view_list;
+  std::forward_list<View>::iterator it = view_list.before_begin();
+  size_t length = end - begin;
+  for (const auto& fragment : fragments_) {
+    if (begin >= fragment.size()) {
+      begin -= fragment.size();
+    } else {
+      View view(fragment, begin, begin + std::min(length, fragment.size() - begin));
+      length -= view.size();
+      it = view_list.insert_after(it, view);
+      begin = 0;
+    }
+  }
+  return view_list;
+}
+
+template <bool little_endian>
+PacketView<true> PacketView<little_endian>::GetLittleEndianSubview(size_t begin, size_t end) const {
+  return PacketView<true>(GetSubviewList(begin, end));
+}
+
+template <bool little_endian>
+PacketView<false> PacketView<little_endian>::GetBigEndianSubview(size_t begin, size_t end) const {
+  return PacketView<false>(GetSubviewList(begin, end));
+}
+
+// Explicit instantiations for both types of PacketViews.
+template class PacketView<true>;
+template class PacketView<false>;
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/packet_view.h b/gd/packet/packet_view.h
new file mode 100644
index 0000000..4b2f191
--- /dev/null
+++ b/gd/packet/packet_view.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+
+#include "packet/iterator.h"
+#include "packet/view.h"
+
+namespace bluetooth {
+namespace packet {
+
+static const bool kLittleEndian = true;
+
+// Abstract base class that is subclassed to provide type-specifc accessors.
+// Holds a shared pointer to the underlying data.
+// The template parameter little_endian controls the generation of extract().
+template <bool little_endian>
+class PacketView {
+ public:
+  PacketView(const std::forward_list<class View> fragments);
+  PacketView(const PacketView& PacketView) = default;
+  PacketView(std::shared_ptr<std::vector<uint8_t>> packet);
+  virtual ~PacketView() = default;
+
+  virtual Iterator<little_endian> begin() const;
+
+  virtual Iterator<little_endian> end() const;
+
+  uint8_t operator[](size_t i) const;
+
+  uint8_t at(size_t index) const;
+
+  size_t size() const;
+
+  PacketView<true> GetLittleEndianSubview(size_t begin, size_t end) const;
+
+  PacketView<false> GetBigEndianSubview(size_t begin, size_t end) const;
+
+ private:
+  std::forward_list<View> fragments_;
+  size_t length_;
+  PacketView<little_endian>() = delete;
+  std::forward_list<View> GetSubviewList(size_t begin, size_t end) const;
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/packet_view_unittest.cc b/gd/packet/packet_view_unittest.cc
new file mode 100644
index 0000000..e88c2cf
--- /dev/null
+++ b/gd/packet/packet_view_unittest.cc
@@ -0,0 +1,510 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/packet_view.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "common/address.h"
+
+using bluetooth::common::Address;
+using bluetooth::packet::PacketView;
+using bluetooth::packet::View;
+using std::vector;
+
+namespace {
+vector<uint8_t> count_all = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> count_1 = {
+    0x00,
+    0x01,
+    0x02,
+};
+
+vector<uint8_t> count_2 = {
+    0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+vector<uint8_t> count_3 = {
+    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+}  // namespace
+
+namespace bluetooth {
+namespace packet {
+
+template <typename T>
+class IteratorTest : public ::testing::Test {
+ public:
+  IteratorTest() = default;
+  ~IteratorTest() = default;
+
+  void SetUp() {
+    packet = std::shared_ptr<T>(new T({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())}));
+  }
+
+  void TearDown() {
+    packet.reset();
+  }
+
+  std::shared_ptr<T> packet;
+};
+
+using PacketViewTypes = ::testing::Types<PacketView<true>, PacketView<false>>;
+TYPED_TEST_CASE(IteratorTest, PacketViewTypes);
+
+class IteratorExtractTest : public ::testing::Test {
+ public:
+  IteratorExtractTest() = default;
+  ~IteratorExtractTest() = default;
+};
+
+template <typename T>
+class PacketViewTest : public IteratorTest<T> {
+ public:
+  PacketViewTest() = default;
+  ~PacketViewTest() = default;
+};
+
+using PacketViewTypes = ::testing::Types<PacketView<true>, PacketView<false>>;
+TYPED_TEST_CASE(PacketViewTest, PacketViewTypes);
+
+class PacketViewMultiViewTest : public ::testing::Test {
+ public:
+  PacketViewMultiViewTest() = default;
+  ~PacketViewMultiViewTest() = default;
+};
+
+class ViewTest : public ::testing::Test {
+ public:
+  ViewTest() = default;
+  ~ViewTest() = default;
+};
+
+TEST(IteratorExtractTest, extractLeTest) {
+  PacketView<true> packet({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  auto general_case = packet.begin();
+
+  ASSERT_EQ(0x00, general_case.extract<uint8_t>());
+  ASSERT_EQ(0x0201, general_case.extract<uint16_t>());
+  ASSERT_EQ(0x06050403u, general_case.extract<uint32_t>());
+  ASSERT_EQ(0x0e0d0c0b0a090807u, general_case.extract<uint64_t>());
+  ASSERT_EQ(0x0f, general_case.extract<uint8_t>());
+  Address raw({0x10, 0x11, 0x12, 0x13, 0x14, 0x15});
+  ASSERT_EQ(raw, general_case.extract<Address>());
+  ASSERT_EQ(0x16, general_case.extract<uint8_t>());
+}
+
+TEST(IteratorExtractTest, extractBeTest) {
+  PacketView<false> packet({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  auto general_case = packet.begin();
+
+  ASSERT_EQ(0x00, general_case.extract<uint8_t>());
+  ASSERT_EQ(0x0102, general_case.extract<uint16_t>());
+  ASSERT_EQ(0x03040506u, general_case.extract<uint32_t>());
+  ASSERT_EQ(0x0708090a0b0c0d0eu, general_case.extract<uint64_t>());
+  ASSERT_EQ(0x0f, general_case.extract<uint8_t>());
+  Address raw({0x15, 0x14, 0x13, 0x12, 0x11, 0x10});
+  ASSERT_EQ(raw, general_case.extract<Address>());
+  ASSERT_EQ(0x16, general_case.extract<uint8_t>());
+}
+
+TYPED_TEST(IteratorTest, extractBoundsDeathTest) {
+  auto bounds_test = this->packet->end();
+
+  ASSERT_DEATH(bounds_test.template extract<uint8_t>(), "");
+  ASSERT_DEATH(bounds_test.template extract<uint16_t>(), "");
+  ASSERT_DEATH(bounds_test.template extract<uint32_t>(), "");
+  ASSERT_DEATH(bounds_test.template extract<uint64_t>(), "");
+}
+
+TYPED_TEST(IteratorTest, dereferenceDeathTest) {
+  auto dereference_test = this->packet->end();
+
+  ASSERT_DEATH(*dereference_test, "");
+  ASSERT_EQ(0x1f, *(dereference_test - 1));
+}
+
+TYPED_TEST(IteratorTest, plusEqTest) {
+  auto plus_eq = this->packet->begin();
+  for (size_t i = 0; i < count_all.size(); i += 2) {
+    ASSERT_EQ(count_all[i], *plus_eq) << "+= test: Dereferenced iterator does not equal expected at index " << i;
+    plus_eq += 2;
+  }
+}
+
+TYPED_TEST(IteratorTest, preIncrementTest) {
+  auto plus_plus = this->packet->begin();
+  for (size_t i = 0; i < count_all.size() - 1; i++) {
+    ASSERT_EQ(count_all[i + 1], *(++plus_plus)) << "Pre-increment test: Dereferenced iterator does not equal expected "
+                                                << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, postIncrementTest) {
+  auto plus_plus = this->packet->begin();
+  for (size_t i = 0; i < count_all.size(); i++) {
+    ASSERT_EQ(count_all[i], *(plus_plus++)) << "Post-increment test: Dereferenced iterator does not equal expected "
+                                            << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, additionTest) {
+  auto plus = this->packet->begin();
+  for (size_t i = 0; i < count_all.size(); i++) {
+    ASSERT_EQ(count_all[i], *plus) << "+ test: Dereferenced iterator does not equal expected at index " << i;
+    plus = plus + 1;
+  }
+}
+
+TYPED_TEST(IteratorTest, minusEqTest) {
+  auto minus_eq = this->packet->end();
+  minus_eq -= 1;
+  size_t index = count_all.size() - 1;
+  for (size_t i = 0; index > i; i++) {
+    ASSERT_EQ(count_all[index], *minus_eq)
+        << "-= test: Dereferenced iterator does not equal expected at index " << index;
+    index -= i;
+    minus_eq -= i;
+  }
+}
+
+TYPED_TEST(IteratorTest, preDecrementTest) {
+  auto minus_minus = this->packet->end();
+  for (size_t i = count_all.size(); i > 0; i--) {
+    ASSERT_EQ(count_all[i - 1], *(--minus_minus))
+        << "Pre-decrement test: Dereferenced iterator does not equal expected "
+        << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, postDecrementTest) {
+  auto minus_minus = this->packet->end();
+  minus_minus--;
+  for (size_t i = count_all.size() - 1; i > 0; i--) {
+    ASSERT_EQ(count_all[i], *(minus_minus--)) << "Post-decrement test: Dereferenced iterator does not equal expected "
+                                              << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, subtractionTest) {
+  auto minus = this->packet->end();
+  minus = minus - 1;
+  for (size_t i = count_all.size() - 1; i > 0; i--) {
+    ASSERT_EQ(count_all[i], *minus) << "- test: Dereferenced iterator does not equal expected at index " << i;
+    minus = minus - 1;
+  }
+}
+
+TYPED_TEST(IteratorTest, differenceTest) {
+  auto begin = this->packet->begin();
+  auto end = this->packet->end();
+  int difference = end - begin;
+  ASSERT_EQ(difference, static_cast<int>(count_all.size()));
+  int neg_difference = begin - end;
+  ASSERT_EQ(neg_difference, -static_cast<int>(count_all.size()));
+}
+
+TYPED_TEST(IteratorTest, equalityTest) {
+  auto begin = this->packet->begin();
+  auto end = this->packet->end();
+  auto begin_copy = this->packet->begin();
+  auto end_copy = this->packet->end();
+  ASSERT_EQ(begin_copy, begin);
+  ASSERT_EQ(end_copy, end);
+}
+
+TYPED_TEST(IteratorTest, comparisonsTest) {
+  auto begin = this->packet->begin();
+  auto end = this->packet->end();
+  auto begin_copy = this->packet->begin();
+  auto end_copy = this->packet->end();
+  ASSERT_EQ(begin_copy, begin);
+  ASSERT_EQ(end_copy, end);
+  ASSERT_NE(begin, end);
+  ASSERT_TRUE(begin < end);
+  ASSERT_FALSE(end < end);
+  ASSERT_FALSE(end < begin);
+  ASSERT_FALSE(begin > end);
+  ASSERT_FALSE(end > end);
+  ASSERT_TRUE(end > begin);
+  ASSERT_TRUE(begin <= end);
+  ASSERT_TRUE(end <= end);
+  ASSERT_FALSE(end <= begin);
+  ASSERT_FALSE(begin >= end);
+  ASSERT_TRUE(end >= end);
+  ASSERT_TRUE(end >= begin);
+}
+
+TYPED_TEST(PacketViewTest, getLengthTest) {
+  size_t length = this->packet->size();
+  ASSERT_EQ(length, count_all.size());
+}
+
+TYPED_TEST(PacketViewTest, getAtIndexTest) {
+  size_t past_end = this->packet->size();
+  ASSERT_DEATH(this->packet->at(past_end), "");
+  size_t working_index = 0x1f;
+  ASSERT_EQ(0x1f, this->packet->at(working_index));
+}
+
+TYPED_TEST(PacketViewTest, arrayOperatorTest) {
+  size_t past_end = this->packet->size();
+  ASSERT_DEATH((*(this->packet))[past_end], "");
+  size_t working_index = 0x1f;
+  ASSERT_EQ(0x1f, (*(this->packet))[working_index]);
+}
+
+TYPED_TEST(PacketViewTest, numBytesRemainingTest) {
+  auto all = this->packet->begin();
+  size_t remaining = all.NumBytesRemaining();
+  for (size_t n = remaining; n > 0; n--) {
+    ASSERT_EQ(remaining, all.NumBytesRemaining());
+    all++;
+    remaining--;
+  }
+  ASSERT_EQ(static_cast<size_t>(0), all.NumBytesRemaining());
+  ASSERT_DEATH(*(all++), "");
+  all++;
+  ASSERT_EQ(static_cast<size_t>(0), all.NumBytesRemaining());
+  ASSERT_DEATH(*(all++), "");
+}
+
+using SubviewTestParam = std::pair<size_t, size_t>;
+class SubviewBaseTest : public ::testing::TestWithParam<SubviewTestParam> {
+ public:
+  class SubPacketView : public PacketView<true> {
+   public:
+    using PacketView<true>::PacketView;
+    PacketView<true> Slice(size_t header, size_t tail) {
+      return PacketView<true>::GetLittleEndianSubview(header, tail);
+    }
+  };
+};
+
+class SubviewPassTest : public SubviewBaseTest {};
+
+TEST_P(SubviewPassTest, subviewTest) {
+  auto header = GetParam().first;
+  auto tail = GetParam().second;
+  SubPacketView single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  SubPacketView multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+
+  auto single_slice = single_view.Slice(header, tail);
+  auto multi_slice = multi_view.Slice(header, tail);
+
+  ASSERT_EQ(single_slice.size(), tail - header);
+  ASSERT_EQ(single_slice.size(), multi_slice.size());
+  for (size_t i = 0; i < single_slice.size(); i++) {
+    ASSERT_EQ(single_slice[i], multi_slice[i]);
+  }
+}
+
+static const size_t boundary_1 = count_1.size();
+static const size_t boundary_2 = count_1.size() + count_2.size();
+
+INSTANTIATE_TEST_CASE_P(
+    chopomatic, SubviewPassTest,
+    ::testing::Values(
+        // {begin, end} pairs for subsets into the PacketView
+        SubviewTestParam{0, 0}, SubviewTestParam{0, boundary_1}, SubviewTestParam{0, boundary_1 + 1},
+        SubviewTestParam{0, boundary_2}, SubviewTestParam{0, boundary_2 + 1}, SubviewTestParam{0, count_all.size()},
+        SubviewTestParam{boundary_1 - 1, boundary_1}, SubviewTestParam{boundary_1 - 1, boundary_1 + 1},
+        SubviewTestParam{boundary_1 - 1, boundary_2}, SubviewTestParam{boundary_1 - 1, boundary_2 + 1},
+        SubviewTestParam{boundary_1 - 1, count_all.size()}, SubviewTestParam{boundary_1, boundary_1},
+        SubviewTestParam{boundary_1, boundary_2}, SubviewTestParam{boundary_1, boundary_2 + 1},
+        SubviewTestParam{boundary_1, count_all.size()}, SubviewTestParam{boundary_2 - 1, boundary_2},
+        SubviewTestParam{boundary_2 - 1, boundary_2 + 1}, SubviewTestParam{boundary_2 - 1, count_all.size()},
+        SubviewTestParam{boundary_2, boundary_2}, SubviewTestParam{boundary_2, boundary_2 + 1},
+        SubviewTestParam{boundary_2, count_all.size()}, SubviewTestParam{count_all.size() - 1, count_all.size()},
+        SubviewTestParam{count_all.size(), count_all.size()}));
+
+class SubviewDeathTest : public SubviewBaseTest {};
+
+TEST_P(SubviewDeathTest, subviewDeathTest) {
+  auto header = GetParam().first;
+  auto tail = GetParam().second;
+  SubPacketView single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  SubPacketView multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+
+  ASSERT_DEATH(auto single_slice = single_view.Slice(header, tail), "");
+  ASSERT_DEATH(auto multi_slice = multi_view.Slice(header, tail), "");
+}
+
+INSTANTIATE_TEST_CASE_P(chopomaticDeath, SubviewDeathTest,
+                        ::testing::Values(
+                            // {begin, end} pairs for subsets into the PacketView
+                            SubviewTestParam{1, 0}, SubviewTestParam{count_all.size(), count_all.size() - 1},
+                            SubviewTestParam{count_all.size(), count_all.size() + 1}));
+
+TEST(SubviewTest, simpleSubviewTest) {
+  PacketView<true> view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> sub_1_view = view.GetLittleEndianSubview(0, view.size());
+  PacketView<true> sub_2_view = sub_1_view.GetLittleEndianSubview(0, sub_1_view.size());
+  PacketView<true> sub_3_view = sub_2_view.GetLittleEndianSubview(0, sub_2_view.size());
+  PacketView<true> sub_4_view = sub_3_view.GetLittleEndianSubview(0, sub_3_view.size());
+  ASSERT_EQ(sub_1_view.size(), view.size());
+  ASSERT_EQ(sub_2_view.size(), view.size());
+  ASSERT_EQ(sub_3_view.size(), view.size());
+  ASSERT_EQ(sub_4_view.size(), view.size());
+}
+
+TEST(SubviewTest, realSubviewTest) {
+  PacketView<true> view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  std::vector<PacketView<true>> sub_views{view};
+  for (size_t i = 1; i < 6; i++) {
+    size_t parent_size = sub_views[i - 1].size();
+    sub_views.push_back(sub_views[i - 1].GetLittleEndianSubview(1, parent_size - 1));
+    ASSERT_EQ(sub_views[i][0], i);
+    ASSERT_EQ(sub_views[i].size(), parent_size - 2);
+  }
+}
+
+TEST(SubviewTest, subSubviewTest) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  ASSERT_EQ(single_view.size(), multi_view.size());
+  for (size_t i = 0; i < count_all.size() / 2; i++) {
+    PacketView<true> sub_single_view = single_view.GetLittleEndianSubview(i, count_all.size() - i);
+    PacketView<true> sub_multi_view = multi_view.GetLittleEndianSubview(i, count_all.size() - i);
+    ASSERT_EQ(count_all.size() - 2 * i, sub_single_view.size());
+    ASSERT_EQ(sub_single_view.size(), sub_multi_view.size());
+    for (size_t j = 0; j < sub_single_view.size() / 2; j++) {
+      PacketView<true> sub_sub_single_view = sub_single_view.GetLittleEndianSubview(j, sub_single_view.size() - j);
+      PacketView<true> sub_sub_multi_view = sub_multi_view.GetLittleEndianSubview(j, sub_multi_view.size() - j);
+      ASSERT_EQ(sub_single_view.size() - 2 * j, sub_sub_single_view.size());
+      ASSERT_EQ(sub_sub_single_view.size(), sub_sub_multi_view.size());
+    }
+  }
+}
+
+TEST(PacketViewMultiViewTest, sizeTest) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  ASSERT_EQ(single_view.size(), multi_view.size());
+}
+
+TEST(PacketViewMultiViewTest, dereferenceTestLittleEndian) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  auto single_itr = single_view.begin();
+  auto multi_itr = multi_view.begin();
+  for (size_t i = 0; i < single_view.size(); i++) {
+    ASSERT_EQ(*(single_itr++), *(multi_itr++));
+  }
+  ASSERT_DEATH(*multi_itr, "");
+}
+
+TEST(PacketViewMultiViewTest, dereferenceTestBigEndian) {
+  PacketView<false> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<false> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  auto single_itr = single_view.begin();
+  auto multi_itr = multi_view.begin();
+  for (size_t i = 0; i < single_view.size(); i++) {
+    ASSERT_EQ(*(single_itr++), *(multi_itr++));
+  }
+  ASSERT_DEATH(*multi_itr, "");
+}
+
+TEST(PacketViewMultiViewTest, arrayOperatorTest) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  for (size_t i = 0; i < single_view.size(); i++) {
+    ASSERT_EQ(single_view[i], multi_view[i]);
+  }
+  ASSERT_DEATH(multi_view[single_view.size()], "");
+}
+
+TEST(ViewTest, arrayOperatorTest) {
+  View view_all(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  size_t past_end = view_all.size();
+  for (size_t i = 0; i < past_end; i++) {
+    ASSERT_EQ(view_all[i], count_all[i]);
+  }
+  ASSERT_DEATH(view_all[past_end], "");
+
+  size_t header_size = 2;
+  size_t tail_size = 3;
+  View view_subset(std::make_shared<const vector<uint8_t>>(count_all), header_size, count_all.size() - tail_size);
+  View view_subset2(view_all, header_size, count_all.size() - tail_size);
+  size_t subset_length = view_subset.size();
+  for (size_t i = 0; i < subset_length; i++) {
+    ASSERT_EQ(view_subset[i], count_all[header_size + i]);
+    ASSERT_EQ(view_subset[i], view_subset2[i]);
+  }
+  ASSERT_DEATH(view_subset[subset_length + 1], "");
+  ASSERT_DEATH(view_subset2[subset_length + 1], "");
+}
+
+TEST(ViewTest, earlySubSubviewTest) {
+  View view(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  View sub_1_view(view, view.size() - 3, view.size() - 1);
+  View sub_2_view(sub_1_view, 1, 2);
+  ASSERT_EQ(sub_1_view.size(), 2u);
+  ASSERT_EQ(sub_2_view.size(), 1u);
+}
+
+TEST(ViewTest, subSubviewTest) {
+  View view(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  std::vector<View> sub_views{view};
+  for (size_t i = 1; i < 6; i++) {
+    size_t parent_size = sub_views[i - 1].size();
+    sub_views.push_back({View(sub_views[i - 1], 1, parent_size - 1)});
+    ASSERT_EQ(sub_views[i][0], i);
+    ASSERT_EQ(sub_views[i].size(), parent_size - 2);
+  }
+}
+
+TEST(ViewTest, zeroSubviewTest) {
+  View view(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  View subview(view, view.size(), view.size() + 1);
+  ASSERT_EQ(subview.size(), 0u);
+}
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/raw_builder.cc b/gd/packet/raw_builder.cc
new file mode 100644
index 0000000..fd61417
--- /dev/null
+++ b/gd/packet/raw_builder.cc
@@ -0,0 +1,109 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/raw_builder.h"
+
+#include <algorithm>
+
+#include "os/log.h"
+
+using std::vector;
+using bluetooth::common::Address;
+
+namespace bluetooth {
+namespace packet {
+
+RawBuilder::RawBuilder(size_t max_bytes) : max_bytes_(max_bytes) {}
+
+bool RawBuilder::AddOctets(size_t octets, const vector<uint8_t>& bytes) {
+  if (payload_.size() + octets > max_bytes_) return false;
+
+  if (octets != bytes.size()) return false;
+
+  payload_.insert(payload_.end(), bytes.begin(), bytes.end());
+
+  return true;
+}
+
+bool RawBuilder::AddOctets(const vector<uint8_t>& bytes) {
+  return AddOctets(bytes.size(), bytes);
+}
+
+bool RawBuilder::AddOctets(size_t octets, uint64_t value) {
+  vector<uint8_t> val_vector;
+
+  uint64_t v = value;
+
+  if (octets > sizeof(uint64_t)) return false;
+
+  for (size_t i = 0; i < octets; i++) {
+    val_vector.push_back(v & 0xff);
+    v = v >> 8;
+  }
+
+  if (v != 0) return false;
+
+  return AddOctets(octets, val_vector);
+}
+
+bool RawBuilder::AddAddress(const Address& address) {
+  if (payload_.size() + Address::kLength > max_bytes_) return false;
+
+  for (size_t i = 0; i < Address::kLength; i++) {
+    payload_.push_back(address.address[i]);
+  }
+  return true;
+}
+
+bool RawBuilder::AddOctets1(uint8_t value) {
+  return AddOctets(1, value);
+}
+
+bool RawBuilder::AddOctets2(uint16_t value) {
+  return AddOctets(2, value);
+}
+
+bool RawBuilder::AddOctets3(uint32_t value) {
+  return AddOctets(3, value);
+}
+
+bool RawBuilder::AddOctets4(uint32_t value) {
+  return AddOctets(4, value);
+}
+
+bool RawBuilder::AddOctets6(uint64_t value) {
+  return AddOctets(6, value);
+}
+
+bool RawBuilder::AddOctets8(uint64_t value) {
+  return AddOctets(8, value);
+}
+
+bool RawBuilder::CanAddOctets(size_t num_bytes) const {
+  return payload_.size() + num_bytes <= max_bytes_;
+}
+
+void RawBuilder::Serialize(BitInserter& it) const {
+  for (const auto& val : payload_) {
+    insert(val, it);
+  }
+}
+
+size_t RawBuilder::size() const {
+  return payload_.size();
+}
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/raw_builder.h b/gd/packet/raw_builder.h
new file mode 100644
index 0000000..8f9edf5
--- /dev/null
+++ b/gd/packet/raw_builder.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "common/address.h"
+#include "packet/bit_inserter.h"
+#include "packet/packet_builder.h"
+
+namespace bluetooth {
+namespace packet {
+
+class RawBuilder : public PacketBuilder<true> {
+ public:
+  RawBuilder() = default;
+  RawBuilder(size_t max_bytes);
+  virtual ~RawBuilder() = default;
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(BitInserter& it) const;
+
+  // Add |address| to the payload.  Return true if:
+  // - the new size of the payload is still <= |max_bytes_|
+  bool AddAddress(const common::Address& address);
+
+  // Return true if |num_bytes| can be added to the payload.
+  bool CanAddOctets(size_t num_bytes) const;
+
+  // Add |octets| bytes to the payload.  Return true if:
+  // - the size of |bytes| is equal to |octets| and
+  // - the new size of the payload is still <= |max_bytes_|
+  bool AddOctets(size_t octets, const std::vector<uint8_t>& bytes);
+
+  bool AddOctets(const std::vector<uint8_t>& bytes);
+
+  bool AddOctets1(uint8_t value);
+  bool AddOctets2(uint16_t value);
+  bool AddOctets3(uint32_t value);
+  bool AddOctets4(uint32_t value);
+  bool AddOctets6(uint64_t value);
+  bool AddOctets8(uint64_t value);
+
+ private:
+  // Add |octets| bytes to the payload.  Return true if:
+  // - the value of |value| fits in |octets| bytes and
+  // - the new size of the payload is still <= |max_bytes_|
+  bool AddOctets(size_t octets, uint64_t value);
+
+  size_t max_bytes_{255};
+
+  // Underlying containers for storing the actual packet
+  std::vector<uint8_t> payload_;
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/raw_builder_unittest.cc b/gd/packet/raw_builder_unittest.cc
new file mode 100644
index 0000000..27cecd6
--- /dev/null
+++ b/gd/packet/raw_builder_unittest.cc
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/raw_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "common/address.h"
+
+using bluetooth::common::Address;
+using bluetooth::packet::BitInserter;
+using std::vector;
+
+namespace {
+vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+}  // namespace
+
+namespace bluetooth {
+namespace packet {
+
+class RawBuilderTest : public ::testing::Test {
+ public:
+  RawBuilderTest() = default;
+  ~RawBuilderTest() = default;
+};
+
+TEST(RawBuilderTest, buildCountTest) {
+  std::unique_ptr<RawBuilder> count_builder = std::make_unique<RawBuilder>();
+  ASSERT_EQ(0u, count_builder->size());
+  count_builder->AddOctets8(0x0706050403020100);
+  count_builder->AddOctets4(0x0b0a0908);
+  count_builder->AddOctets2(0x0d0c);
+  count_builder->AddOctets1(0x0e);
+  count_builder->AddOctets1(0x0f);
+  count_builder->AddAddress(Address({0x10, 0x11, 0x12, 0x13, 0x14, 0x15}));
+  std::vector<uint8_t> count_subset(count.begin() + 0x16, count.end());
+  count_builder->AddOctets(count_subset);
+
+  ASSERT_EQ(count.size(), count_builder->size());
+
+  std::vector<uint8_t> packet;
+  BitInserter it(packet);
+
+  count_builder->Serialize(it);
+
+  ASSERT_EQ(count, packet);
+}
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/view.cc b/gd/packet/view.cc
new file mode 100644
index 0000000..a98fb6c
--- /dev/null
+++ b/gd/packet/view.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet/view.h"
+
+#include "os/log.h"
+
+namespace bluetooth {
+namespace packet {
+
+View::View(std::shared_ptr<const std::vector<uint8_t>> data, size_t begin, size_t end)
+    : data_(data), begin_(begin < data_->size() ? begin : data_->size()),
+      end_(end < data_->size() ? end : data_->size()) {}
+
+View::View(const View& view, size_t begin, size_t end) : data_(view.data_) {
+  begin_ = (begin < view.size() ? begin : view.size());
+  begin_ += view.begin_;
+  end_ = (end < view.size() ? end : view.size());
+  end_ += view.begin_;
+}
+
+uint8_t View::operator[](size_t i) const {
+  ASSERT_LOG(i + begin_ < end_, "Out of bounds access at %zu", i);
+  return data_->operator[](i + begin_);
+}
+
+size_t View::size() const {
+  return end_ - begin_;
+}
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/gd/packet/view.h b/gd/packet/view.h
new file mode 100644
index 0000000..4f3b508
--- /dev/null
+++ b/gd/packet/view.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+namespace bluetooth {
+namespace packet {
+
+// Base class that holds a shared pointer to data with bounds.
+class View {
+ public:
+  View(std::shared_ptr<const std::vector<uint8_t>> data, size_t begin, size_t end);
+  View(const View& view, size_t begin, size_t end);
+  View(const View& view) = default;
+  virtual ~View() = default;
+
+  uint8_t operator[](size_t i) const;
+
+  size_t size() const;
+
+ private:
+  std::shared_ptr<const std::vector<uint8_t>> data_;
+  size_t begin_;
+  size_t end_;
+};
+
+}  // namespace packet
+}  // namespace bluetooth
diff --git a/hci/AndroidTest.xml b/hci/AndroidTest.xml
deleted file mode 100644
index 944b454..0000000
--- a/hci/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2017 The Android Open Source Project
-
-     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.
--->
-<configuration description="Config for net_test_hci">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="net_test_hci->/data/local/tmp/net_test_hci" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="net_test_hci" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/hci/BUILD.gn b/hci/BUILD.gn
index fc9c2ce..e29e256 100644
--- a/hci/BUILD.gn
+++ b/hci/BUILD.gn
@@ -38,6 +38,7 @@
   ]
 
   deps = [
+    "//common",
     "//third_party/libchrome:base",
   ]
 }
diff --git a/hci/include/btsnoop.h b/hci/include/btsnoop.h
index e897a96..476c62d 100644
--- a/hci/include/btsnoop.h
+++ b/hci/include/btsnoop.h
@@ -29,6 +29,28 @@
   // true, the packet is marked as incoming. Otherwise, the packet is marked
   // as outgoing.
   void (*capture)(const BT_HDR* packet, bool is_received);
+
+  // Set a L2CAP channel as whitelisted, allowing packets with that L2CAP CID
+  // to show up in the snoop logs.
+  void (*whitelist_l2c_channel)(uint16_t conn_handle, uint16_t local_cid,
+                                uint16_t remote_cid);
+
+  // Set a RFCOMM dlci as whitelisted, allowing packets with that RFCOMM CID
+  // to show up in the snoop logs. The local_cid is used to associate it with
+  // its corrisponding ACL connection. The dlci is the channel with direction
+  // so there is no chance of a collision if two services are using the same
+  // channel but in different directions.
+  void (*whitelist_rfc_dlci)(uint16_t local_cid, uint8_t dlci);
+
+  // Indicate that the provided L2CAP channel is being used for RFCOMM.
+  // If packets with the provided L2CAP CID are encountered, they will be
+  // filtered on RFCOMM based on channels provided to |filter_rfc_channel|.
+  void (*add_rfc_l2c_channel)(uint16_t conn_handle, uint16_t local_cid,
+                              uint16_t remote_cid);
+
+  // Clear an L2CAP channel from being filtered.
+  void (*clear_l2cap_whitelist)(uint16_t conn_handle, uint16_t local_cid,
+                                uint16_t remote_cid);
 } btsnoop_t;
 
 const btsnoop_t* btsnoop_get_interface(void);
diff --git a/hci/include/hci_layer.h b/hci/include/hci_layer.h
index 59ee443..5eb2bd5 100644
--- a/hci/include/hci_layer.h
+++ b/hci/include/hci_layer.h
@@ -18,8 +18,8 @@
 
 #pragma once
 
-#include <base/bind.h>
-#include <base/tracked_objects.h>
+#include <base/callback.h>
+#include <base/location.h>
 #include <stdbool.h>
 
 #include "bt_types.h"
@@ -70,8 +70,7 @@
 typedef struct hci_t {
   // Set the callback that the HCI layer uses to send data upwards
   void (*set_data_cb)(
-      base::Callback<void(const tracked_objects::Location&, BT_HDR*)>
-          send_data_cb);
+      base::Callback<void(const base::Location&, BT_HDR*)> send_data_cb);
 
   // Send a command through the HCI layer
   void (*transmit_command)(BT_HDR* command,
@@ -91,7 +90,6 @@
     const btsnoop_t* btsnoop_interface,
     const packet_fragmenter_t* packet_fragmenter_interface);
 
-void post_to_hci_message_loop(const tracked_objects::Location& from_here,
-                              BT_HDR* p_msg);
+void post_to_main_message_loop(const base::Location& from_here, BT_HDR* p_msg);
 
 void hci_layer_cleanup_interface();
diff --git a/hci/src/btsnoop.cc b/hci/src/btsnoop.cc
index 9812b61..ad06ac7 100644
--- a/hci/src/btsnoop.cc
+++ b/hci/src/btsnoop.cc
@@ -21,6 +21,7 @@
 #include <mutex>
 
 #include <arpa/inet.h>
+#include <base/logging.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
@@ -34,14 +35,21 @@
 #include <sys/time.h>
 #include <sys/uio.h>
 #include <unistd.h>
+#include <mutex>
+#include <unordered_map>
+#include <unordered_set>
 
 #include "bt_types.h"
+#include "common/time_util.h"
 #include "hci/include/btsnoop.h"
 #include "hci/include/btsnoop_mem.h"
 #include "hci_layer.h"
+#include "internal_include/bt_trace.h"
 #include "osi/include/log.h"
 #include "osi/include/properties.h"
-#include "osi/include/time.h"
+#include "stack/include/hcimsgs.h"
+#include "stack/include/rfcdefs.h"
+#include "stack/l2cap/l2c_int.h"
 #include "stack_config.h"
 
 // The number of of packets per btsnoop file before we rotate to the next
@@ -50,7 +58,14 @@
 // property
 #define DEFAULT_BTSNOOP_SIZE 0xffff
 
-#define BTSNOOP_ENABLE_PROPERTY "persist.bluetooth.btsnoopenable"
+#define IS_DEBUGGABLE_PROPERTY "ro.debuggable"
+
+#define BTSNOOP_LOG_MODE_PROPERTY "persist.bluetooth.btsnooplogmode"
+#define BTSNOOP_DEFAULT_MODE_PROPERTY "persist.bluetooth.btsnoopdefaultmode"
+#define BTSNOOP_MODE_DISABLED "disabled"
+#define BTSNOOP_MODE_FILTERED "filtered"
+#define BTSNOOP_MODE_FULL "full"
+
 #define BTSNOOP_PATH_PROPERTY "persist.bluetooth.btsnooppath"
 #define DEFAULT_BTSNOOP_PATH "/data/misc/bluetooth/logs/btsnoop_hci.log"
 #define BTSNOOP_MAX_PACKETS_PROPERTY "persist.bluetooth.btsnoopsize"
@@ -65,33 +80,138 @@
 // Epoch in microseconds since 01/01/0000.
 static const uint64_t BTSNOOP_EPOCH_DELTA = 0x00dcddb30f2f8000ULL;
 
+// Number of bytes into a packet where you can find the value for a channel.
+static const size_t ACL_CHANNEL_OFFSET = 0;
+static const size_t L2C_CHANNEL_OFFSET = 6;
+static const size_t RFC_CHANNEL_OFFSET = 8;
+static const size_t RFC_EVENT_OFFSET = 9;
+
+// The size of the L2CAP header. All information past this point is removed from
+// a filtered packet.
+static const uint32_t L2C_HEADER_SIZE = 9;
+
 static int logfile_fd = INVALID_FD;
 static std::mutex btsnoop_mutex;
 
 static int32_t packets_per_file;
 static int32_t packet_counter;
 
+// Channel tracking variables for filtering.
+
+// Keeps track of L2CAP channels that need to be filtered out of the snoop
+// logs.
+class FilterTracker {
+ public:
+  // NOTE: 1 is used as a static CID for L2CAP signaling
+  std::unordered_set<uint16_t> l2c_local_cid = {1};
+  std::unordered_set<uint16_t> l2c_remote_cid = {1};
+  uint16_t rfc_local_cid = 0;
+  uint16_t rfc_remote_cid = 0;
+  std::unordered_set<uint16_t> rfc_channels = {0};
+
+  // Adds L2C channel to whitelist.
+  void addL2cCid(uint16_t local_cid, uint16_t remote_cid) {
+    l2c_local_cid.insert(local_cid);
+    l2c_remote_cid.insert(remote_cid);
+  }
+
+  // Sets L2CAP channel that RFCOMM uses.
+  void setRfcCid(uint16_t local_cid, uint16_t remote_cid) {
+    rfc_local_cid = local_cid;
+    rfc_remote_cid = remote_cid;
+  }
+
+  // Remove L2C channel from whitelist.
+  void removeL2cCid(uint16_t local_cid, uint16_t remote_cid) {
+    if (rfc_local_cid == local_cid) {
+      rfc_channels.clear();
+      rfc_channels.insert(0);
+      rfc_local_cid = 0;
+      rfc_remote_cid = 0;
+    }
+
+    l2c_local_cid.erase(local_cid);
+    l2c_remote_cid.erase(remote_cid);
+  }
+
+  void addRfcDlci(uint8_t channel) { rfc_channels.insert(channel); }
+
+  bool isWhitelistedL2c(bool local, uint16_t cid) {
+    const auto& set = local ? l2c_local_cid : l2c_remote_cid;
+    return (set.find(cid) != set.end());
+  }
+
+  bool isRfcChannel(bool local, uint16_t cid) {
+    const auto& channel = local ? rfc_local_cid : rfc_remote_cid;
+    return cid == channel;
+  }
+
+  bool isWhitelistedDlci(uint8_t dlci) {
+    return rfc_channels.find(dlci) != rfc_channels.end();
+  }
+};
+
+std::mutex filter_list_mutex;
+std::unordered_map<uint16_t, FilterTracker> filter_list;
+std::unordered_map<uint16_t, uint16_t> local_cid_to_acl;
+
+// Cached value for whether full snoop logs are enabled. So the property isn't
+// checked for every packet.
+static bool is_btsnoop_enabled;
+static bool is_btsnoop_filtered;
+
 // TODO(zachoverflow): merge btsnoop and btsnoop_net together
 void btsnoop_net_open();
 void btsnoop_net_close();
 void btsnoop_net_write(const void* data, size_t length);
 
-static void delete_btsnoop_files();
-static bool is_btsnoop_enabled();
-static char* get_btsnoop_log_path(char* log_path);
-static char* get_btsnoop_last_log_path(char* last_log_path, char* log_path);
+static void delete_btsnoop_files(bool filtered);
+static std::string get_btsnoop_log_path(bool filtered);
+static std::string get_btsnoop_last_log_path(std::string log_path);
 static void open_next_snoop_file();
 static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
                                  bool is_received, uint64_t timestamp_us);
 
 // Module lifecycle functions
 
-static future_t* start_up(void) {
+static future_t* start_up() {
+  std::array<char, PROPERTY_VALUE_MAX> property = {};
   std::lock_guard<std::mutex> lock(btsnoop_mutex);
 
-  if (!is_btsnoop_enabled()) {
-    delete_btsnoop_files();
+  // Default mode is FILTERED on userdebug/eng build, DISABLED on user build.
+  // It can also be overwritten by modifying the global setting.
+  int is_debuggable = osi_property_get_int32(IS_DEBUGGABLE_PROPERTY, 0);
+  std::string default_mode = BTSNOOP_MODE_DISABLED;
+  if (is_debuggable) {
+    int len = osi_property_get(BTSNOOP_DEFAULT_MODE_PROPERTY, property.data(),
+                               BTSNOOP_MODE_DISABLED);
+    default_mode = std::string(property.data(), len);
+  }
+
+  // Get the actual mode
+  int len = osi_property_get(BTSNOOP_LOG_MODE_PROPERTY, property.data(),
+                             default_mode.c_str());
+  std::string btsnoop_mode(property.data(), len);
+
+  if (btsnoop_mode == BTSNOOP_MODE_FILTERED) {
+    LOG(INFO) << __func__ << ": Filtered Snoop Logs enabled";
+    is_btsnoop_enabled = true;
+    is_btsnoop_filtered = true;
+    delete_btsnoop_files(false);
+  } else if (btsnoop_mode == BTSNOOP_MODE_FULL) {
+    LOG(INFO) << __func__ << ": Snoop Logs fully enabled";
+    is_btsnoop_enabled = true;
+    is_btsnoop_filtered = false;
+    delete_btsnoop_files(true);
   } else {
+    LOG(INFO) << __func__ << ": Snoop Logs disabled";
+    is_btsnoop_enabled = false;
+    is_btsnoop_filtered = false;
+    delete_btsnoop_files(true);
+    delete_btsnoop_files(false);
+  }
+
+  if (is_btsnoop_enabled) {
     open_next_snoop_file();
     packets_per_file = osi_property_get_int32(BTSNOOP_MAX_PACKETS_PROPERTY,
                                               DEFAULT_BTSNOOP_SIZE);
@@ -104,14 +224,21 @@
 static future_t* shut_down(void) {
   std::lock_guard<std::mutex> lock(btsnoop_mutex);
 
-  if (!is_btsnoop_enabled()) {
-    delete_btsnoop_files();
+  if (is_btsnoop_enabled) {
+    if (is_btsnoop_filtered) {
+      delete_btsnoop_files(false);
+    } else {
+      delete_btsnoop_files(true);
+    }
+  } else {
+    delete_btsnoop_files(true);
+    delete_btsnoop_files(false);
   }
 
   if (logfile_fd != INVALID_FD) close(logfile_fd);
   logfile_fd = INVALID_FD;
 
-  btsnoop_net_close();
+  if (is_btsnoop_enabled) btsnoop_net_close();
 
   return NULL;
 }
@@ -129,7 +256,12 @@
   uint8_t* p = const_cast<uint8_t*>(buffer->data + buffer->offset);
 
   std::lock_guard<std::mutex> lock(btsnoop_mutex);
-  uint64_t timestamp_us = time_gettimeofday_us();
+
+  struct timespec ts_now = {};
+  clock_gettime(CLOCK_REALTIME, &ts_now);
+  uint64_t timestamp_us =
+      ((uint64_t)ts_now.tv_sec * 1000000L) + ((uint64_t)ts_now.tv_nsec / 1000);
+
   btsnoop_mem_capture(buffer, timestamp_us);
 
   if (logfile_fd == INVALID_FD) return;
@@ -152,39 +284,75 @@
   }
 }
 
-static const btsnoop_t interface = {capture};
+static void whitelist_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
+                                  uint16_t remote_cid) {
+  LOG(INFO) << __func__
+            << ": Whitelisting l2cap channel. conn_handle=" << conn_handle
+            << " cid=" << loghex(local_cid) << ":" << loghex(remote_cid);
+  std::lock_guard lock(filter_list_mutex);
 
-const btsnoop_t* btsnoop_get_interface() {
-  return &interface;
+  // This will create the entry if there is no associated filter with the
+  // connection.
+  filter_list[conn_handle].addL2cCid(local_cid, remote_cid);
 }
 
-// Internal functions
-static void delete_btsnoop_files() {
-  LOG_VERBOSE(LOG_TAG, "Deleting snoop log if it exists");
-  char log_path[PROPERTY_VALUE_MAX];
-  char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
-  get_btsnoop_log_path(log_path);
-  get_btsnoop_last_log_path(last_log_path, log_path);
-  remove(log_path);
-  remove(last_log_path);
+static void whitelist_rfc_dlci(uint16_t local_cid, uint8_t dlci) {
+  LOG(INFO) << __func__
+            << ": Whitelisting rfcomm channel. L2CAP CID=" << loghex(local_cid)
+            << " DLCI=" << loghex(dlci);
+  std::lock_guard lock(filter_list_mutex);
+
+  tL2C_CCB* p_ccb = l2cu_find_ccb_by_cid(nullptr, local_cid);
+  filter_list[p_ccb->p_lcb->handle].addRfcDlci(dlci);
 }
 
-static bool is_btsnoop_enabled() {
-  char btsnoop_enabled[PROPERTY_VALUE_MAX] = {0};
-  osi_property_get(BTSNOOP_ENABLE_PROPERTY, btsnoop_enabled, "false");
-  return strncmp(btsnoop_enabled, "true", 4) == 0;
+static void add_rfc_l2c_channel(uint16_t conn_handle, uint16_t local_cid,
+                                uint16_t remote_cid) {
+  LOG(INFO) << __func__
+            << ": rfcomm data going over l2cap channel. conn_handle="
+            << conn_handle << " cid=" << loghex(local_cid) << ":"
+            << loghex(remote_cid);
+  std::lock_guard lock(filter_list_mutex);
+
+  filter_list[conn_handle].setRfcCid(local_cid, remote_cid);
+  local_cid_to_acl.insert({local_cid, conn_handle});
 }
 
-static char* get_btsnoop_log_path(char* btsnoop_path) {
+static void clear_l2cap_whitelist(uint16_t conn_handle, uint16_t local_cid,
+                                  uint16_t remote_cid) {
+  LOG(INFO) << __func__
+            << ": Clearing whitelist from l2cap channel. conn_handle="
+            << conn_handle << " cid=" << local_cid << ":" << remote_cid;
+
+  std::lock_guard lock(filter_list_mutex);
+  filter_list[conn_handle].removeL2cCid(local_cid, remote_cid);
+}
+
+static const btsnoop_t interface = {capture, whitelist_l2c_channel,
+                                    whitelist_rfc_dlci, add_rfc_l2c_channel,
+                                    clear_l2cap_whitelist};
+
+const btsnoop_t* btsnoop_get_interface() { return &interface; }
+
+static void delete_btsnoop_files(bool filtered) {
+  LOG(INFO) << __func__
+            << ": Deleting snoop logs if they exist. filtered = " << filtered;
+  auto log_path = get_btsnoop_log_path(filtered);
+  remove(log_path.c_str());
+  remove(get_btsnoop_last_log_path(log_path).c_str());
+}
+
+std::string get_btsnoop_log_path(bool filtered) {
+  char btsnoop_path[PROPERTY_VALUE_MAX];
   osi_property_get(BTSNOOP_PATH_PROPERTY, btsnoop_path, DEFAULT_BTSNOOP_PATH);
-  return btsnoop_path;
+  std::string result(btsnoop_path);
+  if (filtered) result = result.append(".filtered");
+
+  return result;
 }
 
-static char* get_btsnoop_last_log_path(char* last_log_path,
-                                       char* btsnoop_path) {
-  snprintf(last_log_path, PROPERTY_VALUE_MAX + sizeof(".last"), "%s.last",
-           btsnoop_path);
-  return last_log_path;
+std::string get_btsnoop_last_log_path(std::string btsnoop_path) {
+  return btsnoop_path.append(".last");
 }
 
 static void open_next_snoop_file() {
@@ -195,22 +363,20 @@
     logfile_fd = INVALID_FD;
   }
 
-  char log_path[PROPERTY_VALUE_MAX];
-  char last_log_path[PROPERTY_VALUE_MAX + sizeof(".last")];
-  get_btsnoop_log_path(log_path);
-  get_btsnoop_last_log_path(last_log_path, log_path);
+  auto log_path = get_btsnoop_log_path(is_btsnoop_filtered);
+  auto last_log_path = get_btsnoop_last_log_path(log_path);
 
-  if (rename(log_path, last_log_path) != 0 && errno != ENOENT)
-    LOG_ERROR(LOG_TAG, "%s unable to rename '%s' to '%s': %s", __func__,
-              log_path, last_log_path, strerror(errno));
+  if (rename(log_path.c_str(), last_log_path.c_str()) != 0 && errno != ENOENT)
+    LOG(ERROR) << __func__ << ": unable to rename '" << log_path << "' to '"
+               << last_log_path << "' : " << strerror(errno);
 
   mode_t prevmask = umask(0);
-  logfile_fd = open(log_path, O_WRONLY | O_CREAT | O_TRUNC,
+  logfile_fd = open(log_path.c_str(), O_WRONLY | O_CREAT | O_TRUNC,
                     S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
   umask(prevmask);
   if (logfile_fd == INVALID_FD) {
-    LOG_ERROR(LOG_TAG, "%s unable to open '%s': %s", __func__, log_path,
-              strerror(errno));
+    LOG(ERROR) << __func__ << ": unable to open '" << log_path
+               << "' : " << strerror(errno);
     return;
   }
 
@@ -235,6 +401,32 @@
   return ll;
 }
 
+static bool should_filter_log(bool is_received, uint8_t* packet) {
+  uint16_t acl_handle =
+      HCID_GET_HANDLE((((uint16_t)packet[ACL_CHANNEL_OFFSET + 1]) << 8) +
+                      packet[ACL_CHANNEL_OFFSET]);
+
+  std::lock_guard lock(filter_list_mutex);
+  auto& filters = filter_list[acl_handle];
+  uint16_t l2c_channel =
+      (packet[L2C_CHANNEL_OFFSET + 1] << 8) + packet[L2C_CHANNEL_OFFSET];
+  if (filters.isRfcChannel(is_received, l2c_channel)) {
+    uint8_t rfc_event = packet[RFC_EVENT_OFFSET] & 0b11101111;
+    if (rfc_event == RFCOMM_SABME || rfc_event == RFCOMM_UA) {
+      return false;
+    }
+
+    uint8_t rfc_dlci = packet[RFC_CHANNEL_OFFSET] >> 2;
+    if (!filters.isWhitelistedDlci(rfc_dlci)) {
+      return true;
+    }
+  } else if (!filters.isWhitelistedL2c(is_received, l2c_channel)) {
+    return true;
+  }
+
+  return false;
+}
+
 static void btsnoop_write_packet(packet_type_t type, uint8_t* packet,
                                  bool is_received, uint64_t timestamp_us) {
   uint32_t length_he = 0;
@@ -261,7 +453,15 @@
 
   btsnoop_header_t header;
   header.length_original = htonl(length_he);
-  header.length_captured = header.length_original;
+
+  bool blacklisted = false;
+  if (is_btsnoop_filtered && type == kAclPacket) {
+    blacklisted = should_filter_log(is_received, packet);
+  }
+
+  header.length_captured =
+      blacklisted ? htonl(L2C_HEADER_SIZE) : header.length_original;
+  if (blacklisted) length_he = L2C_HEADER_SIZE;
   header.flags = htonl(flags);
   header.dropped_packets = 0;
   header.timestamp = htonll(timestamp_us + BTSNOOP_EPOCH_DELTA);
diff --git a/hci/src/hci_layer.cc b/hci/src/hci_layer.cc
index f1e0e7a..ed2908c 100644
--- a/hci/src/hci_layer.cc
+++ b/hci/src/hci_layer.cc
@@ -25,6 +25,7 @@
 #include <base/run_loop.h>
 #include <base/sequenced_task_runner.h>
 #include <base/threading/thread.h>
+#include <frameworks/base/core/proto/android/bluetooth/hci/enums.pb.h>
 
 #include <signal.h>
 #include <string.h>
@@ -37,6 +38,8 @@
 #include "btcore/include/module.h"
 #include "btsnoop.h"
 #include "buffer_allocator.h"
+#include "common/message_loop_thread.h"
+#include "common/metrics.h"
 #include "hci_inject.h"
 #include "hci_internals.h"
 #include "hcidefs.h"
@@ -50,6 +53,8 @@
 
 #define BT_HCI_TIMEOUT_TAG_NUM 1010000
 
+using bluetooth::common::MessageLoopThread;
+
 extern void hci_initialize();
 extern void hci_transmit(BT_HDR* packet);
 extern void hci_close();
@@ -70,17 +75,17 @@
 } waiting_command_t;
 
 // Using a define here, because it can be stringified for the property lookup
-#define DEFAULT_STARTUP_TIMEOUT_MS 8000
+// Default timeout should be less than BLE_START_TIMEOUT and
+// having less than 3 sec would hold the wakelock for init
+#define DEFAULT_STARTUP_TIMEOUT_MS 2900
 #define STRING_VALUE_OF(x) #x
 
-// RT priority for HCI thread
-static const int BT_HCI_RT_PRIORITY = 1;
-
 // Abort if there is no response to an HCI command.
 static const uint32_t COMMAND_PENDING_TIMEOUT_MS = 2000;
 static const uint32_t COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS = 500;
 static const uint32_t COMMAND_TIMEOUT_RESTART_MS = 5000;
 static const int HCI_UNKNOWN_COMMAND_TIMED_OUT = 0x00ffffff;
+static const int HCI_STARTUP_TIMED_OUT = 0x00eeeeee;
 
 // Our interface
 static bool interface_created;
@@ -92,10 +97,7 @@
 static const packet_fragmenter_t* packet_fragmenter;
 
 static future_t* startup_future;
-static thread_t* thread;  // We own this
-static std::mutex message_loop_mutex;
-static base::MessageLoop* message_loop_ = nullptr;
-static base::RunLoop* run_loop_ = nullptr;
+static MessageLoopThread hci_thread("bt_hci_thread");
 
 static alarm_t* startup_timer;
 
@@ -111,8 +113,7 @@
 static alarm_t* hci_timeout_abort_timer;
 
 // The hand-off point for data going to a higher layer, set by the higher layer
-static base::Callback<void(const tracked_objects::Location&, BT_HDR*)>
-    send_data_upwards;
+static base::Callback<void(const base::Location&, BT_HDR*)> send_data_upwards;
 
 static bool filter_incoming_event(BT_HDR* packet);
 static waiting_command_t* get_waiting_command(command_opcode_t opcode);
@@ -138,13 +139,10 @@
     transmit_fragment, dispatch_reassembled, fragmenter_transmit_finished};
 
 void initialization_complete() {
-  std::lock_guard<std::mutex> lock(message_loop_mutex);
-  message_loop_->task_runner()->PostTask(
-      FROM_HERE, base::Bind(&event_finish_startup, nullptr));
+  hci_thread.DoInThread(FROM_HERE, base::Bind(&event_finish_startup, nullptr));
 }
 
-void hci_event_received(const tracked_objects::Location& from_here,
-                        BT_HDR* packet) {
+void hci_event_received(const base::Location& from_here, BT_HDR* packet) {
   btsnoop->capture(packet, true);
 
   if (!filter_incoming_event(packet)) {
@@ -166,26 +164,6 @@
 
 static future_t* hci_module_shut_down();
 
-void message_loop_run(UNUSED_ATTR void* context) {
-  {
-    std::lock_guard<std::mutex> lock(message_loop_mutex);
-    message_loop_ = new base::MessageLoop();
-    run_loop_ = new base::RunLoop();
-  }
-
-  message_loop_->task_runner()->PostTask(FROM_HERE,
-                                         base::Bind(&hci_initialize));
-  run_loop_->Run();
-
-  {
-    std::lock_guard<std::mutex> lock(message_loop_mutex);
-    delete message_loop_;
-    message_loop_ = nullptr;
-    delete run_loop_;
-    run_loop_ = nullptr;
-  }
-}
-
 static future_t* hci_module_start_up(void) {
   LOG_INFO(LOG_TAG, "%s", __func__);
 
@@ -196,7 +174,7 @@
   command_credits = 1;
 
   // For now, always use the default timeout on non-Android builds.
-  period_ms_t startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
+  uint64_t startup_timeout_ms = DEFAULT_STARTUP_TIMEOUT_MS;
 
   // Grab the override startup timeout ms, if present.
   char timeout_prop[PROPERTY_VALUE_MAX];
@@ -217,13 +195,14 @@
     goto error;
   }
 
-  thread = thread_new("hci_thread");
-  if (!thread) {
-    LOG_ERROR(LOG_TAG, "%s unable to create thread.", __func__);
+  hci_thread.StartUp();
+  if (!hci_thread.IsRunning()) {
+    LOG_ERROR(LOG_TAG, "%s unable to start thread.", __func__);
     goto error;
   }
-  if (!thread_set_rt_priority(thread, BT_HCI_RT_PRIORITY)) {
+  if (!hci_thread.EnableRealTimeScheduling()) {
     LOG_ERROR(LOG_TAG, "%s unable to make thread RT.", __func__);
+    goto error;
   }
 
   commands_pending_response = list_new(NULL);
@@ -242,7 +221,7 @@
 
   packet_fragmenter->init(&packet_fragmenter_callbacks);
 
-  thread_post(thread, message_loop_run, NULL);
+  hci_thread.DoInThread(FROM_HERE, base::Bind(&hci_initialize));
 
   LOG_DEBUG(LOG_TAG, "%s starting async portion", __func__);
   return local_startup_future;
@@ -265,16 +244,7 @@
     startup_timer = NULL;
   }
 
-  {
-    std::lock_guard<std::mutex> lock(message_loop_mutex);
-    message_loop_->task_runner()->PostTask(FROM_HERE, run_loop_->QuitClosure());
-  }
-
-  // Stop the thread to prevent Send() calls.
-  if (thread) {
-    thread_stop(thread);
-    thread_join(thread);
-  }
+  hci_thread.ShutDown();
 
   // Close HCI to prevent callbacks.
   hci_close();
@@ -288,9 +258,6 @@
 
   packet_fragmenter->cleanup();
 
-  thread_free(thread);
-  thread = NULL;
-
   // Clean up abort timer, if it exists.
   if (hci_timeout_abort_timer != NULL) {
     alarm_free(hci_timeout_abort_timer);
@@ -316,8 +283,7 @@
 // Interface functions
 
 static void set_data_cb(
-    base::Callback<void(const tracked_objects::Location&, BT_HDR*)>
-        send_data_cb) {
+    base::Callback<void(const base::Location&, BT_HDR*)> send_data_cb) {
   send_data_upwards = std::move(send_data_cb);
 }
 
@@ -378,6 +344,9 @@
   std::lock_guard<std::recursive_timed_mutex> lock(
       commands_pending_response_mutex);
   alarm_cancel(startup_timer);
+  if (!startup_future) {
+    return;
+  }
   future_ready(startup_future, FUTURE_SUCCESS);
   startup_future = NULL;
 }
@@ -385,18 +354,8 @@
 static void startup_timer_expired(UNUSED_ATTR void* context) {
   LOG_ERROR(LOG_TAG, "%s", __func__);
 
-  std::unique_lock<std::recursive_timed_mutex> lock(
-      commands_pending_response_mutex, std::defer_lock);
-  if (!lock.try_lock_for(std::chrono::milliseconds(
-          COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS))) {
-    LOG_ERROR(LOG_TAG, "%s: Cannot obtain the mutex", __func__);
-    // We cannot recover if the startup timer expired and we are deadlock,
-    // hence abort.
-    abort();
-  }
-  future_ready(startup_future, FUTURE_FAIL);
-  startup_future = NULL;
-  lock.unlock();
+  LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, HCI_STARTUP_TIMED_OUT);
+  abort();
 }
 
 // Command/packet transmitting functions
@@ -405,14 +364,12 @@
 
   std::lock_guard<std::mutex> command_credits_lock(command_credits_mutex);
   if (command_credits > 0) {
-    std::lock_guard<std::mutex> message_loop_lock(message_loop_mutex);
-    if (message_loop_ == nullptr) {
-      // HCI Layer was shut down
+    if (!hci_thread.DoInThread(FROM_HERE, std::move(callback))) {
+      // HCI Layer was shut down or not running
       buffer_allocator->free(wait_entry->command);
       osi_free(wait_entry);
       return;
     }
-    message_loop_->task_runner()->PostTask(FROM_HERE, std::move(callback));
     command_credits--;
   } else {
     command_queue.push(std::move(callback));
@@ -434,14 +391,12 @@
 }
 
 static void enqueue_packet(void* packet) {
-  std::lock_guard<std::mutex> lock(message_loop_mutex);
-  if (message_loop_ == nullptr) {
-    // HCI Layer was shut down
+  if (!hci_thread.DoInThread(FROM_HERE,
+                             base::Bind(&event_packet_ready, packet))) {
+    // HCI Layer was shut down or not running
     buffer_allocator->free(packet);
     return;
   }
-  message_loop_->task_runner()->PostTask(
-      FROM_HERE, base::Bind(&event_packet_ready, packet));
 }
 
 static void event_packet_ready(void* pkt) {
@@ -519,6 +474,7 @@
     }
 
     LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, wait_entry->opcode);
+    bluetooth::common::LogHciTimeoutEvent(wait_entry->opcode);
   }
 }
 
@@ -531,6 +487,7 @@
           COMMAND_PENDING_MUTEX_ACQUIRE_TIMEOUT_MS))) {
     LOG_ERROR(LOG_TAG, "%s: Cannot obtain the mutex", __func__);
     LOG_EVENT_INT(BT_HCI_TIMEOUT_TAG_NUM, HCI_UNKNOWN_COMMAND_TIMED_OUT);
+    bluetooth::common::LogHciTimeoutEvent(android::bluetooth::hci::CMD_UNKNOWN);
   } else {
     command_timed_out_log_info(original_wait_entry);
     lock.unlock();
@@ -576,19 +533,19 @@
 // Event/packet receiving functions
 void process_command_credits(int credits) {
   std::lock_guard<std::mutex> command_credits_lock(command_credits_mutex);
-  std::lock_guard<std::mutex> message_loop_lock(message_loop_mutex);
 
-  if (message_loop_ == nullptr) {
-    // HCI Layer was shut down
+  if (!hci_thread.IsRunning()) {
+    // HCI Layer was shut down or not running
     return;
   }
 
   // Subtract commands in flight.
   command_credits = credits - get_num_waiting_commands();
 
-  while (command_credits > 0 && command_queue.size() > 0) {
-    message_loop_->task_runner()->PostTask(FROM_HERE,
-                                           std::move(command_queue.front()));
+  while (command_credits > 0 && !command_queue.empty()) {
+    if (!hci_thread.DoInThread(FROM_HERE, std::move(command_queue.front()))) {
+      LOG(ERROR) << __func__ << ": failed to enqueue command";
+    }
     command_queue.pop();
     command_credits--;
   }
diff --git a/hci/src/hci_layer_android.cc b/hci/src/hci_layer_android.cc
index 183b74e..92be0df 100644
--- a/hci/src/hci_layer_android.cc
+++ b/hci/src/hci_layer_android.cc
@@ -37,23 +37,32 @@
 #define LOG_PATH "/data/misc/bluetooth/logs/firmware_events.log"
 #define LAST_LOG_PATH "/data/misc/bluetooth/logs/firmware_events.log.last"
 
-using android::hardware::bluetooth::V1_0::IBluetoothHci;
-using android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
-using android::hardware::bluetooth::V1_0::HciPacket;
-using android::hardware::bluetooth::V1_0::Status;
-using android::hardware::ProcessState;
+using ::android::hardware::hidl_death_recipient;
+using ::android::hardware::hidl_vec;
+using ::android::hardware::ProcessState;
 using ::android::hardware::Return;
 using ::android::hardware::Void;
-using ::android::hardware::hidl_vec;
+using ::android::hardware::bluetooth::V1_0::HciPacket;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHci;
+using ::android::hardware::bluetooth::V1_0::IBluetoothHciCallbacks;
+using ::android::hardware::bluetooth::V1_0::Status;
 
 extern void initialization_complete();
-extern void hci_event_received(const tracked_objects::Location& from_here,
-                               BT_HDR* packet);
+extern void hci_event_received(const base::Location& from_here, BT_HDR* packet);
 extern void acl_event_received(BT_HDR* packet);
 extern void sco_data_received(BT_HDR* packet);
 
 android::sp<IBluetoothHci> btHci;
 
+class BluetoothHciDeathRecipient : public hidl_death_recipient {
+ public:
+  virtual void serviceDied(uint64_t /*cookie*/, const android::wp<::android::hidl::base::V1_0::IBase>& /*who*/) {
+    LOG_ERROR(LOG_TAG, "Bluetooth HAL service died!");
+    abort();
+  }
+};
+android::sp<BluetoothHciDeathRecipient> bluetoothHciDeathRecipient = new BluetoothHciDeathRecipient();
+
 class BluetoothHciCallbacks : public IBluetoothHciCallbacks {
  public:
   BluetoothHciCallbacks() {
@@ -107,6 +116,11 @@
   btHci = IBluetoothHci::getService();
   // If android.hardware.bluetooth* is not found, Bluetooth can not continue.
   CHECK(btHci != nullptr);
+  auto death_link = btHci->linkToDeath(bluetoothHciDeathRecipient, 0);
+  if (!death_link.isOk()) {
+    LOG_ERROR(LOG_TAG, "%s: Unable to set the death recipient for the Bluetooth HAL", __func__);
+    abort();
+  }
   LOG_INFO(LOG_TAG, "%s: IBluetoothHci::getService() returned %p (%s)",
            __func__, btHci.get(), (btHci->isRemote() ? "remote" : "local"));
 
@@ -118,6 +132,12 @@
 }
 
 void hci_close() {
+  if (btHci != nullptr) {
+    auto death_unlink = btHci->unlinkToDeath(bluetoothHciDeathRecipient);
+    if (!death_unlink.isOk()) {
+      LOG_ERROR(LOG_TAG, "%s: Error unlinking death recipient from the Bluetooth HAL", __func__);
+    }
+  }
   btHci->close();
   btHci = nullptr;
 }
diff --git a/hci/src/hci_layer_linux.cc b/hci/src/hci_layer_linux.cc
index e32b5ef..01ff5af 100644
--- a/hci/src/hci_layer_linux.cc
+++ b/hci/src/hci_layer_linux.cc
@@ -93,8 +93,7 @@
 };
 
 extern void initialization_complete();
-extern void hci_event_received(const tracked_objects::Location& from_here,
-                               BT_HDR* packet);
+extern void hci_event_received(const base::Location& from_here, BT_HDR* packet);
 extern void acl_event_received(BT_HDR* packet);
 extern void sco_data_received(BT_HDR* packet);
 
@@ -204,12 +203,12 @@
   addr.hci_dev = hci_interface;
   addr.hci_channel = HCI_CHANNEL_USER;
   if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
-    LOG(FATAL) << "socket bind error " << strerror(errno);
+    PLOG(FATAL) << "socket bind error";
   }
 
   int sv[2];
   if (socketpair(AF_UNIX, SOCK_STREAM, 0, sv) < 0) {
-    LOG(FATAL) << "socketpair failed: " << strerror(errno);
+    PLOG(FATAL) << "socketpair failed";
   }
 
   reader_thread_ctrl_fd = sv[0];
@@ -246,7 +245,7 @@
 }
 
 void hci_transmit(BT_HDR* packet) {
-  uint8_t type;
+  uint8_t type = 0;
 
   CHECK(bt_vendor_fd != -1);
 
@@ -275,7 +274,7 @@
 
   if (ret != packet->len + 1) LOG(ERROR) << "Should have send whole packet";
 
-  if (ret == -1) LOG(FATAL) << strerror(errno);
+  if (ret == -1) PLOG(FATAL) << "write failed";
 }
 
 static int wait_hcidev(void) {
@@ -289,7 +288,7 @@
 
   fd = socket(PF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
   if (fd < 0) {
-    LOG(ERROR) << "Bluetooth socket error: %s" << strerror(errno);
+    PLOG(ERROR) << "Bluetooth socket error";
     return -1;
   }
 
@@ -299,7 +298,7 @@
   addr.hci_channel = HCI_CHANNEL_CONTROL;
 
   if (bind(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
-    LOG(ERROR) << "HCI Channel Control: " << strerror(errno);
+    PLOG(ERROR) << "HCI Channel Control";
     close(fd);
     return -1;
   }
@@ -315,7 +314,7 @@
   ssize_t wrote;
   OSI_NO_INTR(wrote = write(fd, &ev, 6));
   if (wrote != 6) {
-    LOG(ERROR) << "Unable to write mgmt command: " << strerror(errno);
+    PLOG(ERROR) << "Unable to write mgmt command";
     ret = -1;
     goto end;
   }
@@ -324,7 +323,7 @@
     int n;
     OSI_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT));
     if (n == -1) {
-      LOG(ERROR) << "Poll error: " << strerror(errno);
+      PLOG(ERROR) << "Poll error";
       ret = -1;
       break;
     } else if (n == 0) {
@@ -336,7 +335,7 @@
     if (fds[0].revents & POLLIN) {
       OSI_NO_INTR(n = read(fd, &ev, sizeof(struct mgmt_pkt)));
       if (n < 0) {
-        LOG(ERROR) << "Error reading control channel: " << strerror(errno);
+        PLOG(ERROR) << "Error reading control channel";
         ret = -1;
         break;
       }
diff --git a/hci/src/packet_fragmenter.cc b/hci/src/packet_fragmenter.cc
index 921ac82..5036ed5 100644
--- a/hci/src/packet_fragmenter.cc
+++ b/hci/src/packet_fragmenter.cc
@@ -123,12 +123,10 @@
   if ((packet->event & MSG_EVT_MASK) == MSG_HC_TO_STACK_HCI_ACL) {
     uint8_t* stream = packet->data;
     uint16_t handle;
-    uint16_t l2cap_length;
     uint16_t acl_length;
 
     STREAM_TO_UINT16(handle, stream);
     STREAM_TO_UINT16(acl_length, stream);
-    STREAM_TO_UINT16(l2cap_length, stream);
 
     CHECK(acl_length == packet->len - HCI_ACL_PREAMBLE_SIZE);
 
@@ -136,6 +134,13 @@
     handle = handle & HANDLE_MASK;
 
     if (boundary_flag == START_PACKET_BOUNDARY) {
+      if (acl_length < 2) {
+        LOG_WARN(LOG_TAG, "%s invalid acl_length %d", __func__, acl_length);
+        buffer_allocator->free(packet);
+        return;
+      }
+      uint16_t l2cap_length;
+      STREAM_TO_UINT16(l2cap_length, stream);
       auto map_iter = partial_packets.find(handle);
       if (map_iter != partial_packets.end()) {
         LOG_WARN(LOG_TAG,
diff --git a/include/hardware/avrcp/avrcp.h b/include/hardware/avrcp/avrcp.h
index 8adba47..577acb9 100644
--- a/include/hardware/avrcp/avrcp.h
+++ b/include/hardware/avrcp/avrcp.h
@@ -19,7 +19,7 @@
 #include <set>
 #include <string>
 
-#include <base/bind.h>
+#include <base/callback_forward.h>
 
 #include "avrcp_common.h"
 #include "raw_address.h"
@@ -72,10 +72,11 @@
 
 class MediaCallbacks {
  public:
-  virtual void SendMediaUpdate(bool track_changed, bool play_state, bool queue);
+  virtual void SendMediaUpdate(bool track_changed, bool play_state,
+                               bool queue) = 0;
   virtual void SendFolderUpdate(bool available_players, bool addressed_players,
-                                bool uids_changed);
-  virtual void SendActiveDeviceChanged(const RawAddress& address);
+                                bool uids_changed) = 0;
+  virtual void SendActiveDeviceChanged(const RawAddress& address) = 0;
   virtual ~MediaCallbacks() = default;
 };
 
diff --git a/include/hardware/bluetooth.h b/include/hardware/bluetooth.h
index 36680bf..063abf9 100644
--- a/include/hardware/bluetooth.h
+++ b/include/hardware/bluetooth.h
@@ -38,7 +38,6 @@
 #define BT_PROFILE_HANDSFREE_CLIENT_ID "handsfree_client"
 #define BT_PROFILE_ADVANCED_AUDIO_ID "a2dp"
 #define BT_PROFILE_ADVANCED_AUDIO_SINK_ID "a2dp_sink"
-#define BT_PROFILE_HEALTH_ID "health"
 #define BT_PROFILE_SOCKETS_ID "socket"
 #define BT_PROFILE_HIDHOST_ID "hidhost"
 #define BT_PROFILE_HIDDEV_ID "hiddev"
@@ -50,9 +49,6 @@
 #define BT_PROFILE_AV_RC_CTRL_ID "avrcp_ctrl"
 #define BT_PROFILE_HEARING_AID_ID "hearing_aid"
 
-/** Bluetooth test interface IDs */
-#define BT_TEST_INTERFACE_MCAP_ID "mcap_test"
-
 /** Bluetooth Device Name */
 typedef struct { uint8_t name[249]; } __attribute__((packed)) bt_bdname_t;
 
@@ -66,6 +62,18 @@
 /** Bluetooth Adapter State */
 typedef enum { BT_STATE_OFF, BT_STATE_ON } bt_state_t;
 
+/** Bluetooth Adapter Input Output Capabilities which determine Pairing/Security
+ */
+typedef enum {
+  BT_IO_CAP_OUT,    /* DisplayOnly */
+  BT_IO_CAP_IO,     /* DisplayYesNo */
+  BT_IO_CAP_IN,     /* KeyboardOnly */
+  BT_IO_CAP_NONE,   /* NoInputNoOutput */
+  BT_IO_CAP_KBDISP, /* Keyboard display */
+  BT_IO_CAP_MAX,
+  BT_IO_CAP_UNKNOWN = 0xFF /* Unknown value */
+} bt_io_cap_t;
+
 /** Bluetooth Error Status */
 /** We need to build on this */
 
@@ -240,6 +248,20 @@
    */
   BT_PROPERTY_LOCAL_LE_FEATURES,
 
+  /**
+   * Description - Local Input/Output Capabilities for classic Bluetooth
+   * Access mode - GET and SET
+   * Data Type - bt_io_cap_t.
+   */
+  BT_PROPERTY_LOCAL_IO_CAPS,
+
+  /**
+   * Description - Local Input/Output Capabilities for BLE
+   * Access mode - GET and SET
+   * Data Type - bt_io_cap_t.
+   */
+  BT_PROPERTY_LOCAL_IO_CAPS_BLE,
+
   BT_PROPERTY_REMOTE_DEVICE_TIMESTAMP = 0xFF,
 } bt_property_type_t;
 
@@ -444,11 +466,16 @@
   /**
    * Opens the interface and provides the callback routines
    * to the implemenation of this interface.
+   * The |start_restricted| flag inits the adapter in restricted mode. In
+   * restricted mode, bonds that are created are marked as restricted in the
+   * config file. These devices are deleted upon leaving restricted mode.
+   * The |is_single_user_mode| flag inits the adapter in NIAP mode.
    */
-  int (*init)(bt_callbacks_t* callbacks);
+  int (*init)(bt_callbacks_t* callbacks, bool guest_mode,
+              bool is_single_user_mode);
 
   /** Enable Bluetooth. */
-  int (*enable)(bool guest_mode);
+  int (*enable)();
 
   /** Disable Bluetooth. */
   int (*disable)(void);
@@ -590,6 +617,14 @@
    * Get the AvrcpTarget Service interface to interact with the Avrcp Service
    */
   bluetooth::avrcp::ServiceInterface* (*get_avrcp_service)(void);
+
+  /**
+   * Obfuscate Bluetooth MAC address into a PII free ID string
+   *
+   * @param address Bluetooth MAC address to be obfuscated
+   * @return a string of uint8_t that is unique to this MAC address
+   */
+  std::string (*obfuscate_address)(const RawAddress& address);
 } bt_interface_t;
 
 #define BLUETOOTH_INTERFACE_STRING "bluetoothInterface"
diff --git a/include/hardware/bluetooth_headset_interface.h b/include/hardware/bluetooth_headset_interface.h
index a3e0e37..8527919 100644
--- a/include/hardware/bluetooth_headset_interface.h
+++ b/include/hardware/bluetooth_headset_interface.h
@@ -195,6 +195,7 @@
    * @param call_setup_state current call setup state
    * @param number phone number of the call
    * @param type type of the call
+   * @param name caller display name
    * @param bd_addr remote device address
    * @return BT_STATUS_SUCCESS on success
    */
@@ -202,6 +203,7 @@
                                        bthf_call_state_t call_setup_state,
                                        const char* number,
                                        bthf_call_addrtype_t type,
+                                       const char* name,
                                        RawAddress* bd_addr) = 0;
 
   /**
diff --git a/include/hardware/bt_av.h b/include/hardware/bt_av.h
index bdb1285..d38beaa 100644
--- a/include/hardware/bt_av.h
+++ b/include/hardware/bt_av.h
@@ -62,6 +62,7 @@
   // Add an entry for each sink codec here
   BTAV_A2DP_CODEC_INDEX_SINK_SBC = BTAV_A2DP_CODEC_INDEX_SINK_MIN,
   BTAV_A2DP_CODEC_INDEX_SINK_AAC,
+  BTAV_A2DP_CODEC_INDEX_SINK_LDAC,
 
   BTAV_A2DP_CODEC_INDEX_SINK_MAX,
 
@@ -154,6 +155,9 @@
       case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
         codec_name_str = "AAC (Sink)";
         break;
+      case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
+        codec_name_str = "LDAC (Sink)";
+        break;
       case BTAV_A2DP_CODEC_INDEX_MAX:
         codec_name_str = "Unknown(CODEC_INDEX_MAX)";
         break;
@@ -309,6 +313,9 @@
   /** dis-connect from headset */
   bt_status_t (*disconnect)(const RawAddress& bd_addr);
 
+  /** sets the connected device silence state */
+  bt_status_t (*set_silence_device)(const RawAddress& bd_addr, bool silence);
+
   /** sets the connected device as active */
   bt_status_t (*set_active_device)(const RawAddress& bd_addr);
 
diff --git a/include/hardware/bt_hearing_aid.h b/include/hardware/bt_hearing_aid.h
index 7ab0dc7..1911159 100644
--- a/include/hardware/bt_hearing_aid.h
+++ b/include/hardware/bt_hearing_aid.h
@@ -62,9 +62,6 @@
   /** Add a hearing aid device to white list */
   virtual void AddToWhiteList(const RawAddress& address) = 0;
 
-  /** Remove a hearing aid device from white list */
-  virtual void RemoveFromWhiteList(const RawAddress& address) = 0;
-
   /** Set the volume */
   virtual void SetVolume(int8_t volume) = 0;
 
diff --git a/include/hardware/bt_hl.h b/include/hardware/bt_hl.h
deleted file mode 100644
index 682605b..0000000
--- a/include/hardware/bt_hl.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- * Copyright (C) 2012 The Android Open Source Project
- *
- * 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.
- */
-
-#ifndef ANDROID_INCLUDE_BT_HL_H
-#define ANDROID_INCLUDE_BT_HL_H
-
-__BEGIN_DECLS
-
-/* HL connection states */
-
-typedef enum { BTHL_MDEP_ROLE_SOURCE, BTHL_MDEP_ROLE_SINK } bthl_mdep_role_t;
-
-typedef enum {
-  BTHL_APP_REG_STATE_REG_SUCCESS,
-  BTHL_APP_REG_STATE_REG_FAILED,
-  BTHL_APP_REG_STATE_DEREG_SUCCESS,
-  BTHL_APP_REG_STATE_DEREG_FAILED
-} bthl_app_reg_state_t;
-
-typedef enum {
-  BTHL_CHANNEL_TYPE_RELIABLE,
-  BTHL_CHANNEL_TYPE_STREAMING,
-  BTHL_CHANNEL_TYPE_ANY
-} bthl_channel_type_t;
-
-/* HL connection states */
-typedef enum {
-  BTHL_CONN_STATE_CONNECTING,
-  BTHL_CONN_STATE_CONNECTED,
-  BTHL_CONN_STATE_DISCONNECTING,
-  BTHL_CONN_STATE_DISCONNECTED,
-  BTHL_CONN_STATE_DESTROYED
-} bthl_channel_state_t;
-
-typedef struct {
-  bthl_mdep_role_t mdep_role;
-  int data_type;
-  bthl_channel_type_t channel_type;
-  const char* mdep_description; /* MDEP description to be used in the SDP
-                                   (optional); null terminated */
-} bthl_mdep_cfg_t;
-
-typedef struct {
-  const char* application_name;
-  const char*
-      provider_name;    /* provider name to be used in the SDP (optional); null
-                           terminated */
-  const char* srv_name; /* service name to be used in the SDP (optional); null
-                           terminated*/
-  const char*
-      srv_desp; /* service description to be used in the SDP (optional); null
-                   terminated */
-  int number_of_mdeps;
-  bthl_mdep_cfg_t* mdep_cfg; /* Dynamic array */
-} bthl_reg_param_t;
-
-/** Callback for application registration status.
- *  state will have one of the values from  bthl_app_reg_state_t
- */
-typedef void (*bthl_app_reg_state_callback)(int app_id,
-                                            bthl_app_reg_state_t state);
-
-/** Callback for channel connection state change.
- *  state will have one of the values from
- *  bthl_connection_state_t and fd (file descriptor)
- */
-typedef void (*bthl_channel_state_callback)(int app_id, RawAddress* bd_addr,
-                                            int mdep_cfg_index, int channel_id,
-                                            bthl_channel_state_t state, int fd);
-
-/** BT-HL callback structure. */
-typedef struct {
-  /** set to sizeof(bthl_callbacks_t) */
-  size_t size;
-  bthl_app_reg_state_callback app_reg_state_cb;
-  bthl_channel_state_callback channel_state_cb;
-} bthl_callbacks_t;
-
-/** Represents the standard BT-HL interface. */
-typedef struct {
-  /** set to sizeof(bthl_interface_t)  */
-  size_t size;
-
-  /**
-   * Register the Bthl callbacks
-   */
-  bt_status_t (*init)(bthl_callbacks_t* callbacks);
-
-  /** Register HL application */
-  bt_status_t (*register_application)(bthl_reg_param_t* p_reg_param,
-                                      int* app_id);
-
-  /** Unregister HL application */
-  bt_status_t (*unregister_application)(int app_id);
-
-  /** connect channel */
-  bt_status_t (*connect_channel)(int app_id, RawAddress* bd_addr,
-                                 int mdep_cfg_index, int* channel_id);
-
-  /** destroy channel */
-  bt_status_t (*destroy_channel)(int channel_id);
-
-  /** Close the  Bthl callback **/
-  void (*cleanup)(void);
-
-} bthl_interface_t;
-__END_DECLS
-
-#endif /* ANDROID_INCLUDE_BT_HL_H */
diff --git a/include/hardware/bt_rc.h b/include/hardware/bt_rc.h
index 9349eed..dc46eca 100644
--- a/include/hardware/bt_rc.h
+++ b/include/hardware/bt_rc.h
@@ -613,6 +613,11 @@
                                                       uint8_t depth);
 typedef void (*btrc_ctrl_set_addressed_player_callback)(
     const RawAddress& bd_addr, uint8_t status);
+typedef void (*btrc_ctrl_addressed_player_changed_callback)(
+    const RawAddress& bd_addr, uint16_t id);
+typedef void (*btrc_ctrl_now_playing_contents_changed_callback)(
+    const RawAddress& bd_addr);
+
 /** BT-RC Controller callback structure. */
 typedef struct {
   /** set to sizeof(BtRcCallbacks) */
@@ -635,6 +640,9 @@
   btrc_ctrl_change_path_callback change_folder_path_cb;
   btrc_ctrl_set_browsed_player_callback set_browsed_player_cb;
   btrc_ctrl_set_addressed_player_callback set_addressed_player_cb;
+  btrc_ctrl_addressed_player_changed_callback addressed_player_changed_cb;
+  btrc_ctrl_now_playing_contents_changed_callback
+      now_playing_contents_changed_cb;
 } btrc_ctrl_callbacks_t;
 
 /** Represents the standard BT-RC AVRCP Controller interface. */
diff --git a/internal_include/bt_target.h b/internal_include/bt_target.h
index cf09b15..67a67c5 100644
--- a/internal_include/bt_target.h
+++ b/internal_include/bt_target.h
@@ -275,9 +275,8 @@
 #define BTM_NO_SSP_ON_INQUIRY FALSE
 #endif
 
-/* Includes SCO if TRUE */
-#ifndef BTM_SCO_INCLUDED
-#define BTM_SCO_INCLUDED TRUE /* TRUE includes SCO code */
+#ifndef DISABLE_WBS
+#define DISABLE_WBS FALSE
 #endif
 
 /*  This is used to work around a controller bug that doesn't like Disconnect
@@ -349,7 +348,7 @@
 
 /* The number of SCO links. */
 #ifndef BTM_MAX_SCO_LINKS
-#define BTM_MAX_SCO_LINKS 3
+#define BTM_MAX_SCO_LINKS 6
 #endif
 
 /* The number of security records for peer devices. */
@@ -405,14 +404,8 @@
 #define BTM_PM_DEBUG FALSE
 #endif
 
-/* This is set to TRUE if link is to be unparked due to BTM_CreateSCO API. */
-#ifndef BTM_SCO_WAKE_PARKED_LINK
-#define BTM_SCO_WAKE_PARKED_LINK TRUE
-#endif
-
 /* If the user does not respond to security process requests within this many
- * seconds,
- * a negative response would be sent automatically.
+ * seconds, a negative response would be sent automatically.
  * 30 is LMP response timeout value */
 #ifndef BTM_SEC_TIMEOUT_VALUE
 #define BTM_SEC_TIMEOUT_VALUE 35
@@ -662,6 +655,11 @@
 #define GATT_MAX_APPS 32 /* note: 2 apps used internally GATT and GAP */
 #endif
 
+/* connection manager doesn't generate it's own IDs. Instead, all GATT clients
+ * use their gatt_if to identify against conection manager. When stack tries to
+ * create l2cap connection, it will use this fixed ID. */
+#define CONN_MGR_ID_L2CAP (GATT_MAX_APPS + 10)
+
 #ifndef GATT_MAX_PHY_CHANNEL
 #define GATT_MAX_PHY_CHANNEL 7
 #endif
@@ -1228,118 +1226,6 @@
 
 /******************************************************************************
  *
- * MCAP
- *
- *****************************************************************************/
-#ifndef MCA_INCLUDED
-#define MCA_INCLUDED FALSE
-#endif
-
-/* The MTU size for the L2CAP configuration on control channel. 48 is the
- * minimal */
-#ifndef MCA_CTRL_MTU
-#define MCA_CTRL_MTU 60
-#endif
-
-/* The maximum number of registered MCAP instances. */
-#ifndef MCA_NUM_REGS
-#define MCA_NUM_REGS 12
-#endif
-
-/* The maximum number of control channels (to difference devices) per registered
- * MCAP instances. */
-#ifndef MCA_NUM_LINKS
-#define MCA_NUM_LINKS 3
-#endif
-
-/* The maximum number of MDEP (including HDP echo) per registered MCAP
- * instances. */
-#ifndef MCA_NUM_DEPS
-#define MCA_NUM_DEPS 13
-#endif
-
-/* The maximum number of MDL link per control channel. */
-#ifndef MCA_NUM_MDLS
-#define MCA_NUM_MDLS 4
-#endif
-
-/* Buffer size to reassemble the SDU. */
-#ifndef MCA_USER_RX_BUF_SIZE
-#define MCA_USER_RX_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
-#endif
-
-/* Buffer size to hold the SDU. */
-#ifndef MCA_USER_TX_BUF_SIZE
-#define MCA_USER_TX_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
-#endif
-
-/*
- * Buffer size used to hold MPS segments during SDU reassembly
- */
-#ifndef MCA_FCR_RX_BUF_SIZE
-#define MCA_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).
- */
-#ifndef MCA_FCR_TX_BUF_SIZE
-#define MCA_FCR_TX_BUF_SIZE BT_DEFAULT_BUFFER_SIZE
-#endif
-
-/* MCAP control channel FCR Option:
-Size of the transmission window when using enhanced retransmission mode.
-1 is defined by HDP specification for control channel.
-*/
-#ifndef MCA_FCR_OPT_TX_WINDOW_SIZE
-#define MCA_FCR_OPT_TX_WINDOW_SIZE 1
-#endif
-
-/* MCAP control channel FCR Option:
-Number of transmission attempts for a single I-Frame before taking
-Down the connection. Used In ERTM mode only. Value is Ignored in basic and
-Streaming modes.
-Range: 0, 1-0xFF
-0 - infinite retransmissions
-1 - single transmission
-*/
-#ifndef MCA_FCR_OPT_MAX_TX_B4_DISCNT
-#define MCA_FCR_OPT_MAX_TX_B4_DISCNT 20
-#endif
-
-/* MCAP control channel FCR Option: Retransmission Timeout
-The AVRCP specification set a value in the range of 300 - 2000 ms
-Timeout (in msecs) to detect Lost I-Frames. Only used in Enhanced retransmission
-mode.
-Range: Minimum 2000 (2 secs) when supporting PBF.
- */
-#ifndef MCA_FCR_OPT_RETX_TOUT
-#define MCA_FCR_OPT_RETX_TOUT 2000
-#endif
-
-/* MCAP control channel FCR Option: Monitor Timeout
-The AVRCP specification set a value in the range of 300 - 2000 ms
-Timeout (in msecs) to detect Lost S-Frames. Only used in Enhanced retransmission
-mode.
-Range: Minimum 12000 (12 secs) when supporting PBF.
-*/
-#ifndef MCA_FCR_OPT_MONITOR_TOUT
-#define MCA_FCR_OPT_MONITOR_TOUT 12000
-#endif
-
-/* MCAP control channel FCR Option: Maximum PDU payload size.
-The maximum number of payload octets that the local device can receive in a
-single PDU.
-*/
-#ifndef MCA_FCR_OPT_MPS_SIZE
-#define MCA_FCR_OPT_MPS_SIZE 1000
-#endif
-
-/******************************************************************************
- *
  * BTA
  *
  *****************************************************************************/
diff --git a/internal_include/bt_trace.h b/internal_include/bt_trace.h
index 97c761b..f27563d 100644
--- a/internal_include/bt_trace.h
+++ b/internal_include/bt_trace.h
@@ -66,7 +66,7 @@
 #define BTTRC_ID_STK_SPP 39
 #define BTTRC_ID_STK_TCS 40
 #define BTTRC_ID_STK_VDP 41
-#define BTTRC_ID_STK_MCAP 42
+#define BTTRC_ID_STK_MCAP 42 /* OBSOLETE */
 #define BTTRC_ID_STK_GATT 43
 #define BTTRC_ID_STK_SMP 44
 #define BTTRC_ID_STK_NFC 45
@@ -182,10 +182,6 @@
 #define AVRC_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING
 #endif
 
-#ifndef MCA_INITIAL_TRACE_LEVEL
-#define MCA_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING
-#endif
-
 #ifndef HID_INITIAL_TRACE_LEVEL
 #define HID_INITIAL_TRACE_LEVEL BT_TRACE_LEVEL_WARNING
 #endif
@@ -556,33 +552,6 @@
       BT_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 tracing for the SMP unit */
 #define SMP_TRACE_ERROR(...)                                      \
   {                                                               \
@@ -729,7 +698,7 @@
 
 #include <base/logging.h>
 
-/* Prints intergral parameter x as hex string, with '0' fill */
+/* Prints integral parameter x as hex string, with '0' fill */
 template <typename T>
 std::string loghex(T x) {
   static_assert(std::is_integral<T>::value,
@@ -740,6 +709,19 @@
   return tmp.str();
 }
 
+/* Prints integral array as hex string, with '0' fill */
+template <typename T, size_t N>
+std::string loghex(std::array<T, N> array) {
+  static_assert(std::is_integral<T>::value,
+                "type stored in array must be integral.");
+  std::stringstream tmp;
+  for (const auto& x : array) {
+    tmp << std::internal << std::hex << std::setfill('0')
+        << std::setw((sizeof(uint8_t) * 2) + 2) << +x;
+  }
+  return tmp.str();
+}
+
 /**
  * Obtains the string representation of a boolean value.
  *
@@ -771,4 +753,53 @@
   return *p_result;
 }
 
+// This object puts the stream in a state where every time that a new line
+// occurs, the next line is indented a certain number of spaces. The stream is
+// reset to its previous state when the object is destroyed.
+class ScopedIndent {
+ public:
+  ScopedIndent(std::ostream& stream, int indent_size = DEFAULT_TAB)
+      : indented_buf_(stream, indent_size) {
+    old_stream_ = &stream;
+    old_stream_buf_ = stream.rdbuf();
+    stream.rdbuf(&indented_buf_);
+  }
+
+  ~ScopedIndent() { old_stream_->rdbuf(old_stream_buf_); }
+
+  static const size_t DEFAULT_TAB = 2;
+
+ private:
+  class IndentedStreamBuf : public std::streambuf {
+   public:
+    IndentedStreamBuf(std::ostream& stream, int indent_size)
+        : wrapped_buf_(stream.rdbuf()),
+          indent_size_(indent_size),
+          indent_next_line_(true){};
+
+   protected:
+    virtual int overflow(int character) override {
+      if (indent_next_line_ && character != '\n') {
+        for (int i = 0; i < indent_size_; i++) wrapped_buf_->sputc(' ');
+      }
+
+      indent_next_line_ = false;
+      if (character == '\n') {
+        indent_next_line_ = true;
+      }
+
+      return wrapped_buf_->sputc(character);
+    }
+
+   private:
+    std::streambuf* wrapped_buf_;
+    int indent_size_;
+    bool indent_next_line_;
+  };
+
+  std::ostream* old_stream_;
+  std::streambuf* old_stream_buf_;
+  IndentedStreamBuf indented_buf_;
+};
+
 #endif
diff --git a/linux_include/log/log.h b/linux_include/log/log.h
new file mode 100644
index 0000000..2802f77
--- /dev/null
+++ b/linux_include/log/log.h
@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+#pragma once
+
+/* This file provides empty implementation of android_errorWriteLog, which is
+ * not required on linux. It should be on include path only for linux build. */
+
+#if defined(OS_GENERIC)
+
+#include <cstdint>
+
+inline int android_errorWriteLog(int, const char*) { return 0; };
+inline int android_errorWriteWithInfoLog(int tag, const char* subTag,
+                                         int32_t uid, const char* data,
+                                         uint32_t dataLen) {
+  return 0;
+};
+#endif
diff --git a/main/Android.bp b/main/Android.bp
index a3aebbc..f787e9e 100644
--- a/main/Android.bp
+++ b/main/Android.bp
@@ -42,13 +42,16 @@
     shared_libs: [
         "android.hardware.bluetooth@1.0",
         "android.hardware.bluetooth.a2dp@1.0",
+        "android.hardware.bluetooth.audio@2.0",
         "libaudioclient",
         "libcutils",
         "libdl",
+        "libfmq",
         "libhidlbase",
         "libhidltransport",
         "libhwbinder",
         "liblog",
+        "libprocessgroup",
         "libprotobuf-cpp-lite",
         "libutils",
         "libtinyxml2",
@@ -60,7 +63,6 @@
         "libkeystore_aidl",
         "libkeystore_binder",
         "libkeystore_parcelables",
-        "libstatslog",
     ],
     static_libs: [
         "libbt-sbc-decoder",
@@ -71,6 +73,7 @@
     ],
     whole_static_libs: [
         "libbt-bta",
+        "libbt-common",
         "libbtdevice",
         "libbtif",
         "libbt-hci",
@@ -95,6 +98,9 @@
     cflags: [
         "-DBUILDCFG",
     ],
+    sanitize: {
+        scs: true,
+    },
 }
 
 cc_library_static {
diff --git a/main/BUILD.gn b/main/BUILD.gn
index 2a07d7b..8152e3b 100644
--- a/main/BUILD.gn
+++ b/main/BUILD.gn
@@ -70,9 +70,11 @@
     "//btcore",
     "//btif",
     "//device",
+    "//embdrv/g722",
     "//embdrv/sbc",
     "//hci",
     "//osi",
+    "//packet",
     "//stack",
     "//third_party/libchrome:base",
     "//third_party/tinyxml2",
diff --git a/main/bte_init.cc b/main/bte_init.cc
index afbd6bf..7addb18 100644
--- a/main/bte_init.cc
+++ b/main/bte_init.cc
@@ -48,10 +48,6 @@
 #include "hidh_api.h"
 #endif
 
-#if (MCA_INCLUDED == TRUE)
-#include "mca_api.h"
-#endif
-
 #include "gatt_api.h"
 #include "smp_api.h"
 
@@ -104,8 +100,4 @@
 #if (HID_HOST_INCLUDED == TRUE)
   HID_HostInit();
 #endif
-
-#if (MCA_INCLUDED == TRUE)
-  MCA_Init();
-#endif
 }
diff --git a/main/bte_logmsg.cc b/main/bte_logmsg.cc
index 3ccb64d..22c357d 100644
--- a/main/bte_logmsg.cc
+++ b/main/bte_logmsg.cc
@@ -71,15 +71,55 @@
 
 /* LayerIDs for BTA, currently everything maps onto appl_trace_level */
 static const char* const bt_layer_tags[] = {
-    "bt_btif", "bt_usb",  "bt_serial", "bt_socket", "bt_rs232", "bt_lc",
-    "bt_lm",   "bt_hci",  "bt_l2cap",  "bt_rfcomm", "bt_sdp",   "bt_tcs",
-    "bt_obex", "bt_btm",  "bt_gap",    "UNUSED",    "UNUSED",   "bt_icp",
-    "bt_hsp2", "bt_spp",  "bt_ctp",    "bt_bpp",    "bt_hcrp",  "bt_ftp",
-    "bt_opp",  "bt_btu",  "bt_gki", /* OBSOLETED */
-    "bt_bnep", "bt_pan",  "bt_hfp",    "bt_hid",    "bt_bip",   "bt_avp",
-    "bt_a2d",  "bt_sap",  "bt_amp",    "bt_mca",    "bt_att",   "bt_smp",
-    "bt_nfc",  "bt_nci",  "bt_idep",   "bt_ndep",   "bt_llcp",  "bt_rw",
-    "bt_ce",   "bt_snep", "bt_ndef",   "bt_nfa",
+    "bt_btif",
+    "bt_usb",
+    "bt_serial",
+    "bt_socket",
+    "bt_rs232",
+    "bt_lc",
+    "bt_lm",
+    "bt_hci",
+    "bt_l2cap",
+    "bt_rfcomm",
+    "bt_sdp",
+    "bt_tcs",
+    "bt_obex",
+    "bt_btm",
+    "bt_gap",
+    "UNUSED",
+    "UNUSED",
+    "bt_icp",
+    "bt_hsp2",
+    "bt_spp",
+    "bt_ctp",
+    "bt_bpp",
+    "bt_hcrp",
+    "bt_ftp",
+    "bt_opp",
+    "bt_btu",
+    "bt_gki_deprecated",
+    "bt_bnep",
+    "bt_pan",
+    "bt_hfp",
+    "bt_hid",
+    "bt_bip",
+    "bt_avp",
+    "bt_a2d",
+    "bt_sap",
+    "bt_amp",
+    "bt_mca_deprecated",
+    "bt_att",
+    "bt_smp",
+    "bt_nfc",
+    "bt_nci",
+    "bt_idep",
+    "bt_ndep",
+    "bt_llcp",
+    "bt_rw",
+    "bt_ce",
+    "bt_snep",
+    "bt_ndef",
+    "bt_nfa",
 };
 static uint8_t BTAPP_SetTraceLevel(uint8_t new_level);
 static uint8_t BTIF_SetTraceLevel(uint8_t new_level);
diff --git a/main/bte_main.cc b/main/bte_main.cc
index 7fdeef03..0498439 100644
--- a/main/bte_main.cc
+++ b/main/bte_main.cc
@@ -53,7 +53,6 @@
 #include "osi/include/future.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "osi/include/thread.h"
 #include "stack_config.h"
 
 /*******************************************************************************
@@ -92,22 +91,17 @@
  *
  * Function         post_to_hci_message_loop
  *
- * Description      Post an HCI event to the hci message queue
+ * Description      Post an HCI event to the main thread
  *
  * Returns          None
  *
  *****************************************************************************/
-void post_to_hci_message_loop(const tracked_objects::Location& from_here,
-                              BT_HDR* p_msg) {
-  base::MessageLoop* hci_message_loop = get_message_loop();
-  if (!hci_message_loop || !hci_message_loop->task_runner().get()) {
-    LOG_ERROR(LOG_TAG, "%s: HCI message loop not running, accessed from %s",
-              __func__, from_here.ToString().c_str());
-    return;
+void post_to_main_message_loop(const base::Location& from_here, BT_HDR* p_msg) {
+  if (do_in_main_thread(from_here, base::Bind(&btu_hci_msg_process, p_msg)) !=
+      BT_STATUS_SUCCESS) {
+    LOG(ERROR) << __func__ << ": do_in_main_thread failed from "
+               << from_here.ToString();
   }
-
-  hci_message_loop->task_runner()->PostTask(
-      from_here, base::Bind(&btu_hci_msg_process, p_msg));
 }
 
 /******************************************************************************
@@ -128,7 +122,7 @@
     return;
   }
 
-  hci->set_data_cb(base::Bind(&post_to_hci_message_loop));
+  hci->set_data_cb(base::Bind(&post_to_main_message_loop));
 
   module_init(get_module(STACK_CONFIG_MODULE));
 }
diff --git a/osi/Android.bp b/osi/Android.bp
index ad2f44b..e6c95d0 100644
--- a/osi/Android.bp
+++ b/osi/Android.bp
@@ -54,7 +54,6 @@
         "src/future.cc",
         "src/hash_map_utils.cc",
         "src/list.cc",
-        "src/metrics.cc",
         "src/mutex.cc",
         "src/osi.cc",
         "src/properties.cc",
@@ -65,7 +64,6 @@
         "src/socket_utils/socket_local_client.cc",
         "src/socket_utils/socket_local_server.cc",
         "src/thread.cc",
-        "src/time.cc",
         "src/wakelock.cc",
     ],
     shared_libs: [
@@ -104,24 +102,23 @@
         "test/fixed_queue_test.cc",
         "test/future_test.cc",
         "test/hash_map_utils_test.cc",
-        "test/leaky_bonded_queue_test.cc",
         "test/list_test.cc",
-        "test/metrics_test.cc",
         "test/properties_test.cc",
         "test/rand_test.cc",
         "test/reactor_test.cc",
         "test/ringbuffer_test.cc",
         "test/semaphore_test.cc",
         "test/thread_test.cc",
-        "test/time_test.cc",
         "test/wakelock_test.cc",
     ],
     shared_libs: [
         "liblog",
         "libprotobuf-cpp-lite",
         "libcutils",
+        "libcrypto",
     ],
     static_libs: [
+        "libbt-common",
         "libbt-protos-lite",
         "libgmock",
         "libosi",
diff --git a/osi/AndroidTest.xml b/osi/AndroidTest.xml
deleted file mode 100644
index aa723bb..0000000
--- a/osi/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2017 The Android Open Source Project
-
-     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.
--->
-<configuration description="Config for net_test_osi">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="net_test_osi->/data/local/tmp/net_test_osi" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="net_test_osi" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/osi/BUILD.gn b/osi/BUILD.gn
index 93b74cc..c4fb0cb 100644
--- a/osi/BUILD.gn
+++ b/osi/BUILD.gn
@@ -27,7 +27,6 @@
     "src/future.cc",
     "src/hash_map_utils.cc",
     "src/list.cc",
-    "src/metrics_linux.cc",
     "src/mutex.cc",
     "src/osi.cc",
     "src/properties.cc",
@@ -41,17 +40,19 @@
     "src/socket_utils/socket_local_client.cc",
     "src/socket_utils/socket_local_server.cc",
     "src/thread.cc",
-    "src/time.cc",
     "src/wakelock.cc",
   ]
 
   include_dirs = [
     "//",
+    "//linux_include",
+    "//internal_include",
     "//utils/include",
     "//stack/include",
   ]
 
   deps = [
+    "//common",
     "//third_party/libchrome:base",
   ]
 }
@@ -68,14 +69,12 @@
     "test/config_test.cc",
     "test/future_test.cc",
     "test/hash_map_utils_test.cc",
-    "test/leaky_bonded_queue_test.cc",
     "test/list_test.cc",
     "test/properties_test.cc",
     "test/rand_test.cc",
     "test/reactor_test.cc",
     "test/ringbuffer_test.cc",
     "test/thread_test.cc",
-    "test/time_test.cc",
   ]
 
   include_dirs = [
diff --git a/osi/include/alarm.h b/osi/include/alarm.h
index b7395ca..2db228b 100644
--- a/osi/include/alarm.h
+++ b/osi/include/alarm.h
@@ -20,7 +20,6 @@
 
 #include <stdbool.h>
 #include <stdint.h>
-#include "osi/include/time.h"
 
 typedef struct alarm_t alarm_t;
 typedef struct fixed_queue_t fixed_queue_t;
@@ -71,13 +70,13 @@
 // thread is not same as the caller’s thread. If two (or more)
 // alarms are set back-to-back with the same |interval_ms|, the
 // callbacks will be called in the order the alarms are set.
-void alarm_set(alarm_t* alarm, period_ms_t interval_ms, alarm_callback_t cb,
+void alarm_set(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb,
                void* data);
 
 // Sets an |alarm| to execute a callback in the main message loop. This function
 // is same as |alarm_set| except that the |cb| callback is scheduled for
 // execution in the context of the main message loop.
-void alarm_set_on_mloop(alarm_t* alarm, period_ms_t interval_ms,
+void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms,
                         alarm_callback_t cb, void* data);
 
 // This function cancels the |alarm| if it was previously set.
@@ -94,7 +93,7 @@
 // Figure out how much time until next expiration.
 // Returns 0 if not armed. |alarm| may not be NULL.
 // TODO: Remove this function once PM timers can be re-factored
-period_ms_t alarm_get_remaining_ms(const alarm_t* alarm);
+uint64_t alarm_get_remaining_ms(const alarm_t* alarm);
 
 // Cleanup the alarm internal state.
 // This function should be called by the OSI module cleanup during
diff --git a/osi/include/metrics.h b/osi/include/metrics.h
deleted file mode 100644
index 504a16a..0000000
--- a/osi/include/metrics.h
+++ /dev/null
@@ -1,276 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2016 Google, Inc.
- *
- *  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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <bta/include/bta_api.h>
-#include <stdint.h>
-#include <memory>
-#include <string>
-
-namespace system_bt_osi {
-
-// Typedefs to hide protobuf definition to the rest of stack
-
-typedef enum {
-  DEVICE_TYPE_UNKNOWN,
-  DEVICE_TYPE_BREDR,
-  DEVICE_TYPE_LE,
-  DEVICE_TYPE_DUMO,
-} device_type_t;
-
-typedef enum {
-  WAKE_EVENT_UNKNOWN,
-  WAKE_EVENT_ACQUIRED,
-  WAKE_EVENT_RELEASED,
-} wake_event_type_t;
-
-typedef enum {
-  SCAN_TYPE_UNKNOWN,
-  SCAN_TECH_TYPE_LE,
-  SCAN_TECH_TYPE_BREDR,
-  SCAN_TECH_TYPE_BOTH,
-} scan_tech_t;
-
-typedef enum {
-  CONNECTION_TECHNOLOGY_TYPE_UNKNOWN,
-  CONNECTION_TECHNOLOGY_TYPE_LE,
-  CONNECTION_TECHNOLOGY_TYPE_BREDR,
-} connection_tech_t;
-
-typedef enum {
-  DISCONNECT_REASON_UNKNOWN,
-  DISCONNECT_REASON_METRICS_DUMP,
-  DISCONNECT_REASON_NEXT_START_WITHOUT_END_PREVIOUS,
-} disconnect_reason_t;
-
-/* Values of A2DP metrics that we care about
- *
- *    audio_duration_ms : sum of audio duration (in milliseconds).
- *    device_class: device class of the paired device.
- *    media_timer_min_ms : minimum scheduled time (in milliseconds)
- *                         of the media timer.
- *    media_timer_max_ms: maximum scheduled time (in milliseconds)
- *                        of the media timer.
- *    media_timer_avg_ms: average scheduled time (in milliseconds)
- *                        of the media timer.
- *    buffer_overruns_max_count: TODO - not clear what this is.
- *    buffer_overruns_total : number of times the media buffer with
- *                            audio data has overrun
- *    buffer_underruns_average: TODO - not clear what this is.
- *    buffer_underruns_count: number of times there was no enough
- *                            audio data to add to the media buffer.
- * NOTE: Negative values are invalid
-*/
-class A2dpSessionMetrics {
- public:
-  A2dpSessionMetrics() {}
-
-  /*
-   * Update the metrics value in the current metrics object using the metrics
-   * objects supplied
-   */
-  void Update(const A2dpSessionMetrics& metrics);
-
-  /*
-   * Compare whether two metrics objects are equal
-   */
-  bool operator==(const A2dpSessionMetrics& rhs) const;
-
-  /*
-   * Initialize all values to -1 which is invalid in order to make a distinction
-   * between 0 and invalid values
-   */
-  int64_t audio_duration_ms = -1;
-  int32_t media_timer_min_ms = -1;
-  int32_t media_timer_max_ms = -1;
-  int32_t media_timer_avg_ms = -1;
-  int64_t total_scheduling_count = -1;
-  int32_t buffer_overruns_max_count = -1;
-  int32_t buffer_overruns_total = -1;
-  float buffer_underruns_average = -1;
-  int32_t buffer_underruns_count = -1;
-  int64_t codec_index = -1;
-  bool is_a2dp_offload = false;
-};
-
-class BluetoothMetricsLogger {
- public:
-  static BluetoothMetricsLogger* GetInstance() {
-    static BluetoothMetricsLogger* instance = new BluetoothMetricsLogger();
-    return instance;
-  }
-
-  /*
-   * Record a pairing event
-   *
-   * Parameters:
-   *    timestamp_ms: Unix epoch time in milliseconds
-   *    device_class: class of remote device
-   *    device_type: type of remote device
-   *    disconnect_reason: HCI reason for pairing disconnection.
-   *                       See: stack/include/hcidefs.h
-   */
-  void LogPairEvent(uint32_t disconnect_reason, uint64_t timestamp_ms,
-                    uint32_t device_class, device_type_t device_type);
-
-  /*
-   * Record a wake event
-   *
-   * Parameters:
-   *    timestamp_ms: Unix epoch time in milliseconds
-   *    type: whether it was acquired or released
-   *    requestor: if provided is the service requesting the wake lock
-   *    name: the name of the wake lock held
-   */
-  void LogWakeEvent(wake_event_type_t type, const std::string& requestor,
-                    const std::string& name, uint64_t timestamp_ms);
-
-  /*
-   * Record a scan event
-   *
-   * Parameters
-   *    timestamp_ms : Unix epoch time in milliseconds
-   *    start : true if this is the beginning of the scan
-   *    initiator: a unique ID identifying the app starting the scan
-   *    type: whether the scan reports BR/EDR, LE, or both.
-   *    results: number of results to be reported.
-   */
-  void LogScanEvent(bool start, const std::string& initator, scan_tech_t type,
-                    uint32_t results, uint64_t timestamp_ms);
-
-  /*
-   * Start logging a Bluetooth session
-   *
-   * A Bluetooth session is defined a a connection between this device and
-   * another remote device which may include multiple profiles and protocols
-   *
-   * Only one Bluetooth session can exist at one time. Calling this method twice
-   * without LogBluetoothSessionEnd will result in logging a premature end of
-   * current Bluetooth session
-   *
-   * Parameters:
-   *    connection_tech_type : type of connection technology
-   *    timestamp_ms : the timestamp for session start, 0 means now
-   *
-   */
-  void LogBluetoothSessionStart(connection_tech_t connection_tech_type,
-                                uint64_t timestamp_ms);
-
-  /*
-   * Stop logging a Bluetooth session and pushes it to the log queue
-   *
-   * If no Bluetooth session exist, this method exits immediately
-   *
-   * Parameters:
-   *    disconnect_reason : A string representation of disconnect reason
-   *    timestamp_ms : the timestamp of session end, 0 means now
-   *
-   */
-  void LogBluetoothSessionEnd(disconnect_reason_t disconnect_reason,
-                              uint64_t timestamp_ms);
-
-  /*
-   * Log information about remote device in a current Bluetooth session
-   *
-   * If a Bluetooth session does not exist, create one with default parameter
-   * and timestamp now
-   *
-   * Parameters:
-   *    device_class : device_class defined in btm_api_types.h
-   *    device_type : type of remote device
-   */
-  void LogBluetoothSessionDeviceInfo(uint32_t device_class,
-                                     device_type_t device_type);
-
-  /*
-   * Log A2DP Audio Session Information
-   *
-   * - Repeated calls to this method will override previous metrics if in the
-   *   same Bluetooth connection
-   * - If a Bluetooth session does not exist, create one with default parameter
-   *   and timestamp now
-   *
-   * Parameters:
-   *    a2dp_session_metrics - pointer to struct holding a2dp stats
-   *
-   */
-  void LogA2dpSession(const A2dpSessionMetrics& a2dp_session_metrics);
-
-  /**
-   * Log Headset profile RFCOMM connection event
-   *
-   * @param service_id the BTA service ID for this headset connection
-   */
-  void LogHeadsetProfileRfcConnection(tBTA_SERVICE_ID service_id);
-
-  /*
-   * Writes the metrics, in base64 protobuf format, into the descriptor FD,
-   * metrics events are always cleared after dump
-   */
-  void WriteBase64(int fd);
-  void WriteBase64String(std::string* serialized);
-  void WriteString(std::string* serialized);
-
-  /*
-   * Reset the metrics logger by cleaning up its staging queues and existing
-   * protobuf objects.
-   */
-  void Reset();
-
-  /*
-   * Maximum number of log entries for each session or event
-   */
-  static const size_t kMaxNumBluetoothSession = 50;
-  static const size_t kMaxNumPairEvent = 50;
-  static const size_t kMaxNumWakeEvent = 1000;
-  static const size_t kMaxNumScanEvent = 50;
-
- private:
-  BluetoothMetricsLogger();
-
-  /*
-   * When a Bluetooth session is on and the user initiates a metrics dump, we
-   * need to be able to upload whatever we have first. This method breaks the
-   * ongoing Bluetooth session into two sessions with the previous one labeled
-   * as "METRICS_DUMP" for the disconnect reason.
-   */
-  void CutoffSession();
-
-  /*
-   * Build the internal metrics object using information gathered
-   */
-  void Build();
-
-  /*
-   * Reset objects related to current Bluetooth session
-   */
-  void ResetSession();
-
-  /*
-   * Reset the underlining BluetoothLog object
-   */
-  void ResetLog();
-
-  /*
-   * PIMPL style implementation to hide internal dependencies
-   */
-  struct impl;
-  std::unique_ptr<impl> const pimpl_;
-};
-}
diff --git a/osi/include/time.h b/osi/include/time.h
deleted file mode 100644
index 8f533d0..0000000
--- a/osi/include/time.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2015 Google, Inc.
- *
- *  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.
- *
- ******************************************************************************/
-
-#pragma once
-
-#include <stdint.h>
-
-typedef uint64_t period_ms_t;
-
-// Get the OS boot time in milliseconds.
-//
-// NOTE: The return value will rollover every 49.7 days,
-// hence it cannot be used for absolute time comparison.
-// Relative time comparison using 32-bits integers such
-// as (t2_u32 - t1_u32 < delta_u32) should work as expected as long
-// as there is no multiple rollover between t2_u32 and t1_u32.
-//
-// TODO: This function's return type should be modified to |period_ms_t|.
-// Be careful: some of the code that is using it assumes the return type
-// is uint32_t.
-uint32_t time_get_os_boottime_ms(void);
-
-// Get the OS boot time in microseconds.
-uint64_t time_get_os_boottime_us(void);
-
-// Get the current wall clock time in microseconds.
-uint64_t time_gettimeofday_us(void);
diff --git a/osi/src/alarm.cc b/osi/src/alarm.cc
index 07d8704..bc1eee5 100644
--- a/osi/src/alarm.cc
+++ b/osi/src/alarm.cc
@@ -46,21 +46,20 @@
 #include "osi/include/semaphore.h"
 #include "osi/include/thread.h"
 #include "osi/include/wakelock.h"
+#include "stack/include/btu.h"
 
 using base::Bind;
 using base::CancelableClosure;
 using base::MessageLoop;
 
-extern base::MessageLoop* get_message_loop();
-
 // Callback and timer threads should run at RT priority in order to ensure they
 // meet audio deadlines.  Use this priority for all audio/timer related thread.
 static const int THREAD_RT_PRIORITY = 1;
 
 typedef struct {
   size_t count;
-  period_ms_t total_ms;
-  period_ms_t max_ms;
+  uint64_t total_ms;
+  uint64_t max_ms;
 } stat_t;
 
 // Alarm-related information and statistics
@@ -70,7 +69,7 @@
   size_t canceled_count;
   size_t rescheduled_count;
   size_t total_updates;
-  period_ms_t last_update_ms;
+  uint64_t last_update_ms;
   stat_t overdue_scheduling;
   stat_t premature_scheduling;
 } alarm_stats_t;
@@ -93,10 +92,10 @@
   // mutex to provide a guarantee to its caller that the callback will not be
   // in progress when it returns.
   std::shared_ptr<std::recursive_mutex> callback_mutex;
-  period_ms_t creation_time;
-  period_ms_t period;
-  period_ms_t deadline;
-  period_ms_t prev_deadline;  // Previous deadline - used for accounting of
+  uint64_t creation_time_ms;
+  uint64_t period_ms;
+  uint64_t deadline_ms;
+  uint64_t prev_deadline_ms;  // Previous deadline - used for accounting of
                               // periodic timers
   bool is_periodic;
   fixed_queue_t* queue;  // The processing queue to add this alarm to
@@ -115,12 +114,6 @@
 int64_t TIMER_INTERVAL_FOR_WAKELOCK_IN_MS = 3000;
 static const clockid_t CLOCK_ID = CLOCK_BOOTTIME;
 
-#if (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.
@@ -141,8 +134,8 @@
 
 static alarm_t* alarm_new_internal(const char* name, bool is_periodic);
 static bool lazy_initialize(void);
-static period_ms_t now(void);
-static void alarm_set_internal(alarm_t* alarm, period_ms_t period,
+static uint64_t now_ms(void);
+static void alarm_set_internal(alarm_t* alarm, uint64_t period_ms,
                                alarm_callback_t cb, void* data,
                                fixed_queue_t* queue, bool for_msg_loop);
 static void alarm_cancel_internal(alarm_t* alarm);
@@ -153,16 +146,16 @@
 static void timer_callback(void* data);
 static void callback_dispatch(void* context);
 static bool timer_create_internal(const clockid_t clock_id, timer_t* timer);
-static void update_scheduling_stats(alarm_stats_t* stats, period_ms_t now_ms,
-                                    period_ms_t deadline_ms);
+static void update_scheduling_stats(alarm_stats_t* stats, uint64_t now_ms,
+                                    uint64_t deadline_ms);
 // Registers |queue| for processing alarm callbacks on |thread|.
 // |queue| may not be NULL. |thread| may not be NULL.
 static void alarm_register_processing_queue(fixed_queue_t* queue,
                                             thread_t* thread);
 
-static void update_stat(stat_t* stat, period_ms_t delta) {
-  if (stat->max_ms < delta) stat->max_ms = delta;
-  stat->total_ms += delta;
+static void update_stat(stat_t* stat, uint64_t delta_ms) {
+  if (stat->max_ms < delta_ms) stat->max_ms = delta_ms;
+  stat->total_ms += delta_ms;
   stat->count++;
 }
 
@@ -205,30 +198,31 @@
   osi_free(alarm);
 }
 
-period_ms_t alarm_get_remaining_ms(const alarm_t* alarm) {
+uint64_t alarm_get_remaining_ms(const alarm_t* alarm) {
   CHECK(alarm != NULL);
-  period_ms_t remaining_ms = 0;
-  period_ms_t just_now = now();
+  uint64_t remaining_ms = 0;
+  uint64_t just_now_ms = now_ms();
 
   std::lock_guard<std::mutex> lock(alarms_mutex);
-  if (alarm->deadline > just_now) remaining_ms = alarm->deadline - just_now;
+  if (alarm->deadline_ms > just_now_ms)
+    remaining_ms = alarm->deadline_ms - just_now_ms;
 
   return remaining_ms;
 }
 
-void alarm_set(alarm_t* alarm, period_ms_t interval_ms, alarm_callback_t cb,
+void alarm_set(alarm_t* alarm, uint64_t interval_ms, alarm_callback_t cb,
                void* data) {
   alarm_set_internal(alarm, interval_ms, cb, data, default_callback_queue,
                      false);
 }
 
-void alarm_set_on_mloop(alarm_t* alarm, period_ms_t interval_ms,
+void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms,
                         alarm_callback_t cb, void* data) {
   alarm_set_internal(alarm, interval_ms, cb, data, NULL, true);
 }
 
 // Runs in exclusion with alarm_cancel and timer_callback.
-static void alarm_set_internal(alarm_t* alarm, period_ms_t period,
+static void alarm_set_internal(alarm_t* alarm, uint64_t period_ms,
                                alarm_callback_t cb, void* data,
                                fixed_queue_t* queue, bool for_msg_loop) {
   CHECK(alarms != NULL);
@@ -237,8 +231,8 @@
 
   std::lock_guard<std::mutex> lock(alarms_mutex);
 
-  alarm->creation_time = now();
-  alarm->period = period;
+  alarm->creation_time_ms = now_ms();
+  alarm->period_ms = period_ms;
   alarm->queue = queue;
   alarm->callback = cb;
   alarm->data = data;
@@ -252,7 +246,7 @@
   CHECK(alarms != NULL);
   if (!alarm) return;
 
-  std::shared_ptr<std::recursive_mutex> local_mutex_ref = alarm->callback_mutex;
+  std::shared_ptr<std::recursive_mutex> local_mutex_ref;
   {
     std::lock_guard<std::mutex> lock(alarms_mutex);
     local_mutex_ref = alarm->callback_mutex;
@@ -271,8 +265,8 @@
 
   remove_pending_alarm(alarm);
 
-  alarm->deadline = 0;
-  alarm->prev_deadline = 0;
+  alarm->deadline_ms = 0;
+  alarm->prev_deadline_ms = 0;
   alarm->callback = NULL;
   alarm->data = NULL;
   alarm->stats.canceled_count++;
@@ -330,7 +324,11 @@
   if (!timer_create_internal(CLOCK_ID, &timer)) goto error;
   timer_initialized = true;
 
-  if (!timer_create_internal(CLOCK_ID_ALARM, &wakeup_timer)) goto error;
+  if (!timer_create_internal(CLOCK_BOOTTIME_ALARM, &wakeup_timer)) {
+    if (!timer_create_internal(CLOCK_BOOTTIME, &wakeup_timer)) {
+      goto error;
+    }
+  }
   wakeup_timer_initialized = true;
 
   alarm_expired = semaphore_new(0);
@@ -390,7 +388,7 @@
   return false;
 }
 
-static period_ms_t now(void) {
+static uint64_t now_ms(void) {
   CHECK(alarms != NULL);
 
   struct timespec ts;
@@ -428,22 +426,23 @@
   if (alarm->callback) remove_pending_alarm(alarm);
 
   // Calculate the next deadline for this alarm
-  period_ms_t just_now = now();
-  period_ms_t ms_into_period = 0;
-  if ((alarm->is_periodic) && (alarm->period != 0))
-    ms_into_period = ((just_now - alarm->creation_time) % alarm->period);
-  alarm->deadline = just_now + (alarm->period - ms_into_period);
+  uint64_t just_now_ms = now_ms();
+  uint64_t ms_into_period = 0;
+  if ((alarm->is_periodic) && (alarm->period_ms != 0))
+    ms_into_period =
+        ((just_now_ms - alarm->creation_time_ms) % alarm->period_ms);
+  alarm->deadline_ms = just_now_ms + (alarm->period_ms - ms_into_period);
 
   // Add it into the timer list sorted by deadline (earliest deadline first).
   if (list_is_empty(alarms) ||
-      ((alarm_t*)list_front(alarms))->deadline > alarm->deadline) {
+      ((alarm_t*)list_front(alarms))->deadline_ms > alarm->deadline_ms) {
     list_prepend(alarms, alarm);
   } else {
     for (list_node_t* node = list_begin(alarms); node != list_end(alarms);
          node = list_next(node)) {
       list_node_t* next = list_next(node);
       if (next == list_end(alarms) ||
-          ((alarm_t*)list_node(next))->deadline > alarm->deadline) {
+          ((alarm_t*)list_node(next))->deadline_ms > alarm->deadline_ms) {
         list_insert_after(alarms, node, alarm);
         break;
       }
@@ -473,7 +472,7 @@
   if (list_is_empty(alarms)) goto done;
 
   next = static_cast<alarm_t*>(list_front(alarms));
-  next_expiration = next->deadline - now();
+  next_expiration = next->deadline_ms - now_ms();
   if (next_expiration < TIMER_INTERVAL_FOR_WAKELOCK_IN_MS) {
     if (!timer_set) {
       if (!wakelock_acquire()) {
@@ -482,8 +481,8 @@
       }
     }
 
-    timer_time.it_value.tv_sec = (next->deadline / 1000);
-    timer_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
+    timer_time.it_value.tv_sec = (next->deadline_ms / 1000);
+    timer_time.it_value.tv_nsec = (next->deadline_ms % 1000) * 1000000LL;
 
     // It is entirely unsafe to call timer_settime(2) with a zeroed timerspec
     // for timers with *_ALARM clock IDs. Although the man page states that the
@@ -508,8 +507,8 @@
     struct itimerspec wakeup_time;
     memset(&wakeup_time, 0, sizeof(wakeup_time));
 
-    wakeup_time.it_value.tv_sec = (next->deadline / 1000);
-    wakeup_time.it_value.tv_nsec = (next->deadline % 1000) * 1000000LL;
+    wakeup_time.it_value.tv_sec = (next->deadline_ms / 1000);
+    wakeup_time.it_value.tv_nsec = (next->deadline_ms % 1000) * 1000000LL;
     if (timer_settime(wakeup_timer, TIMER_ABSTIME, &wakeup_time, NULL) == -1)
       LOG_ERROR(LOG_TAG, "%s unable to set wakeup timer: %s", __func__,
                 strerror(errno));
@@ -563,20 +562,25 @@
   if (alarm == NULL) {
     return;  // The alarm was probably canceled
   }
+
   //
   // If the alarm is not periodic, we've fully serviced it now, and can reset
   // some of its internal state. This is useful to distinguish between expired
   // alarms and active ones.
   //
+  if (!alarm->callback) {
+    LOG(FATAL) << __func__
+               << ": timer callback is NULL! Name=" << alarm->stats.name;
+  }
   alarm_callback_t callback = alarm->callback;
   void* data = alarm->data;
-  period_ms_t deadline = alarm->deadline;
+  uint64_t deadline_ms = alarm->deadline_ms;
   if (alarm->is_periodic) {
     // The periodic alarm has been rescheduled and alarm->deadline has been
     // updated, hence we need to use the previous deadline.
-    deadline = alarm->prev_deadline;
+    deadline_ms = alarm->prev_deadline_ms;
   } else {
-    alarm->deadline = 0;
+    alarm->deadline_ms = 0;
     alarm->callback = NULL;
     alarm->data = NULL;
     alarm->queue = NULL;
@@ -589,7 +593,7 @@
   lock.unlock();
 
   // Update the statistics
-  update_scheduling_stats(&alarm->stats, now(), deadline);
+  update_scheduling_stats(&alarm->stats, now_ms(), deadline_ms);
 
   // NOTE: Do NOT access "alarm" after the callback, as a safety precaution
   // in case the callback itself deleted the alarm.
@@ -630,7 +634,8 @@
     // We're done here if there are no alarms or the alarm at the front is in
     // the future. Exit right away since there's nothing left to do.
     if (list_is_empty(alarms) ||
-        (alarm = static_cast<alarm_t*>(list_front(alarms)))->deadline > now()) {
+        (alarm = static_cast<alarm_t*>(list_front(alarms)))->deadline_ms >
+            now_ms()) {
       reschedule_root_alarm();
       continue;
     }
@@ -638,7 +643,7 @@
     list_remove(alarms, alarm);
 
     if (alarm->is_periodic) {
-      alarm->prev_deadline = alarm->deadline;
+      alarm->prev_deadline_ms = alarm->deadline_ms;
       schedule_next_instance(alarm);
       alarm->stats.rescheduled_count++;
     }
@@ -646,15 +651,15 @@
 
     // Enqueue the alarm for processing
     if (alarm->for_msg_loop) {
-      if (!get_message_loop()) {
+      if (!get_main_message_loop()) {
         LOG_ERROR(LOG_TAG, "%s: message loop already NULL. Alarm: %s", __func__,
                   alarm->stats.name);
         continue;
       }
 
       alarm->closure.i.Reset(Bind(alarm_ready_mloop, alarm));
-      get_message_loop()->task_runner()->PostTask(FROM_HERE,
-                                                  alarm->closure.i.callback());
+      get_main_message_loop()->task_runner()->PostTask(
+          FROM_HERE, alarm->closure.i.callback());
     } else {
       fixed_queue_enqueue(alarm->queue, alarm);
     }
@@ -698,24 +703,24 @@
   return true;
 }
 
-static void update_scheduling_stats(alarm_stats_t* stats, period_ms_t now_ms,
-                                    period_ms_t deadline_ms) {
+static void update_scheduling_stats(alarm_stats_t* stats, uint64_t now_ms,
+                                    uint64_t deadline_ms) {
   stats->total_updates++;
   stats->last_update_ms = now_ms;
 
   if (deadline_ms < now_ms) {
     // Overdue scheduling
-    period_ms_t delta_ms = now_ms - deadline_ms;
+    uint64_t delta_ms = now_ms - deadline_ms;
     update_stat(&stats->overdue_scheduling, delta_ms);
   } else if (deadline_ms > now_ms) {
     // Premature scheduling
-    period_ms_t delta_ms = deadline_ms - now_ms;
+    uint64_t delta_ms = deadline_ms - now_ms;
     update_stat(&stats->premature_scheduling, delta_ms);
   }
 }
 
 static void dump_stat(int fd, stat_t* stat, const char* description) {
-  period_ms_t average_time_ms = 0;
+  uint64_t average_time_ms = 0;
   if (stat->count != 0) average_time_ms = stat->total_ms / stat->count;
 
   dprintf(fd, "%-51s: %llu / %llu / %llu\n", description,
@@ -733,7 +738,7 @@
     return;
   }
 
-  period_ms_t just_now = now();
+  uint64_t just_now_ms = now_ms();
 
   dprintf(fd, "  Total Alarms: %zu\n\n", list_length(alarms));
 
@@ -757,9 +762,9 @@
 
     dprintf(fd, "%-51s: %llu / %llu / %lld\n",
             "    Time in ms (since creation/interval/remaining)",
-            (unsigned long long)(just_now - alarm->creation_time),
-            (unsigned long long)alarm->period,
-            (long long)(alarm->deadline - just_now));
+            (unsigned long long)(just_now_ms - alarm->creation_time_ms),
+            (unsigned long long)alarm->period_ms,
+            (long long)(alarm->deadline_ms - just_now_ms));
 
     dump_stat(fd, &stats->overdue_scheduling,
               "    Overdue scheduling time in ms (total/max/avg)");
diff --git a/osi/src/config.cc b/osi/src/config.cc
index ac9e3cf..de7e6e6 100644
--- a/osi/src/config.cc
+++ b/osi/src/config.cc
@@ -17,7 +17,6 @@
  ******************************************************************************/
 
 #include "osi/include/config.h"
-#include "log/log.h"
 
 #include <base/files/file_util.h>
 #include <base/logging.h>
@@ -25,6 +24,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <libgen.h>
+#include <log/log.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -185,7 +185,7 @@
   }
 
   std::string value_no_newline;
-  size_t newline_position = value.find("\n");
+  size_t newline_position = value.find('\n');
   if (newline_position != std::string::npos) {
     android_errorWriteLog(0x534e4554, "70808273");
     value_no_newline = value.substr(0, newline_position);
@@ -236,10 +236,11 @@
   // Steps to ensure content of config file gets to disk:
   //
   // 1) Open and write to temp file (e.g. bt_config.conf.new).
-  // 2) Sync the temp file to disk with fsync().
-  // 3) Rename temp file to actual config file (e.g. bt_config.conf).
+  // 2) Flush the stream buffer to the temp file.
+  // 3) Sync the temp file to disk with fsync().
+  // 4) Rename temp file to actual config file (e.g. bt_config.conf).
   //    This ensures atomic update.
-  // 4) Sync directory that has the conf file with fsync().
+  // 5) Sync directory that has the conf file with fsync().
   //    This ensures directory entries are up-to-date.
   int dir_fd = -1;
   FILE* fp = nullptr;
@@ -285,6 +286,13 @@
     goto error;
   }
 
+  // Flush the stream buffer to the temp file.
+  if (fflush(fp) < 0) {
+    LOG(ERROR) << __func__ << ": unable to write flush buffer to file '"
+               << temp_filename << "': " << strerror(errno);
+    goto error;
+  }
+
   // Sync written temp file out to disk. fsync() is blocking until data makes it
   // to disk.
   if (fsync(fileno(fp)) < 0) {
diff --git a/osi/src/metrics_linux.cc b/osi/src/metrics_linux.cc
deleted file mode 100644
index 162f4ca..0000000
--- a/osi/src/metrics_linux.cc
+++ /dev/null
@@ -1,204 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2016 Google, Inc.
- *
- *  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.
- *
- ******************************************************************************/
-#define LOG_TAG "bt_osi_metrics"
-
-#include <unistd.h>
-#include <algorithm>
-#include <cerrno>
-#include <chrono>
-#include <cstdint>
-#include <cstring>
-#include <memory>
-#include <mutex>
-
-#include <base/base64.h>
-#include <base/logging.h>
-
-#include "osi/include/leaky_bonded_queue.h"
-#include "osi/include/log.h"
-#include "osi/include/osi.h"
-#include "osi/include/time.h"
-
-#include "osi/include/metrics.h"
-
-namespace system_bt_osi {
-
-// Maximum number of log entries for each repeated field
-#define MAX_NUM_BLUETOOTH_SESSION 50
-#define MAX_NUM_PAIR_EVENT 50
-#define MAX_NUM_WAKE_EVENT 50
-#define MAX_NUM_SCAN_EVENT 50
-
-static float combine_averages(float avg_a, int64_t ct_a, float avg_b,
-                              int64_t ct_b) {
-  if (ct_a > 0 && ct_b > 0) {
-    return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
-  } else if (ct_b > 0) {
-    return avg_b;
-  } else {
-    return avg_a;
-  }
-}
-
-static int32_t combine_averages(int32_t avg_a, int64_t ct_a, int32_t avg_b,
-                                int64_t ct_b) {
-  if (ct_a > 0 && ct_b > 0) {
-    return (avg_a * ct_a + avg_b * ct_b) / (ct_a + ct_b);
-  } else if (ct_b > 0) {
-    return avg_b;
-  } else {
-    return avg_a;
-  }
-}
-
-void A2dpSessionMetrics::Update(const A2dpSessionMetrics& metrics) {
-  if (metrics.audio_duration_ms > 0) {
-    audio_duration_ms = std::max(static_cast<int64_t>(0), audio_duration_ms);
-    audio_duration_ms += metrics.audio_duration_ms;
-  }
-  if (metrics.media_timer_min_ms > 0) {
-    if (media_timer_min_ms < 0) {
-      media_timer_min_ms = metrics.media_timer_min_ms;
-    } else {
-      media_timer_min_ms =
-          std::min(media_timer_min_ms, metrics.media_timer_min_ms);
-    }
-  }
-  if (metrics.media_timer_max_ms > 0) {
-    media_timer_max_ms =
-        std::max(media_timer_max_ms, metrics.media_timer_max_ms);
-  }
-  if (metrics.media_timer_avg_ms > 0 && metrics.total_scheduling_count > 0) {
-    if (media_timer_avg_ms < 0 || total_scheduling_count < 0) {
-      media_timer_avg_ms = metrics.media_timer_avg_ms;
-      total_scheduling_count = metrics.total_scheduling_count;
-    } else {
-      media_timer_avg_ms = combine_averages(
-          media_timer_avg_ms, total_scheduling_count,
-          metrics.media_timer_avg_ms, metrics.total_scheduling_count);
-      total_scheduling_count += metrics.total_scheduling_count;
-    }
-  }
-  if (metrics.buffer_overruns_max_count > 0) {
-    buffer_overruns_max_count =
-        std::max(buffer_overruns_max_count, metrics.buffer_overruns_max_count);
-  }
-  if (metrics.buffer_overruns_total > 0) {
-    buffer_overruns_total =
-        std::max(static_cast<int32_t>(0), buffer_overruns_total);
-    buffer_overruns_total += metrics.buffer_overruns_total;
-  }
-  if (metrics.buffer_underruns_average > 0 &&
-      metrics.buffer_underruns_count > 0) {
-    if (buffer_underruns_average < 0 || buffer_underruns_count < 0) {
-      buffer_underruns_average = metrics.buffer_underruns_average;
-      buffer_underruns_count = metrics.buffer_underruns_count;
-    } else {
-      buffer_underruns_average = combine_averages(
-          metrics.buffer_underruns_average, metrics.buffer_underruns_count,
-          buffer_underruns_average, buffer_underruns_count);
-      buffer_underruns_count += metrics.buffer_underruns_count;
-    }
-  }
-}
-
-bool A2dpSessionMetrics::operator==(const A2dpSessionMetrics& rhs) const {
-  return audio_duration_ms == rhs.audio_duration_ms &&
-         media_timer_min_ms == rhs.media_timer_min_ms &&
-         media_timer_max_ms == rhs.media_timer_max_ms &&
-         media_timer_avg_ms == rhs.media_timer_avg_ms &&
-         total_scheduling_count == rhs.total_scheduling_count &&
-         buffer_overruns_max_count == rhs.buffer_overruns_max_count &&
-         buffer_overruns_total == rhs.buffer_overruns_total &&
-         buffer_underruns_average == rhs.buffer_underruns_average &&
-         buffer_underruns_count == rhs.buffer_underruns_count;
-}
-
-struct BluetoothMetricsLogger::impl {
-  // TODO(siyuanh): Implement for linux
-};
-
-BluetoothMetricsLogger::BluetoothMetricsLogger() : pimpl_(new impl) {}
-
-void BluetoothMetricsLogger::LogPairEvent(uint32_t disconnect_reason,
-                                          uint64_t timestamp_ms,
-                                          uint32_t device_class,
-                                          device_type_t device_type) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::LogWakeEvent(wake_event_type_t type,
-                                          const std::string& requestor,
-                                          const std::string& name,
-                                          uint64_t timestamp_ms) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::LogScanEvent(bool start,
-                                          const std::string& initator,
-                                          scan_tech_t type, uint32_t results,
-                                          uint64_t timestamp_ms) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::LogBluetoothSessionStart(
-    connection_tech_t connection_tech_type, uint64_t timestamp_ms) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::LogBluetoothSessionEnd(
-    disconnect_reason_t disconnect_reason, uint64_t timestamp_ms) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::LogBluetoothSessionDeviceInfo(
-    uint32_t device_class, device_type_t device_type) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::LogA2dpSession(
-    const A2dpSessionMetrics& a2dp_session_metrics) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::WriteString(std::string* serialized, bool clear) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::WriteBase64String(std::string* serialized,
-                                               bool clear) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::WriteBase64(int fd, bool clear) {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::CutoffSession() {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::Build() {
-  // TODO(siyuanh): Implement for linux
-}
-
-void BluetoothMetricsLogger::Reset() {
-  // TODO(siyuanh): Implement for linux
-}
-
-}  // namespace system_bt_osi
diff --git a/osi/src/reactor.cc b/osi/src/reactor.cc
index ce1251c..7898170 100644
--- a/osi/src/reactor.cc
+++ b/osi/src/reactor.cc
@@ -72,7 +72,7 @@
   ret->epoll_fd = INVALID_FD;
   ret->event_fd = INVALID_FD;
 
-  ret->epoll_fd = epoll_create(MAX_EVENTS);
+  ret->epoll_fd = epoll_create1(EPOLL_CLOEXEC);
   if (ret->epoll_fd == INVALID_FD) {
     LOG_ERROR(LOG_TAG, "%s unable to create epoll instance: %s", __func__,
               strerror(errno));
diff --git a/osi/src/wakelock.cc b/osi/src/wakelock.cc
index 46c462c..0f9a51b 100644
--- a/osi/src/wakelock.cc
+++ b/osi/src/wakelock.cc
@@ -34,15 +34,15 @@
 #include <string>
 
 #include "base/logging.h"
+#include "common/metrics.h"
 #include "osi/include/alarm.h"
 #include "osi/include/allocator.h"
 #include "osi/include/log.h"
-#include "osi/include/metrics.h"
 #include "osi/include/osi.h"
 #include "osi/include/thread.h"
 #include "osi/include/wakelock.h"
 
-using system_bt_osi::BluetoothMetricsLogger;
+using bluetooth::common::BluetoothMetricsLogger;
 
 static bt_os_callouts_t* wakelock_os_callouts = NULL;
 static bool is_native = true;
@@ -65,13 +65,13 @@
   size_t released_count;
   size_t acquired_errors;
   size_t released_errors;
-  period_ms_t min_acquired_interval_ms;
-  period_ms_t max_acquired_interval_ms;
-  period_ms_t last_acquired_interval_ms;
-  period_ms_t total_acquired_interval_ms;
-  period_ms_t last_acquired_timestamp_ms;
-  period_ms_t last_released_timestamp_ms;
-  period_ms_t last_reset_timestamp_ms;
+  uint64_t min_acquired_interval_ms;
+  uint64_t max_acquired_interval_ms;
+  uint64_t last_acquired_interval_ms;
+  uint64_t total_acquired_interval_ms;
+  uint64_t last_acquired_timestamp_ms;
+  uint64_t last_released_timestamp_ms;
+  uint64_t last_reset_timestamp_ms;
   int last_acquired_error;
   int last_released_error;
 } wakelock_stats_t;
@@ -213,6 +213,10 @@
 }
 
 void wakelock_cleanup(void) {
+  if (wakelock_stats.is_acquired) {
+    LOG_ERROR(LOG_TAG, "%s releasing wake lock as part of cleanup", __func__);
+    wakelock_release();
+  }
   wake_lock_path.clear();
   wake_unlock_path.clear();
   initialized = PTHREAD_ONCE_INIT;
@@ -224,7 +228,7 @@
   if (unlock_path) wake_unlock_path = unlock_path;
 }
 
-static period_ms_t now(void) {
+static uint64_t now_ms(void) {
   struct timespec ts;
   if (clock_gettime(CLOCK_ID, &ts) == -1) {
     LOG_ERROR(LOG_TAG, "%s unable to get current time: %s", __func__,
@@ -251,7 +255,7 @@
   wakelock_stats.total_acquired_interval_ms = 0;
   wakelock_stats.last_acquired_timestamp_ms = 0;
   wakelock_stats.last_released_timestamp_ms = 0;
-  wakelock_stats.last_reset_timestamp_ms = now();
+  wakelock_stats.last_reset_timestamp_ms = now_ms();
 }
 
 //
@@ -263,7 +267,7 @@
 // This function is thread-safe.
 //
 static void update_wakelock_acquired_stats(bt_status_t acquired_status) {
-  const period_ms_t now_ms = now();
+  const uint64_t just_now_ms = now_ms();
 
   std::lock_guard<std::mutex> lock(stats_mutex);
 
@@ -278,10 +282,10 @@
 
   wakelock_stats.is_acquired = true;
   wakelock_stats.acquired_count++;
-  wakelock_stats.last_acquired_timestamp_ms = now_ms;
+  wakelock_stats.last_acquired_timestamp_ms = just_now_ms;
 
   BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
-      system_bt_osi::WAKE_EVENT_ACQUIRED, "", "", now_ms);
+      bluetooth::common::WAKE_EVENT_ACQUIRED, "", "", just_now_ms);
 }
 
 //
@@ -293,7 +297,7 @@
 // This function is thread-safe.
 //
 static void update_wakelock_released_stats(bt_status_t released_status) {
-  const period_ms_t now_ms = now();
+  const uint64_t just_now_ms = now_ms();
 
   std::lock_guard<std::mutex> lock(stats_mutex);
 
@@ -308,10 +312,10 @@
 
   wakelock_stats.is_acquired = false;
   wakelock_stats.released_count++;
-  wakelock_stats.last_released_timestamp_ms = now_ms;
+  wakelock_stats.last_released_timestamp_ms = just_now_ms;
 
   // Compute the acquired interval and update the statistics
-  period_ms_t delta_ms = now_ms - wakelock_stats.last_acquired_timestamp_ms;
+  uint64_t delta_ms = just_now_ms - wakelock_stats.last_acquired_timestamp_ms;
   if (delta_ms < wakelock_stats.min_acquired_interval_ms ||
       wakelock_stats.released_count == 1) {
     wakelock_stats.min_acquired_interval_ms = delta_ms;
@@ -323,32 +327,32 @@
   wakelock_stats.total_acquired_interval_ms += delta_ms;
 
   BluetoothMetricsLogger::GetInstance()->LogWakeEvent(
-      system_bt_osi::WAKE_EVENT_RELEASED, "", "", now_ms);
+      bluetooth::common::WAKE_EVENT_RELEASED, "", "", just_now_ms);
 }
 
 void wakelock_debug_dump(int fd) {
-  const period_ms_t now_ms = now();
+  const uint64_t just_now_ms = now_ms();
 
   std::lock_guard<std::mutex> lock(stats_mutex);
 
   // Compute the last acquired interval if the wakelock is still acquired
-  period_ms_t delta_ms = 0;
-  period_ms_t last_interval = wakelock_stats.last_acquired_interval_ms;
-  period_ms_t min_interval = wakelock_stats.min_acquired_interval_ms;
-  period_ms_t max_interval = wakelock_stats.max_acquired_interval_ms;
-  period_ms_t ave_interval = 0;
+  uint64_t delta_ms = 0;
+  uint64_t last_interval_ms = wakelock_stats.last_acquired_interval_ms;
+  uint64_t min_interval_ms = wakelock_stats.min_acquired_interval_ms;
+  uint64_t max_interval_ms = wakelock_stats.max_acquired_interval_ms;
+  uint64_t avg_interval_ms = 0;
 
   if (wakelock_stats.is_acquired) {
-    delta_ms = now_ms - wakelock_stats.last_acquired_timestamp_ms;
-    if (delta_ms > max_interval) max_interval = delta_ms;
-    if (delta_ms < min_interval) min_interval = delta_ms;
-    last_interval = delta_ms;
+    delta_ms = just_now_ms - wakelock_stats.last_acquired_timestamp_ms;
+    if (delta_ms > max_interval_ms) max_interval_ms = delta_ms;
+    if (delta_ms < min_interval_ms) min_interval_ms = delta_ms;
+    last_interval_ms = delta_ms;
   }
-  period_ms_t total_interval =
+  uint64_t total_interval_ms =
       wakelock_stats.total_acquired_interval_ms + delta_ms;
 
   if (wakelock_stats.acquired_count > 0)
-    ave_interval = total_interval / wakelock_stats.acquired_count;
+    avg_interval_ms = total_interval_ms / wakelock_stats.acquired_count;
 
   dprintf(fd, "\nBluetooth Wakelock Statistics:\n");
   dprintf(fd, "  Is acquired                    : %s\n",
@@ -361,13 +365,14 @@
           wakelock_stats.last_acquired_error,
           wakelock_stats.last_released_error);
   dprintf(fd, "  Last acquired time (ms)        : %llu\n",
-          (unsigned long long)last_interval);
+          (unsigned long long)last_interval_ms);
   dprintf(fd, "  Acquired time min/max/avg (ms) : %llu / %llu / %llu\n",
-          (unsigned long long)min_interval, (unsigned long long)max_interval,
-          (unsigned long long)ave_interval);
+          (unsigned long long)min_interval_ms,
+          (unsigned long long)max_interval_ms,
+          (unsigned long long)avg_interval_ms);
   dprintf(fd, "  Total acquired time (ms)       : %llu\n",
-          (unsigned long long)total_interval);
-  dprintf(
-      fd, "  Total run time (ms)            : %llu\n",
-      (unsigned long long)(now_ms - wakelock_stats.last_reset_timestamp_ms));
+          (unsigned long long)total_interval_ms);
+  dprintf(fd, "  Total run time (ms)            : %llu\n",
+          (unsigned long long)(just_now_ms -
+                               wakelock_stats.last_reset_timestamp_ms));
 }
diff --git a/osi/test/alarm_mock.h b/osi/test/alarm_mock.h
new file mode 100644
index 0000000..44c1c9e
--- /dev/null
+++ b/osi/test/alarm_mock.h
@@ -0,0 +1,52 @@
+#pragma once
+#include <memory>
+
+struct alarm_t;
+
+class AlarmMock {
+ public:
+  MOCK_METHOD1(AlarmNew, alarm_t*(const char*));
+  MOCK_METHOD1(AlarmFree, void(alarm_t*));
+  MOCK_METHOD1(AlarmCancel, void(alarm_t*));
+  MOCK_METHOD4(AlarmSetOnMloop, void(alarm_t* alarm, uint64_t interval_ms,
+                                     alarm_callback_t cb, void* data));
+
+  alarm_t* AlarmNewImpl(const char* name) {
+    AlarmNew(name);
+    // We must return something from alarm_new in tests, if we just return null,
+    // unique_ptr will misbehave. Just reserve few bits they will be freed in
+    // AlarmFreeImpl
+    return (alarm_t*)new uint8_t[30];
+  }
+
+  void AlarmFreeImpl(alarm_t* alarm) {
+    uint8_t* ptr = (uint8_t*)alarm;
+    delete[] ptr;
+    return AlarmFree(alarm);
+  }
+
+  static inline AlarmMock* Get() {
+    if (!localAlarmMock) {
+      localAlarmMock = std::make_unique<AlarmMock>();
+    }
+    return localAlarmMock.get();
+  }
+
+  static inline void Reset() { localAlarmMock = std::make_unique<AlarmMock>(); }
+
+ private:
+  static std::unique_ptr<AlarmMock> localAlarmMock;
+};
+
+std::unique_ptr<AlarmMock> AlarmMock::localAlarmMock;
+
+alarm_t* alarm_new(const char* name) {
+  return AlarmMock::Get()->AlarmNewImpl(name);
+}
+
+void alarm_free(alarm_t* alarm) { AlarmMock::Get()->AlarmFreeImpl(alarm); }
+
+void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms,
+                        alarm_callback_t cb, void* data) {
+  AlarmMock::Get()->AlarmSetOnMloop(alarm, interval_ms, cb, data);
+}
diff --git a/osi/test/alarm_test.cc b/osi/test/alarm_test.cc
index 0066e19..dad54ef 100644
--- a/osi/test/alarm_test.cc
+++ b/osi/test/alarm_test.cc
@@ -22,14 +22,15 @@
 
 #include "AlarmTestHarness.h"
 
+#include "common/message_loop_thread.h"
 #include "osi/include/alarm.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/osi.h"
 #include "osi/include/semaphore.h"
-#include "osi/include/thread.h"
 
 using base::Closure;
 using base::TimeDelta;
+using bluetooth::common::MessageLoopThread;
 
 static semaphore_t* semaphore;
 static int cb_counter;
@@ -39,25 +40,9 @@
 
 static void msleep(uint64_t ms) { usleep(ms * 1000); }
 
-base::MessageLoop* message_loop_;
-base::RunLoop* run_loop_;
-static semaphore_t* msg_loop_ready;
+static base::MessageLoop* message_loop_;
 
-void message_loop_run(UNUSED_ATTR void* context) {
-  message_loop_ = new base::MessageLoop();
-  run_loop_ = new base::RunLoop();
-
-  semaphore_post(msg_loop_ready);
-  run_loop_->Run();
-
-  delete message_loop_;
-  message_loop_ = nullptr;
-
-  delete run_loop_;
-  run_loop_ = nullptr;
-}
-
-base::MessageLoop* get_message_loop() { return message_loop_; }
+base::MessageLoop* get_main_message_loop() { return message_loop_; }
 
 class AlarmTest : public AlarmTestHarness {
  protected:
@@ -318,15 +303,12 @@
   alarm_t* alarms[100];
 
   // Initialize MesageLoop, and wait till it's initialized.
-  msg_loop_ready = semaphore_new(0);
-  thread_t* message_loop_thread_ = thread_new("btu message loop");
-  if (!message_loop_thread_) {
+  MessageLoopThread message_loop_thread("btu message loop");
+  message_loop_thread.StartUp();
+  if (!message_loop_thread.IsRunning()) {
     FAIL() << "unable to create btu message loop thread.";
   }
-
-  thread_post(message_loop_thread_, message_loop_run, nullptr);
-  semaphore_wait(msg_loop_ready);
-  semaphore_free(msg_loop_ready);
+  message_loop_ = message_loop_thread.message_loop();
 
   for (int i = 0; i < 100; i++) {
     const std::string alarm_name =
@@ -347,9 +329,7 @@
 
   for (int i = 0; i < 100; i++) alarm_free(alarms[i]);
 
-  message_loop_->task_runner()->PostTask(FROM_HERE,
-                                         run_loop_->QuitWhenIdleClosure());
-  thread_free(message_loop_thread_);
+  message_loop_thread.ShutDown();
   EXPECT_FALSE(WakeLockHeld());
 }
 
diff --git a/osi/test/future_test.cc b/osi/test/future_test.cc
index 26d319a..5e78739 100644
--- a/osi/test/future_test.cc
+++ b/osi/test/future_test.cc
@@ -20,9 +20,11 @@
 
 #include "AllocationTestHarness.h"
 
+#include "common/message_loop_thread.h"
 #include "osi/include/future.h"
 #include "osi/include/osi.h"
-#include "osi/include/thread.h"
+
+using bluetooth::common::MessageLoopThread;
 
 static const char* pass_back_data0 = "fancy a sandwich? it's a fancy sandwich";
 static const char* pass_back_data1 =
@@ -38,12 +40,13 @@
   future_t* future = future_new();
   ASSERT_TRUE(future != NULL);
 
-  thread_t* worker_thread = thread_new("worker thread");
-  thread_post(worker_thread, post_to_future, future);
+  MessageLoopThread worker_thread("worker_thread");
+  worker_thread.StartUp();
+  worker_thread.DoInThread(FROM_HERE, base::Bind(post_to_future, future));
 
   EXPECT_EQ(pass_back_data0, future_await(future));
 
-  thread_free(worker_thread);
+  worker_thread.ShutDown();
 }
 
 TEST_F(FutureTest, test_future_immediate) {
diff --git a/osi/test/semaphore_test.cc b/osi/test/semaphore_test.cc
index 44aee8d..54046a8 100644
--- a/osi/test/semaphore_test.cc
+++ b/osi/test/semaphore_test.cc
@@ -6,10 +6,12 @@
 #include <sys/select.h>
 #include <unistd.h>
 
+#include "common/message_loop_thread.h"
 #include "osi/include/osi.h"
 #include "osi/include/reactor.h"
 #include "osi/include/semaphore.h"
-#include "osi/include/thread.h"
+
+using bluetooth::common::MessageLoopThread;
 
 struct SemaphoreTestSequenceHelper {
   semaphore_t* semaphore;
@@ -71,16 +73,18 @@
 TEST_F(SemaphoreTest, test_ensure_wait) {
   semaphore_t* semaphore = semaphore_new(0);
   ASSERT_TRUE(semaphore != NULL);
-  thread_t* thread = thread_new("semaphore_test_thread");
-  ASSERT_TRUE(thread != NULL);
+  MessageLoopThread thread("semaphore_test_thread");
+  thread.StartUp();
+  ASSERT_TRUE(thread.IsRunning());
 
   EXPECT_FALSE(semaphore_try_wait(semaphore));
   SemaphoreTestSequenceHelper sequence_helper = {semaphore, 0};
-  thread_post(thread, sleep_then_increment_counter, &sequence_helper);
+  thread.DoInThread(FROM_HERE,
+                    base::Bind(sleep_then_increment_counter, &sequence_helper));
   semaphore_wait(semaphore);
   EXPECT_EQ(sequence_helper.counter, 1)
       << "semaphore_wait() did not wait for counter to increment";
 
   semaphore_free(semaphore);
-  thread_free(thread);
+  thread.ShutDown();
 }
diff --git a/osi/test/time_test.cc b/osi/test/time_test.cc
deleted file mode 100644
index f14842d..0000000
--- a/osi/test/time_test.cc
+++ /dev/null
@@ -1,154 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2015 Google, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-#include <gtest/gtest.h>
-
-#include "AllocationTestHarness.h"
-
-#include "osi/include/time.h"
-
-// Generous upper bound: 10 seconds
-static const uint32_t TEST_TIME_DELTA_UPPER_BOUND_MS = 10 * 1000;
-
-class TimeTest : public AllocationTestHarness {};
-
-//
-// Test that the return value of time_get_os_boottime_ms() is not zero.
-//
-// NOTE: For now this test is disabled, because the return value
-// of time_get_os_boottime_ms() is 32-bits integer that could wrap-around
-// in 49.7 days. It should be re-enabled if/after the wrap-around issue
-// is resolved (e.g., if the return value is 64-bits integer).
-//
-#if 0
-TEST_F(TimeTest, test_time_get_os_boottime_ms_not_zero) {
-  uint32_t t1 = time_get_os_boottime_ms();
-  ASSERT_TRUE(t1 > 0);
-}
-#endif
-
-//
-// Test that the return value of time_get_os_boottime_us() is not zero.
-//
-TEST_F(TimeTest, test_time_get_os_boottime_us_not_zero) {
-  uint64_t t1 = time_get_os_boottime_us();
-  ASSERT_TRUE(t1 > 0);
-}
-
-//
-// Test that the return value of time_get_os_boottime_ms()
-// is monotonically increasing within reasonable boundries.
-//
-TEST_F(TimeTest, test_time_get_os_boottime_ms_increases_upper_bound) {
-  uint32_t t1 = time_get_os_boottime_ms();
-  uint32_t t2 = time_get_os_boottime_ms();
-  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS);
-}
-
-//
-// Test that the return value of time_get_os_boottime_us()
-// is monotonically increasing within reasonable boundries.
-//
-TEST_F(TimeTest, test_time_get_os_boottime_us_increases_upper_bound) {
-  uint64_t t1 = time_get_os_boottime_us();
-  uint64_t t2 = time_get_os_boottime_us();
-  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
-}
-
-//
-// Test that the return value of time_get_os_boottime_ms()
-// is increasing.
-//
-TEST_F(TimeTest, test_time_get_os_boottime_ms_increases_lower_bound) {
-  static const uint32_t TEST_TIME_SLEEP_MS = 100;
-  struct timespec delay;
-
-  delay.tv_sec = TEST_TIME_SLEEP_MS / 1000;
-  delay.tv_nsec = 1000 * 1000 * (TEST_TIME_SLEEP_MS % 1000);
-
-  // Take two timestamps with sleep in-between
-  uint32_t t1 = time_get_os_boottime_ms();
-  int err = nanosleep(&delay, &delay);
-  uint32_t t2 = time_get_os_boottime_ms();
-
-  ASSERT_TRUE(err == 0);
-  ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_MS);
-  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS);
-}
-
-//
-// Test that the return value of time_get_os_boottime_us()
-// is increasing.
-//
-TEST_F(TimeTest, test_time_get_os_boottime_us_increases_lower_bound) {
-  static const uint64_t TEST_TIME_SLEEP_US = 100 * 1000;
-  struct timespec delay;
-
-  delay.tv_sec = TEST_TIME_SLEEP_US / (1000 * 1000);
-  delay.tv_nsec = 1000 * (TEST_TIME_SLEEP_US % (1000 * 1000));
-
-  // Take two timestamps with sleep in-between
-  uint64_t t1 = time_get_os_boottime_us();
-  int err = nanosleep(&delay, &delay);
-  uint64_t t2 = time_get_os_boottime_us();
-
-  ASSERT_TRUE(err == 0);
-  ASSERT_TRUE(t2 > t1);
-  ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_US);
-  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
-}
-
-//
-// Test that the return value of time_gettimeofday_us() is not zero.
-//
-TEST_F(TimeTest, test_time_gettimeofday_us_not_zero) {
-  uint64_t t1 = time_gettimeofday_us();
-  ASSERT_TRUE(t1 > 0);
-}
-
-//
-// Test that the return value of time_gettimeofday_us()
-// is monotonically increasing within reasonable boundaries.
-//
-TEST_F(TimeTest, test_time_gettimeofday_us_increases_upper_bound) {
-  uint64_t t1 = time_gettimeofday_us();
-  uint64_t t2 = time_gettimeofday_us();
-  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
-}
-
-//
-// Test that the return value of time_gettimeofday_us()
-// is increasing.
-//
-TEST_F(TimeTest, test_time_gettimeofday_us_increases_lower_bound) {
-  static const uint64_t TEST_TIME_SLEEP_US = 100 * 1000;
-  struct timespec delay;
-
-  delay.tv_sec = TEST_TIME_SLEEP_US / (1000 * 1000);
-  delay.tv_nsec = 1000 * (TEST_TIME_SLEEP_US % (1000 * 1000));
-
-  // Take two timestamps with sleep in-between
-  uint64_t t1 = time_gettimeofday_us();
-  int err = nanosleep(&delay, &delay);
-  uint64_t t2 = time_gettimeofday_us();
-
-  ASSERT_TRUE(err == 0);
-  ASSERT_TRUE(t2 > t1);
-  ASSERT_TRUE((t2 - t1) >= TEST_TIME_SLEEP_US);
-  ASSERT_TRUE((t2 - t1) < TEST_TIME_DELTA_UPPER_BOUND_MS * 1000);
-}
diff --git a/packet/Android.bp b/packet/Android.bp
index 8338c2d..44d0625 100644
--- a/packet/Android.bp
+++ b/packet/Android.bp
@@ -15,8 +15,13 @@
 cc_test {
     name: "net_test_btpackets",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     host_supported: true,
     local_include_dirs: ["tests"],
+    include_dirs: [
+        "system/bt/",
+        "system/bt/include",
+    ],
     srcs: [
         "tests/avrcp/avrcp_browse_packet_test.cc",
         "tests/avrcp/avrcp_packet_test.cc",
diff --git a/packet/BUILD.gn b/packet/BUILD.gn
new file mode 100644
index 0000000..37d6ca4
--- /dev/null
+++ b/packet/BUILD.gn
@@ -0,0 +1,52 @@
+#
+#  Copyright 2018 Android Open Source Project
+#
+#  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.
+#
+
+static_library("packet") {
+  sources = [
+    "avrcp/get_folder_items.cc",
+    "avrcp/register_notification_packet.cc",
+    "avrcp/change_path.cc",
+    "avrcp/get_total_number_of_items.cc",
+    "avrcp/capabilities_packet.cc",
+    "avrcp/pass_through_packet.cc",
+    "avrcp/set_browsed_player.cc",
+    "avrcp/avrcp_reject_packet.cc",
+    "avrcp/set_absolute_volume.cc",
+    "avrcp/avrcp_packet.cc",
+    "avrcp/get_element_attributes_packet.cc",
+    "avrcp/get_play_status_packet.cc",
+    "avrcp/general_reject_packet.cc",
+    "avrcp/avrcp_browse_packet.cc",
+    "avrcp/get_item_attributes.cc",
+    "avrcp/play_item.cc",
+    "avrcp/vendor_packet.cc",
+    "avrcp/set_addressed_player.cc",
+    "base/iterator.cc",
+    "base/packet.cc",
+    "base/packet_builder.cc",
+ ]
+
+  include_dirs = [
+    "//",
+    "//internal_include",
+    "//stack/include",
+    "//profile/avrcp",
+  ]
+
+  deps = [
+    "//third_party/libchrome:base"
+  ]
+}
diff --git a/packet/avrcp/Android.bp b/packet/avrcp/Android.bp
index 80e93e8..b54288f 100644
--- a/packet/avrcp/Android.bp
+++ b/packet/avrcp/Android.bp
@@ -5,6 +5,10 @@
     export_header_lib_headers: ["avrcp_headers"],
     export_include_dirs: ["."],
     host_supported: true,
+    include_dirs: [
+        "system/bt/",
+        "system/bt/include",
+    ],
     srcs: [
         "avrcp_browse_packet.cc",
         "avrcp_packet.cc",
diff --git a/packet/avrcp/avrcp_browse_packet.cc b/packet/avrcp/avrcp_browse_packet.cc
index f4a7691..07b5485 100644
--- a/packet/avrcp/avrcp_browse_packet.cc
+++ b/packet/avrcp/avrcp_browse_packet.cc
@@ -61,7 +61,7 @@
 
 uint16_t BrowsePacket::GetLength() const {
   auto it = begin() + static_cast<size_t>(1);
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 bool BrowsePacket::IsValid() const {
@@ -88,4 +88,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/avrcp_browse_packet.h b/packet/avrcp/avrcp_browse_packet.h
index d62f0e2..038f576 100644
--- a/packet/avrcp/avrcp_browse_packet.h
+++ b/packet/avrcp/avrcp_browse_packet.h
@@ -20,11 +20,11 @@
 #include <base/macros.h>
 #include <iostream>
 
-#include "avrcp_common.h"
-#include "avrcp_logging_helper.h"
-#include "iterator.h"
-#include "packet.h"
-#include "packet_builder.h"
+#include "hardware/avrcp/avrcp_common.h"
+#include "hardware/avrcp/avrcp_logging_helper.h"
+#include "packet/base/iterator.h"
+#include "packet/base/packet.h"
+#include "packet/base/packet_builder.h"
 
 namespace bluetooth {
 namespace avrcp {
@@ -75,7 +75,7 @@
   using ::bluetooth::Packet::Packet;
 
  private:
-  virtual std::pair<size_t, size_t> GetPayloadIndecies() const;
+  virtual std::pair<size_t, size_t> GetPayloadIndecies() const override;
   DISALLOW_COPY_AND_ASSIGN(BrowsePacket);
 };
 
diff --git a/packet/avrcp/avrcp_packet.h b/packet/avrcp/avrcp_packet.h
index 1e56186..ee0e0d5 100644
--- a/packet/avrcp/avrcp_packet.h
+++ b/packet/avrcp/avrcp_packet.h
@@ -20,11 +20,11 @@
 #include <base/macros.h>
 #include <iostream>
 
-#include "avrcp_common.h"
-#include "avrcp_logging_helper.h"
-#include "iterator.h"
-#include "packet.h"
-#include "packet_builder.h"
+#include "hardware/avrcp/avrcp_common.h"
+#include "hardware/avrcp/avrcp_logging_helper.h"
+#include "packet/base/iterator.h"
+#include "packet/base/packet.h"
+#include "packet/base/packet_builder.h"
 
 namespace bluetooth {
 namespace avrcp {
@@ -87,7 +87,7 @@
   Opcode GetOpcode() const;
 
   // Overloaded Functions
-  virtual bool IsValid() const;
+  virtual bool IsValid() const override;
   virtual std::string ToString() const override;
 
  protected:
@@ -103,9 +103,9 @@
   }
 
  private:
-  virtual std::pair<size_t, size_t> GetPayloadIndecies() const;
+  virtual std::pair<size_t, size_t> GetPayloadIndecies() const override;
   DISALLOW_COPY_AND_ASSIGN(Packet);
 };
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/change_path.cc b/packet/avrcp/change_path.cc
index 3c69903..b5f9ab4 100644
--- a/packet/avrcp/change_path.cc
+++ b/packet/avrcp/change_path.cc
@@ -52,7 +52,7 @@
 
 uint16_t ChangePathRequest::GetUidCounter() const {
   auto it = begin() + BrowsePacket::kMinSize();
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 Direction ChangePathRequest::GetDirection() const {
@@ -62,7 +62,7 @@
 
 uint64_t ChangePathRequest::GetUid() const {
   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(3);
-  return base::ByteSwap(it.extract<uint64_t>());
+  return it.extractBE<uint64_t>();
 }
 
 bool ChangePathRequest::IsValid() const {
@@ -109,4 +109,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/general_reject_packet.cc b/packet/avrcp/general_reject_packet.cc
index cde0031..db3d31a 100644
--- a/packet/avrcp/general_reject_packet.cc
+++ b/packet/avrcp/general_reject_packet.cc
@@ -19,11 +19,9 @@
 namespace bluetooth {
 namespace avrcp {
 
-std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(
-    BrowsePdu pdu, Status reason) {
+std::unique_ptr<GeneralRejectBuilder> GeneralRejectBuilder::MakeBuilder(Status reason) {
   std::unique_ptr<GeneralRejectBuilder> builder =
-      std::unique_ptr<GeneralRejectBuilder>(
-          new GeneralRejectBuilder(pdu, reason));
+      std::unique_ptr<GeneralRejectBuilder>(new GeneralRejectBuilder(reason));
 
   return builder;
 }
diff --git a/packet/avrcp/general_reject_packet.h b/packet/avrcp/general_reject_packet.h
index 4058fd4..b3fb2fe 100644
--- a/packet/avrcp/general_reject_packet.h
+++ b/packet/avrcp/general_reject_packet.h
@@ -25,8 +25,7 @@
  public:
   virtual ~GeneralRejectBuilder() = default;
 
-  static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(BrowsePdu pdu,
-                                                           Status reason);
+  static std::unique_ptr<GeneralRejectBuilder> MakeBuilder(Status reason);
 
   virtual size_t size() const override;
   virtual bool Serialize(
@@ -35,8 +34,7 @@
  protected:
   Status reason_;
 
-  GeneralRejectBuilder(BrowsePdu pdu, Status reason)
-      : BrowsePacketBuilder(pdu), reason_(reason){};
+  GeneralRejectBuilder(Status reason) : BrowsePacketBuilder(BrowsePdu::GENERAL_REJECT), reason_(reason){};
 };
 
 }  // namespace avrcp
diff --git a/packet/avrcp/get_element_attributes_packet.cc b/packet/avrcp/get_element_attributes_packet.cc
index c26207e..8634ce0 100644
--- a/packet/avrcp/get_element_attributes_packet.cc
+++ b/packet/avrcp/get_element_attributes_packet.cc
@@ -40,7 +40,7 @@
   std::vector<Attribute> attribute_list;
 
   for (size_t i = 0; i < number_of_attributes; i++) {
-    attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
+    attribute_list.push_back((Attribute)it.extractBE<uint32_t>());
   }
 
   return attribute_list;
@@ -132,7 +132,7 @@
   VendorPacketBuilder::PushHeader(pkt, size() - VendorPacket::kMinSize());
 
   AddPayloadOctets1(pkt, entries_.size());
-  for (auto attribute_entry : entries_) {
+  for (const auto& attribute_entry : entries_) {
     PushAttributeValue(pkt, attribute_entry);
   }
 
@@ -140,4 +140,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/get_element_attributes_packet.h b/packet/avrcp/get_element_attributes_packet.h
index 03fa8d1..e60844c 100644
--- a/packet/avrcp/get_element_attributes_packet.h
+++ b/packet/avrcp/get_element_attributes_packet.h
@@ -51,7 +51,7 @@
   std::vector<Attribute> GetAttributesRequested() const;
 
   // Overloaded Functions
-  virtual bool IsValid() const;
+  virtual bool IsValid() const override;
   virtual std::string ToString() const override;
 
  protected:
diff --git a/packet/avrcp/get_folder_items.cc b/packet/avrcp/get_folder_items.cc
index c95bb4a..4e6e3a1 100644
--- a/packet/avrcp/get_folder_items.cc
+++ b/packet/avrcp/get_folder_items.cc
@@ -236,12 +236,12 @@
 
 uint32_t GetFolderItemsRequest::GetStartItem() const {
   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(1);
-  return base::ByteSwap(it.extract<uint32_t>());
+  return it.extractBE<uint32_t>();
 }
 
 uint32_t GetFolderItemsRequest::GetEndItem() const {
   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(5);
-  return base::ByteSwap(it.extract<uint32_t>());
+  return it.extractBE<uint32_t>();
 }
 
 uint8_t GetFolderItemsRequest::GetNumAttributes() const {
@@ -263,7 +263,7 @@
   // to have this function return a vector with all the attributes
 
   for (size_t i = 0; i < number_of_attributes; i++) {
-    attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
+    attribute_list.push_back((Attribute)it.extractBE<uint32_t>());
   }
 
   return attribute_list;
@@ -342,4 +342,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/get_item_attributes.cc b/packet/avrcp/get_item_attributes.cc
index 3430474..fb2ba87 100644
--- a/packet/avrcp/get_item_attributes.cc
+++ b/packet/avrcp/get_item_attributes.cc
@@ -70,7 +70,7 @@
   if (status_ != Status::NO_ERROR) return true;
 
   AddPayloadOctets1(pkt, entries_.size());
-  for (auto entry : entries_) {
+  for (const auto& entry : entries_) {
     AddPayloadOctets4(pkt, base::ByteSwap((uint32_t)entry.attribute()));
     uint16_t character_set = 0x006a;  // UTF-8
     AddPayloadOctets2(pkt, base::ByteSwap(character_set));
@@ -91,12 +91,12 @@
 
 uint64_t GetItemAttributesRequest::GetUid() const {
   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(1);
-  return base::ByteSwap(it.extract<uint64_t>());
+  return it.extractBE<uint64_t>();
 }
 
 uint16_t GetItemAttributesRequest::GetUidCounter() const {
   auto it = begin() + BrowsePacket::kMinSize() + static_cast<size_t>(9);
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 uint8_t GetItemAttributesRequest::GetNumAttributes() const {
@@ -111,7 +111,7 @@
 
   std::vector<Attribute> attribute_list;
   for (size_t i = 0; i < number_of_attributes; i++) {
-    attribute_list.push_back((Attribute)base::ByteSwap(it.extract<uint32_t>()));
+    attribute_list.push_back((Attribute)it.extractBE<uint32_t>());
   }
 
   return attribute_list;
@@ -147,4 +147,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/play_item.cc b/packet/avrcp/play_item.cc
index 27b242b..d7bb9b7 100644
--- a/packet/avrcp/play_item.cc
+++ b/packet/avrcp/play_item.cc
@@ -53,12 +53,12 @@
 
 uint64_t PlayItemRequest::GetUid() const {
   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
-  return base::ByteSwap(it.extract<uint64_t>());
+  return it.extractBE<uint64_t>();
 }
 
 uint16_t PlayItemRequest::GetUidCounter() const {
   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(9);
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 bool PlayItemRequest::IsValid() const {
@@ -86,4 +86,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/register_notification_packet.cc b/packet/avrcp/register_notification_packet.cc
index 86115e1..6bbd16a 100644
--- a/packet/avrcp/register_notification_packet.cc
+++ b/packet/avrcp/register_notification_packet.cc
@@ -39,8 +39,9 @@
 bool RegisterNotificationResponse::IsValid() const {
   if (!VendorPacket::IsValid()) return false;
   if (size() < kMinSize()) return false;
-  if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED)
+  if (GetCType() != CType::INTERIM && GetCType() != CType::CHANGED && GetCType() != CType::REJECTED) {
     return false;
+  }
 
   switch (GetEvent()) {
     case Event::VOLUME_CHANGED:
@@ -234,7 +235,7 @@
 
 uint32_t RegisterNotificationRequest::GetInterval() const {
   auto it = begin() + VendorPacket::kMinSize() + static_cast<size_t>(1);
-  return base::ByteSwap(it.extract<uint32_t>());
+  return it.extractBE<uint32_t>();
 }
 
 bool RegisterNotificationRequest::IsValid() const {
@@ -288,4 +289,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/set_addressed_player.cc b/packet/avrcp/set_addressed_player.cc
index f4b4ddd..d1a9909 100644
--- a/packet/avrcp/set_addressed_player.cc
+++ b/packet/avrcp/set_addressed_player.cc
@@ -48,7 +48,7 @@
 
 uint16_t SetAddressedPlayerRequest::GetPlayerId() const {
   auto it = begin() + VendorPacket::kMinSize();
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 bool SetAddressedPlayerRequest::IsValid() const {
@@ -74,4 +74,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/set_browsed_player.cc b/packet/avrcp/set_browsed_player.cc
index b8463fa..fa0c768 100644
--- a/packet/avrcp/set_browsed_player.cc
+++ b/packet/avrcp/set_browsed_player.cc
@@ -80,7 +80,7 @@
 
 uint16_t SetBrowsedPlayerRequest::GetPlayerId() const {
   auto it = begin() + BrowsePacket::kMinSize();
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 bool SetBrowsedPlayerRequest::IsValid() const {
@@ -100,4 +100,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/avrcp/vendor_packet.cc b/packet/avrcp/vendor_packet.cc
index 982cf81..4525cfb 100644
--- a/packet/avrcp/vendor_packet.cc
+++ b/packet/avrcp/vendor_packet.cc
@@ -96,7 +96,7 @@
 uint16_t VendorPacket::GetParameterLength() const {
   auto it = begin() + Packet::kMinSize() + static_cast<size_t>(5);
   // Swap to little endian
-  return base::ByteSwap(it.extract<uint16_t>());
+  return it.extractBE<uint16_t>();
 }
 
 bool VendorPacket::IsValid() const {
@@ -128,4 +128,4 @@
 }
 
 }  // namespace avrcp
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/base/iterator.h b/packet/base/iterator.h
index c4ad32c..782150d 100644
--- a/packet/base/iterator.h
+++ b/packet/base/iterator.h
@@ -71,6 +71,22 @@
     return extracted_value;
   }
 
+  // Extract in Little Endian Format
+  template <typename FixedWidthIntegerType>
+  FixedWidthIntegerType extractBE() {
+    static_assert(std::is_integral<FixedWidthIntegerType>::value,
+                  "Iterator::extract requires an integral type.");
+
+    FixedWidthIntegerType extracted_value = 0;
+    for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
+      extracted_value |= static_cast<FixedWidthIntegerType>(**this)
+                         << (sizeof(FixedWidthIntegerType) - 1 - i) * 8;
+      (*this)++;
+    }
+
+    return extracted_value;
+  }
+
   uint8_t extract8() { return extract<uint8_t>(); }
   uint16_t extract16() { return extract<uint16_t>(); }
   uint32_t extract32() { return extract<uint32_t>(); }
@@ -81,4 +97,4 @@
   size_t index_;
 };  // Iterator
 
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/packet/tests/avrcp/avrcp_test_packets.h b/packet/tests/avrcp/avrcp_test_packets.h
index 13994d0..14e30e7 100644
--- a/packet/tests/avrcp/avrcp_test_packets.h
+++ b/packet/tests/avrcp/avrcp_test_packets.h
@@ -106,8 +106,8 @@
     0x00, 0x05, 0x0d, 0x00, 0x00, 0x00, 0x00};
 
 // AVRCP Register Notification without any parameter
-std::vector<uint8_t> register_notification_invalid = {
-    0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31, 0x00, 0x00, 0x05};
+std::vector<uint8_t> register_notification_invalid = {0x03, 0x48, 0x00, 0x00, 0x19, 0x58, 0x31,
+                                                      0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00};
 
 // AVRCP Interim Playback Status Notification
 std::vector<uint8_t> interim_play_status_notification = {
@@ -208,9 +208,8 @@
 //    start_item = 0x00
 //    end_item = 0x05
 //    attributes_requested: All Items
-std::vector<uint8_t> get_folder_items_request_now_playing = {
-    0x71, 0x00, 0x0e, 0x03, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
+std::vector<uint8_t> get_folder_items_request_now_playing = {0x71, 0x00, 0x0a, 0x03, 0x00, 0x00, 0x00,
+                                                             0x00, 0x00, 0x00, 0x00, 0x05, 0x00};
 
 // AVRCP Browse Get Folder Items Response packet with range out of bounds error
 std::vector<uint8_t> get_folder_items_error_response = {0x71, 0x00, 0x01, 0x0b};
@@ -356,4 +355,36 @@
 std::vector<uint8_t> set_absolute_volume_response = {
     0x09, 0x48, 0x00, 0x00, 0x19, 0x58, 0x50, 0x00, 0x00, 0x01, 0x43};
 
+// Invalid Packets
+// Short Vendor Packet
+std::vector<uint8_t> short_vendor_packet = {0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x01};
+
+// Short Get Capabilities Request Packet
+std::vector<uint8_t> short_get_capabilities_request = {0x01, 0x48, 0x00, 0x00, 0x19, 0x58, 0x10, 0x00, 0x00, 0x00};
+
+// Short Get Element Attributes Request Packet
+std::vector<uint8_t> short_get_element_attributes_request = {0x01, 0x48, 0x00, 0x00, 0x19,
+                                                             0x58, 0x20, 0x00, 0x00, 0x00};
+
+// Short Play Item Request Packet
+std::vector<uint8_t> short_play_item_request = {0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x74, 0x00, 0x00, 0x00};
+
+// Short Set Addressed Player Request Packet
+std::vector<uint8_t> short_set_addressed_player_request = {0x00, 0x48, 0x00, 0x00, 0x19, 0x58, 0x60, 0x00, 0x00, 0x00};
+
+// Short Browse Packet
+std::vector<uint8_t> short_browse_packet = {0x71, 0x00, 0x0a};
+
+// Short Get Folder Items Request Packet
+std::vector<uint8_t> short_get_folder_items_request = {0x71, 0x00, 0x00};
+
+// Short Get Total Number of Items Request Packet
+std::vector<uint8_t> short_get_total_number_of_items_request = {0x75, 0x00, 0x00};
+
+// Short Change Path Request Packet
+std::vector<uint8_t> short_change_path_request = {0x72, 0x00, 0x00};
+
+// Short Get Item Attributes Request Packet
+std::vector<uint8_t> short_get_item_attributes_request = {0x73, 0x00, 0x00};
+
 }  // namespace
diff --git a/packet/tests/avrcp/general_reject_packet_test.cc b/packet/tests/avrcp/general_reject_packet_test.cc
index e27d0b7..4d73dba 100644
--- a/packet/tests/avrcp/general_reject_packet_test.cc
+++ b/packet/tests/avrcp/general_reject_packet_test.cc
@@ -26,8 +26,7 @@
 using TestGeneralRejectPacket = TestPacketType<BrowsePacket>;
 
 TEST(GeneralRejectPacketBuilderTest, buildPacketTest) {
-  auto builder = GeneralRejectBuilder::MakeBuilder(BrowsePdu::GENERAL_REJECT,
-                                                   Status::INVALID_COMMAND);
+  auto builder = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
 
   ASSERT_EQ(builder->size(), general_reject_invalid_command_packet.size());
 
diff --git a/packet/tests/base/iterator_test.cc b/packet/tests/base/iterator_test.cc
index 5794686..57743de 100644
--- a/packet/tests/base/iterator_test.cc
+++ b/packet/tests/base/iterator_test.cc
@@ -65,6 +65,16 @@
   ASSERT_EQ(0x00010000000a0013u, general_case.extract<uint64_t>());
 }
 
+TEST_F(IteratorTest, extractBETest) {
+  auto packet = TestPacket::Make(test_l2cap_data);
+  Iterator general_case = packet->begin();
+
+  ASSERT_EQ(0x02u, general_case.extractBE<uint8_t>());
+  ASSERT_EQ(0xdc2eu, general_case.extractBE<uint16_t>());
+  ASSERT_EQ(0x66006200u, general_case.extractBE<uint32_t>());
+  ASSERT_EQ(0x13000a0000000100u, general_case.extractBE<uint64_t>());
+}
+
 TEST_P(IteratorTest, payloadBoundsTest) {
   auto packet = GetTestPacket();
   ASSERT_EQ(static_cast<size_t>(packet->end() - packet->begin()),
@@ -89,6 +99,19 @@
                "index_ != packet_->packet_end_index_");
 }
 
+TEST_P(IteratorTest, extractBEBoundsDeathTest) {
+  auto packet = GetTestPacket();
+  Iterator bounds_test = packet->end();
+  ASSERT_DEATH(bounds_test.extractBE<uint8_t>(),
+               "index_ != packet_->packet_end_index_");
+  ASSERT_DEATH(bounds_test.extractBE<uint16_t>(),
+               "index_ != packet_->packet_end_index_");
+  ASSERT_DEATH(bounds_test.extractBE<uint32_t>(),
+               "index_ != packet_->packet_end_index_");
+  ASSERT_DEATH(bounds_test.extractBE<uint64_t>(),
+               "index_ != packet_->packet_end_index_");
+}
+
 TEST_P(IteratorTest, dereferenceDeathTest) {
   auto packet = GetTestPacket();
   Iterator dereference_test = packet->end();
@@ -273,4 +296,4 @@
   }
 }
 
-}  // namespace bluetooth
\ No newline at end of file
+}  // namespace bluetooth
diff --git a/profile/avrcp/Android.bp b/profile/avrcp/Android.bp
index 3d95e9f..d452cb0 100644
--- a/profile/avrcp/Android.bp
+++ b/profile/avrcp/Android.bp
@@ -1,6 +1,9 @@
 cc_library_static {
     name: "avrcp-target-service",
-    defaults: ["fluoride_defaults"],
+    defaults: [
+        "fluoride_defaults",
+        "clang_file_coverage"
+    ],
     host_supported: true,
     include_dirs: [
         "system/bt",
@@ -18,11 +21,18 @@
         "libbluetooth-types",
         "libosi",
     ],
+    shared_libs: [
+        "libchrome",
+    ],
 }
 
 cc_test {
     name: "net_test_avrcp",
-    defaults: ["fluoride_defaults"],
+    test_suites: ["general-tests"],
+    defaults: [
+        "fluoride_defaults",
+        "clang_coverage_bin",
+    ],
     host_supported: true,
     include_dirs: [
         "system/bt",
@@ -37,11 +47,14 @@
     static_libs: [
         "libgmock",
         "lib-bt-packets",
-        "avrcp-target-service",
-        "libbtdevice",
         "libosi",
         "liblog",
         "libcutils",
+        "libbtdevice",
+        "avrcp-target-service",
+    ],
+    shared_libs: [
+        "libchrome",
     ],
     sanitize: {
         cfi: false,
diff --git a/tools/mcap_tool/BUILD.gn b/profile/avrcp/BUILD.gn
similarity index 64%
rename from tools/mcap_tool/BUILD.gn
rename to profile/avrcp/BUILD.gn
index d41ed56..c37e0a7 100644
--- a/tools/mcap_tool/BUILD.gn
+++ b/profile/avrcp/BUILD.gn
@@ -1,5 +1,5 @@
 #
-#  Copyright 2017 Google, Inc.
+#  Copyright 2018 Android Open Source Project
 #
 #  Licensed under the Apache License, Version 2.0 (the "License");
 #  you may not use this file except in compliance with the License.
@@ -13,32 +13,22 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 #
-executable("mcap_tool") {
-  testonly = true
+
+static_library("profile_avrcp") {
   sources = [
-    "mcap_tool.cc",
-    "mcap_test_app.cc",
-    "mcap_test_mcl.cc",
-    "mcap_test_mdep.cc",
-    "mcap_test_mdl.cc",
+    "connection_handler.cc",
+    "device.cc",
   ]
+
   include_dirs = [
     "//",
+    "//btcore/include",
     "//internal_include",
     "//stack/include",
-    "//btif/include",
-    "//btcore/include",
-    "//tools/mcap_tool",
+    "//profile/avrcp",
   ]
-  libs = [
-    "-lpthread",
-    "-lrt",
-    "-ldl",
-  ]
+
   deps = [
-    "//btcore",
-    "//osi",
-    "//third_party/libchrome:base",
-    "//types",
+    "//third_party/libchrome:base"
   ]
 }
diff --git a/profile/avrcp/avrcp_internal.h b/profile/avrcp/avrcp_internal.h
index c2e6549..4aeffdf 100644
--- a/profile/avrcp/avrcp_internal.h
+++ b/profile/avrcp/avrcp_internal.h
@@ -82,6 +82,7 @@
 class A2dpInterface {
  public:
   virtual RawAddress active_peer() = 0;
+  virtual bool is_peer_in_silence_mode(const RawAddress& peer_address) = 0;
 
   virtual ~A2dpInterface() = default;
-};
\ No newline at end of file
+};
diff --git a/profile/avrcp/avrcp_message_converter.h b/profile/avrcp/avrcp_message_converter.h
index 389a497..8de704b 100644
--- a/profile/avrcp/avrcp_message_converter.h
+++ b/profile/avrcp/avrcp_message_converter.h
@@ -19,7 +19,7 @@
 #include <iostream>
 #include <vector>
 
-#include "avrcp_packet.h"
+#include "packet/avrcp/avrcp_packet.h"
 
 // These classes are temporary placeholders to easily switch between BT_HDR and
 // packets.
@@ -41,7 +41,7 @@
 
   const std::vector<uint8_t>& GetData() { return *data_; };
 
-  virtual std::string ToString() const {
+  virtual std::string ToString() const override {
     std::stringstream ss;
     ss << "VectorPacket:" << std::endl;
     ss << "  â”” Payload =";
diff --git a/profile/avrcp/connection_handler.cc b/profile/avrcp/connection_handler.cc
index 66237ed..3177506 100644
--- a/profile/avrcp/connection_handler.cc
+++ b/profile/avrcp/connection_handler.cc
@@ -22,9 +22,9 @@
 
 #include "avrc_defs.h"
 #include "avrcp_message_converter.h"
-#include "avrcp_packet.h"
 #include "bt_types.h"
 #include "btu.h"
+#include "packet/avrcp/avrcp_packet.h"
 // TODO (apanicke): Remove dependency on this header once we cleanup feature
 // handling.
 #include "bta/include/bta_av_api.h"
@@ -151,7 +151,7 @@
 std::vector<std::shared_ptr<Device>> ConnectionHandler::GetListOfDevices()
     const {
   std::vector<std::shared_ptr<Device>> list;
-  for (auto device : device_map_) {
+  for (const auto& device : device_map_) {
     list.push_back(device.second);
   }
   return list;
@@ -176,8 +176,9 @@
 
   return avrc_->FindService(
              UUID_SERVCLASS_AV_REMOTE_CONTROL, bdaddr, &db_params,
-             base::Bind(&ConnectionHandler::SdpCb, base::Unretained(this),
-                        bdaddr, cb, disc_db)) == AVRC_SUCCESS;
+             base::Bind(&ConnectionHandler::SdpCb,
+                        weak_ptr_factory_.GetWeakPtr(), bdaddr, cb, disc_db)) ==
+         AVRC_SUCCESS;
 }
 
 bool ConnectionHandler::AvrcpConnect(bool initiator, const RawAddress& bdaddr) {
@@ -192,7 +193,7 @@
                                     weak_ptr_factory_.GetWeakPtr());
   }
   open_cb.msg_cback =
-      base::Bind(&ConnectionHandler::MessageCb, base::Unretained(this));
+      base::Bind(&ConnectionHandler::MessageCb, weak_ptr_factory_.GetWeakPtr());
   open_cb.company_id = AVRC_CO_GOOGLE;
   open_cb.conn = initiator ? AVRC_CONN_INT
                            : AVRC_CONN_ACP;  // 0 if initiator, 1 if acceptor
@@ -272,13 +273,20 @@
       device_map_.erase(handle);
     } break;
 
-    case AVRC_BROWSE_OPEN_IND_EVT:
+    case AVRC_BROWSE_OPEN_IND_EVT: {
       LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
       // NOTE (apanicke): We don't need to explicitly handle this message
       // since the AVCTP Layer will still send us browsing messages
       // regardless. It would be useful to note this though for future
       // compatibility issues.
-      break;
+      if (device_map_.find(handle) == device_map_.end()) {
+        LOG(WARNING) << "Browse Opened received from device that doesn't exist";
+        return;
+      }
+
+      auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
+      device_map_[handle]->SetBrowseMtu(browse_mtu);
+    } break;
     case AVRC_BROWSE_CLOSE_IND_EVT:
       LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
       break;
@@ -302,7 +310,7 @@
       LOG(INFO) << __PRETTY_FUNCTION__ << ": Connection Opened Event";
 
       auto&& callback = base::Bind(&ConnectionHandler::SendMessage,
-                                   base::Unretained(this), handle);
+                                   weak_ptr_factory_.GetWeakPtr(), handle);
       auto&& ctrl_mtu = avrc_->GetPeerMtu(handle) - AVCT_HDR_LEN;
       auto&& browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
       std::shared_ptr<Device> newDevice = std::make_shared<Device>(
@@ -356,13 +364,20 @@
       device_map_.erase(handle);
     } break;
 
-    case AVRC_BROWSE_OPEN_IND_EVT:
+    case AVRC_BROWSE_OPEN_IND_EVT: {
       LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Open Event";
       // NOTE (apanicke): We don't need to explicitly handle this message
       // since the AVCTP Layer will still send us browsing messages
       // regardless. It would be useful to note this though for future
       // compatibility issues.
-      break;
+      if (device_map_.find(handle) == device_map_.end()) {
+        LOG(WARNING) << "Browse Opened received from device that doesn't exist";
+        return;
+      }
+
+      auto browse_mtu = avrc_->GetBrowseMtu(handle) - AVCT_HDR_LEN;
+      device_map_[handle]->SetBrowseMtu(browse_mtu);
+    } break;
     case AVRC_BROWSE_CLOSE_IND_EVT:
       LOG(INFO) << __PRETTY_FUNCTION__ << ": Browse Close Event";
       break;
@@ -374,7 +389,7 @@
 
 void ConnectionHandler::MessageCb(uint8_t handle, uint8_t label, uint8_t opcode,
                                   tAVRC_MSG* p_msg) {
-  if (device_map_[handle] == nullptr) {
+  if (device_map_.find(handle) == device_map_.end()) {
     LOG(ERROR) << "Message received for unconnected device: handle="
                << loghex(handle);
     return;
diff --git a/profile/avrcp/connection_handler.h b/profile/avrcp/connection_handler.h
index 63bc8a0..e22cb6a 100644
--- a/profile/avrcp/connection_handler.h
+++ b/profile/avrcp/connection_handler.h
@@ -22,9 +22,9 @@
 #include <memory>
 
 #include "avrcp_internal.h"
-#include "avrcp_packet.h"
-#include "device.h"
-#include "packet.h"
+#include "packet/avrcp/avrcp_packet.h"
+#include "packet/base/packet.h"
+#include "profile/avrcp/device.h"
 #include "raw_address.h"
 
 namespace bluetooth {
diff --git a/profile/avrcp/device.cc b/profile/avrcp/device.cc
index 7f8ecae..4ca624b 100644
--- a/profile/avrcp/device.cc
+++ b/profile/avrcp/device.cc
@@ -13,11 +13,17 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+#include "device.h"
 
 #include <base/message_loop/message_loop.h>
 
 #include "connection_handler.h"
-#include "device.h"
+#include "packet/avrcp/avrcp_reject_packet.h"
+#include "packet/avrcp/general_reject_packet.h"
+#include "packet/avrcp/get_play_status_packet.h"
+#include "packet/avrcp/pass_through_packet.h"
+#include "packet/avrcp/set_absolute_volume.h"
+#include "packet/avrcp/set_addressed_player.h"
 #include "stack_config.h"
 
 namespace bluetooth {
@@ -52,17 +58,35 @@
   volume_interface_ = volume_interface;
 }
 
-base::WeakPtr<Device> Device::Get() { return weak_ptr_factory_.GetWeakPtr(); }
+base::WeakPtr<Device> Device::Get() {
+  return weak_ptr_factory_.GetWeakPtr();
+}
+
+void Device::SetBrowseMtu(uint16_t browse_mtu) {
+  DEVICE_LOG(INFO) << __PRETTY_FUNCTION__ << ": browse_mtu = " << browse_mtu;
+  browse_mtu_ = browse_mtu;
+}
 
 bool Device::IsActive() const {
   return address_ == a2dp_interface_->active_peer();
 }
 
+bool Device::IsInSilenceMode() const {
+  return a2dp_interface_->is_peer_in_silence_mode(address_);
+}
+
 void Device::VendorPacketHandler(uint8_t label,
                                  std::shared_ptr<VendorPacket> pkt) {
   CHECK(media_interface_);
   DEVICE_VLOG(3) << __func__ << ": pdu=" << pkt->GetCommandPdu();
 
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   // All CTypes at and above NOT_IMPLEMENTED are all response types.
   if (pkt->GetCType() == CType::NOT_IMPLEMENTED) {
     return;
@@ -108,9 +132,15 @@
     } break;
 
     case CommandPdu::GET_ELEMENT_ATTRIBUTES: {
-      media_interface_->GetSongInfo(base::Bind(
-          &Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
-          label, Packet::Specialize<GetElementAttributesRequest>(pkt)));
+      auto get_element_attributes_request_pkt = Packet::Specialize<GetElementAttributesRequest>(pkt);
+
+      if (!get_element_attributes_request_pkt->IsValid()) {
+        DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+        send_message(label, false, std::move(response));
+      }
+      media_interface_->GetSongInfo(base::Bind(&Device::GetElementAttributesResponse, weak_ptr_factory_.GetWeakPtr(),
+                                               label, get_element_attributes_request_pkt));
     } break;
 
     case CommandPdu::GET_PLAY_STATUS: {
@@ -128,9 +158,17 @@
       // this currently since the current implementation only has one
       // player and the player will never change, but we need it for a
       // more complete implementation.
-      media_interface_->GetMediaPlayerList(base::Bind(
-          &Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
-          label, Packet::Specialize<SetAddressedPlayerRequest>(pkt)));
+      auto set_addressed_player_request = Packet::Specialize<SetAddressedPlayerRequest>(pkt);
+
+      if (!set_addressed_player_request->IsValid()) {
+        DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+        auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+        send_message(label, false, std::move(response));
+        return;
+      }
+
+      media_interface_->GetMediaPlayerList(base::Bind(&Device::HandleSetAddressedPlayer, weak_ptr_factory_.GetWeakPtr(),
+                                                      label, set_addressed_player_request));
     } break;
 
     default: {
@@ -147,6 +185,13 @@
   DEVICE_VLOG(4) << __func__
                  << ": capability=" << pkt->GetCapabilityRequested();
 
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   switch (pkt->GetCapabilityRequested()) {
     case Capability::COMPANY_ID: {
       auto response =
@@ -185,7 +230,7 @@
 void Device::HandleNotification(
     uint8_t label, const std::shared_ptr<RegisterNotificationRequest>& pkt) {
   if (!pkt->IsValid()) {
-    DEVICE_LOG(ERROR) << __func__ << ": Request packet is not valid";
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
     auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(),
                                                Status::INVALID_PARAMETER);
     send_message(label, false, std::move(response));
@@ -290,6 +335,17 @@
 void Device::HandleVolumeChanged(
     uint8_t label, const std::shared_ptr<RegisterNotificationResponse>& pkt) {
   DEVICE_VLOG(1) << __func__ << ": interim=" << pkt->IsInterim();
+
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+    send_message(label, false, std::move(response));
+    active_labels_.erase(label);
+    volume_interface_ = nullptr;
+    volume_ = VOL_REGISTRATION_FAILED;
+    return;
+  }
+
   if (volume_interface_ == nullptr) return;
 
   if (pkt->GetCType() == CType::REJECTED) {
@@ -457,7 +513,7 @@
   // We still try to send updates while music is playing to the non active
   // device even though the device thinks the music is paused. This makes
   // the status bar on the remote device move.
-  if (status.state == PlayState::PLAYING) {
+  if (status.state == PlayState::PLAYING && !IsInSilenceMode()) {
     DEVICE_VLOG(0) << __func__ << ": Queue next play position update";
     play_pos_update_cb_.Reset(base::Bind(&Device::HandlePlayPosUpdate,
                                          weak_ptr_factory_.GetWeakPtr()));
@@ -529,6 +585,7 @@
     uint8_t label, std::shared_ptr<GetElementAttributesRequest> pkt,
     SongInfo info) {
   DEVICE_VLOG(2) << __func__;
+
   auto get_element_attributes_pkt = pkt;
   auto attributes_requested =
       get_element_attributes_pkt->GetAttributesRequested();
@@ -553,10 +610,15 @@
 }
 
 void Device::MessageReceived(uint8_t label, std::shared_ptr<Packet> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(4) << __func__ << ": opcode=" << pkt->GetOpcode();
-
   active_labels_.insert(label);
-
   switch (pkt->GetOpcode()) {
     // TODO (apanicke): Remove handling of UNIT_INFO and SUBUNIT_INFO from
     // the AVRC_API and instead handle it here to reduce fragmentation.
@@ -566,6 +628,14 @@
     } break;
     case Opcode::PASS_THROUGH: {
       auto pass_through_packet = Packet::Specialize<PassThroughPacket>(pkt);
+
+      if (!pass_through_packet->IsValid()) {
+        DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+        auto response = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+        send_message(label, false, std::move(response));
+        return;
+      }
+
       auto response = PassThroughPacketBuilder::MakeBuilder(
           true, pass_through_packet->GetKeyState() == KeyState::PUSHED,
           pass_through_packet->GetOperationId());
@@ -616,6 +686,13 @@
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
                  << " uid=" << pkt->GetUid();
 
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = RejectBuilder::MakeBuilder(pkt->GetCommandPdu(), Status::INVALID_PARAMETER);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   std::string media_id = "";
   switch (pkt->GetScope()) {
     case Scope::NOW_PLAYING:
@@ -663,6 +740,13 @@
 
 void Device::BrowseMessageReceived(uint8_t label,
                                    std::shared_ptr<BrowsePacket> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
+    send_message(label, false, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(1) << __func__ << ": pdu=" << pkt->GetPdu();
 
   switch (pkt->GetPdu()) {
@@ -687,8 +771,7 @@
       break;
     default:
       DEVICE_LOG(WARNING) << __func__ << ": " << pkt->GetPdu();
-      auto response = GeneralRejectBuilder::MakeBuilder(
-          BrowsePdu::GENERAL_REJECT, Status::INVALID_COMMAND);
+      auto response = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
       send_message(label, true, std::move(response));
 
       break;
@@ -697,6 +780,15 @@
 
 void Device::HandleGetFolderItems(uint8_t label,
                                   std::shared_ptr<GetFolderItemsRequest> pkt) {
+  if (!pkt->IsValid()) {
+    // The specific get folder items builder is unimportant on failure.
+    DEVICE_LOG(WARNING) << __func__ << ": Get folder items request packet is not valid";
+    auto response =
+        GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0x0000, browse_mtu_);
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
 
   switch (pkt->GetScope()) {
@@ -718,12 +810,21 @@
       break;
     default:
       DEVICE_LOG(ERROR) << __func__ << ": " << pkt->GetScope();
+      auto response = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0, browse_mtu_);
+      send_message(label, true, std::move(response));
       break;
   }
 }
 
 void Device::HandleGetTotalNumberOfItems(
     uint8_t label, std::shared_ptr<GetTotalNumberOfItemsRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0);
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope();
 
   switch (pkt->GetScope()) {
@@ -779,6 +880,13 @@
 
 void Device::HandleChangePath(uint8_t label,
                               std::shared_ptr<ChangePathRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = ChangePathResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0);
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": direction=" << pkt->GetDirection()
                  << " uid=" << loghex(pkt->GetUid());
 
@@ -829,6 +937,13 @@
 
 void Device::HandleGetItemAttributes(
     uint8_t label, std::shared_ptr<GetItemAttributesRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto builder = GetItemAttributesResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, browse_mtu_);
+    send_message(label, true, std::move(builder));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": scope=" << pkt->GetScope()
                  << " uid=" << loghex(pkt->GetUid())
                  << " uid counter=" << loghex(pkt->GetUidCounter());
@@ -839,6 +954,7 @@
     send_message(label, true, std::move(builder));
     return;
   }
+
   switch (pkt->GetScope()) {
     case Scope::NOW_PLAYING: {
       media_interface_->GetNowPlayingList(
@@ -1041,7 +1157,7 @@
       // right now we always use folders of mixed type
       FolderItem folder_item(vfs_ids_.get_uid(folder.media_id), 0x00,
                              folder.is_playable, folder.name);
-      builder->AddFolder(folder_item);
+      if (!builder->AddFolder(folder_item)) break;
     } else if (items[i].type == ListItem::SONG) {
       auto song = items[i].song;
       auto title =
@@ -1058,7 +1174,9 @@
             filter_attributes_requested(song, pkt->GetAttributesRequested());
       }
 
-      builder->AddSong(song_item);
+      // If we fail to add a song, don't accidentally add one later that might
+      // fit.
+      if (!builder->AddSong(song_item)) break;
     }
   }
 
@@ -1091,7 +1209,10 @@
       item.attributes_ =
           filter_attributes_requested(song, pkt->GetAttributesRequested());
     }
-    builder->AddSong(item);
+
+    // If we fail to add a song, don't accidentally add one later that might
+    // fit.
+    if (!builder->AddSong(item)) break;
   }
 
   send_message(label, true, std::move(builder));
@@ -1099,6 +1220,13 @@
 
 void Device::HandleSetBrowsedPlayer(
     uint8_t label, std::shared_ptr<SetBrowsedPlayerRequest> pkt) {
+  if (!pkt->IsValid()) {
+    DEVICE_LOG(WARNING) << __func__ << ": Request packet is not valid";
+    auto response = SetBrowsedPlayerResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0, 0, "");
+    send_message(label, true, std::move(response));
+    return;
+  }
+
   DEVICE_VLOG(2) << __func__ << ": player_id=" << pkt->GetPlayerId();
   media_interface_->SetBrowsedPlayer(
       pkt->GetPlayerId(),
@@ -1131,9 +1259,12 @@
 }
 
 void Device::SendMediaUpdate(bool metadata, bool play_status, bool queue) {
+  bool is_silence = IsInSilenceMode();
+
   CHECK(media_interface_);
   DEVICE_VLOG(4) << __func__ << ": Metadata=" << metadata
-                 << " : play_status= " << play_status << " : queue=" << queue;
+                 << " : play_status= " << play_status << " : queue=" << queue
+                 << " ; is_silence=" << is_silence;
 
   if (queue) {
     HandleNowPlayingUpdate();
@@ -1141,7 +1272,9 @@
 
   if (play_status) {
     HandlePlayStatusUpdate();
-    HandlePlayPosUpdate();
+    if (!is_silence) {
+      HandlePlayPosUpdate();
+    }
   }
 
   if (metadata) HandleTrackUpdate();
@@ -1284,40 +1417,29 @@
 }
 
 std::ostream& operator<<(std::ostream& out, const Device& d) {
-  out << "  " << d.address_.ToString();
+  out << d.address_.ToString();
   if (d.IsActive()) out << " <Active>";
   out << std::endl;
-  out << "    Current Volume: " << volumeToStr(d.volume_) << std::endl;
-  out << "    Current Browsed Player ID: " << d.curr_browsed_player_id_
-      << std::endl;
-  out << "    Registered Notifications: " << std::endl;
-  if (d.track_changed_.first) {
-    out << "      Track Changed" << std::endl;
-  }
-  if (d.play_status_changed_.first) {
-    out << "      Play Status" << std::endl;
-  }
-  if (d.play_pos_changed_.first) {
-    out << "      Play Position" << std::endl;
-  }
-  if (d.now_playing_changed_.first) {
-    out << "      Now Playing" << std::endl;
-  }
-  if (d.addr_player_changed_.first) {
-    out << "      Addressed Player" << std::endl;
-  }
-  if (d.avail_players_changed_.first) {
-    out << "      Available Players" << std::endl;
-  }
-  if (d.uids_changed_.first) {
-    out << "      UIDs Changed" << std::endl;
-  }
 
-  out << "    Last Play State: " << d.last_play_status_.state << std::endl;
-  out << "    Last Song Sent ID: \"" << d.last_song_info_.media_id << "\""
+  ScopedIndent indent(out);
+  out << "Current Volume: " << volumeToStr(d.volume_) << std::endl;
+  out << "Current Browsed Player ID: " << d.curr_browsed_player_id_
       << std::endl;
-  out << "    Current Folder: \"" << d.CurrentFolder() << "\"" << std::endl;
-  out << "    MTU Sizes: CTRL=" << d.ctrl_mtu_ << " BROWSE=" << d.browse_mtu_
+  out << "Registered Notifications:\n";
+  {
+    ScopedIndent indent(out);
+    if (d.track_changed_.first) out << "Track Changed\n";
+    if (d.play_status_changed_.first) out << "Play Status\n";
+    if (d.play_pos_changed_.first) out << "Play Position\n";
+    if (d.now_playing_changed_.first) out << "Now Playing\n";
+    if (d.addr_player_changed_.first) out << "Addressed Player\n";
+    if (d.avail_players_changed_.first) out << "Available Players\n";
+    if (d.uids_changed_.first) out << "UIDs Changed\n";
+  }
+  out << "Last Play State: " << d.last_play_status_.state << std::endl;
+  out << "Last Song Sent ID: \"" << d.last_song_info_.media_id << "\"\n";
+  out << "Current Folder: \"" << d.CurrentFolder() << "\"\n";
+  out << "MTU Sizes: CTRL=" << d.ctrl_mtu_ << " BROWSE=" << d.browse_mtu_
       << std::endl;
   // TODO (apanicke): Add supported features as well as media keys
   return out;
diff --git a/profile/avrcp/device.h b/profile/avrcp/device.h
index b1f3420..18bfc98 100644
--- a/profile/avrcp/device.h
+++ b/profile/avrcp/device.h
@@ -23,10 +23,22 @@
 #include <base/bind.h>
 #include <base/cancelable_callback.h>
 
-#include "avrcp.h"
 #include "avrcp_internal.h"
-#include "avrcp_packet.h"
-#include "media_id_map.h"
+#include "hardware/avrcp/avrcp.h"
+#include "packet/avrcp/avrcp_browse_packet.h"
+#include "packet/avrcp/avrcp_packet.h"
+#include "packet/avrcp/capabilities_packet.h"
+#include "packet/avrcp/change_path.h"
+#include "packet/avrcp/get_element_attributes_packet.h"
+#include "packet/avrcp/get_folder_items.h"
+#include "packet/avrcp/get_item_attributes.h"
+#include "packet/avrcp/get_total_number_of_items.h"
+#include "packet/avrcp/play_item.h"
+#include "packet/avrcp/register_notification_packet.h"
+#include "packet/avrcp/set_addressed_player.h"
+#include "packet/avrcp/set_browsed_player.h"
+#include "packet/avrcp/vendor_packet.h"
+#include "profile/avrcp/media_id_map.h"
 #include "raw_address.h"
 
 namespace bluetooth {
@@ -69,6 +81,11 @@
   bool Disconnect();
 
   /**
+   * Returns true if the current device is silenced.
+   */
+  bool IsInSilenceMode() const;
+
+  /**
    * Returns true if the current device is active.
    */
   bool IsActive() const;
@@ -85,6 +102,12 @@
                           VolumeInterface* volume_interface);
 
   /**
+   * Set the maximum size of a AVRCP Browsing Packet. This is done after the
+   * connection of the Browsing channel.
+   */
+  void SetBrowseMtu(uint16_t browse_mtu);
+
+  /**
    * Notify the device that metadata, play_status, and/or queue have updated
    * via a boolean. Each boolean represents whether its respective content has
    * updated.
diff --git a/profile/avrcp/tests/avrcp_device_test.cc b/profile/avrcp/tests/avrcp_device_test.cc
index 1a9f29a..c608da6 100644
--- a/profile/avrcp/tests/avrcp_device_test.cc
+++ b/profile/avrcp/tests/avrcp_device_test.cc
@@ -41,8 +41,8 @@
 using TestBrowsePacket = TestPacketType<BrowsePacket>;
 
 using ::testing::_;
-using ::testing::MockFunction;
 using ::testing::Mock;
+using ::testing::MockFunction;
 using ::testing::NiceMock;
 using ::testing::Return;
 using ::testing::SaveArg;
@@ -813,16 +813,24 @@
       base::Bind([](MockFunction<void(uint8_t, bool, const AvrcpResponse&)>* a,
                     uint8_t b, bool c, AvrcpResponse d) { a->Call(b, c, d); },
                  &response_cb);
-  Device device(RawAddress::kAny, true, cb, 0xFFFF, truncated_packet->size());
+
+  Device device(RawAddress::kAny, true, cb, 0xFFFF,
+                truncated_packet->size() + FolderItem::kHeaderSize() + 5);
   device.RegisterInterfaces(&interface, &a2dp_interface, nullptr);
 
   FolderInfo info0 = {"test_id0", true, "Test Folder0"};
   FolderInfo info1 = {"test_id1", true, "Test Folder1"};
-  FolderInfo info2 = {"test_id1", true, "Truncated folder"};
+  FolderInfo info2 = {"test_id2", true, "Truncated folder"};
+  // Used to ensure that adding an item that would fit in the MTU fails if
+  // adding a large item failed.
+  FolderInfo small_info = {"test_id2", true, "Small"};
+
   ListItem item0 = {ListItem::FOLDER, info0, SongInfo()};
   ListItem item1 = {ListItem::FOLDER, info1, SongInfo()};
-  ListItem item2 = {ListItem::FOLDER, info1, SongInfo()};
-  std::vector<ListItem> list0 = {item0, item1, item2};
+  ListItem item2 = {ListItem::FOLDER, info2, SongInfo()};
+  ListItem item3 = {ListItem::FOLDER, small_info, SongInfo()};
+
+  std::vector<ListItem> list0 = {item0, item1, item2, item3};
   EXPECT_CALL(interface, GetFolderItems(_, "", _))
       .WillRepeatedly(InvokeCb<2>(list0));
 
@@ -1350,6 +1358,126 @@
   SendMessage(1, reg_notif_request);
 }
 
+TEST_F(AvrcpDeviceTest, invalidVendorPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(static_cast<CommandPdu>(0), Status::INVALID_COMMAND);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_vendor_packet);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidCapabilitiesPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::GET_CAPABILITIES, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_get_capabilities_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetElementAttributesPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::GET_ELEMENT_ATTRIBUTES, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_get_element_attributes_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidPlayItemPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::PLAY_ITEM, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_play_item_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidSetAddressedPlayerPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = RejectBuilder::MakeBuilder(CommandPdu::SET_ADDRESSED_PLAYER, Status::INVALID_PARAMETER);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestAvrcpPacket::Make(short_set_addressed_player_request);
+  SendMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidBrowsePacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GeneralRejectBuilder::MakeBuilder(Status::INVALID_COMMAND);
+  EXPECT_CALL(response_cb, Call(1, false, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_browse_packet);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetFolderItemsPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GetFolderItemsResponseBuilder::MakePlayerListBuilder(Status::INVALID_PARAMETER, 0x0000, 0xFFFF);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_get_folder_items_request);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetTotalNumberOfItemsPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GetTotalNumberOfItemsResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0x0000, 0xFFFF);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_get_total_number_of_items_request);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidChangePathPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = ChangePathResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_change_path_request);
+  SendBrowseMessage(1, short_packet);
+}
+
+TEST_F(AvrcpDeviceTest, invalidGetItemAttributesPacketTest) {
+  MockMediaInterface interface;
+  NiceMock<MockA2dpInterface> a2dp_interface;
+
+  test_device->RegisterInterfaces(&interface, &a2dp_interface, nullptr);
+
+  auto rsp = GetItemAttributesResponseBuilder::MakeBuilder(Status::INVALID_PARAMETER, 0xFFFF);
+  EXPECT_CALL(response_cb, Call(1, true, matchPacket(std::move(rsp)))).Times(1);
+  auto short_packet = TestBrowsePacket::Make(short_get_item_attributes_request);
+  SendBrowseMessage(1, short_packet);
+}
+
 }  // namespace avrcp
 }  // namespace bluetooth
 
diff --git a/profile/avrcp/tests/avrcp_test_helper.h b/profile/avrcp/tests/avrcp_test_helper.h
index 16fc31f..edf3592 100644
--- a/profile/avrcp/tests/avrcp_test_helper.h
+++ b/profile/avrcp/tests/avrcp_test_helper.h
@@ -76,6 +76,7 @@
   MOCK_METHOD1(event_open, void(const RawAddress&));
   MOCK_METHOD1(event_close, void(const RawAddress&));
   MOCK_METHOD0(active_peer, RawAddress());
+  MOCK_METHOD1(is_peer_in_silence_mode, bool(const RawAddress&));
 };
 
 class MockSdpInterface : public SdpInterface {
diff --git a/profile/sdp/Android.bp b/profile/sdp/Android.bp
new file mode 100644
index 0000000..9254337
--- /dev/null
+++ b/profile/sdp/Android.bp
@@ -0,0 +1,40 @@
+cc_library_static {
+  name: "sdp_service",
+  defaults: [
+    "fluoride_defaults",
+    "clang_file_coverage"
+  ],
+  host_supported: true,
+  include_dirs: [
+    "system/bt/",
+  ],
+  srcs: [
+    "common/data_element_reader.cc",
+  ],
+  static_libs: [
+    "lib-bt-packets",
+    "libbluetooth-types",
+  ],
+}
+
+cc_test {
+  name: "bluetooth_test_sdp",
+  test_suites: ["general-tests"],
+  defaults: [
+    "fluoride_defaults",
+    "clang_coverage_bin",
+  ],
+  host_supported: true,
+  include_dirs: [
+    "system/bt/",
+  ],
+  srcs: [
+    "common/test/data_element_reader_test.cc",
+  ],
+  static_libs: [
+    "libgmock",
+    "sdp_service",
+    "lib-bt-packets",
+    "libbluetooth-types",
+  ],
+}
diff --git a/profile/sdp/common/data_element_reader.cc b/profile/sdp/common/data_element_reader.cc
new file mode 100644
index 0000000..675100f
--- /dev/null
+++ b/profile/sdp/common/data_element_reader.cc
@@ -0,0 +1,238 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "data_element_reader.h"
+
+#include <base/logging.h>
+#include <type_traits>
+
+#include "sdp_logging_helper.h"
+
+// A helper macro that can verify that there is enough data remaining in the
+// reader to extract without overflowing. end_ - it_ should never be negative
+// so casting it to a size_t is always safe. If it does fail, set it_ to end_
+// so that all additional readings fail.
+#define CHECK_REMAINING_LEN(x)                                              \
+  do {                                                                      \
+    if ((size_t)(end_ - it_) < x) {                                         \
+      LOG(WARNING) << __func__ << ": Extract would read past end of data."; \
+      return ParseFail();                                                   \
+    }                                                                       \
+  } while (0)
+
+namespace bluetooth {
+namespace sdp {
+
+DataElementReader::DataElement DataElementReader::ReadNext() {
+  if (it_ > end_) LOG(FATAL) << "Beginning of buffer is past end of buffer.";
+  if (it_ == end_) return std::monostate();
+
+  uint8_t descriptor = *it_++;
+  DataElementType type = static_cast<DataElementType>(descriptor >> 3);
+  DataElementSize size = static_cast<DataElementSize>(descriptor & 0b00000111);
+
+  // All types with a value greater than URL are currently reserved.
+  if (type > DataElementType::MAX_VALUE) {
+    LOG(WARNING) << __func__ << ": Trying to use a reserved data element type";
+    return ParseFail();
+  }
+
+  switch (type) {
+    case DataElementType::BOOLEAN:
+      if (size != DataElementSize::BYTE1) {
+        LOG(WARNING) << __func__ << ": Invalid size for bool: " << size;
+        return ParseFail();
+      }
+
+      CHECK_REMAINING_LEN(1);
+      return (it_.extract<uint8_t>() != 0);
+    case DataElementType::SIGNED_INT:
+      return ReadSignedInt(size);
+    case DataElementType::UNSIGNED_INT:
+      return ReadUnsignedInt(size);
+    case DataElementType::UUID:
+      return ReadUuid(size);
+    case DataElementType::STRING:
+      return ReadString(size);
+    case DataElementType::DATA_ELEMENT_SEQUENCE:
+      return ReadSequence(size);
+    default:
+      // TODO: The other data element types are never used in the previous SDP
+      // implementation. We should properly handle them in the future though
+      // for completeness.
+      LOG(ERROR) << __func__ << ": Unhandled Data Element Type: " << type;
+  }
+
+  return ParseFail();
+}
+
+DataElementReader::DataElement DataElementReader::ParseFail() {
+  it_ = end_;
+  return std::monostate();
+}
+
+template <class IntegerType>
+DataElementReader::DataElement DataElementReader::ReadInteger() {
+  static_assert(std::is_integral<IntegerType>::value,
+                "ReadInteger requires an integral type.");
+
+  CHECK_REMAINING_LEN(sizeof(IntegerType));
+  return it_.extractBE<IntegerType>();
+}
+
+DataElementReader::DataElement DataElementReader::ReadLargeInt() {
+  CHECK_REMAINING_LEN(16);
+
+  std::array<uint8_t, 16> array;
+  for (size_t i = 0; i < sizeof(uint8_t[16]); i++) {
+    array[i] = it_.extract<uint8_t>();
+  }
+
+  return array;
+}
+
+DataElementReader::DataElement DataElementReader::ReadSignedInt(
+    DataElementSize size) {
+  switch (size) {
+    case DataElementSize::BYTE1:
+      return ReadInteger<int8_t>();
+    case DataElementSize::BYTE2:
+      return ReadInteger<int16_t>();
+    case DataElementSize::BYTE4:
+      return ReadInteger<int32_t>();
+    case DataElementSize::BYTE8:
+      return ReadInteger<int64_t>();
+    case DataElementSize::BYTE16:
+      return ReadLargeInt();
+    default:
+      LOG(WARNING) << __func__ << ": Invalid size for int: " << size;
+  }
+
+  return ParseFail();
+}
+
+DataElementReader::DataElement DataElementReader::ReadUnsignedInt(
+    DataElementSize size) {
+  switch (size) {
+    case DataElementSize::BYTE1:
+      return ReadInteger<uint8_t>();
+    case DataElementSize::BYTE2:
+      return ReadInteger<uint16_t>();
+    case DataElementSize::BYTE4:
+      return ReadInteger<uint32_t>();
+    case DataElementSize::BYTE8:
+      return ReadInteger<uint64_t>();
+    case DataElementSize::BYTE16:
+      return ReadLargeInt();
+    default:
+      LOG(WARNING) << __func__ << ": Invalid size for uint: " << size;
+  }
+
+  return ParseFail();
+}
+
+DataElementReader::DataElement DataElementReader::ReadUuid(
+    DataElementSize size) {
+  if (size == DataElementSize::BYTE2) {
+    CHECK_REMAINING_LEN(2);
+    return Uuid::From16Bit(it_.extractBE<uint16_t>());
+  }
+
+  if (size == DataElementSize::BYTE4) {
+    CHECK_REMAINING_LEN(4);
+    return Uuid::From32Bit(it_.extractBE<uint32_t>());
+  }
+
+  if (size == DataElementSize::BYTE16) {
+    CHECK_REMAINING_LEN(16);
+
+    Uuid::UUID128Bit uuid_array;
+    for (int i = 0; i < 16; i++) {
+      uuid_array[i] = it_.extract<uint8_t>();
+    }
+
+    return Uuid::From128BitBE(uuid_array);
+  }
+
+  LOG(WARNING) << __func__ << ": Invalid size for UUID: " << size;
+  return ParseFail();
+}
+
+DataElementReader::DataElement DataElementReader::ReadString(
+    DataElementSize size) {
+  uint32_t num_bytes = 0;
+
+  switch (size) {
+    case DataElementSize::ADDITIONAL_8BIT:
+      CHECK_REMAINING_LEN(1);
+      num_bytes = it_.extractBE<uint8_t>();
+      break;
+    case DataElementSize::ADDITIONAL_16BIT:
+      CHECK_REMAINING_LEN(2);
+      num_bytes = it_.extractBE<uint16_t>();
+      break;
+    case DataElementSize::ADDITIONAL_32BIT:
+      CHECK_REMAINING_LEN(4);
+      num_bytes = it_.extractBE<uint32_t>();
+      break;
+    default:
+      LOG(WARNING) << __func__ << ": Invalid size for string: " << size;
+      return ParseFail();
+  }
+
+  CHECK_REMAINING_LEN(num_bytes);
+
+  std::string str;
+  for (uint32_t i = 0; i < num_bytes; i++) {
+    str.push_back(it_.extractBE<uint8_t>());
+  }
+
+  return str;
+}
+
+DataElementReader::DataElement DataElementReader::ReadSequence(
+    DataElementSize size) {
+  uint32_t num_bytes = 0;
+
+  switch (size) {
+    case DataElementSize::ADDITIONAL_8BIT:
+      CHECK_REMAINING_LEN(1);
+      num_bytes = it_.extractBE<uint8_t>();
+      break;
+    case DataElementSize::ADDITIONAL_16BIT:
+      CHECK_REMAINING_LEN(2);
+      num_bytes = it_.extractBE<uint16_t>();
+      break;
+    case DataElementSize::ADDITIONAL_32BIT:
+      CHECK_REMAINING_LEN(4);
+      num_bytes = it_.extractBE<uint32_t>();
+      break;
+    default:
+      LOG(WARNING) << __func__ << ": Invalid size for string: " << size;
+      return ParseFail();
+  }
+
+  CHECK_REMAINING_LEN(num_bytes);
+
+  // Create a parser that points to the beginning of the next sequence and move
+  // the iterator to past the end of the new sequence.
+  auto&& temp = DataElementReader(it_, it_ + num_bytes);
+  it_ += num_bytes;
+  return std::move(temp);
+}
+
+}  // namespace sdp
+}  // namespace bluetooth
diff --git a/profile/sdp/common/data_element_reader.h b/profile/sdp/common/data_element_reader.h
new file mode 100644
index 0000000..13346bd
--- /dev/null
+++ b/profile/sdp/common/data_element_reader.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <array>
+#include <variant>
+
+#include "bluetooth/uuid.h"
+#include "packet.h"
+#include "sdp_common.h"
+#include "stack/include/bt_types.h"
+
+namespace bluetooth {
+namespace sdp {
+
+// A helper class that helps extract data element objects from SDP packets.
+class DataElementReader {
+ public:
+  // If the DataElement contains monostate, that means parsing has failed.
+  using DataElement =
+      std::variant<std::monostate, bool, int8_t, int16_t, int32_t, int64_t,
+                   uint8_t, uint16_t, uint32_t, uint64_t, Octet16, Uuid,
+                   std::string, DataElementReader>;
+
+  DataElementReader(Iterator begin, Iterator end) : it_(begin), end_(end){};
+
+  // Get the next Data Element in the data. If reading fails for any reason,
+  // the DataElementReader becomes invalid and will continuously fail to read
+  // from that point onward.
+  DataElement ReadNext();
+
+ private:
+  // Extraction Helpers
+  DataElement ParseFail();
+  template <class IntegerType>
+  DataElement ReadInteger();
+  DataElement ReadLargeInt();
+
+  // Extraction Functions
+  DataElement ReadSignedInt(DataElementSize size);
+  DataElement ReadUnsignedInt(DataElementSize size);
+  DataElement ReadUuid(DataElementSize size);
+  DataElement ReadString(DataElementSize size);
+  DataElement ReadSequence(DataElementSize size);
+
+  Iterator it_;
+  Iterator end_;
+};
+
+}  // namespace sdp
+}  // namespace bluetooth
diff --git a/profile/sdp/common/test/data_element_reader_test.cc b/profile/sdp/common/test/data_element_reader_test.cc
new file mode 100644
index 0000000..9361ac7
--- /dev/null
+++ b/profile/sdp/common/test/data_element_reader_test.cc
@@ -0,0 +1,412 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <base/logging.h>
+#include <gtest/gtest.h>
+
+#include "common/data_element_reader.h"
+
+namespace bluetooth {
+namespace sdp {
+
+using namespace testing;
+using DataElement = DataElementReader::DataElement;
+
+// A helper class to help work with the Data Element classes.
+class ReaderPacket : public ::bluetooth::Packet {
+ public:
+  using Packet::Packet;
+
+  static std::shared_ptr<ReaderPacket> Make(std::vector<uint8_t> payload) {
+    auto pkt = std::shared_ptr<ReaderPacket>(new ReaderPacket());
+    pkt->packet_start_index_ = 0;
+    pkt->packet_end_index_ = payload.size();
+    pkt->data_ = std::make_shared<std::vector<uint8_t>>(std::move(payload));
+    return pkt;
+  }
+
+  std::string ToString() const override { return ""; }
+  bool IsValid() const override { return true; }
+  std::pair<size_t, size_t> GetPayloadIndecies() const override {
+    return std::pair<size_t, size_t>(packet_start_index_, packet_end_index_);
+  }
+};
+
+bool operator!=(DataElementReader a, DataElementReader b);
+
+// A helper function to help compare DataElementReader objects.
+bool operator==(DataElementReader a, DataElementReader b) {
+  while (true) {
+    DataElement a_elem = a.ReadNext();
+    DataElement b_elem = b.ReadNext();
+
+    if (a_elem != b_elem) return false;
+
+    // If we get here that means both a and b have reached the end.
+    if (a_elem == DataElement(std::monostate())) break;
+  }
+
+  return true;
+}
+
+bool operator!=(DataElementReader a, DataElementReader b) { return !(a == b); }
+
+// A helper function to convert a type and a size to a descriptor byte.
+constexpr uint8_t Desc(DataElementType t, DataElementSize s) {
+  return static_cast<uint8_t>(t) << 3 | static_cast<uint8_t>(s);
+}
+
+// Helper that can create a Data Element reader from a vector.
+DataElementReader CreateReader(std::vector<uint8_t> payload) {
+  auto packet = ReaderPacket::Make(std::move(payload));
+  return DataElementReader(packet->begin(), packet->end());
+}
+
+// Test all the valid cases of reading the next Data Element.
+using ValidTestParam = std::tuple<std::vector<uint8_t>, DataElement>;
+class ValidReadTest : public TestWithParam<ValidTestParam> {};
+
+std::vector<ValidTestParam> valid_values = {
+    // Boolean Tests
+    ValidTestParam{
+        {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01},
+        true,
+    },
+    ValidTestParam{
+        {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
+        false,
+    },
+
+    // Signed Integer Tests
+    ValidTestParam{
+        {Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE1), 0xFF},
+        static_cast<int8_t>(-1)},
+    ValidTestParam{
+        {Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0xFF, 0xFF},
+        static_cast<int16_t>(-1)},
+    ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE4),
+                    0xFF, 0xFF, 0xFF, 0xFF},
+                   static_cast<int32_t>(-1)},
+    ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE8),
+                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+                   static_cast<int64_t>(-1)},
+    ValidTestParam{{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE16),
+                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
+                   std::array<uint8_t, 16>{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                                           0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                                           0xFF, 0xFF, 0xFF, 0xFF}},
+
+    // Unsigned Integer Tests
+    ValidTestParam{
+        {Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE1), 0x01},
+        static_cast<uint8_t>(1)},
+    ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE2),
+                    0x00, 0x01},
+                   static_cast<uint16_t>(1)},
+    ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE4),
+                    0x00, 0x00, 0x00, 0x01},
+                   static_cast<uint32_t>(1)},
+    ValidTestParam{{Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE8),
+                    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+                   static_cast<uint64_t>(1)},
+    ValidTestParam{
+        {Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE16), 0x00,
+         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+         0x00, 0x00, 0x01},
+        std::array<uint8_t, 16>{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                                0x01}},
+
+    // UUID Tests
+    ValidTestParam{
+        {Desc(DataElementType::UUID, DataElementSize::BYTE2), 0x01, 0x02},
+        Uuid::From16Bit(0x0102)},
+    ValidTestParam{{Desc(DataElementType::UUID, DataElementSize::BYTE4), 0x01,
+                    0x02, 0x03, 0x04},
+                   Uuid::From32Bit(0x01020304)},
+    ValidTestParam{
+        {Desc(DataElementType::UUID, DataElementSize::BYTE16), 0x00, 0x01, 0x02,
+         0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
+         0x0F},
+        Uuid::From128BitBE({0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+                            0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F})},
+
+    // String Tests
+    ValidTestParam{
+        {Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT), 0x05,
+         'T', 'e', 's', 't', '1'},
+        std::string("Test1")},
+    ValidTestParam{
+        {Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_16BIT), 0x00,
+         0x05, 'T', 'e', 's', 't', '2'},
+        std::string("Test2")},
+    ValidTestParam{
+        {Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_32BIT), 0x00,
+         0x00, 0x00, 0x05, 'T', 'e', 's', 't', '3'},
+        std::string("Test3")},
+
+    // Nested Data Element List Tests
+    ValidTestParam{
+        {Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+              DataElementSize::ADDITIONAL_8BIT),
+         0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
+         Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
+        CreateReader(
+            {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
+             Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})},
+    ValidTestParam{
+        {Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+              DataElementSize::ADDITIONAL_16BIT),
+         0x00, 0x04, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1),
+         0x01, Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
+        CreateReader(
+            {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
+             Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})},
+    ValidTestParam{
+        {Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+              DataElementSize::ADDITIONAL_32BIT),
+         0x00, 0x00, 0x00, 0x04,
+         Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
+         Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00},
+        CreateReader(
+            {Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
+             Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00})},
+};
+
+INSTANTIATE_TEST_CASE_P(ReadNext, ValidReadTest, ValuesIn(valid_values));
+TEST_P(ValidReadTest, Test) {
+  auto packet = ReaderPacket::Make(std::get<0>(GetParam()));
+  auto value = std::get<1>(GetParam());
+
+  DataElementReader reader(packet->begin(), packet->end());
+  auto read_value = reader.ReadNext();
+
+  ASSERT_EQ(value, read_value);
+
+  // Test that there is no additional data to read.
+  ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
+}
+
+// Test that a nested reader is correctly bounded and can't read past its
+// defined end.
+TEST(ReadNext, BoundedSubreaderTest) {
+  std::vector<uint8_t> payload = {
+      // Subsequence descriptor byte.
+      Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+           DataElementSize::ADDITIONAL_8BIT),
+      // Subsequence length.
+      0x04,
+      // Subsequence that contains two booleans with values true and false.
+      Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x01,
+      Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1), 0x00,
+      // Additional int16 at the end of the original sequence.
+      Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2), 0x01, 0x23};
+
+  auto packet = ReaderPacket::Make(payload);
+  DataElementReader reader(packet->begin(), packet->end());
+
+  // The first thing read should be the subsequence.
+  auto data_element = reader.ReadNext();
+  ASSERT_TRUE(std::holds_alternative<DataElementReader>(data_element));
+
+  // Check that the subsequence matches the premade sequence.
+  auto subreader = std::get<DataElementReader>(data_element);
+  data_element = subreader.ReadNext();
+  ASSERT_TRUE(std::holds_alternative<bool>(data_element));
+  ASSERT_TRUE(std::get<bool>(data_element));
+  data_element = subreader.ReadNext();
+  ASSERT_TRUE(std::holds_alternative<bool>(data_element));
+  ASSERT_FALSE(std::get<bool>(data_element));
+
+  // Check that there is no additional data to be read from the subreader.
+  ASSERT_EQ(subreader.ReadNext(), DataElement(std::monostate()));
+
+  // Check that we can still read the int16 from the original reader.
+  data_element = reader.ReadNext();
+  ASSERT_TRUE(std::holds_alternative<int16_t>(data_element));
+  auto int16_value = std::get<int16_t>(data_element);
+  ASSERT_EQ(int16_value, 0x0123);
+
+  // Check that there is no additional data to be read from the base reader.
+  ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
+}
+
+// Test that trying to read an empty packet fails.
+TEST(ReadNext, NoDataTest) {
+  auto packet = ReaderPacket::Make({});
+  DataElementReader reader(packet->begin(), packet->end());
+
+  ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
+}
+
+// Test that using a reserved value for type fails.
+TEST(ReadNext, InvalidTypeTest) {
+  auto packet = ReaderPacket::Make({0xFF});
+  DataElementReader reader(packet->begin(), packet->end());
+
+  ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
+}
+
+// Test all invalid parses due to incorrect lengths or invalid sizes. All tests
+// should return std::monostate.
+using InvalidTestParam = std::vector<uint8_t>;
+class InvalidReadTest : public TestWithParam<InvalidTestParam> {};
+
+std::vector<InvalidTestParam> invalid_values = {
+    // Boolean Tests:
+    //   Invalid size field.
+    InvalidTestParam{
+        Desc(DataElementType::BOOLEAN, DataElementSize::BYTE2),
+    },
+    //   Insufficient data.
+    InvalidTestParam{Desc(DataElementType::BOOLEAN, DataElementSize::BYTE1)},
+
+    // Signed Integer Tests:
+    //   Invalid size field.
+    InvalidTestParam{
+        Desc(DataElementType::SIGNED_INT, DataElementSize::ADDITIONAL_8BIT)},
+    //   1 byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE1)},
+    //   2 byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE2),
+                     0x00},
+    //   4 byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE4),
+                     0x00, 0x00, 0x00},
+    //  8 Byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE8),
+                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+    //  16 Byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::SIGNED_INT, DataElementSize::BYTE16),
+                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x00, 0x00},
+
+    // Unsigned Integer Tests:
+    //   Invalid size field.
+    InvalidTestParam{
+        Desc(DataElementType::UNSIGNED_INT, DataElementSize::ADDITIONAL_8BIT)},
+    //   1 byte insufficient data.
+    InvalidTestParam{
+        Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE1)},
+    //   2 byte insufficient data.
+    InvalidTestParam{
+        Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE2), 0x00},
+    //   4 byte insufficient data.
+    InvalidTestParam{
+        Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE4), 0x00, 0x00,
+        0x00},
+    //  8 Byte insufficient data.
+    InvalidTestParam{
+        Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE8), 0x00, 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00},
+    //  16 Byte insufficient data.
+    InvalidTestParam{
+        Desc(DataElementType::UNSIGNED_INT, DataElementSize::BYTE16), 0x00,
+        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+
+    // UUID Tests:
+    //   Invalid size field.
+    InvalidTestParam{
+        Desc(DataElementType::UUID, DataElementSize::ADDITIONAL_8BIT)},
+    //   2 byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE2), 0x00},
+    //   4 byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE4), 0x00,
+                     0x00, 0x00},
+    //  16 Byte insufficient data.
+    InvalidTestParam{Desc(DataElementType::UUID, DataElementSize::BYTE16), 0x00,
+                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                     0x00, 0x00},
+
+    // String Tests:
+    //   Invalid size field.
+    InvalidTestParam{Desc(DataElementType::STRING, DataElementSize::BYTE1)},
+    //   Insufficient data for additional 8 bits len.
+    InvalidTestParam{
+        Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT)},
+    //   Insufficient data for additional 16 bits len.
+    InvalidTestParam{
+        Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_16BIT),
+        0x00,
+    },
+    //   Insufficient data for additional 32 bit len.
+    InvalidTestParam{
+        Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_32BIT),
+        0x00,
+        0x00,
+        0x00,
+    },
+    //   Insufficient data for reported length.
+    InvalidTestParam{
+        Desc(DataElementType::STRING, DataElementSize::ADDITIONAL_8BIT), 0x04,
+        '1', '2', '3'},
+
+    // Nested Data Element List Tests:
+    //   Invalid size field.
+    InvalidTestParam{
+        Desc(DataElementType::DATA_ELEMENT_SEQUENCE, DataElementSize::BYTE1)},
+    //   Insufficient data for additional 8 bits len.
+    InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+                          DataElementSize::ADDITIONAL_8BIT)},
+    //   Insufficient data for additional 16 bits len.
+    InvalidTestParam{
+        Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+             DataElementSize::ADDITIONAL_16BIT),
+        0x00,
+    },
+    //   Insufficient data for additional 32 bit len.
+    InvalidTestParam{
+        Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+             DataElementSize::ADDITIONAL_32BIT),
+        0x00,
+        0x00,
+        0x00,
+    },
+    //   Insufficient data for reported length.
+    InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_SEQUENCE,
+                          DataElementSize::ADDITIONAL_8BIT),
+                     0x04, 0x00, 0x00, 0x00},
+
+    // Unhandled Data Element Types Tests:
+    // NOTE: These tests should go away as we begin to handle the types.
+    //   Nil Type.
+    InvalidTestParam{Desc(DataElementType::NIL, DataElementSize::BYTE1)},
+    //   Data Element Alternative List Type.
+    InvalidTestParam{Desc(DataElementType::DATA_ELEMENT_ALTERNATIVE,
+                          DataElementSize::ADDITIONAL_8BIT),
+                     0x00},
+    //   URL Type.
+    InvalidTestParam{
+        Desc(DataElementType::URL, DataElementSize::ADDITIONAL_8BIT), 0x00}};
+
+INSTANTIATE_TEST_CASE_P(ReadNext, InvalidReadTest, ValuesIn(invalid_values));
+TEST_P(InvalidReadTest, Test) {
+  auto packet = ReaderPacket::Make(GetParam());
+  DataElementReader reader(packet->begin(), packet->end());
+
+  ASSERT_EQ(reader.ReadNext(), DataElement(std::monostate()));
+}
+
+// Test that trying to read from a reader with start > end crashes.
+TEST(DataElementReader, BadBoundsDeathTest) {
+  auto packet = ReaderPacket::Make({0x00, 0x00, 0x00, 0x00});
+  DataElementReader reader(packet->end(), packet->begin());
+  ASSERT_DEATH(reader.ReadNext(), "Beginning of buffer is past end of buffer.");
+}
+
+}  // namespace sdp
+}  // namespace bluetooth
diff --git a/profile/sdp/sdp_common.h b/profile/sdp/sdp_common.h
new file mode 100644
index 0000000..4a07a63
--- /dev/null
+++ b/profile/sdp/sdp_common.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+namespace bluetooth {
+namespace sdp {
+
+enum class PduId : uint8_t {
+  RESERVED = 0x00,
+  ERROR = 0x01,
+  SERVICE_SEARCH_REQUEST = 0x02,
+  SERVICE_SEARCH_RESPONSE = 0x03,
+  SERVICE_ATTRIBUTE_REQUEST = 0x04,
+  SERVICE_ATTRIBUTE_RESPONSE = 0x05,
+  SERVICE_SEARCH_ATTRIBUTE_REQUEST = 0x06,
+  SERVICE_SEARCH_ATTRIBUTE_RESPONSE = 0x07,
+  MAX_VALUE = 0x07,
+};
+
+enum class AttributeId : uint16_t {
+  SERVICE_RECORD_HANDLE = 0x0000,
+  SERVICE_CLASS_ID_LIST = 0x0001,
+  SERVICE_RECORD_STATE = 0x0002,
+  SERVICE_ID = 0x0003,
+  PROTOCOL_DESCRIPTOR_LIST = 0x0004,
+  BROWSE_GROUP_LIST = 0x0005,
+  LANGUAGE_BASE_ATTRIBUTE_ID_LIST = 0x0006,
+  SERVICE_INFO_TIME_TO_LIVE = 0x0007,
+  SERVICE_AVAILABILITY = 0x0008,
+  PROFILE_DESCRIPTOR_LIST = 0x0009,
+  DOCUMENTATION_URL = 0x000A,
+  CLIENT_EXECUTABLE_URL = 0x000B,
+  ICON_URL = 0x000C,
+  ADDITIONAL_PROTOCOL_DESCRIPTOR_LIST = 0x000D,
+
+  // The following attributes are only used in the SDP server service record.
+  // They are only valid if ServiceDiscoveryServerServiceClassID is in the
+  // ServiceClassIDList. See Bluetooth Core v5.0 Section 5.2.
+  VERSION_NUMBER_LIST = 0x0200,
+  SERVICE_DATABASE_STATE = 0x0201,
+};
+
+// The Attribute ID's of these attributes are calculated by adding the offset
+// value for the attribute to the attribute ID base (contained in the
+// LanguageBaseAttributeIDList attribute value).
+enum AttributeIdOffset : uint16_t {
+  SERVICE_NAME = 0x0000,
+  SERVICE_DESCRIPTION = 0x0001,
+  PROVIDER_NAME = 0x0002,
+};
+
+// Constant that define the different types of data element.
+enum class DataElementType : uint8_t {
+  NIL = 0x00,
+  UNSIGNED_INT = 0x01,
+  SIGNED_INT = 0x02,
+  UUID = 0x03,
+  STRING = 0x04,
+  BOOLEAN = 0x05,
+  DATA_ELEMENT_SEQUENCE = 0x06,
+  DATA_ELEMENT_ALTERNATIVE = 0x07,
+  URL = 0x08,
+  MAX_VALUE = 0x08,
+};
+
+// Constant that define the different sizes of data element.
+enum class DataElementSize : uint8_t {
+  BYTE1 = 0x0,  // Exception: If the data element is NIL then size is 0 bytes
+  BYTE2 = 0x1,
+  BYTE4 = 0x2,
+  BYTE8 = 0x3,
+  BYTE16 = 0x4,
+  // The size types below represent that the first X bits of the value
+  // represents the size of the remaining data.
+  ADDITIONAL_8BIT = 0x5,
+  ADDITIONAL_16BIT = 0x6,
+  ADDITIONAL_32BIT = 0x7,
+};
+
+}  // namespace sdp
+}  // namespace bluetooth
diff --git a/profile/sdp/sdp_logging_helper.h b/profile/sdp/sdp_logging_helper.h
new file mode 100644
index 0000000..e947329
--- /dev/null
+++ b/profile/sdp/sdp_logging_helper.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <iomanip>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <type_traits>
+
+#include "bt_trace.h"
+#include "sdp_common.h"
+
+namespace bluetooth {
+namespace sdp {
+
+#ifndef CASE_RETURN_TEXT
+#define CASE_RETURN_TEXT(code) \
+  case code:                   \
+    return #code
+#endif
+
+inline std::string PduIdText(const PduId& id) {
+  switch (id) {
+    CASE_RETURN_TEXT(PduId::RESERVED);
+    CASE_RETURN_TEXT(PduId::ERROR);
+    CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_REQUEST);
+    CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_RESPONSE);
+    CASE_RETURN_TEXT(PduId::SERVICE_ATTRIBUTE_REQUEST);
+    CASE_RETURN_TEXT(PduId::SERVICE_ATTRIBUTE_RESPONSE);
+    CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_ATTRIBUTE_REQUEST);
+    CASE_RETURN_TEXT(PduId::SERVICE_SEARCH_ATTRIBUTE_RESPONSE);
+    default:
+      return "Unknown PduId: " + loghex((uint8_t)id);
+  }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const PduId& id) {
+  return os << PduIdText(id);
+}
+
+inline std::string AttributeIdText(const AttributeId& id) {
+  switch (id) {
+    CASE_RETURN_TEXT(AttributeId::SERVICE_RECORD_HANDLE);
+    CASE_RETURN_TEXT(AttributeId::SERVICE_CLASS_ID_LIST);
+    CASE_RETURN_TEXT(AttributeId::SERVICE_RECORD_STATE);
+    CASE_RETURN_TEXT(AttributeId::SERVICE_ID);
+    CASE_RETURN_TEXT(AttributeId::PROTOCOL_DESCRIPTOR_LIST);
+    CASE_RETURN_TEXT(AttributeId::BROWSE_GROUP_LIST);
+    CASE_RETURN_TEXT(AttributeId::LANGUAGE_BASE_ATTRIBUTE_ID_LIST);
+    CASE_RETURN_TEXT(AttributeId::SERVICE_INFO_TIME_TO_LIVE);
+    CASE_RETURN_TEXT(AttributeId::SERVICE_AVAILABILITY);
+    CASE_RETURN_TEXT(AttributeId::PROFILE_DESCRIPTOR_LIST);
+    CASE_RETURN_TEXT(AttributeId::DOCUMENTATION_URL);
+    CASE_RETURN_TEXT(AttributeId::CLIENT_EXECUTABLE_URL);
+    CASE_RETURN_TEXT(AttributeId::ICON_URL);
+    CASE_RETURN_TEXT(AttributeId::ADDITIONAL_PROTOCOL_DESCRIPTOR_LIST);
+    CASE_RETURN_TEXT(AttributeId::VERSION_NUMBER_LIST);
+    CASE_RETURN_TEXT(AttributeId::SERVICE_DATABASE_STATE);
+    default:
+      return "Unknown AttributeId: " + loghex((uint16_t)id);
+  }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const AttributeId& id) {
+  return os << AttributeIdText(id);
+}
+
+inline std::string DataElementTypeText(const DataElementType& type) {
+  switch (type) {
+    CASE_RETURN_TEXT(DataElementType::NIL);
+    CASE_RETURN_TEXT(DataElementType::UNSIGNED_INT);
+    CASE_RETURN_TEXT(DataElementType::SIGNED_INT);
+    CASE_RETURN_TEXT(DataElementType::UUID);
+    CASE_RETURN_TEXT(DataElementType::STRING);
+    CASE_RETURN_TEXT(DataElementType::BOOLEAN);
+    CASE_RETURN_TEXT(DataElementType::DATA_ELEMENT_SEQUENCE);
+    CASE_RETURN_TEXT(DataElementType::DATA_ELEMENT_ALTERNATIVE);
+    CASE_RETURN_TEXT(DataElementType::URL);
+    default:
+      return "Unknown DataElementType: " + loghex((uint8_t)type);
+  }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const DataElementType& type) {
+  return os << DataElementTypeText(type);
+}
+
+inline std::string DataElementSizeText(const DataElementSize& size) {
+  switch (size) {
+    CASE_RETURN_TEXT(DataElementSize::BYTE1);
+    CASE_RETURN_TEXT(DataElementSize::BYTE2);
+    CASE_RETURN_TEXT(DataElementSize::BYTE4);
+    CASE_RETURN_TEXT(DataElementSize::BYTE8);
+    CASE_RETURN_TEXT(DataElementSize::BYTE16);
+    CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_8BIT);
+    CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_16BIT);
+    CASE_RETURN_TEXT(DataElementSize::ADDITIONAL_32BIT);
+    default:
+      return "Unknown DataElementSize: " + loghex((uint8_t)size);
+  }
+}
+
+inline std::ostream& operator<<(std::ostream& os, const DataElementSize& size) {
+  return os << DataElementSizeText(size);
+}
+
+}  // namespace sdp
+}  // namespace bluetooth
diff --git a/service/Android.bp b/service/Android.bp
index d24e0fa..d57119a 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -14,11 +14,17 @@
 // Source variables
 // ========================================================
 btserviceDaemonSrc = [
+    "a2dp_sink.cc",
+    "a2dp_source.cc",
     "adapter.cc",
+    "avrcp_control.cc",
+    "avrcp_target.cc",
     "daemon.cc",
     "gatt_client.cc",
     "gatt_server.cc",
     "gatt_server_old.cc",
+    "hal/bluetooth_av_interface.cc",
+    "hal/bluetooth_avrcp_interface.cc",
     "hal/bluetooth_gatt_interface.cc",
     "hal/bluetooth_interface.cc",
     "ipc/ipc_handler.cc",
@@ -36,6 +42,10 @@
 ]
 
 btserviceBinderDaemonSrc = [
+    "ipc/binder/bluetooth_a2dp_sink_binder_server.cc",
+    "ipc/binder/bluetooth_a2dp_source_binder_server.cc",
+    "ipc/binder/bluetooth_avrcp_control_binder_server.cc",
+    "ipc/binder/bluetooth_avrcp_target_binder_server.cc",
     "ipc/binder/bluetooth_binder_server.cc",
     "ipc/binder/bluetooth_gatt_client_binder_server.cc",
     "ipc/binder/bluetooth_gatt_server_binder_server.cc",
@@ -49,8 +59,10 @@
 // Main unit test sources. These get built for host and target.
 // ========================================================
 btserviceBaseTestSrc = [
+    "hal/fake_bluetooth_av_interface.cc",
     "hal/fake_bluetooth_gatt_interface.cc",
     "hal/fake_bluetooth_interface.cc",
+    "test/a2dp_sink_unittest.cc",
     "test/adapter_unittest.cc",
     "test/advertise_data_unittest.cc",
     "test/fake_hal_util.cc",
@@ -79,6 +91,7 @@
     ],
 
     shared_libs: [
+        "libchrome",
         "libbinder",
         "libcutils",
         "liblog",
@@ -109,7 +122,12 @@
         "libgmock",
         "liblog",
         "libbluetooth-types",
+        "libutils",
     ],
+    shared_libs: [
+        "libchrome",
+    ],
+
     host_supported: true,
     target: {
         // This includes Binder related tests that can only be run
@@ -124,7 +142,6 @@
             ],
             shared_libs: [
                 "libbinder",
-                "libutils",
             ],
         },
         host: {
diff --git a/service/AndroidTest.xml b/service/AndroidTest.xml
deleted file mode 100644
index 0beba75..0000000
--- a/service/AndroidTest.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2017 The Android Open Source Project
-
-     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.
--->
-<configuration description="Config for bluetoothtbd_test">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="bluetoothtbd_test->/data/local/tmp/bluetoothtbd_test" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="bluetoothtbd_test" />
-    </test>
-</configuration>
\ No newline at end of file
diff --git a/service/BUILD.gn b/service/BUILD.gn
index 2fb94b5..59acb16 100644
--- a/service/BUILD.gn
+++ b/service/BUILD.gn
@@ -16,12 +16,21 @@
 
 source_set("service") {
   sources = [
+    "a2dp_sink.cc",
+    "a2dp_source.cc",
     "adapter.cc",
+    "avrcp_control.cc",
+    "avrcp_target.cc",
+    "common/bluetooth/a2dp_codec_config.cc",
     "common/bluetooth/adapter_state.cc",
     "common/bluetooth/advertise_data.cc",
     "common/bluetooth/advertise_settings.cc",
+    "common/bluetooth/avrcp_int_value.cc",
+    "common/bluetooth/avrcp_media_attr.cc",
+    "common/bluetooth/avrcp_register_notification_response.cc",
     "common/bluetooth/characteristic.cc",
     "common/bluetooth/descriptor.cc",
+    "common/bluetooth/remote_device_props.cc",
     "common/bluetooth/scan_filter.cc",
     "common/bluetooth/scan_result.cc",
     "common/bluetooth/scan_settings.cc",
@@ -35,6 +44,8 @@
     "hal/bluetooth_interface.cc",
     "ipc/dbus/bluetooth_adapter.cc",
     "ipc/dbus/ipc_handler_dbus.cc",
+    "hal/bluetooth_av_interface.cc",
+    "hal/bluetooth_avrcp_interface.cc",
     "hal/fake_bluetooth_gatt_interface.cc",
     "hal/fake_bluetooth_interface.cc",
     "ipc/ipc_handler.cc",
@@ -50,6 +61,7 @@
 
   include_dirs = [
     "//",
+    "//linux_include",
     "//include",
     "//service/common",
     "//third_party/modp_b64/modp64",
@@ -57,6 +69,7 @@
 
   deps = [
     "//types",
+    "//osi",
     "//third_party/libchrome:base",
   ]
 }
diff --git a/service/a2dp_sink.cc b/service/a2dp_sink.cc
new file mode 100644
index 0000000..4d59c7c
--- /dev/null
+++ b/service/a2dp_sink.cc
@@ -0,0 +1,154 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/a2dp_sink.h"
+
+#include <base/logging.h>
+#include <base/memory/ptr_util.h>
+
+#include "service/logging_helpers.h"
+
+using bluetooth::hal::BluetoothAvInterface;
+
+namespace bluetooth {
+
+// static
+const int A2dpSink::kSingletonInstanceId = 0;
+
+A2dpSink::A2dpSink(const Uuid& uuid) : app_identifier_(uuid) {
+  hal::BluetoothAvInterface::Get()->AddA2dpSinkObserver(this);
+}
+
+A2dpSink::~A2dpSink() {
+  hal::BluetoothAvInterface::Get()->RemoveA2dpSinkObserver(this);
+}
+
+const Uuid& A2dpSink::GetAppIdentifier() const { return app_identifier_; }
+
+int A2dpSink::GetInstanceId() const { return kSingletonInstanceId; }
+
+void A2dpSink::SetDelegate(Delegate* delegate) {
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  delegate_ = delegate;
+}
+
+bool A2dpSink::Enable() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  return hal::BluetoothAvInterface::Get()->A2dpSinkEnable();
+}
+
+void A2dpSink::Disable() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  hal::BluetoothAvInterface::Get()->A2dpSinkDisable();
+}
+
+bool A2dpSink::Connect(const std::string& device_address) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  RawAddress addr;
+  if (!RawAddress::FromString(device_address, addr)) {
+    LOG(ERROR) << "Invalid device address given: " << device_address;
+    return false;
+  }
+
+  bt_status_t status =
+      hal::BluetoothAvInterface::Get()->GetA2dpSinkHALInterface()->connect(
+          addr);
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR) << "Failed to connect";
+    return false;
+  }
+
+  return true;
+}
+
+bool A2dpSink::Disconnect(const std::string& device_address) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  RawAddress addr;
+  if (!RawAddress::FromString(device_address, addr)) {
+    LOG(ERROR) << "Invalid device address given: " << device_address;
+    return false;
+  }
+
+  bt_status_t status =
+      hal::BluetoothAvInterface::Get()->GetA2dpSinkHALInterface()->disconnect(
+          addr);
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR) << "Failed to disconnect";
+    return false;
+  }
+
+  return true;
+}
+
+void A2dpSink::SetAudioFocusState(int focus_state) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  hal::BluetoothAvInterface::Get()
+      ->GetA2dpSinkHALInterface()
+      ->set_audio_focus_state(focus_state);
+}
+
+void A2dpSink::SetAudioTrackGain(float gain) {
+  std::lock_guard<std::mutex> lock(mutex_);
+  hal::BluetoothAvInterface::Get()
+      ->GetA2dpSinkHALInterface()
+      ->set_audio_track_gain(gain);
+}
+
+void A2dpSink::ConnectionStateCallback(BluetoothAvInterface* iface,
+                                       const RawAddress& bd_addr,
+                                       btav_connection_state_t state) {
+  std::string device_address = BtAddrString(&bd_addr);
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+
+  if (delegate_)
+    delegate_->OnConnectionState(device_address, static_cast<int>(state));
+}
+
+void A2dpSink::AudioStateCallback(BluetoothAvInterface* iface,
+                                  const RawAddress& bd_addr,
+                                  btav_audio_state_t state) {
+  std::string device_address = BtAddrString(&bd_addr);
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+
+  if (delegate_)
+    delegate_->OnAudioState(device_address, static_cast<int>(state));
+}
+
+void A2dpSink::AudioConfigCallback(BluetoothAvInterface* iface,
+                                   const RawAddress& bd_addr,
+                                   uint32_t sample_rate,
+                                   uint8_t channel_count) {
+  std::string device_address = BtAddrString(&bd_addr);
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnAudioConfig(device_address, sample_rate, channel_count);
+}
+
+// A2dpSinkFactory implementation
+// ========================================================
+A2dpSinkFactory::A2dpSinkFactory() = default;
+A2dpSinkFactory::~A2dpSinkFactory() = default;
+
+bool A2dpSinkFactory::RegisterInstance(const Uuid& uuid,
+                                       const RegisterCallback& callback) {
+  VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
+
+  auto a2dp_sink = base::WrapUnique(new A2dpSink(uuid));
+  callback(BLE_STATUS_SUCCESS, uuid, std::move(a2dp_sink));
+  return true;
+}
+
+}  // namespace bluetooth
diff --git a/service/a2dp_sink.h b/service/a2dp_sink.h
new file mode 100644
index 0000000..7a62805
--- /dev/null
+++ b/service/a2dp_sink.h
@@ -0,0 +1,103 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "service/bluetooth_instance.h"
+#include "service/hal/bluetooth_av_interface.h"
+
+namespace bluetooth {
+
+class A2dpSink : public BluetoothInstance,
+                 private hal::BluetoothAvInterface::A2dpSinkObserver {
+ public:
+  // We only allow one instance of this object at a time.
+  static const int kSingletonInstanceId;
+
+  class Delegate {
+   public:
+    virtual void OnConnectionState(const std::string& device_address,
+                                   int state) = 0;
+    virtual void OnAudioState(const std::string& device_address, int state) = 0;
+    virtual void OnAudioConfig(const std::string& device_address,
+                               uint32_t sample_rate, uint8_t channel_count) = 0;
+
+   protected:
+    virtual ~Delegate() = default;
+  };
+
+  ~A2dpSink() override;
+
+  void SetDelegate(Delegate* delegate);
+
+  // BluetoothInstance implementation:
+  const Uuid& GetAppIdentifier() const override;
+  int GetInstanceId() const override;
+
+  bool Enable();
+  void Disable();
+  bool Connect(const std::string& device_address);
+  bool Disconnect(const std::string& device_address);
+  void SetAudioFocusState(int focus_state);
+  void SetAudioTrackGain(float gain);
+
+ private:
+  friend class A2dpSinkFactory;
+
+  explicit A2dpSink(const Uuid& uuid);
+
+  // hal::bluetooth::hal::BluetoothAvInterface::Observer implementation:
+  void ConnectionStateCallback(bluetooth::hal::BluetoothAvInterface* iface,
+                               const RawAddress& bd_addr,
+                               btav_connection_state_t state) override;
+  void AudioStateCallback(bluetooth::hal::BluetoothAvInterface* iface,
+                          const RawAddress& bd_addr,
+                          btav_audio_state_t state) override;
+  void AudioConfigCallback(bluetooth::hal::BluetoothAvInterface* iface,
+                           const RawAddress& bd_addr, uint32_t sample_rate,
+                           uint8_t channel_count) override;
+
+  // See getters above for documentation.
+  const Uuid app_identifier_;
+
+  std::mutex mutex_;
+  std::mutex delegate_mutex_;
+  Delegate* delegate_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(A2dpSink);
+};
+
+class A2dpSinkFactory : public BluetoothInstanceFactory {
+ public:
+  A2dpSinkFactory();
+  ~A2dpSinkFactory() override;
+
+  // BluetoothInstanceFactory override:
+  bool RegisterInstance(const Uuid& uuid,
+                        const RegisterCallback& callback) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(A2dpSinkFactory);
+};
+
+}  // namespace bluetooth
diff --git a/service/a2dp_source.cc b/service/a2dp_source.cc
new file mode 100644
index 0000000..9e77007
--- /dev/null
+++ b/service/a2dp_source.cc
@@ -0,0 +1,216 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/a2dp_source.h"
+
+#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "service/logging_helpers.h"
+
+#define PARSE_ADDR(str)                                        \
+  ({                                                           \
+    RawAddress tmp;                                            \
+    if (!RawAddress::FromString((str), tmp)) {                 \
+      LOG(ERROR) << "Invalid device address given: " << (str); \
+      return false;                                            \
+    }                                                          \
+    tmp;                                                       \
+  })
+
+#define TRY_RET(expr, err_msg) \
+  do {                         \
+    if (!(expr)) {             \
+      LOG(ERROR) << err_msg;   \
+      return false;            \
+    }                          \
+    return true;               \
+  } while (0)
+
+#define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
+
+using bluetooth::hal::BluetoothAvInterface;
+using LockGuard = std::lock_guard<std::mutex>;
+
+namespace bluetooth {
+
+namespace {
+
+btav_a2dp_codec_config_t CodecConfigToFluoride(const A2dpCodecConfig& config) {
+  btav_a2dp_codec_config_t ret = {
+      .codec_type = static_cast<btav_a2dp_codec_index_t>(config.codec_type()),
+      .codec_priority =
+          static_cast<btav_a2dp_codec_priority_t>(config.codec_priority()),
+      .sample_rate =
+          static_cast<btav_a2dp_codec_sample_rate_t>(config.sample_rate()),
+      .bits_per_sample = static_cast<btav_a2dp_codec_bits_per_sample_t>(
+          config.bits_per_sample()),
+      .channel_mode =
+          static_cast<btav_a2dp_codec_channel_mode_t>(config.channel_mode()),
+      .codec_specific_1 = config.codec_specific_1(),
+      .codec_specific_2 = config.codec_specific_2(),
+      .codec_specific_3 = config.codec_specific_3(),
+      .codec_specific_4 = config.codec_specific_4(),
+  };
+
+  return ret;
+}
+
+std::vector<btav_a2dp_codec_config_t> CodecConfigsToFluoride(
+    const std::vector<A2dpCodecConfig>& configs) {
+  std::vector<btav_a2dp_codec_config_t> ret;
+  ret.reserve(configs.size());
+  for (const auto& config : configs) {
+    ret.push_back(CodecConfigToFluoride(config));
+  }
+
+  return ret;
+}
+A2dpCodecConfig FluorideCodecToCodec(const btav_a2dp_codec_config_t& config) {
+  A2dpCodecConfig ret(config.codec_type, config.codec_priority,
+                      config.sample_rate, config.bits_per_sample,
+                      config.channel_mode, config.codec_specific_1,
+                      config.codec_specific_2, config.codec_specific_3,
+                      config.codec_specific_4);
+
+  return ret;
+}
+
+std::vector<A2dpCodecConfig> FluorideCodecsToCodec(
+    const std::vector<btav_a2dp_codec_config_t>& configs) {
+  std::vector<A2dpCodecConfig> ret;
+  ret.reserve(configs.size());
+  for (const auto& config : configs) {
+    ret.push_back(FluorideCodecToCodec(config));
+  }
+
+  return ret;
+}
+
+}  // namespace
+
+// static
+const int A2dpSource::kSingletonInstanceId = 0;
+
+A2dpSource::A2dpSource(const Uuid& uuid) : app_identifier_(uuid) {
+  hal::BluetoothAvInterface::Get()->AddA2dpSourceObserver(this);
+}
+
+A2dpSource::~A2dpSource() {
+  hal::BluetoothAvInterface::Get()->RemoveA2dpSourceObserver(this);
+}
+
+const Uuid& A2dpSource::GetAppIdentifier() const { return app_identifier_; }
+
+int A2dpSource::GetInstanceId() const { return kSingletonInstanceId; }
+
+void A2dpSource::SetDelegate(Delegate* delegate) {
+  LockGuard lock(delegate_mutex_);
+  delegate_ = delegate;
+}
+
+bool A2dpSource::Enable(const std::vector<A2dpCodecConfig>& codec_priorities) {
+  auto fluoride_priorities = CodecConfigsToFluoride(codec_priorities);
+  LockGuard lock(mutex_);
+  return hal::BluetoothAvInterface::Get()->A2dpSourceEnable(
+      fluoride_priorities);
+}
+
+void A2dpSource::Disable() {
+  LockGuard lock(mutex_);
+  hal::BluetoothAvInterface::Get()->A2dpSourceDisable();
+}
+
+bool A2dpSource::Connect(const std::string& device_address) {
+  RawAddress addr = PARSE_ADDR(device_address);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(
+      hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->connect(
+          addr) == BT_STATUS_SUCCESS);
+}
+
+bool A2dpSource::Disconnect(const std::string& device_address) {
+  RawAddress addr = PARSE_ADDR(device_address);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(
+      hal::BluetoothAvInterface::Get()->GetA2dpSourceHALInterface()->disconnect(
+          addr) == BT_STATUS_SUCCESS);
+}
+
+bool A2dpSource::ConfigCodec(
+    const std::string& device_address,
+    const std::vector<A2dpCodecConfig>& codec_preferences) {
+  RawAddress addr = PARSE_ADDR(device_address);
+  auto fluoride_preferences = CodecConfigsToFluoride(codec_preferences);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvInterface::Get()
+                   ->GetA2dpSourceHALInterface()
+                   ->config_codec(addr, fluoride_preferences) ==
+               BT_STATUS_SUCCESS);
+}
+
+void A2dpSource::ConnectionStateCallback(BluetoothAvInterface* iface,
+                                         const RawAddress& bd_addr,
+                                         btav_connection_state_t state) {
+  auto device_address = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnConnectionState(device_address, static_cast<int>(state));
+}
+
+void A2dpSource::AudioStateCallback(BluetoothAvInterface* iface,
+                                    const RawAddress& bd_addr,
+                                    btav_audio_state_t state) {
+  auto device_address = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnAudioState(device_address, static_cast<int>(state));
+}
+
+void A2dpSource::AudioConfigCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    const btav_a2dp_codec_config_t& codec_config_fluoride,
+    const std::vector<btav_a2dp_codec_config_t>
+        codecs_local_capabilities_fluoride,
+    const std::vector<btav_a2dp_codec_config_t>
+        codecs_selectable_capabilities_fluoride) {
+  auto device_address = BtAddrString(&bd_addr);
+  auto codec_config = FluorideCodecToCodec(codec_config_fluoride);
+  auto codecs_local_capabilities =
+      FluorideCodecsToCodec(codecs_local_capabilities_fluoride);
+  auto codecs_selectable_capabilities =
+      FluorideCodecsToCodec(codecs_selectable_capabilities_fluoride);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnAudioConfig(device_address, codec_config,
+                             codecs_local_capabilities,
+                             codecs_selectable_capabilities);
+}
+
+// A2dpSourceFactory implementation
+// ========================================================
+A2dpSourceFactory::A2dpSourceFactory() = default;
+A2dpSourceFactory::~A2dpSourceFactory() = default;
+
+bool A2dpSourceFactory::RegisterInstance(const Uuid& uuid,
+                                         const RegisterCallback& callback) {
+  VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+
+  auto a2dp_source = base::WrapUnique(new A2dpSource(uuid));
+  callback(BLE_STATUS_SUCCESS, uuid, std::move(a2dp_source));
+  return true;
+}
+
+}  // namespace bluetooth
diff --git a/service/a2dp_source.h b/service/a2dp_source.h
new file mode 100644
index 0000000..f4e3ab3
--- /dev/null
+++ b/service/a2dp_source.h
@@ -0,0 +1,116 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <atomic>
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include "service/bluetooth_instance.h"
+#include "service/common/bluetooth/a2dp_codec_config.h"
+#include "service/hal/bluetooth_av_interface.h"
+
+namespace bluetooth {
+
+class A2dpSource : public BluetoothInstance,
+                   private hal::BluetoothAvInterface::A2dpSourceObserver {
+ public:
+  // We only allow one instance of this object at a time.
+  static const int kSingletonInstanceId;
+
+  class Delegate {
+   public:
+    virtual void OnConnectionState(const std::string& device_address,
+                                   int state) = 0;
+    virtual void OnAudioState(const std::string& device_address, int state) = 0;
+    virtual void OnAudioConfig(
+        const std::string& device_address, A2dpCodecConfig codec_config,
+        const std::vector<A2dpCodecConfig>& codecs_local_capabilities,
+        const std::vector<A2dpCodecConfig>& codecs_selectable_capabilities) = 0;
+
+   protected:
+    virtual ~Delegate() = default;
+  };
+
+  ~A2dpSource() override;
+
+  void SetDelegate(Delegate* delegate);
+
+  // BluetoothInstance implementation:
+  const Uuid& GetAppIdentifier() const override;
+  int GetInstanceId() const override;
+
+  bool Enable(const std::vector<A2dpCodecConfig>& codec_priorities);
+  void Disable();
+  bool Connect(const std::string& device_address);
+  bool Disconnect(const std::string& device_address);
+  bool ConfigCodec(const std::string& device_address,
+                   const std::vector<A2dpCodecConfig>& codec_preferences);
+
+ private:
+  friend class A2dpSourceFactory;
+
+  explicit A2dpSource(const Uuid& uuid);
+
+  // hal::bluetooth::hal::BluetoothAvInterface::Observer implementation:
+  void ConnectionStateCallback(hal::BluetoothAvInterface* iface,
+                               const RawAddress& bd_addr,
+                               btav_connection_state_t state) override;
+  void AudioStateCallback(hal::BluetoothAvInterface* iface,
+                          const RawAddress& bd_addr,
+                          btav_audio_state_t state) override;
+  void AudioConfigCallback(
+      hal::BluetoothAvInterface* iface, const RawAddress& bd_addr,
+      const btav_a2dp_codec_config_t& codec_config,
+      const std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
+      const std::vector<btav_a2dp_codec_config_t>
+          codecs_selectable_capabilities) override;
+
+  // For |GetAppIdentifier|.
+  const Uuid app_identifier_;
+
+  std::mutex mutex_;
+
+  // A second mutex is used only for |delegate_|. We cannot use |mutex_| because
+  // it may cause a deadlock if the caller and Delegate both take the same lock
+  // 'clock'.
+  // In that scenario, the caller may take 'clock' first and will try to take
+  // |mutex_| second. The callback will take |mutex_| first and invoke a
+  // delegate function which attempts to take 'clock'.
+  std::mutex delegate_mutex_;
+  Delegate* delegate_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(A2dpSource);
+};
+
+class A2dpSourceFactory : public BluetoothInstanceFactory {
+ public:
+  A2dpSourceFactory();
+  ~A2dpSourceFactory() override;
+
+  // BluetoothInstanceFactory override:
+  bool RegisterInstance(const Uuid& uuid,
+                        const RegisterCallback& callback) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(A2dpSourceFactory);
+};
+
+}  // namespace bluetooth
diff --git a/service/adapter.cc b/service/adapter.cc
index 853ffdf..4d414dd 100644
--- a/service/adapter.cc
+++ b/service/adapter.cc
@@ -24,6 +24,10 @@
 #include <base/logging.h>
 #include <base/observer_list.h>
 
+#include "service/a2dp_sink.h"
+#include "service/a2dp_source.h"
+#include "service/avrcp_control.h"
+#include "service/avrcp_target.h"
 #include "service/common/bluetooth/util/atomic_string.h"
 #include "service/gatt_client.h"
 #include "service/gatt_server.h"
@@ -38,6 +42,89 @@
 
 namespace bluetooth {
 
+namespace {
+
+RemoteDeviceProps ParseRemoteDeviceProps(int num_properties,
+                                         bt_property_t* properties) {
+  std::string name;
+  std::string address;
+  std::vector<Uuid> service_uuids;
+  int32_t device_class = 0;
+  int32_t device_type = 0;
+  int32_t rssi = 0;
+
+  for (int i = 0; i < num_properties; ++i) {
+    bt_property_t* property = properties + i;
+    switch (property->type) {
+      case BT_PROPERTY_BDNAME: {
+        if (property->len < 0) {
+          NOTREACHED() << "Invalid length for BT_PROPERTY_BDNAME";
+          break;
+        }
+        bt_bdname_t* hal_name = reinterpret_cast<bt_bdname_t*>(property->val);
+        name = reinterpret_cast<char*>(hal_name->name);
+        break;
+      }
+      case BT_PROPERTY_BDADDR: {
+        if (property->len != sizeof(RawAddress)) {
+          NOTREACHED() << "Invalid length for BT_PROPERTY_BDADDR";
+          break;
+        }
+        address = BtAddrString(reinterpret_cast<RawAddress*>(property->val));
+        break;
+      }
+      case BT_PROPERTY_UUIDS: {
+        if (property->len < 0) {
+          NOTREACHED() << "Negative length on BT_PROPERTY_UUIDS:";
+          break;
+        }
+        if (property->len % sizeof(Uuid) != 0) {
+          NOTREACHED() << "Trailing bytes on BT_PROPERTY_UUIDS:";
+        }
+        auto uuids = static_cast<const Uuid*>(property->val);
+
+        for (size_t i = 0; i < property->len / sizeof(Uuid); ++i) {
+          service_uuids.push_back(uuids[i]);
+        }
+        break;
+      }
+      case BT_PROPERTY_CLASS_OF_DEVICE: {
+        if (property->len != sizeof(int32_t)) {
+          NOTREACHED() << "Invalid length for BT_PROPERTY_CLASS_OF_DEVICE";
+          break;
+        }
+        device_class = *reinterpret_cast<const int32_t*>(property->val);
+        break;
+      }
+      case BT_PROPERTY_TYPE_OF_DEVICE: {
+        if (property->len != sizeof(int32_t)) {
+          NOTREACHED() << "Invalid length for BT_PROPERTY_TYPE_OF_DEVICE";
+          break;
+        }
+        device_type = *reinterpret_cast<const int32_t*>(property->val);
+        break;
+      }
+      case BT_PROPERTY_REMOTE_RSSI: {
+        if (property->len != sizeof(int8_t)) {
+          NOTREACHED() << "Invalid length for BT_PROPERTY_REMOTE_RSSI";
+          break;
+        }
+        rssi = *reinterpret_cast<const int8_t*>(property->val);
+        break;
+      }
+      default:
+        VLOG(1) << "Unhandled adapter property: "
+                << BtPropertyText(property->type);
+        break;
+    }
+  }
+
+  return RemoteDeviceProps(name, address, service_uuids, device_class,
+                           device_type, rssi);
+}
+
+}  // namespace
+
 // static
 const char Adapter::kDefaultAddress[] = "00:00:00:00:00:00";
 // static
@@ -69,6 +156,41 @@
   // Default implementation does nothing
 }
 
+void Adapter::Observer::OnScanEnableChanged(Adapter* adapter,
+                                            bool scan_enabled) {
+  // Default implementation does nothing
+}
+
+void Adapter::Observer::OnSspRequest(Adapter* adapter,
+                                     const std::string& device_address,
+                                     const std::string& device_name, int cod,
+                                     int pairing_variant, int pass_key) {
+  // Default implementation does nothing
+}
+
+void Adapter::Observer::OnBondStateChanged(Adapter* adapter, int status,
+                                           const std::string& device_address,
+                                           int state) {
+  // Default implementation does nothing
+}
+
+void Adapter::Observer::OnGetBondedDevices(
+    Adapter* adapter, int status,
+    const std::vector<std::string>& bonded_devices) {
+  // Default implementation does nothing
+}
+
+void Adapter::Observer::OnGetRemoteDeviceProperties(
+    Adapter* adapter, int status, const std::string& device_address,
+    const RemoteDeviceProps& properties) {
+  // Default implementation does nothing
+}
+
+void Adapter::Observer::OnDeviceFound(Adapter* adapter,
+                                      const RemoteDeviceProps& properties) {
+  // Default implementation does nothing
+}
+
 // The real Adapter implementation used in production.
 class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer {
  public:
@@ -78,6 +200,10 @@
         name_(kDefaultName) {
     memset(&local_le_features_, 0, sizeof(local_le_features_));
     hal::BluetoothInterface::Get()->AddObserver(this);
+    a2dp_sink_factory_.reset(new A2dpSinkFactory);
+    a2dp_source_factory_.reset(new A2dpSourceFactory);
+    avrcp_control_factory_.reset(new AvrcpControlFactory);
+    avrcp_target_factory_.reset(new AvrcpTargetFactory);
     ble_client_factory_.reset(new LowEnergyClientFactory(*this));
     ble_advertiser_factory_.reset(new LowEnergyAdvertiserFactory());
     ble_scanner_factory_.reset(new LowEnergyScannerFactory(*this));
@@ -104,7 +230,7 @@
 
   bool IsEnabled() const override { return state_.load() == ADAPTER_STATE_ON; }
 
-  bool Enable(bool start_restricted) override {
+  bool Enable() override {
     AdapterState current_state = GetState();
     if (current_state != ADAPTER_STATE_OFF) {
       LOG(INFO) << "Adapter not disabled - state: "
@@ -117,8 +243,7 @@
     state_ = ADAPTER_STATE_TURNING_ON;
     NotifyAdapterStateChanged(current_state, state_);
 
-    int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable(
-        start_restricted);
+    int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable();
     if (status != BT_STATUS_SUCCESS) {
       LOG(ERROR) << "Failed to enable Bluetooth - status: "
                  << BtStatusText((const bt_status_t)status);
@@ -183,6 +308,84 @@
 
   std::string GetAddress() const override { return address_.Get(); }
 
+  bool SetScanMode(int scan_mode) override {
+    switch (scan_mode) {
+      case BT_SCAN_MODE_NONE:
+      case BT_SCAN_MODE_CONNECTABLE:
+      case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
+        break;
+      default:
+        LOG(ERROR) << "Unknown scan mode: " << scan_mode;
+        return false;
+    }
+
+    auto bd_scanmode = static_cast<bt_scan_mode_t>(scan_mode);
+
+    if (!SetAdapterProperty(BT_PROPERTY_ADAPTER_SCAN_MODE, &bd_scanmode,
+                            sizeof(bd_scanmode))) {
+      LOG(ERROR) << "Failed to set scan mode to : " << scan_mode;
+      return false;
+    }
+
+    return true;
+  }
+
+  bool SetScanEnable(bool scan_enable) override {
+    if (scan_enable) {
+      int status =
+          hal::BluetoothInterface::Get()->GetHALInterface()->start_discovery();
+      if (status != BT_STATUS_SUCCESS) {
+        LOG(ERROR) << "Failed to enable scanning";
+        return false;
+      }
+    } else {
+      int status =
+          hal::BluetoothInterface::Get()->GetHALInterface()->cancel_discovery();
+      if (status != BT_STATUS_SUCCESS) {
+        LOG(ERROR) << "Failed to disable scanning";
+        return false;
+      }
+    }
+    return true;
+  }
+
+  bool SspReply(const std::string& device_address, int variant, bool accept,
+                int32_t pass_key) override {
+    RawAddress addr;
+    if (!RawAddress::FromString(device_address, addr)) {
+      LOG(ERROR) << "Invalid device address given: " << device_address;
+      return false;
+    }
+
+    int status = hal::BluetoothInterface::Get()->GetHALInterface()->ssp_reply(
+        &addr, static_cast<bt_ssp_variant_t>(variant), accept, pass_key);
+    if (status != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to send SSP response - status: "
+                 << BtStatusText((const bt_status_t)status);
+      return false;
+    }
+
+    return true;
+  }
+
+  bool CreateBond(const std::string& device_address, int transport) override {
+    RawAddress addr;
+    if (!RawAddress::FromString(device_address, addr)) {
+      LOG(ERROR) << "Invalid device address given: " << device_address;
+      return false;
+    }
+
+    int status = hal::BluetoothInterface::Get()->GetHALInterface()->create_bond(
+        &addr, transport);
+    if (status != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to create bond - status: "
+                 << BtStatusText((const bt_status_t)status);
+      return false;
+    }
+
+    return true;
+  }
+
   bool IsMultiAdvertisementSupported() override {
     lock_guard<mutex> lock(local_le_features_lock_);
     return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv;
@@ -209,6 +412,72 @@
            kMinOffloadedScanStorageBytes;
   }
 
+  bool GetBondedDevices() override {
+    int status =
+        hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_property(
+            BT_PROPERTY_ADAPTER_BONDED_DEVICES);
+    if (status != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to get bonded devices. Status: "
+                 << BtStatusText(static_cast<bt_status_t>(status));
+      return false;
+    }
+
+    return true;
+  }
+
+  bool RemoveBond(const std::string& device_address) override {
+    RawAddress addr;
+    if (!RawAddress::FromString(device_address, addr)) {
+      LOG(ERROR) << "Invalid device address given: " << device_address;
+      return false;
+    }
+
+    int status =
+        hal::BluetoothInterface::Get()->GetHALInterface()->remove_bond(&addr);
+    if (status != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to send remove bond - status: "
+                 << BtStatusText(static_cast<bt_status_t>(status));
+      return false;
+    }
+
+    return true;
+  }
+
+  bool GetRemoteDeviceProperties(const std::string& device_address) override {
+    RawAddress addr;
+    if (!RawAddress::FromString(device_address, addr)) {
+      LOG(ERROR) << "Invalid device address given: " << device_address;
+      return false;
+    }
+
+    int status = hal::BluetoothInterface::Get()
+                     ->GetHALInterface()
+                     ->get_remote_device_properties(&addr);
+    if (status != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to send GetRemoteDeviceProperties - status: "
+                 << BtStatusText((const bt_status_t)status);
+      return false;
+    }
+
+    return true;
+  }
+
+  A2dpSinkFactory* GetA2dpSinkFactory() const override {
+    return a2dp_sink_factory_.get();
+  }
+
+  A2dpSourceFactory* GetA2dpSourceFactory() const override {
+    return a2dp_source_factory_.get();
+  }
+
+  AvrcpControlFactory* GetAvrcpControlFactory() const override {
+    return avrcp_control_factory_.get();
+  }
+
+  AvrcpTargetFactory* GetAvrcpTargetFactory() const override {
+    return avrcp_target_factory_.get();
+  }
+
   LowEnergyClientFactory* GetLowEnergyClientFactory() const override {
     return ble_client_factory_.get();
   }
@@ -257,6 +526,16 @@
 
     if (status != BT_STATUS_SUCCESS) {
       LOG(ERROR) << "status: " << BtStatusText(status);
+
+      for (int i = 0; i < num_properties; ++i) {
+        bt_property_t* property = properties + i;
+        if (property->type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
+          lock_guard<mutex> lock(observers_lock_);
+          for (auto& observer : observers_) {
+            observer.OnGetBondedDevices(this, status, {});
+          }
+        }
+      }
       return;
     }
 
@@ -290,6 +569,29 @@
           LOG(INFO) << "Supported LE features updated";
           break;
         }
+        case BT_PROPERTY_ADAPTER_BONDED_DEVICES: {
+          if (property->len < 0) {
+            NOTREACHED() << "Negative property length";
+            break;
+          }
+          auto addrs = reinterpret_cast<const RawAddress*>(property->val);
+          if (property->len % sizeof(addrs[0]) != 0) {
+            LOG(ERROR) << "Invalid property length: " << property->len;
+            // TODO(bcf): Seems to be a bug where we hit this somewhat
+            // frequently.
+            break;
+          }
+          std::vector<std::string> str_addrs;
+
+          for (size_t i = 0; i < property->len / sizeof(addrs[0]); ++i)
+            str_addrs.push_back(BtAddrString(addrs + i));
+
+          lock_guard<mutex> lock(observers_lock_);
+          for (auto& observer : observers_) {
+            observer.OnGetBondedDevices(this, status, str_addrs);
+          }
+          break;
+        }
         default:
           VLOG(1) << "Unhandled adapter property: "
                   << BtPropertyText(property->type);
@@ -300,9 +602,82 @@
     }
   }
 
-  void SSPRequestCallback(RawAddress*, bt_bdname_t*, uint32_t, bt_ssp_variant_t,
+  void RemoteDevicePropertiesCallback(bt_status_t status,
+                                      RawAddress* remote_bdaddr,
+                                      int num_properties,
+                                      bt_property_t* properties) override {
+    std::string device_address = BtAddrString(remote_bdaddr);
+    if (status != BT_STATUS_SUCCESS) {
+      lock_guard<mutex> lock(observers_lock_);
+      for (auto& observer : observers_) {
+        observer.OnGetRemoteDeviceProperties(this, status, device_address,
+                                             RemoteDeviceProps());
+      }
+      return;
+    }
+
+    RemoteDeviceProps props =
+        ParseRemoteDeviceProps(num_properties, properties);
+
+    std::string address = BtAddrString(remote_bdaddr);
+    props.set_address(address);
+
+    lock_guard<mutex> lock(observers_lock_);
+    for (auto& observer : observers_) {
+      observer.OnGetRemoteDeviceProperties(this, status, device_address, props);
+    }
+  }
+
+  void DeviceFoundCallback(int num_properties,
+                           bt_property_t* properties) override {
+    RemoteDeviceProps props =
+        ParseRemoteDeviceProps(num_properties, properties);
+
+    lock_guard<mutex> lock(observers_lock_);
+    for (auto& observer : observers_) {
+      observer.OnDeviceFound(this, props);
+    }
+  }
+
+  void DiscoveryStateChangedCallback(bt_discovery_state_t state) override {
+    bool enabled = false;
+    switch (state) {
+      case BT_DISCOVERY_STOPPED:
+        enabled = false;
+        break;
+      case BT_DISCOVERY_STARTED:
+        enabled = true;
+        break;
+      default:
+        NOTREACHED();
+    }
+
+    for (auto& observer : observers_) {
+      observer.OnScanEnableChanged(this, enabled);
+    }
+  }
+
+  void SSPRequestCallback(RawAddress* remote_bdaddr, bt_bdname_t* bd_name,
+                          uint32_t cod, bt_ssp_variant_t pairing_variant,
                           uint32_t pass_key) override {
-    LOG(INFO) << "Passkey is: " << pass_key;
+    std::string device_address = BtAddrString(remote_bdaddr);
+    std::string name = reinterpret_cast<char*>(bd_name->name);
+
+    lock_guard<mutex> lock(observers_lock_);
+    for (auto& observer : observers_) {
+      observer.OnSspRequest(this, device_address, name, cod, pairing_variant,
+                            pass_key);
+    }
+  }
+
+  void BondStateChangedCallback(bt_status_t status, RawAddress* remote_bdaddr,
+                                bt_bond_state_t state) override {
+    std::string device_address = BtAddrString(remote_bdaddr);
+
+    lock_guard<mutex> lock(observers_lock_);
+    for (auto& observer : observers_) {
+      observer.OnBondStateChanged(this, status, device_address, state);
+    }
   }
 
   void AclStateChangedCallback(bt_status_t status,
@@ -392,6 +767,18 @@
   std::mutex connected_devices_lock_;
   std::unordered_set<std::string> connected_devices_;
 
+  // Factory used to create per-app A2dpSink instances.
+  std::unique_ptr<A2dpSinkFactory> a2dp_sink_factory_;
+
+  // Factory used to create per-app A2dpSource instances.
+  std::unique_ptr<A2dpSourceFactory> a2dp_source_factory_;
+
+  // Factory used to create per-app AvrcpControl instances.
+  std::unique_ptr<AvrcpControlFactory> avrcp_control_factory_;
+
+  // Factory used to create per-app AvrcpTarget instances.
+  std::unique_ptr<AvrcpTargetFactory> avrcp_target_factory_;
+
   // Factory used to create per-app LowEnergyClient instances.
   std::unique_ptr<LowEnergyClientFactory> ble_client_factory_;
 
diff --git a/service/adapter.h b/service/adapter.h
index 3becaae..a4e517c 100644
--- a/service/adapter.h
+++ b/service/adapter.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2015 Google, Inc.
+//  Copyright (C) 2015 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -17,13 +17,20 @@
 #pragma once
 
 #include <memory>
+#include <string>
+#include <vector>
 
 #include <base/macros.h>
 
 #include "service/common/bluetooth/adapter_state.h"
+#include "service/common/bluetooth/remote_device_props.h"
 
 namespace bluetooth {
 
+class A2dpSinkFactory;
+class A2dpSourceFactory;
+class AvrcpControlFactory;
+class AvrcpTargetFactory;
 class GattClientFactory;
 class GattServerFactory;
 class LowEnergyAdvertiserFactory;
@@ -61,6 +68,34 @@
     // true and vice versa.
     virtual void OnDeviceConnectionStateChanged(
         Adapter* adapter, const std::string& device_address, bool connected);
+
+    // Called when scanning is enabled or disabled.
+    virtual void OnScanEnableChanged(Adapter* adapter, bool scan_enabled);
+
+    // Called when a SSP pairing request comes from a remote device.
+    virtual void OnSspRequest(Adapter* adapter,
+                              const std::string& device_address,
+                              const std::string& device_name, int cod,
+                              int pairing_variant, int pass_key);
+
+    // Called when a remote device bond state changes.
+    virtual void OnBondStateChanged(Adapter* adapter, int status,
+                                    const std::string& device_address,
+                                    int state);
+
+    // Called in response to |GetBondedDevices|.
+    virtual void OnGetBondedDevices(
+        Adapter* adapter, int status,
+        const std::vector<std::string>& bonded_devices);
+
+    // Called in response to |GetRemoteDeviceProperties|.
+    virtual void OnGetRemoteDeviceProperties(Adapter* adapter, int status,
+                                             const std::string& device_address,
+                                             const RemoteDeviceProps& props);
+
+    // Called when a device is found through scanning.
+    virtual void OnDeviceFound(Adapter* adapter,
+                               const RemoteDeviceProps& props);
   };
 
   // Returns an Adapter implementation to be used in production. Don't use these
@@ -84,10 +119,7 @@
   // to the controller, otherwise returns false. A successful call to this
   // method only means that the enable request has been sent to the Bluetooth
   // controller and does not imply that the operation itself succeeded.
-  // The |start_restricted| flag enables the adapter in restricted mode. In
-  // restricted mode, bonds that are created are marked as restricted in the
-  // config file. These devices are deleted upon leaving restricted mode.
-  virtual bool Enable(bool start_restricted) = 0;
+  virtual bool Enable() = 0;
 
   // Powers off the Bluetooth radio. Returns true, if the disable request was
   // successfully sent to the Bluetooth controller.
@@ -103,6 +135,19 @@
   // Returns the local adapter addess in string form (XX:XX:XX:XX:XX:XX).
   virtual std::string GetAddress() const = 0;
 
+  // Set discoverability mode.
+  virtual bool SetScanMode(int scan_mode) = 0;
+
+  // Enable or disable discoverability.
+  virtual bool SetScanEnable(bool scan_enable) = 0;
+
+  // Reply to an SSP request received in |OnSspRequest|.
+  virtual bool SspReply(const std::string& device_address, int variant,
+                        bool accept, int32_t pass_key) = 0;
+
+  // Create a bond with device specified by |device_address|.
+  virtual bool CreateBond(const std::string& device_address, int transport) = 0;
+
   // Returns true if the local adapter supports the Low-Energy
   // multi-advertisement feature.
   virtual bool IsMultiAdvertisementSupported() = 0;
@@ -122,6 +167,36 @@
   // Returns true if hardware-backed batch scanning is supported.
   virtual bool IsOffloadedScanBatchingSupported() = 0;
 
+  // When the stack call completes, |OnGetBondedDevices| will be called.
+  virtual bool GetBondedDevices() = 0;
+
+  // When the stack call completets, |OnBondStateChanged| will be called.
+  virtual bool RemoveBond(const std::string& device_address) = 0;
+
+  // When the stack call completets, |OnGetRemoteDeviceProperties| will be
+  // called.
+  virtual bool GetRemoteDeviceProperties(const std::string& device_address) = 0;
+
+  // Returns a pointer to the A2dpSinkFactory. This can be used to
+  // register per-application A2dpSinkClient instances to perform A2DP sink
+  // operations.
+  virtual A2dpSinkFactory* GetA2dpSinkFactory() const = 0;
+
+  // Returns a pointer to the A2dpSourceFactory. This can be used to
+  // register per-application A2dpSourceClient instances to perform A2DP source
+  // operations.
+  virtual A2dpSourceFactory* GetA2dpSourceFactory() const = 0;
+
+  // Returns a pointer to the AvrcpControlFactory. This can be used to register
+  // per-application AvrcpControlClient instances to perform AVRCP control
+  // operations.
+  virtual AvrcpControlFactory* GetAvrcpControlFactory() const = 0;
+
+  // Returns a pointer to the AvrcpTargetFactory. This can be used to register
+  // per-application AvrcpTargetClient instances to perform AVRCP target
+  // operations.
+  virtual AvrcpTargetFactory* GetAvrcpTargetFactory() const = 0;
+
   // Returns a pointer to the LowEnergyClientFactory. This can be used to
   // register per-application LowEnergyClient instances to perform BLE GAP
   // operations.
diff --git a/service/avrcp_control.cc b/service/avrcp_control.cc
new file mode 100644
index 0000000..18dc2aa
--- /dev/null
+++ b/service/avrcp_control.cc
@@ -0,0 +1,231 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/avrcp_control.h"
+
+#include <cerrno>
+#include <climits>
+#include <string>
+
+#include <base/logging.h>
+#include <base/memory/ptr_util.h>
+#include <base/strings/string_number_conversions.h>
+
+#include "service/logging_helpers.h"
+
+#include "stack/include/avrc_defs.h"
+
+
+namespace bluetooth {
+
+AvrcpControl::AvrcpControl(const Uuid& uuid, int control_id)
+    : app_identifier_(uuid), control_id_(control_id) {
+  hal::BluetoothAvrcpInterface::Get()->AddControlObserver(this);
+}
+
+AvrcpControl::~AvrcpControl() {
+  hal::BluetoothAvrcpInterface::Get()->RemoveControlObserver(this);
+}
+
+const Uuid& AvrcpControl::GetAppIdentifier() const { return app_identifier_; }
+
+int AvrcpControl::GetInstanceId() const { return control_id_; }
+
+void AvrcpControl::SetDelegate(Delegate* delegate) {
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  delegate_ = delegate;
+}
+
+bool AvrcpControl::Enable() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  return hal::BluetoothAvrcpInterface::Get()->AvrcpControlEnable();
+}
+
+void AvrcpControl::Disable() {
+  std::lock_guard<std::mutex> lock(mutex_);
+  hal::BluetoothAvrcpInterface::Get()->AvrcpControlDisable();
+}
+
+bool AvrcpControl::SendPassThroughCommand(const std::string& device_address,
+                                          uint8_t key_code, bool key_pressed) {
+  RawAddress addr;
+  if (!RawAddress::FromString(device_address, addr)) {
+    LOG(ERROR) << "Invalid device address given: " << device_address;
+    return false;
+  }
+
+  uint8_t key_state = key_pressed ? AVRC_STATE_PRESS : AVRC_STATE_RELEASE;
+  bt_status_t status;
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    status = hal::BluetoothAvrcpInterface::Get()
+                 ->GetControlHALInterface()
+                 ->send_pass_through_cmd(addr, key_code, key_state);
+  }
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR) << "Failed to send passthrough command";
+    return false;
+  }
+
+  return true;
+}
+
+bool AvrcpControl::SetAbsVolumeResponse(const std::string& device_address,
+                                        int32_t abs_vol, int32_t label) {
+  RawAddress addr;
+  if (!RawAddress::FromString(device_address, addr)) {
+    LOG(ERROR) << "Invalid device address given: " << device_address;
+    return false;
+  }
+
+  bt_status_t status;
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    status = hal::BluetoothAvrcpInterface::Get()
+                 ->GetControlHALInterface()
+                 ->set_volume_rsp(addr, abs_vol, label);
+  }
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR) << "Failed to send set absolute volume response";
+    return false;
+  }
+
+  return true;
+}
+
+bool AvrcpControl::RegisterForAbsVolumeCallbackResponse(
+    const std::string& device_address, int32_t response_type, int32_t abs_vol,
+    int32_t label) {
+  RawAddress addr;
+  if (!RawAddress::FromString(device_address, addr)) {
+    LOG(ERROR) << "Invalid device address given: " << device_address;
+    return false;
+  }
+
+  bt_status_t status;
+  {
+    std::lock_guard<std::mutex> lock(mutex_);
+    status = hal::BluetoothAvrcpInterface::Get()
+                 ->GetControlHALInterface()
+                 ->register_abs_vol_rsp(
+                     addr, static_cast<btrc_notification_type_t>(response_type),
+                     abs_vol, label);
+  }
+  if (status != BT_STATUS_SUCCESS) {
+    LOG(ERROR)
+        << "Failed to send send register for absolute volume change callback";
+    return false;
+  }
+
+  return true;
+}
+
+void AvrcpControl::ConnectionStateCallback(bool rc_connect, bool bt_connect,
+                                           const RawAddress& bd_addr) {
+  std::string device_address = BtAddrString(&bd_addr);
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnConnectionState(rc_connect, bt_connect, device_address);
+}
+
+void AvrcpControl::CtrlSetabsvolCmdCallback(const RawAddress& bd_addr,
+                                            uint8_t abs_vol, uint8_t label) {
+  std::string device_address = BtAddrString(&bd_addr);
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnSetAbsVolumeRequest(device_address, abs_vol, label);
+}
+
+void AvrcpControl::CtrlRegisternotificationAbsVolCallback(
+    const RawAddress& bd_addr, uint8_t label) {
+  std::string device_address = BtAddrString(&bd_addr);
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnRegisterForAbsVolumeCallbackRequest(device_address, label);
+}
+
+void AvrcpControl::CtrlTrackChangedCallback(const RawAddress& bd_addr,
+                                            uint8_t num_attr,
+                                            btrc_element_attr_val_t* p_attrs) {
+  std::string device_address = BtAddrString(&bd_addr);
+
+  std::string title;
+  std::string artist;
+  std::string album;
+  std::string genre;
+  int track_num = -1;
+  int num_tracks = -1;
+  int play_time = -1;
+
+  for (size_t i = 0; i < num_attr; ++i) {
+    auto attr_text = reinterpret_cast<char*>(p_attrs[i].text);
+    switch (p_attrs[i].attr_id) {
+      case BTRC_MEDIA_ATTR_ID_TITLE:
+        title = attr_text;
+        break;
+      case BTRC_MEDIA_ATTR_ID_ARTIST:
+        artist = attr_text;
+        break;
+      case BTRC_MEDIA_ATTR_ID_ALBUM:
+        album = attr_text;
+        break;
+      case BTRC_MEDIA_ATTR_ID_TRACK_NUM:
+        if (!base::StringToInt(attr_text, &track_num)) {
+          LOG(ERROR) << "Failed to parse track number";
+        }
+        break;
+      case BTRC_MEDIA_ATTR_ID_NUM_TRACKS:
+        if (!base::StringToInt(attr_text, &num_tracks)) {
+          LOG(ERROR) << "Failed to parse number of tracks";
+        }
+        break;
+      case BTRC_MEDIA_ATTR_ID_GENRE:
+        genre = attr_text;
+        break;
+      case BTRC_MEDIA_ATTR_ID_PLAYING_TIME:
+        if (!base::StringToInt(attr_text, &play_time)) {
+          LOG(ERROR) << "Failed to parse playing time";
+        }
+        break;
+      default:
+        NOTREACHED();
+    }
+  }
+
+  const AvrcpMediaAttr attr(title, artist, album, genre, track_num, num_tracks,
+                            play_time);
+
+  std::lock_guard<std::mutex> lock(delegate_mutex_);
+  if (delegate_) delegate_->OnTrackChanged(device_address, attr);
+}
+
+// AvrcpControlFactory implementation
+// ========================================================
+
+AvrcpControlFactory::AvrcpControlFactory() = default;
+AvrcpControlFactory::~AvrcpControlFactory() = default;
+
+bool AvrcpControlFactory::RegisterInstance(const Uuid& uuid,
+                                           const RegisterCallback& callback) {
+  VLOG(1) << __func__ << " - Uuid: " << uuid.ToString();
+
+  int control_id = next_control_id_++;
+  std::unique_ptr<AvrcpControl> hf_client(new AvrcpControl(uuid, control_id));
+  callback(BLE_STATUS_SUCCESS, uuid, std::move(hf_client));
+  return true;
+}
+
+}  // namespace bluetooth
diff --git a/service/avrcp_control.h b/service/avrcp_control.h
new file mode 100644
index 0000000..7cde24d
--- /dev/null
+++ b/service/avrcp_control.h
@@ -0,0 +1,135 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <atomic>
+#include <mutex>
+
+#include "base/macros.h"
+
+#include "bluetooth/uuid.h"
+#include "service/bluetooth_instance.h"
+#include "service/common/bluetooth/avrcp_media_attr.h"
+#include "service/common/bluetooth/service.h"
+#include "service/hal/bluetooth_avrcp_interface.h"
+
+namespace bluetooth {
+
+class AvrcpControl : public BluetoothInstance,
+                     private hal::BluetoothAvrcpInterface::ControlObserver {
+ public:
+  class Delegate {
+   public:
+    virtual void OnConnectionState(bool rc_connect, bool bt_connect,
+                                   const std::string& device_address) = 0;
+
+    virtual void OnTrackChanged(const std::string& device_address,
+                                const AvrcpMediaAttr& attr) = 0;
+
+    virtual void OnSetAbsVolumeRequest(const std::string& device_address,
+                                       int32_t abs_vol, int32_t label) = 0;
+
+    virtual void OnRegisterForAbsVolumeCallbackRequest(
+        const std::string& device_address, int32_t label) = 0;
+
+   protected:
+    virtual ~Delegate() = default;
+  };
+
+  // The destructor automatically unregisters this instance from the stack.
+  ~AvrcpControl() override;
+
+  // Assigns a delegate to this instance. |delegate| must out-live this
+  // AvrcpControl instance.
+  void SetDelegate(Delegate* delegate);
+
+  // BluetoothClientInstace overrides:
+  const Uuid& GetAppIdentifier() const override;
+  int GetInstanceId() const override;
+
+  bool Enable();
+  void Disable();
+
+  // Send a remote control button command. Commands which can be sent
+  // are defined here:
+  // http://1394ta.org/wp-content/uploads/2015/07/2007001.pdf
+  bool SendPassThroughCommand(const std::string& device_address,
+                              uint8_t key_code, bool key_pressed);
+
+  // Send a response to a request to change absolute volume.
+  bool SetAbsVolumeResponse(const std::string& device_address, int32_t abs_vol,
+                            int32_t label);
+
+  // Send a response to a register for absolute volume change callback.
+  bool RegisterForAbsVolumeCallbackResponse(const std::string& device_address,
+                                            int32_t response_type,
+                                            int32_t abs_vol, int32_t label);
+
+ private:
+  friend class AvrcpControlFactory;
+
+  // Constructor shouldn't be called directly as instances are meant to be
+  // obtained from the factory.
+  AvrcpControl(const Uuid& uuid, int control_id);
+
+  // hal::BluetoothAvrcpInterface::ControlObserver implementation:
+  void ConnectionStateCallback(bool rc_connect, bool bt_connect,
+                               const RawAddress& bd_addr) override;
+  void CtrlSetabsvolCmdCallback(const RawAddress& bd_addr, uint8_t abs_vol,
+                                uint8_t label) override;
+  void CtrlRegisternotificationAbsVolCallback(const RawAddress& bd_addr,
+                                              uint8_t label) override;
+  void CtrlTrackChangedCallback(const RawAddress& bd_addr, uint8_t num_attr,
+                                btrc_element_attr_val_t* p_attrs) override;
+
+  // See getters for documentation.
+  const Uuid app_identifier_;
+  const int control_id_;
+
+  // Mutex that synchronizes access to the entries below.
+  std::mutex mutex_;
+
+  // Raw handle to the Delegate, which must outlive this AvrcpControl instance.
+  std::mutex delegate_mutex_;
+  Delegate* delegate_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(AvrcpControl);
+};
+
+// AvrcpControlFactory is used to register and obtain a per-application
+// AvrcpControl
+// instance. Users should call RegisterClient to obtain their own unique
+// AvrcpControl instance that has been registered with the Bluetooth stack.
+class AvrcpControlFactory
+    : public BluetoothInstanceFactory,
+      private hal::BluetoothAvrcpInterface::ControlObserver {
+ public:
+  // Don't construct/destruct directly except in tests. Instead, obtain a handle
+  // from an Adapter instance.
+  AvrcpControlFactory();
+  ~AvrcpControlFactory() override;
+
+  // BluetoothInstanceFactory override:
+  bool RegisterInstance(const Uuid& uuid,
+                        const RegisterCallback& callback) override;
+
+ private:
+  std::atomic<int> next_control_id_{0};
+  DISALLOW_COPY_AND_ASSIGN(AvrcpControlFactory);
+};
+
+}  // namespace bluetooth
diff --git a/service/avrcp_target.cc b/service/avrcp_target.cc
new file mode 100644
index 0000000..fb63fba
--- /dev/null
+++ b/service/avrcp_target.cc
@@ -0,0 +1,381 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/avrcp_target.h"
+
+#include <algorithm>
+#include <cerrno>
+#include <climits>
+#include <string>
+
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/memory/ptr_util.h"
+#include "service/logging_helpers.h"
+
+#include "stack/include/avrc_defs.h"
+
+#define PARSE_ADDR(str)                                        \
+  ({                                                           \
+    RawAddress tmp;                                            \
+    if (!RawAddress::FromString((str), tmp)) {                 \
+      LOG(ERROR) << "Invalid device address given: " << (str); \
+      return false;                                            \
+    }                                                          \
+    tmp;                                                       \
+  })
+
+#define TRY_RET(expr, err_msg) \
+  do {                         \
+    if (!(expr)) {             \
+      LOG(ERROR) << err_msg;   \
+      return false;            \
+    }                          \
+    return true;               \
+  } while (0)
+
+#define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
+
+using LockGuard = std::lock_guard<std::mutex>;
+
+namespace bluetooth {
+
+namespace {
+
+std::vector<btrc_player_setting_text_t> StringValueToPlayerSettingsText(
+    const std::vector<AvrcpStringValue>& attrs) {
+  std::vector<btrc_player_setting_text_t> btrc_attrs(attrs.size());
+  for (size_t i = 0; i < attrs.size(); ++i) {
+    btrc_attrs[i].id = attrs[i].id();
+    std::string str(attrs[i].value());
+    size_t to_copy = std::min(sizeof(btrc_attrs[i].text) - 1, str.size());
+    if (to_copy < str.size()) {
+      LOG(WARNING) << "Value truncated";
+    }
+
+    memcpy(btrc_attrs[i].text, str.data(), to_copy);
+    btrc_attrs[i].text[to_copy] = '\0';
+  }
+
+  return btrc_attrs;
+}
+
+std::vector<btrc_element_attr_val_t> StringValueToElementAttrVal(
+    const std::vector<AvrcpStringValue>& attrs) {
+  std::vector<btrc_element_attr_val_t> btrc_attrs(attrs.size());
+  for (size_t i = 0; i < attrs.size(); ++i) {
+    btrc_attrs[i].attr_id = attrs[i].id();
+    std::string str(attrs[i].value());
+    size_t to_copy = std::min(sizeof(btrc_attrs[i].text) - 1, str.size());
+    if (to_copy < str.size()) {
+      LOG(WARNING) << "Value truncated";
+    }
+
+    memcpy(btrc_attrs[i].text, str.data(), to_copy);
+    btrc_attrs[i].text[to_copy] = '\0';
+  }
+
+  return btrc_attrs;
+}
+
+}  // namespace
+
+// static
+const int AvrcpTarget::kSingletonInstanceId = 0;
+
+AvrcpTarget::AvrcpTarget(const Uuid& uuid) : app_identifier_(uuid) {
+  hal::BluetoothAvrcpInterface::Get()->AddTargetObserver(this);
+}
+
+AvrcpTarget::~AvrcpTarget() {
+  hal::BluetoothAvrcpInterface::Get()->RemoveTargetObserver(this);
+}
+
+const Uuid& AvrcpTarget::GetAppIdentifier() const { return app_identifier_; }
+
+int AvrcpTarget::GetInstanceId() const { return kSingletonInstanceId; }
+
+void AvrcpTarget::SetDelegate(Delegate* delegate) {
+  LockGuard lock(delegate_mutex_);
+  delegate_ = delegate;
+}
+
+bool AvrcpTarget::Enable() {
+  LockGuard lock(mutex_);
+  return hal::BluetoothAvrcpInterface::Get()->AvrcpTargetEnable();
+}
+
+void AvrcpTarget::Disable() {
+  LockGuard lock(mutex_);
+  hal::BluetoothAvrcpInterface::Get()->AvrcpTargetDisable();
+}
+
+bool AvrcpTarget::GetPlayStatusResponse(const std::string& str_addr,
+                                        int32_t play_status, uint32_t song_len,
+                                        uint32_t song_pos) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->get_play_status_rsp(
+                       addr, static_cast<btrc_play_status_t>(play_status),
+                       song_len, song_pos) == BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::ListPlayerAppAttrResponse(const std::string& str_addr,
+                                            const std::vector<int32_t>& attrs) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+
+  std::vector<btrc_player_attr_t> btrc_attrs;
+  btrc_attrs.reserve(attrs.size());
+  for (auto attr : attrs) {
+    btrc_attrs.push_back(static_cast<btrc_player_attr_t>(attr));
+  }
+
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->list_player_app_attr_rsp(addr, btrc_attrs.size(),
+                                              btrc_attrs.data()) ==
+               BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::GetPlayerAppValueResponse(
+    const std::string& str_addr, const std::vector<AvrcpIntValue>& values) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+  btrc_player_settings_t btrc_values;
+  if (values.size() >= arraysize(btrc_values.attr_ids)) {
+    LOG(ERROR) << "Too many attribute values";
+    return false;
+  }
+
+  btrc_values.num_attr = values.size();
+  for (size_t i = 0; i < values.size(); ++i) {
+    btrc_values.attr_ids[i] = values[i].id();
+    btrc_values.attr_values[i] = values[i].value();
+  }
+
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->get_player_app_value_rsp(addr, &btrc_values) ==
+               BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::GetPlayerAppAttrTextResponse(
+    const std::string& str_addr, const std::vector<AvrcpStringValue>& attrs) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+  auto btrc_attrs = StringValueToPlayerSettingsText(attrs);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->get_player_app_attr_text_rsp(addr, btrc_attrs.size(),
+                                                  btrc_attrs.data()) ==
+               BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::GetPlayerAppValueTextResponse(
+    const std::string& str_addr, const std::vector<AvrcpStringValue>& values) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+  auto btrc_values = StringValueToPlayerSettingsText(values);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->get_player_app_value_text_rsp(addr, btrc_values.size(),
+                                                   btrc_values.data()) ==
+               BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::GetElementAttrResponse(
+    const std::string& str_addr, const std::vector<AvrcpStringValue>& attrs) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+  auto btrc_attrs = StringValueToElementAttrVal(attrs);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(
+      hal::BluetoothAvrcpInterface::Get()
+          ->GetTargetHALInterface()
+          ->get_element_attr_rsp(addr, btrc_attrs.size(), btrc_attrs.data()) ==
+      BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::SetPlayerAppValueResponse(const std::string& str_addr,
+                                            int32_t rsp_status) {
+  RawAddress addr = PARSE_ADDR(str_addr);
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->set_player_app_value_rsp(
+                       addr, static_cast<btrc_status_t>(rsp_status)) ==
+               BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::RegisterNotificationResponse(
+    int32_t event_id, int32_t type,
+    const AvrcpRegisterNotificationResponse& param) {
+  auto param_copy = param.data();
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(hal::BluetoothAvrcpInterface::Get()
+                   ->GetTargetHALInterface()
+                   ->register_notification_rsp(
+                       static_cast<btrc_event_id_t>(event_id),
+                       static_cast<btrc_notification_type_t>(type),
+                       &param_copy) == BT_STATUS_SUCCESS);
+}
+
+bool AvrcpTarget::SetVolume(int volume) {
+  LockGuard lock(mutex_);
+  TRY_RET_FUNC(
+      hal::BluetoothAvrcpInterface::Get()->GetTargetHALInterface()->set_volume(
+          volume) == BT_STATUS_SUCCESS);
+}
+
+void AvrcpTarget::RemoteFeaturesCallback(const RawAddress& bd_addr,
+                                         btrc_remote_features_t features) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnGetRemoteFeatures(str_addr, static_cast<int32_t>(features));
+}
+
+void AvrcpTarget::GetPlayStatusCallback(const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnGetPlayStatus(str_addr);
+}
+
+void AvrcpTarget::ListPlayerAppAttrCallback(const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnListPlayerAppAttr(str_addr);
+}
+
+void AvrcpTarget::ListPlayerAppValuesCallback(btrc_player_attr_t attr_id,
+                                              const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnListPlayerAppValues(str_addr, static_cast<int32_t>(attr_id));
+}
+
+void AvrcpTarget::GetPlayerAppValueCallback(uint8_t num_attr,
+                                            btrc_player_attr_t* p_attrs,
+                                            const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  std::vector<int32_t> attr_vec;
+  attr_vec.reserve(num_attr);
+  for (auto* it = p_attrs; it != p_attrs + num_attr; ++it) {
+    attr_vec.push_back(*it);
+  }
+
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnGetPlayerAppValue(str_addr, attr_vec);
+}
+
+void AvrcpTarget::GetPlayerAppAttrsTextCallback(uint8_t num_attr,
+                                                btrc_player_attr_t* p_attrs,
+                                                const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  std::vector<int32_t> attr_vec;
+  attr_vec.reserve(num_attr);
+  for (auto* it = p_attrs; it != p_attrs + num_attr; ++it) {
+    attr_vec.push_back(*it);
+  }
+
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnGetPlayerAppAttrsText(str_addr, attr_vec);
+}
+
+void AvrcpTarget::GetPlayerAppValuesTextCallback(uint8_t attr_id,
+                                                 uint8_t num_val,
+                                                 uint8_t* p_vals,
+                                                 const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  std::vector<int32_t> val_vec;
+  val_vec.reserve(num_val);
+  for (auto* it = p_vals; it != p_vals + num_val; ++it) {
+    val_vec.push_back(*it);
+  }
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnGetPlayerAppValuesText(str_addr, attr_id, val_vec);
+}
+
+void AvrcpTarget::SetPlayerAppValueCallback(btrc_player_settings_t* p_vals,
+                                            const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  std::vector<AvrcpIntValue> values;
+  values.reserve(p_vals->num_attr);
+  for (size_t i = 0; i < p_vals->num_attr; ++i) {
+    values.emplace_back(p_vals->attr_ids[i], p_vals->attr_values[i]);
+  }
+
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnSetPlayerAppValue(str_addr, values);
+}
+
+void AvrcpTarget::GetElementAttrCallback(uint8_t num_attr,
+                                         btrc_media_attr_t* p_attrs,
+                                         const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  std::vector<int32_t> attr_vec;
+  attr_vec.reserve(num_attr);
+  for (auto* it = p_attrs; it != p_attrs + num_attr; ++it) {
+    attr_vec.push_back(*it);
+  }
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnGetElementAttrs(str_addr, attr_vec);
+}
+
+void AvrcpTarget::RegisterNotificationCallback(btrc_event_id_t event_id,
+                                               uint32_t param,
+                                               const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_)
+    delegate_->OnRegisterNotification(str_addr, static_cast<int32_t>(event_id),
+                                      param);
+}
+
+void AvrcpTarget::VolumeChangeCallback(uint8_t volume, uint8_t ctype,
+                                       const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnVolumeChange(str_addr, volume, ctype);
+}
+
+void AvrcpTarget::PassthroughCmdCallback(int id, int key_state,
+                                         const RawAddress& bd_addr) {
+  auto str_addr = BtAddrString(&bd_addr);
+  LockGuard lock(delegate_mutex_);
+  if (delegate_) delegate_->OnPassThroughCommand(str_addr, id, key_state);
+}
+
+// AvrcpTargetFactory implementation
+// ========================================================
+
+AvrcpTargetFactory::AvrcpTargetFactory() = default;
+AvrcpTargetFactory::~AvrcpTargetFactory() = default;
+
+bool AvrcpTargetFactory::RegisterInstance(const Uuid& uuid,
+                                          const RegisterCallback& callback) {
+  VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
+
+  auto avrcp_target = base::WrapUnique(new AvrcpTarget(uuid));
+  callback(BLE_STATUS_SUCCESS, uuid, std::move(avrcp_target));
+  return true;
+}
+
+}  // namespace bluetooth
diff --git a/service/avrcp_target.h b/service/avrcp_target.h
new file mode 100644
index 0000000..8c2bcce
--- /dev/null
+++ b/service/avrcp_target.h
@@ -0,0 +1,179 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <mutex>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
+#include "service/common/bluetooth/avrcp_int_value.h"
+#include "service/common/bluetooth/avrcp_register_notification_response.h"
+#include "service/common/bluetooth/avrcp_string_value.h"
+
+#include "service/bluetooth_instance.h"
+#include "service/hal/bluetooth_avrcp_interface.h"
+
+namespace bluetooth {
+
+// Note: presently this only supports
+// (BTRC_FEAT_METADATA | BTRC_FEAT_ABSOLUTE_VOLUME)
+class AvrcpTarget : public BluetoothInstance,
+                    private hal::BluetoothAvrcpInterface::TargetObserver {
+ public:
+  // We only allow one instance of this object at a time.
+  static const int kSingletonInstanceId;
+
+  class Delegate {
+   public:
+    virtual void OnGetRemoteFeatures(const std::string& addr,
+                                     int32_t features) = 0;
+    virtual void OnGetPlayStatus(const std::string& addr) = 0;
+    virtual void OnListPlayerAppAttr(const std::string& addr) = 0;
+    virtual void OnListPlayerAppValues(const std::string& addr,
+                                       int32_t attr_id) = 0;
+    virtual void OnGetPlayerAppValue(const std::string& addr,
+                                     const std::vector<int32_t>& attrs) = 0;
+    virtual void OnGetPlayerAppAttrsText(const std::string& addr,
+                                         const std::vector<int32_t>& attrs) = 0;
+    virtual void OnGetPlayerAppValuesText(
+        const std::string& addr, int32_t attr_id,
+        const std::vector<int32_t>& values) = 0;
+    virtual void OnSetPlayerAppValue(
+        const std::string& addr, const std::vector<AvrcpIntValue>& values) = 0;
+    virtual void OnGetElementAttrs(const std::string& addr,
+                                   const std::vector<int32_t>& attrs) = 0;
+    virtual void OnRegisterNotification(const std::string& addr,
+                                        int32_t event_id, uint32_t param) = 0;
+    virtual void OnVolumeChange(const std::string& addr, int32_t volume,
+                                int32_t ctype) = 0;
+    virtual void OnPassThroughCommand(const std::string& addr, int32_t id,
+                                      int32_t key_state) = 0;
+
+   protected:
+    virtual ~Delegate() = default;
+  };
+
+  // The destructor automatically unregisters this instance from the stack.
+  ~AvrcpTarget() override;
+
+  // Assigns a delegate to this instance. |delegate| must out-live this
+  // AvrcpTarget instance.
+  void SetDelegate(Delegate* delegate);
+
+  // BluetoothClientInstace overrides:
+  const Uuid& GetAppIdentifier() const override;
+  int GetInstanceId() const override;
+
+  bool Enable();
+  void Disable();
+
+  bool GetPlayStatusResponse(const std::string& addr, int32_t play_status,
+                             uint32_t song_len, uint32_t song_pos);
+
+  bool ListPlayerAppAttrResponse(const std::string& addr,
+                                 const std::vector<int32_t>& attrs);
+
+  bool GetPlayerAppValueResponse(const std::string& addr,
+                                 const std::vector<AvrcpIntValue>& values);
+
+  bool GetPlayerAppAttrTextResponse(const std::string& addr,
+                                    const std::vector<AvrcpStringValue>& attrs);
+
+  bool GetPlayerAppValueTextResponse(
+      const std::string& addr, const std::vector<AvrcpStringValue>& attrs);
+
+  bool GetElementAttrResponse(const std::string& addr,
+                              const std::vector<AvrcpStringValue>& attrs);
+
+  bool SetPlayerAppValueResponse(const std::string& addr, int32_t rsp_status);
+
+  bool RegisterNotificationResponse(
+      int32_t event_id, int32_t type,
+      const AvrcpRegisterNotificationResponse& param);
+
+  bool SetVolume(int volume);
+
+ private:
+  friend class AvrcpTargetFactory;
+
+  // Constructor shouldn't be called directly as instances are meant to be
+  // obtained from the factory.
+  AvrcpTarget(const Uuid& uuid);
+
+  // hal::BluetoothAvrcpInterface::TargetObserver implementation:
+  void RemoteFeaturesCallback(const RawAddress& bd_addr,
+                              btrc_remote_features_t features) override;
+  void GetPlayStatusCallback(const RawAddress& bd_addr) override;
+  void ListPlayerAppAttrCallback(const RawAddress& bd_addr) override;
+  void ListPlayerAppValuesCallback(btrc_player_attr_t attr_id,
+                                   const RawAddress& bd_addr) override;
+  void GetPlayerAppValueCallback(uint8_t num_attr, btrc_player_attr_t* p_attrs,
+                                 const RawAddress& bd_addr) override;
+  void GetPlayerAppAttrsTextCallback(uint8_t num_attr,
+                                     btrc_player_attr_t* p_attrs,
+                                     const RawAddress& bd_addr) override;
+  void GetPlayerAppValuesTextCallback(uint8_t attr_id, uint8_t num_val,
+                                      uint8_t* p_vals,
+                                      const RawAddress& bd_addr) override;
+  void SetPlayerAppValueCallback(btrc_player_settings_t* p_vals,
+                                 const RawAddress& bd_addr) override;
+  void GetElementAttrCallback(uint8_t num_attr, btrc_media_attr_t* p_attrs,
+                              const RawAddress& bd_addr) override;
+  void RegisterNotificationCallback(btrc_event_id_t event_id, uint32_t param,
+                                    const RawAddress& bd_addr) override;
+  void VolumeChangeCallback(uint8_t volume, uint8_t ctype,
+                            const RawAddress& bd_addr) override;
+  void PassthroughCmdCallback(int id, int key_state,
+                              const RawAddress& bd_addr) override;
+
+  // See getters for documentation.
+  const Uuid app_identifier_;
+
+  // Mutex that synchronizes access to the entries below.
+  std::mutex mutex_;
+
+  // Raw handle to the Delegate, which must outlive this AvrcpTarget instance.
+  std::mutex delegate_mutex_;
+  Delegate* delegate_ = nullptr;
+
+  DISALLOW_COPY_AND_ASSIGN(AvrcpTarget);
+};
+
+// AvrcpTargetFactory is used to register and obtain a per-application
+// AvrcpTarget
+// instance. Users should call RegisterClient to obtain their own unique
+// AvrcpTarget instance that has been registered with the Bluetooth stack.
+class AvrcpTargetFactory
+    : public BluetoothInstanceFactory,
+      private hal::BluetoothAvrcpInterface::TargetObserver {
+ public:
+  // Don't construct/destruct directly except in tests. Instead, obtain a handle
+  // from an Adapter instance.
+  AvrcpTargetFactory();
+  ~AvrcpTargetFactory() override;
+
+  // BluetoothInstanceFactory override:
+  bool RegisterInstance(const Uuid& uuid,
+                        const RegisterCallback& callback) override;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(AvrcpTargetFactory);
+};
+
+}  // namespace bluetooth
diff --git a/service/client/main.cc b/service/client/main.cc
index e3b4c92..6458b2d 100644
--- a/service/client/main.cc
+++ b/service/client/main.cc
@@ -161,6 +161,60 @@
     return Status::ok();
   }
 
+  Status OnSspRequest(const String16& device_address,
+                      const String16& device_name, int32_t cod,
+                      int32_t pairing_variant, int32_t pass_key) override {
+    // no-op
+    return Status::ok();
+  }
+
+  Status OnGetBondedDevices(
+      int32_t status,
+      const ::std::vector<String16>& device_addresses) override {
+    BeginAsyncOut();
+    std::cout << "Bonded devices:\n";
+    for (const auto& device_address : device_addresses) {
+      std::cout << "    " << device_address << "\n";
+    }
+    EndAsyncOut();
+    return Status::ok();
+  }
+
+  Status OnBondStateChanged(int32_t status, const String16& device_address,
+                            int32_t state) override {
+    BeginAsyncOut();
+    std::cout << COLOR_BOLDWHITE "Device address: " << COLOR_BOLDYELLOW "["
+              << device_address << " bond state: " << state << " ] "
+              << COLOR_BOLDWHITE "- status: "
+              << (status == 0 ? "SUCCESS" : "FAIL") << COLOR_OFF;
+    EndAsyncOut();
+    return Status::ok();
+  }
+
+  Status OnGetRemoteDeviceProperties(
+      int32_t status, const String16& device_address,
+      const android::bluetooth::BluetoothRemoteDeviceProps& props) override {
+    // no-op
+    return Status::ok();
+  }
+
+  Status OnDeviceFound(
+      const android::bluetooth::BluetoothRemoteDeviceProps& props) override {
+    // no-op
+    return Status::ok();
+  }
+
+  Status OnDeviceConnectionStateChanged(const String16& device_address,
+                                        bool connected) override {
+    // no-op
+    return Status::ok();
+  }
+
+  Status OnScanEnableChanged(bool scan_enabled) override {
+    // no-op
+    return Status::ok();
+  }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(CLIBluetoothCallback);
 };
@@ -335,25 +389,8 @@
 }
 
 void HandleEnable(IBluetooth* bt_iface, const vector<string>& args) {
-  bool is_restricted_mode = false;
-
-  for (auto iter : args) {
-    const std::string& arg = iter;
-    if (arg == "-h") {
-      static const char kUsage[] =
-          "Usage: start-adv [flags]\n"
-          "\n"
-          "Flags:\n"
-          "\t--restricted|-r\tStart in restricted mode\n";
-      cout << kUsage << endl;
-      return;
-    } else if (arg == "--restricted" || arg == "-r") {
-      is_restricted_mode = true;
-    }
-  }
-
   bool status;
-  bt_iface->Enable(is_restricted_mode, &status);
+  bt_iface->Enable(&status);
   PrintCommandStatus(status);
 }
 
diff --git a/service/common/Android.bp b/service/common/Android.bp
index b3fbfc4..fa63cf9 100644
--- a/service/common/Android.bp
+++ b/service/common/Android.bp
@@ -9,11 +9,16 @@
     host_supported: true,
     header_libs: [ "libbluetooth_headers" ],
     srcs: [
+        "bluetooth/a2dp_codec_config.cc",
         "bluetooth/adapter_state.cc",
         "bluetooth/advertise_data.cc",
         "bluetooth/advertise_settings.cc",
+        "bluetooth/avrcp_int_value.cc",
+        "bluetooth/avrcp_media_attr.cc",
+        "bluetooth/avrcp_register_notification_response.cc",
         "bluetooth/characteristic.cc",
         "bluetooth/descriptor.cc",
+        "bluetooth/remote_device_props.cc",
         "bluetooth/scan_filter.cc",
         "bluetooth/scan_result.cc",
         "bluetooth/scan_settings.cc",
@@ -38,6 +43,14 @@
     header_libs: [ "libbluetooth_headers" ],
     srcs: [
         "android/bluetooth/IBluetooth.aidl",
+        "android/bluetooth/IBluetoothA2dpSink.aidl",
+        "android/bluetooth/IBluetoothA2dpSinkCallback.aidl",
+        "android/bluetooth/IBluetoothA2dpSource.aidl",
+        "android/bluetooth/IBluetoothA2dpSourceCallback.aidl",
+        "android/bluetooth/IBluetoothAvrcpControl.aidl",
+        "android/bluetooth/IBluetoothAvrcpControlCallback.aidl",
+        "android/bluetooth/IBluetoothAvrcpTarget.aidl",
+        "android/bluetooth/IBluetoothAvrcpTargetCallback.aidl",
         "android/bluetooth/IBluetoothCallback.aidl",
         "android/bluetooth/IBluetoothGattClient.aidl",
         "android/bluetooth/IBluetoothGattClientCallback.aidl",
@@ -51,10 +64,16 @@
         "android/bluetooth/IBluetoothLowEnergyCallback.aidl",
         "android/bluetooth/advertise_data.cc",
         "android/bluetooth/advertise_settings.cc",
+        "android/bluetooth/bluetooth_a2dp_codec_config.cc",
+        "android/bluetooth/bluetooth_avrcp_int_value.cc",
+        "android/bluetooth/bluetooth_avrcp_media_attr.cc",
+        "android/bluetooth/bluetooth_avrcp_register_notification_response.cc",
+        "android/bluetooth/bluetooth_avrcp_string_value.cc",
         "android/bluetooth/bluetooth_gatt_characteristic.cc",
         "android/bluetooth/bluetooth_gatt_descriptor.cc",
         "android/bluetooth/bluetooth_gatt_included_service.cc",
         "android/bluetooth/bluetooth_gatt_service.cc",
+        "android/bluetooth/bluetooth_remote_device_props.cc",
         "android/bluetooth/scan_filter.cc",
         "android/bluetooth/scan_result.cc",
         "android/bluetooth/scan_settings.cc",
diff --git a/tools/Android.bp b/service/common/android/bluetooth/BluetoothA2dpCodecConfig.aidl
similarity index 75%
copy from tools/Android.bp
copy to service/common/android/bluetooth/BluetoothA2dpCodecConfig.aidl
index 9f75ba7..083cd75 100644
--- a/tools/Android.bp
+++ b/service/common/android/bluetooth/BluetoothA2dpCodecConfig.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+parcelable BluetoothA2dpCodecConfig cpp_header "android/bluetooth/bluetooth_a2dp_codec_config.h";
diff --git a/tools/Android.bp b/service/common/android/bluetooth/BluetoothAvrcpIntValue.aidl
similarity index 75%
rename from tools/Android.bp
rename to service/common/android/bluetooth/BluetoothAvrcpIntValue.aidl
index 9f75ba7..e126393 100644
--- a/tools/Android.bp
+++ b/service/common/android/bluetooth/BluetoothAvrcpIntValue.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+parcelable BluetoothAvrcpIntValue cpp_header "android/bluetooth/bluetooth_avrcp_int_value.h";
diff --git a/tools/Android.bp b/service/common/android/bluetooth/BluetoothAvrcpMediaAttr.aidl
similarity index 75%
copy from tools/Android.bp
copy to service/common/android/bluetooth/BluetoothAvrcpMediaAttr.aidl
index 9f75ba7..03355ac 100644
--- a/tools/Android.bp
+++ b/service/common/android/bluetooth/BluetoothAvrcpMediaAttr.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+parcelable BluetoothAvrcpMediaAttr cpp_header "android/bluetooth/bluetooth_avrcp_media_attr.h";
diff --git a/tools/Android.bp b/service/common/android/bluetooth/BluetoothAvrcpRegisterNotificationResponse.aidl
similarity index 71%
copy from tools/Android.bp
copy to service/common/android/bluetooth/BluetoothAvrcpRegisterNotificationResponse.aidl
index 9f75ba7..147a187 100644
--- a/tools/Android.bp
+++ b/service/common/android/bluetooth/BluetoothAvrcpRegisterNotificationResponse.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+parcelable BluetoothAvrcpRegisterNotificationResponse cpp_header "android/bluetooth/bluetooth_avrcp_register_notification_response.h";
diff --git a/tools/Android.bp b/service/common/android/bluetooth/BluetoothAvrcpStringValue.aidl
similarity index 74%
copy from tools/Android.bp
copy to service/common/android/bluetooth/BluetoothAvrcpStringValue.aidl
index 9f75ba7..5bbfbd4 100644
--- a/tools/Android.bp
+++ b/service/common/android/bluetooth/BluetoothAvrcpStringValue.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+parcelable BluetoothAvrcpStringValue cpp_header "android/bluetooth/bluetooth_avrcp_string_value.h";
diff --git a/tools/Android.bp b/service/common/android/bluetooth/BluetoothRemoteDeviceProps.aidl
similarity index 74%
copy from tools/Android.bp
copy to service/common/android/bluetooth/BluetoothRemoteDeviceProps.aidl
index 9f75ba7..db80295 100644
--- a/tools/Android.bp
+++ b/service/common/android/bluetooth/BluetoothRemoteDeviceProps.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright (C) 2017 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+package android.bluetooth;
+
+parcelable BluetoothRemoteDeviceProps cpp_header "android/bluetooth/bluetooth_remote_device_props.h";
diff --git a/service/common/android/bluetooth/IBluetooth.aidl b/service/common/android/bluetooth/IBluetooth.aidl
index cc1e015..46c7654 100644
--- a/service/common/android/bluetooth/IBluetooth.aidl
+++ b/service/common/android/bluetooth/IBluetooth.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,13 +22,17 @@
 import android.bluetooth.IBluetoothLeScanner;
 import android.bluetooth.IBluetoothGattClient;
 import android.bluetooth.IBluetoothGattServer;
+import android.bluetooth.IBluetoothA2dpSink;
+import android.bluetooth.IBluetoothA2dpSource;
+import android.bluetooth.IBluetoothAvrcpControl;
+import android.bluetooth.IBluetoothAvrcpTarget;
 
 import android.bluetooth.UUID;
 
 interface IBluetooth {
   boolean IsEnabled();
   int GetState();
-  boolean Enable(boolean startRestricted);
+  boolean Enable();
   boolean EnableNoAutoConnect();
   boolean Disable();
 
@@ -36,6 +40,17 @@
   UUID[] GetUUIDs();
   boolean SetName(String name);
   String GetName();
+  boolean SetScanMode(int scan_mode);
+  boolean SetScanEnable(boolean scan_enable);
+  boolean SspReply(
+      String device_address,
+      int variant,
+      boolean accept,
+      int passkey);
+  boolean CreateBond(String device_address, int transport);
+  boolean GetBondedDevices();
+  boolean RemoveBond(String device_address);
+  boolean GetRemoteDeviceProperties(String device_address);
 
   void RegisterCallback(IBluetoothCallback callback);
   void UnregisterCallback(IBluetoothCallback callback);
@@ -47,4 +62,8 @@
   IBluetoothLeScanner GetLeScannerInterface();
   IBluetoothGattClient GetGattClientInterface();
   IBluetoothGattServer GetGattServerInterface();
+  IBluetoothA2dpSink GetA2dpSinkInterface();
+  IBluetoothA2dpSource GetA2dpSourceInterface();
+  IBluetoothAvrcpControl GetAvrcpControlInterface();
+  IBluetoothAvrcpTarget GetAvrcpTargetInterface();
 }
diff --git a/service/common/android/bluetooth/IBluetoothA2dpSink.aidl b/service/common/android/bluetooth/IBluetoothA2dpSink.aidl
new file mode 100644
index 0000000..dec7d28
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothA2dpSink.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetoothA2dpSinkCallback;
+
+interface IBluetoothA2dpSink {
+  boolean Register(in IBluetoothA2dpSinkCallback callback);
+  void Unregister();
+
+  boolean Enable();
+  boolean Disable();
+  boolean Connect(String device_address);
+  boolean Disconnect(String device_address);
+  boolean SetAudioFocusState(int state);
+  boolean SetAudioTrackGain(float gain);
+}
diff --git a/service/common/android/bluetooth/IBluetoothA2dpSinkCallback.aidl b/service/common/android/bluetooth/IBluetoothA2dpSinkCallback.aidl
new file mode 100644
index 0000000..e12be24
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothA2dpSinkCallback.aidl
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+oneway interface IBluetoothA2dpSinkCallback {
+    void OnRegistered(int status);
+    void OnConnectionState(String device_address, int state);
+    void OnAudioState(String device_address, int state);
+    void OnAudioConfig(String device_address, int sample_rate, int channel_count);
+}
diff --git a/service/common/android/bluetooth/IBluetoothA2dpSource.aidl b/service/common/android/bluetooth/IBluetoothA2dpSource.aidl
new file mode 100644
index 0000000..344292c
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothA2dpSource.aidl
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetoothA2dpSourceCallback;
+import android.bluetooth.BluetoothA2dpCodecConfig;
+
+interface IBluetoothA2dpSource {
+  boolean Register(in IBluetoothA2dpSourceCallback callback);
+  void Unregister();
+
+  boolean Enable(in BluetoothA2dpCodecConfig[] codec_priorities);
+  boolean Disable();
+  boolean Connect(String device_address);
+  boolean Disconnect(String device_address);
+  boolean ConfigCodec(String device_address,
+                      in BluetoothA2dpCodecConfig[] codec_preferences);
+
+}
diff --git a/service/common/android/bluetooth/IBluetoothA2dpSourceCallback.aidl b/service/common/android/bluetooth/IBluetoothA2dpSourceCallback.aidl
new file mode 100644
index 0000000..4d4a82d
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothA2dpSourceCallback.aidl
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothA2dpCodecConfig;
+
+oneway interface IBluetoothA2dpSourceCallback {
+    void OnRegistered(int status);
+    void OnConnectionState(String device_address, int state);
+    void OnAudioState(String device_address, int state);
+    void OnAudioConfig(
+        String device_address,
+        in BluetoothA2dpCodecConfig codec_config,
+        in BluetoothA2dpCodecConfig[] codecs_local_capabilities,
+        in BluetoothA2dpCodecConfig[] codecs_selectable_capabilities);
+}
diff --git a/service/common/android/bluetooth/IBluetoothAvrcpControl.aidl b/service/common/android/bluetooth/IBluetoothAvrcpControl.aidl
new file mode 100644
index 0000000..0e65a71
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothAvrcpControl.aidl
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetoothAvrcpControlCallback;
+
+interface IBluetoothAvrcpControl {
+  boolean Register(in IBluetoothAvrcpControlCallback callback);
+  void Unregister(int id);
+  void UnregisterAll();
+
+  boolean Enable(int id);
+  boolean Disable(int id);
+
+  boolean SendPassThroughCommand(int id, String device_address,
+      int key_code, boolean key_pressed);
+
+  boolean SetAbsVolumeResponse(int id, String device_address, int abs_vol,
+      int label);
+
+  boolean RegisterForAbsVolumeCallbackResponse(int id, String device_address,
+      int response_type, int abs_vol, int label);
+}
diff --git a/service/common/android/bluetooth/IBluetoothAvrcpControlCallback.aidl b/service/common/android/bluetooth/IBluetoothAvrcpControlCallback.aidl
new file mode 100644
index 0000000..68f0db2
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothAvrcpControlCallback.aidl
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothAvrcpMediaAttr;
+
+oneway interface IBluetoothAvrcpControlCallback {
+  void OnRegistered(int status, int id);
+  void OnConnectionState(
+      boolean rc_connect,
+      boolean bt_connect,
+      String device_address);
+
+  void OnTrackChanged(String device_address, in BluetoothAvrcpMediaAttr track_info);
+  void OnSetAbsVolumeRequest(String device_address, int abs_vol, int label);
+  void OnRegisterForAbsVolumeCallbackRequest(String device_address, int label);
+}
diff --git a/service/common/android/bluetooth/IBluetoothAvrcpTarget.aidl b/service/common/android/bluetooth/IBluetoothAvrcpTarget.aidl
new file mode 100644
index 0000000..6654f86
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothAvrcpTarget.aidl
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.IBluetoothAvrcpTargetCallback;
+
+import android.bluetooth.BluetoothAvrcpIntValue;
+import android.bluetooth.BluetoothAvrcpStringValue;
+import android.bluetooth.BluetoothAvrcpRegisterNotificationResponse;
+
+interface IBluetoothAvrcpTarget {
+  boolean Register(in IBluetoothAvrcpTargetCallback callback);
+  void Unregister(int id);
+  void UnregisterAll();
+
+  boolean Enable();
+  boolean Disable();
+
+  boolean GetPlayStatusResponse(String addr,
+      int play_status, int song_len, int song_pos);
+
+  boolean ListPlayerAppAttrResponse(String addr, in int[] attrs);
+
+  boolean GetPlayerAppValueResponse(String addr,
+      in BluetoothAvrcpIntValue[] values);
+
+  boolean GetPlayerAppAttrTextResponse(String addr,
+      in BluetoothAvrcpStringValue[] attrs);
+
+  boolean GetPlayerAppValueTextResponse(String addr,
+      in BluetoothAvrcpStringValue[] values);
+
+  boolean GetElementAttrResponse(String addr,
+      in BluetoothAvrcpStringValue[] attrs);
+
+  boolean SetPlayerAppValueResponse(String addr, int rsp_status);
+
+  boolean RegisterNotificationResponse(
+      int event_id,
+      int type,
+      in BluetoothAvrcpRegisterNotificationResponse param);
+
+  boolean SetVolume(int volume);
+}
diff --git a/service/common/android/bluetooth/IBluetoothAvrcpTargetCallback.aidl b/service/common/android/bluetooth/IBluetoothAvrcpTargetCallback.aidl
new file mode 100644
index 0000000..15d45f3
--- /dev/null
+++ b/service/common/android/bluetooth/IBluetoothAvrcpTargetCallback.aidl
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+package android.bluetooth;
+
+import android.bluetooth.BluetoothAvrcpIntValue;
+
+oneway interface IBluetoothAvrcpTargetCallback {
+  void OnRegistered(int status);
+  void OnGetRemoteFeatures(String addr, int features);
+  void OnGetPlayStatus(String addr);
+  void OnListPlayerAppAttr(String addr);
+  void OnListPlayerAppValues(String addr, int attr_id);
+  void OnGetPlayerAppValue(String addr, in int[] attrs);
+  void OnGetPlayerAppAttrsText(String addr, in int[] attrs);
+  void OnGetPlayerAppValuesText(String addr, int attr_id, in int[] values);
+  void OnSetPlayerAppValue(String addr, in BluetoothAvrcpIntValue[] values);
+  void OnGetElementAttrs(String addr, in int[] attrs);
+  void OnRegisterNotification(String addr, int event_id, int param);
+  void OnVolumeChange(String addr, int volume, int ctype);
+  void OnPassThroughCommand(String addr, int id, int key_state);
+}
diff --git a/service/common/android/bluetooth/IBluetoothCallback.aidl b/service/common/android/bluetooth/IBluetoothCallback.aidl
index 96b7cdc..a83d5d8 100644
--- a/service/common/android/bluetooth/IBluetoothCallback.aidl
+++ b/service/common/android/bluetooth/IBluetoothCallback.aidl
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 The Android Open Source Project
+ * Copyright (C) 2016 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -16,6 +16,26 @@
 
 package android.bluetooth;
 
+import android.bluetooth.BluetoothRemoteDeviceProps;
+
 oneway interface IBluetoothCallback {
-   void OnBluetoothStateChange(int prev_state, int new_state);
+    void OnBluetoothStateChange(int prev_state, int new_state);
+    void OnScanEnableChanged(boolean scan_enabled);
+    void OnDeviceConnectionStateChanged(
+        String device_address,
+        boolean connected);
+    void OnSspRequest(
+        String device_address,
+        String device_name,
+        int cod,
+        int pairing_variant,
+        int pass_key);
+    void OnGetBondedDevices(int status, in String[] device_addresses);
+    void OnBondStateChanged(int status, String device_address, int state);
+    void OnGetRemoteDeviceProperties(
+        int status,
+        String device_address,
+        in BluetoothRemoteDeviceProps props);
+    void OnDeviceFound(
+        in BluetoothRemoteDeviceProps props);
 }
diff --git a/service/common/android/bluetooth/bluetooth_a2dp_codec_config.cc b/service/common/android/bluetooth/bluetooth_a2dp_codec_config.cc
new file mode 100644
index 0000000..8e7b709
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_a2dp_codec_config.cc
@@ -0,0 +1,103 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_a2dp_codec_config.h"
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+using android::OK;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothA2dpCodecConfig::writeToParcel(Parcel* parcel) const {
+  status_t status = parcel->writeInt32(codec_type_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(codec_priority_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(sample_rate_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(bits_per_sample_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(channel_mode_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt64(codec_specific_1_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt64(codec_specific_2_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt64(codec_specific_3_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt64(codec_specific_4_);
+  if (status != OK) return status;
+
+  return status;
+}
+
+status_t BluetoothA2dpCodecConfig::readFromParcel(const Parcel* parcel) {
+  int32_t tmp;
+  status_t status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  codec_type_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  codec_priority_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  sample_rate_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  bits_per_sample_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  channel_mode_ = tmp;
+
+  int64_t tmp64;
+  status = parcel->readInt64(&tmp64);
+  if (status != OK) return status;
+  codec_specific_1_ = tmp64;
+
+  status = parcel->readInt64(&tmp64);
+  if (status != OK) return status;
+  codec_specific_2_ = tmp64;
+
+  status = parcel->readInt64(&tmp64);
+  if (status != OK) return status;
+  codec_specific_3_ = tmp64;
+
+  status = parcel->readInt64(&tmp64);
+  if (status != OK) return status;
+  codec_specific_4_ = tmp64;
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/binder/android/os/parcel_file_descriptor.h b/service/common/android/bluetooth/bluetooth_a2dp_codec_config.h
similarity index 60%
copy from binder/android/os/parcel_file_descriptor.h
copy to service/common/android/bluetooth/bluetooth_a2dp_codec_config.h
index a37b49c..0071d67 100644
--- a/binder/android/os/parcel_file_descriptor.h
+++ b/service/common/android/bluetooth/bluetooth_a2dp_codec_config.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2017, The Android Open Source Project
+//  Copyright (C) 2017 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -19,34 +19,39 @@
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 
-namespace android {
-namespace os {
+#include "bluetooth/a2dp_codec_config.h"
 
-class ParcelFileDescriptor : public android::Parcelable {
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothA2dpCodecConfig : public Parcelable,
+                                 public ::bluetooth::A2dpCodecConfig {
  public:
-  ParcelFileDescriptor() : fd_(-1), takeOwnership_(false) {}
-  ~ParcelFileDescriptor() = default;
+  BluetoothA2dpCodecConfig() = default;
+  BluetoothA2dpCodecConfig(const ::bluetooth::A2dpCodecConfig& other)
+      : ::bluetooth::A2dpCodecConfig(other) {}  // NOLINT(implicit)
+  BluetoothA2dpCodecConfig(const BluetoothA2dpCodecConfig& other)
+      : ::bluetooth::A2dpCodecConfig(other) {}  // NOLINT(implicit)
+  ~BluetoothA2dpCodecConfig() = default;
 
   // Write |this| parcelable to the given |parcel|.  Keep in mind that
   // implementations of writeToParcel must be manually kept in sync
   // with readFromParcel and the Java equivalent versions of these methods.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t writeToParcel(android::Parcel* parcel) const override;
+  status_t writeToParcel(Parcel* parcel) const override;
 
   // Read data from the given |parcel| into |this|.  After readFromParcel
   // completes, |this| should have equivalent state to the object that
   // wrote itself to the parcel.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t readFromParcel(const android::Parcel* parcel) override;
-
-  void setFileDescriptor(int fd, bool takeOwnership);
-
- private:
-  int fd_;
-  bool takeOwnership_;
+  status_t readFromParcel(const Parcel* parcel) override;
 };
 
-}  // namespace os
+}  // namespace bluetooth
 }  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_avrcp_int_value.cc b/service/common/android/bluetooth/bluetooth_avrcp_int_value.cc
new file mode 100644
index 0000000..c2a895c
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_int_value.cc
@@ -0,0 +1,53 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_avrcp_int_value.h"
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+using android::OK;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothAvrcpIntValue::writeToParcel(Parcel* parcel) const {
+  status_t status = parcel->writeInt32(id_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(value_);
+  if (status != OK) return status;
+
+  return status;
+}
+
+status_t BluetoothAvrcpIntValue::readFromParcel(const Parcel* parcel) {
+  int32_t tmp;
+  status_t status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  id_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  value_ = tmp;
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/binder/android/os/parcel_file_descriptor.h b/service/common/android/bluetooth/bluetooth_avrcp_int_value.h
similarity index 61%
rename from binder/android/os/parcel_file_descriptor.h
rename to service/common/android/bluetooth/bluetooth_avrcp_int_value.h
index a37b49c..80eed7c 100644
--- a/binder/android/os/parcel_file_descriptor.h
+++ b/service/common/android/bluetooth/bluetooth_avrcp_int_value.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2017, The Android Open Source Project
+//  Copyright (C) 2017 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -19,34 +19,39 @@
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 
-namespace android {
-namespace os {
+#include "bluetooth/avrcp_int_value.h"
 
-class ParcelFileDescriptor : public android::Parcelable {
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothAvrcpIntValue : public Parcelable,
+                               public ::bluetooth::AvrcpIntValue {
  public:
-  ParcelFileDescriptor() : fd_(-1), takeOwnership_(false) {}
-  ~ParcelFileDescriptor() = default;
+  BluetoothAvrcpIntValue() = default;
+  BluetoothAvrcpIntValue(const ::bluetooth::AvrcpIntValue& other)
+      : ::bluetooth::AvrcpIntValue(other) {}  // NOLINT(implicit)
+  BluetoothAvrcpIntValue(const BluetoothAvrcpIntValue& other)
+      : ::bluetooth::AvrcpIntValue(other) {}  // NOLINT(implicit)
+  ~BluetoothAvrcpIntValue() = default;
 
   // Write |this| parcelable to the given |parcel|.  Keep in mind that
   // implementations of writeToParcel must be manually kept in sync
   // with readFromParcel and the Java equivalent versions of these methods.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t writeToParcel(android::Parcel* parcel) const override;
+  status_t writeToParcel(Parcel* parcel) const override;
 
   // Read data from the given |parcel| into |this|.  After readFromParcel
   // completes, |this| should have equivalent state to the object that
   // wrote itself to the parcel.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t readFromParcel(const android::Parcel* parcel) override;
-
-  void setFileDescriptor(int fd, bool takeOwnership);
-
- private:
-  int fd_;
-  bool takeOwnership_;
+  status_t readFromParcel(const Parcel* parcel) override;
 };
 
-}  // namespace os
+}  // namespace bluetooth
 }  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_avrcp_media_attr.cc b/service/common/android/bluetooth/bluetooth_avrcp_media_attr.cc
new file mode 100644
index 0000000..b29204e
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_media_attr.cc
@@ -0,0 +1,93 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_avrcp_media_attr.h"
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+using android::OK;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothAvrcpMediaAttr::writeToParcel(Parcel* parcel) const {
+  status_t status =
+      parcel->writeString16(String16(title_.c_str(), title_.size()));
+  if (status != OK) return status;
+
+  status = parcel->writeString16(String16(artist_.c_str(), artist_.size()));
+  if (status != OK) return status;
+
+  status = parcel->writeString16(String16(album_.c_str(), album_.size()));
+  if (status != OK) return status;
+
+  status = parcel->writeString16(String16(genre_.c_str(), genre_.size()));
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(track_num_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(num_tracks_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(play_time_);
+  if (status != OK) return status;
+
+  return status;
+}
+
+status_t BluetoothAvrcpMediaAttr::readFromParcel(const Parcel* parcel) {
+  String16 title;
+  status_t status = parcel->readString16(&title);
+  if (status != OK) return status;
+  title_ = String8(title).string();
+
+  String16 artist;
+  status = parcel->readString16(&artist);
+  if (status != OK) return status;
+  artist_ = String8(artist).string();
+
+  String16 album;
+  status = parcel->readString16(&album);
+  if (status != OK) return status;
+  album_ = String8(album).string();
+
+  String16 genre;
+  status = parcel->readString16(&genre);
+  if (status != OK) return status;
+  genre_ = String8(genre).string();
+
+  int32_t tmp;
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  track_num_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  num_tracks_ = tmp;
+
+  status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  play_time_ = tmp;
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/binder/android/os/parcel_file_descriptor.h b/service/common/android/bluetooth/bluetooth_avrcp_media_attr.h
similarity index 61%
copy from binder/android/os/parcel_file_descriptor.h
copy to service/common/android/bluetooth/bluetooth_avrcp_media_attr.h
index a37b49c..d41fef6 100644
--- a/binder/android/os/parcel_file_descriptor.h
+++ b/service/common/android/bluetooth/bluetooth_avrcp_media_attr.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2017, The Android Open Source Project
+//  Copyright (C) 2017 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -19,34 +19,39 @@
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 
-namespace android {
-namespace os {
+#include "bluetooth/avrcp_media_attr.h"
 
-class ParcelFileDescriptor : public android::Parcelable {
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothAvrcpMediaAttr : public Parcelable,
+                                public ::bluetooth::AvrcpMediaAttr {
  public:
-  ParcelFileDescriptor() : fd_(-1), takeOwnership_(false) {}
-  ~ParcelFileDescriptor() = default;
+  BluetoothAvrcpMediaAttr() = default;
+  BluetoothAvrcpMediaAttr(const ::bluetooth::AvrcpMediaAttr& other)
+      : ::bluetooth::AvrcpMediaAttr(other) {}  // NOLINT(implicit)
+  BluetoothAvrcpMediaAttr(const BluetoothAvrcpMediaAttr& other)
+      : ::bluetooth::AvrcpMediaAttr(other) {}  // NOLINT(implicit)
+  ~BluetoothAvrcpMediaAttr() = default;
 
   // Write |this| parcelable to the given |parcel|.  Keep in mind that
   // implementations of writeToParcel must be manually kept in sync
   // with readFromParcel and the Java equivalent versions of these methods.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t writeToParcel(android::Parcel* parcel) const override;
+  status_t writeToParcel(Parcel* parcel) const override;
 
   // Read data from the given |parcel| into |this|.  After readFromParcel
   // completes, |this| should have equivalent state to the object that
   // wrote itself to the parcel.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t readFromParcel(const android::Parcel* parcel) override;
-
-  void setFileDescriptor(int fd, bool takeOwnership);
-
- private:
-  int fd_;
-  bool takeOwnership_;
+  status_t readFromParcel(const Parcel* parcel) override;
 };
 
-}  // namespace os
+}  // namespace bluetooth
 }  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_avrcp_register_notification_response.cc b/service/common/android/bluetooth/bluetooth_avrcp_register_notification_response.cc
new file mode 100644
index 0000000..2ff5a17
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_register_notification_response.cc
@@ -0,0 +1,46 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_avrcp_register_notification_response.h"
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+using android::OK;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothAvrcpRegisterNotificationResponse::writeToParcel(
+    Parcel* parcel) const {
+  status_t status = parcel->write(&data_, sizeof(data_));
+  if (status != OK) return status;
+
+  return status;
+}
+
+status_t BluetoothAvrcpRegisterNotificationResponse::readFromParcel(
+    const Parcel* parcel) {
+  status_t status = parcel->read(&data_, sizeof(data_));
+  if (status != OK) return status;
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_avrcp_register_notification_response.h b/service/common/android/bluetooth/bluetooth_avrcp_register_notification_response.h
new file mode 100644
index 0000000..0a34d1e
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_register_notification_response.h
@@ -0,0 +1,60 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <binder/Parcel.h>
+#include <binder/Parcelable.h>
+
+#include "bluetooth/avrcp_register_notification_response.h"
+
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothAvrcpRegisterNotificationResponse
+    : public Parcelable,
+      public ::bluetooth::AvrcpRegisterNotificationResponse {
+ public:
+  BluetoothAvrcpRegisterNotificationResponse() = default;
+  BluetoothAvrcpRegisterNotificationResponse(
+      const AvrcpRegisterNotificationResponse& other)
+      : ::bluetooth::AvrcpRegisterNotificationResponse(other) {}
+  BluetoothAvrcpRegisterNotificationResponse(
+      const BluetoothAvrcpRegisterNotificationResponse& other)
+      : ::bluetooth::AvrcpRegisterNotificationResponse(other) {}
+  ~BluetoothAvrcpRegisterNotificationResponse() = default;
+
+  // Write |this| parcelable to the given |parcel|.  Keep in mind that
+  // implementations of writeToParcel must be manually kept in sync
+  // with readFromParcel and the Java equivalent versions of these methods.
+  //
+  // Returns android::OK on success and an appropriate error otherwise.
+  status_t writeToParcel(Parcel* parcel) const override;
+
+  // Read data from the given |parcel| into |this|.  After readFromParcel
+  // completes, |this| should have equivalent state to the object that
+  // wrote itself to the parcel.
+  //
+  // Returns android::OK on success and an appropriate error otherwise.
+  status_t readFromParcel(const Parcel* parcel) override;
+};
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_avrcp_string_value.cc b/service/common/android/bluetooth/bluetooth_avrcp_string_value.cc
new file mode 100644
index 0000000..ded9105
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_string_value.cc
@@ -0,0 +1,54 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_avrcp_string_value.h"
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+using android::OK;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothAvrcpStringValue::writeToParcel(Parcel* parcel) const {
+  status_t status = parcel->writeInt32(id_);
+  if (status != OK) return status;
+
+  status = parcel->writeString16(String16(value_.c_str(), value_.size()));
+  if (status != OK) return status;
+
+  return status;
+}
+
+status_t BluetoothAvrcpStringValue::readFromParcel(const Parcel* parcel) {
+  int32_t tmp;
+  status_t status = parcel->readInt32(&tmp);
+  if (status != OK) return status;
+  id_ = tmp;
+
+  String16 value;
+  status = parcel->readString16(&value);
+  if (status != OK) return status;
+  value_ = String8(value).string();
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/binder/android/os/parcel_file_descriptor.h b/service/common/android/bluetooth/bluetooth_avrcp_string_value.h
similarity index 60%
copy from binder/android/os/parcel_file_descriptor.h
copy to service/common/android/bluetooth/bluetooth_avrcp_string_value.h
index a37b49c..8f7e952 100644
--- a/binder/android/os/parcel_file_descriptor.h
+++ b/service/common/android/bluetooth/bluetooth_avrcp_string_value.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2017, The Android Open Source Project
+//  Copyright (C) 2017 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -19,34 +19,39 @@
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 
-namespace android {
-namespace os {
+#include "bluetooth/avrcp_string_value.h"
 
-class ParcelFileDescriptor : public android::Parcelable {
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothAvrcpStringValue : public Parcelable,
+                                  public ::bluetooth::AvrcpStringValue {
  public:
-  ParcelFileDescriptor() : fd_(-1), takeOwnership_(false) {}
-  ~ParcelFileDescriptor() = default;
+  BluetoothAvrcpStringValue() = default;
+  BluetoothAvrcpStringValue(const ::bluetooth::AvrcpStringValue& other)
+      : ::bluetooth::AvrcpStringValue(other) {}  // NOLINT(implicit)
+  BluetoothAvrcpStringValue(const BluetoothAvrcpStringValue& other)
+      : ::bluetooth::AvrcpStringValue(other) {}  // NOLINT(implicit)
+  ~BluetoothAvrcpStringValue() = default;
 
   // Write |this| parcelable to the given |parcel|.  Keep in mind that
   // implementations of writeToParcel must be manually kept in sync
   // with readFromParcel and the Java equivalent versions of these methods.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t writeToParcel(android::Parcel* parcel) const override;
+  status_t writeToParcel(Parcel* parcel) const override;
 
   // Read data from the given |parcel| into |this|.  After readFromParcel
   // completes, |this| should have equivalent state to the object that
   // wrote itself to the parcel.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t readFromParcel(const android::Parcel* parcel) override;
-
-  void setFileDescriptor(int fd, bool takeOwnership);
-
- private:
-  int fd_;
-  bool takeOwnership_;
+  status_t readFromParcel(const Parcel* parcel) override;
 };
 
-}  // namespace os
+}  // namespace bluetooth
 }  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_remote_device_props.cc b/service/common/android/bluetooth/bluetooth_remote_device_props.cc
new file mode 100644
index 0000000..21974da
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_remote_device_props.cc
@@ -0,0 +1,91 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "android/bluetooth/bluetooth_remote_device_props.h"
+
+#include <utils/String16.h>
+#include <utils/String8.h>
+
+#include "android/bluetooth/uuid.h"
+
+using android::OK;
+using android::String16;
+using android::String8;
+
+namespace android {
+namespace bluetooth {
+
+status_t BluetoothRemoteDeviceProps::writeToParcel(Parcel* parcel) const {
+  status_t status =
+      parcel->writeString16(String16(name_.c_str(), name_.size()));
+  if (status != OK) return status;
+
+  status = parcel->writeString16(String16(address_.c_str(), address_.size()));
+  if (status != OK) return status;
+
+  std::vector<UUID> uuids;
+  for (const auto& uuid : service_uuids_) {
+    uuids.push_back(uuid);
+  }
+
+  status = parcel->writeParcelableVector(uuids);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(device_class_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(device_type_);
+  if (status != OK) return status;
+
+  status = parcel->writeInt32(rssi_);
+  if (status != OK) return status;
+
+  return status;
+}
+
+status_t BluetoothRemoteDeviceProps::readFromParcel(const Parcel* parcel) {
+  String16 name;
+  status_t status = parcel->readString16(&name);
+  if (status != OK) return status;
+  name_ = String8(name).string();
+
+  String16 address;
+  status = parcel->readString16(&address);
+  if (status != OK) return status;
+  address_ = String8(address).string();
+
+  std::vector<UUID> uuids;
+  status = parcel->readParcelableVector(&uuids);
+  if (status != OK) return status;
+
+  for (const auto& uuid : uuids) {
+    service_uuids_.push_back(uuid.uuid);
+  }
+
+  status = parcel->readInt32(&device_class_);
+  if (status != OK) return status;
+
+  status = parcel->readInt32(&device_type_);
+  if (status != OK) return status;
+
+  status = parcel->readInt32(&rssi_);
+  if (status != OK) return status;
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/binder/android/os/parcel_file_descriptor.h b/service/common/android/bluetooth/bluetooth_remote_device_props.h
similarity index 60%
copy from binder/android/os/parcel_file_descriptor.h
copy to service/common/android/bluetooth/bluetooth_remote_device_props.h
index a37b49c..e2ad346 100644
--- a/binder/android/os/parcel_file_descriptor.h
+++ b/service/common/android/bluetooth/bluetooth_remote_device_props.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2017, The Android Open Source Project
+//  Copyright (C) 2017 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -19,34 +19,39 @@
 #include <binder/Parcel.h>
 #include <binder/Parcelable.h>
 
-namespace android {
-namespace os {
+#include "bluetooth/remote_device_props.h"
 
-class ParcelFileDescriptor : public android::Parcelable {
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothRemoteDeviceProps : public Parcelable,
+                                   public ::bluetooth::RemoteDeviceProps {
  public:
-  ParcelFileDescriptor() : fd_(-1), takeOwnership_(false) {}
-  ~ParcelFileDescriptor() = default;
+  BluetoothRemoteDeviceProps() = default;
+  BluetoothRemoteDeviceProps(const ::bluetooth::RemoteDeviceProps& other)
+      : ::bluetooth::RemoteDeviceProps(other) {}  // NOLINT(implicit)
+  BluetoothRemoteDeviceProps(const BluetoothRemoteDeviceProps& other)
+      : ::bluetooth::RemoteDeviceProps(other) {}  // NOLINT(implicit)
+  ~BluetoothRemoteDeviceProps() = default;
 
   // Write |this| parcelable to the given |parcel|.  Keep in mind that
   // implementations of writeToParcel must be manually kept in sync
   // with readFromParcel and the Java equivalent versions of these methods.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t writeToParcel(android::Parcel* parcel) const override;
+  status_t writeToParcel(Parcel* parcel) const override;
 
   // Read data from the given |parcel| into |this|.  After readFromParcel
   // completes, |this| should have equivalent state to the object that
   // wrote itself to the parcel.
   //
   // Returns android::OK on success and an appropriate error otherwise.
-  android::status_t readFromParcel(const android::Parcel* parcel) override;
-
-  void setFileDescriptor(int fd, bool takeOwnership);
-
- private:
-  int fd_;
-  bool takeOwnership_;
+  status_t readFromParcel(const Parcel* parcel) override;
 };
 
-}  // namespace os
+}  // namespace bluetooth
 }  // namespace android
diff --git a/service/common/bluetooth/a2dp_codec_config.cc b/service/common/bluetooth/a2dp_codec_config.cc
new file mode 100644
index 0000000..2b5e5ba
--- /dev/null
+++ b/service/common/bluetooth/a2dp_codec_config.cc
@@ -0,0 +1,41 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "bluetooth/a2dp_codec_config.h"
+
+namespace bluetooth {
+
+A2dpCodecConfig::A2dpCodecConfig() = default;
+A2dpCodecConfig::A2dpCodecConfig(const A2dpCodecConfig& other) = default;
+A2dpCodecConfig::A2dpCodecConfig(int codec_type, int codec_priority,
+                                 int sample_rate, int bits_per_sample,
+                                 int channel_mode, int64_t codec_specific_1,
+                                 int64_t codec_specific_2,
+                                 int64_t codec_specific_3,
+                                 int64_t codec_specific_4)
+    : codec_type_(codec_type),
+      codec_priority_(codec_priority),
+      sample_rate_(sample_rate),
+      bits_per_sample_(bits_per_sample),
+      channel_mode_(channel_mode),
+      codec_specific_1_(codec_specific_1),
+      codec_specific_2_(codec_specific_2),
+      codec_specific_3_(codec_specific_3),
+      codec_specific_4_(codec_specific_4) {}
+
+A2dpCodecConfig::~A2dpCodecConfig() = default;
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/a2dp_codec_config.h b/service/common/bluetooth/a2dp_codec_config.h
new file mode 100644
index 0000000..10dbfcb
--- /dev/null
+++ b/service/common/bluetooth/a2dp_codec_config.h
@@ -0,0 +1,56 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <cstdint>
+
+namespace bluetooth {
+
+// Should match btav_a2dp_codec_config_t in bt_av.h
+class A2dpCodecConfig {
+ public:
+  A2dpCodecConfig();
+  A2dpCodecConfig(const A2dpCodecConfig& other);
+  A2dpCodecConfig(int codec_type, int codec_priority, int sample_rate,
+                  int bits_per_sample, int channel_mode,
+                  int64_t codec_specific_1, int64_t codec_specific_2,
+                  int64_t codec_specific_3, int64_t codec_specific_4);
+  ~A2dpCodecConfig();
+
+  int codec_type() const { return codec_type_; }
+  int codec_priority() const { return codec_priority_; }
+  int sample_rate() const { return sample_rate_; }
+  int bits_per_sample() const { return bits_per_sample_; }
+  int channel_mode() const { return channel_mode_; }
+  int64_t codec_specific_1() const { return codec_specific_1_; }
+  int64_t codec_specific_2() const { return codec_specific_2_; }
+  int64_t codec_specific_3() const { return codec_specific_3_; }
+  int64_t codec_specific_4() const { return codec_specific_4_; }
+
+ protected:
+  int codec_type_ = 0;
+  int codec_priority_ = 0;
+  int sample_rate_ = 0;
+  int bits_per_sample_ = 0;
+  int channel_mode_ = 0;
+  int64_t codec_specific_1_ = 0;
+  int64_t codec_specific_2_ = 0;
+  int64_t codec_specific_3_ = 0;
+  int64_t codec_specific_4_ = 0;
+};
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_int_value.cc b/service/common/bluetooth/avrcp_int_value.cc
new file mode 100644
index 0000000..5ea07d4
--- /dev/null
+++ b/service/common/bluetooth/avrcp_int_value.cc
@@ -0,0 +1,26 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "bluetooth/avrcp_int_value.h"
+
+namespace bluetooth {
+
+AvrcpIntValue::AvrcpIntValue() = default;
+AvrcpIntValue::AvrcpIntValue(const AvrcpIntValue& other) = default;
+AvrcpIntValue::AvrcpIntValue(int id, int value) : id_(id), value_(value) {}
+AvrcpIntValue::~AvrcpIntValue() = default;
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_int_value.h b/service/common/bluetooth/avrcp_int_value.h
new file mode 100644
index 0000000..d9cf510
--- /dev/null
+++ b/service/common/bluetooth/avrcp_int_value.h
@@ -0,0 +1,36 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+namespace bluetooth {
+
+class AvrcpIntValue {
+ public:
+  AvrcpIntValue();
+  AvrcpIntValue(const AvrcpIntValue& other);
+  AvrcpIntValue(int id, int value);
+  ~AvrcpIntValue();
+
+  int id() const { return id_; }
+  int value() const { return value_; }
+
+ protected:
+  int id_ = 0;
+  int value_ = 0;
+};
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_media_attr.cc b/service/common/bluetooth/avrcp_media_attr.cc
new file mode 100644
index 0000000..fc50957
--- /dev/null
+++ b/service/common/bluetooth/avrcp_media_attr.cc
@@ -0,0 +1,38 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "bluetooth/avrcp_media_attr.h"
+
+namespace bluetooth {
+
+AvrcpMediaAttr::AvrcpMediaAttr() = default;
+AvrcpMediaAttr::AvrcpMediaAttr(const AvrcpMediaAttr& other) = default;
+AvrcpMediaAttr::AvrcpMediaAttr(const std::string& title,
+                               const std::string& artist,
+                               const std::string& album,
+                               const std::string& genre, int track_num,
+                               int num_tracks, int play_time)
+    : title_(title),
+      artist_(artist),
+      album_(album),
+      genre_(genre),
+      track_num_(track_num),
+      num_tracks_(num_tracks),
+      play_time_(play_time) {}
+
+AvrcpMediaAttr::~AvrcpMediaAttr() = default;
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_media_attr.h b/service/common/bluetooth/avrcp_media_attr.h
new file mode 100644
index 0000000..31a7cfd
--- /dev/null
+++ b/service/common/bluetooth/avrcp_media_attr.h
@@ -0,0 +1,50 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <string>
+
+namespace bluetooth {
+
+class AvrcpMediaAttr {
+ public:
+  AvrcpMediaAttr();
+  AvrcpMediaAttr(const AvrcpMediaAttr& other);
+  AvrcpMediaAttr(const std::string& title, const std::string& artist,
+                 const std::string& album, const std::string& genre,
+                 int track_num, int num_tracks, int play_time);
+  ~AvrcpMediaAttr();
+
+  const std::string& title() const { return title_; }
+  const std::string& artist() const { return artist_; }
+  const std::string& album() const { return album_; }
+  const std::string& genre() const { return genre_; }
+  int track_num() const { return track_num_; }
+  int num_tracks() const { return num_tracks_; }
+  int play_time() const { return play_time_; }
+
+ protected:
+  std::string title_;
+  std::string artist_;
+  std::string album_;
+  std::string genre_;
+  int track_num_ = -1;
+  int num_tracks_ = -1;
+  int play_time_ = -1;
+};
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_register_notification_response.cc b/service/common/bluetooth/avrcp_register_notification_response.cc
new file mode 100644
index 0000000..6200f77
--- /dev/null
+++ b/service/common/bluetooth/avrcp_register_notification_response.cc
@@ -0,0 +1,31 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "bluetooth/avrcp_register_notification_response.h"
+
+namespace bluetooth {
+
+AvrcpRegisterNotificationResponse::AvrcpRegisterNotificationResponse() =
+    default;
+AvrcpRegisterNotificationResponse::AvrcpRegisterNotificationResponse(
+    const AvrcpRegisterNotificationResponse& other) = default;
+AvrcpRegisterNotificationResponse::AvrcpRegisterNotificationResponse(
+    const btrc_register_notification_t& data)
+    : data_(data) {}
+AvrcpRegisterNotificationResponse::~AvrcpRegisterNotificationResponse() =
+    default;
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_register_notification_response.h b/service/common/bluetooth/avrcp_register_notification_response.h
new file mode 100644
index 0000000..3c78da2
--- /dev/null
+++ b/service/common/bluetooth/avrcp_register_notification_response.h
@@ -0,0 +1,38 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <hardware/bt_common_types.h>
+#include <hardware/bt_rc.h>
+
+namespace bluetooth {
+
+class AvrcpRegisterNotificationResponse {
+ public:
+  AvrcpRegisterNotificationResponse();
+  AvrcpRegisterNotificationResponse(
+      const AvrcpRegisterNotificationResponse& other);
+  AvrcpRegisterNotificationResponse(const btrc_register_notification_t& data);
+  ~AvrcpRegisterNotificationResponse();
+
+  const btrc_register_notification_t& data() const { return data_; }
+
+ protected:
+  btrc_register_notification_t data_;
+};
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/avrcp_string_value.h b/service/common/bluetooth/avrcp_string_value.h
new file mode 100644
index 0000000..0b5cca4
--- /dev/null
+++ b/service/common/bluetooth/avrcp_string_value.h
@@ -0,0 +1,38 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <string>
+
+namespace bluetooth {
+
+class AvrcpStringValue {
+ public:
+  AvrcpStringValue() = default;
+  AvrcpStringValue(const AvrcpStringValue& other) = default;
+  AvrcpStringValue(int id, const std::string& value) : id_(id), value_(value){};
+  ~AvrcpStringValue() = default;
+
+  int id() const { return id_; }
+  const std::string& value() const { return value_; }
+
+ protected:
+  int id_ = 0;
+  std::string value_;
+};
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/remote_device_props.cc b/service/common/bluetooth/remote_device_props.cc
new file mode 100644
index 0000000..930421f
--- /dev/null
+++ b/service/common/bluetooth/remote_device_props.cc
@@ -0,0 +1,38 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "bluetooth/remote_device_props.h"
+
+using std::string;
+
+namespace bluetooth {
+
+RemoteDeviceProps::RemoteDeviceProps() = default;
+RemoteDeviceProps::RemoteDeviceProps(const RemoteDeviceProps& other) = default;
+RemoteDeviceProps::RemoteDeviceProps(const std::string& name,
+                                     const std::string& address,
+                                     const std::vector<Uuid>& service_uuids,
+                                     int32_t device_class, int32_t device_type,
+                                     int32_t rssi)
+    : name_(name),
+      address_(address),
+      service_uuids_(service_uuids),
+      device_class_(device_class),
+      device_type_(device_type),
+      rssi_(rssi) {}
+RemoteDeviceProps::~RemoteDeviceProps() = default;
+
+}  // namespace bluetooth
diff --git a/service/common/bluetooth/remote_device_props.h b/service/common/bluetooth/remote_device_props.h
new file mode 100644
index 0000000..f8b3b1b
--- /dev/null
+++ b/service/common/bluetooth/remote_device_props.h
@@ -0,0 +1,53 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "bluetooth/uuid.h"
+
+namespace bluetooth {
+
+class RemoteDeviceProps {
+ public:
+  RemoteDeviceProps();
+  RemoteDeviceProps(const RemoteDeviceProps& other);
+  RemoteDeviceProps(const std::string& name, const std::string& address,
+                    const std::vector<Uuid>& service_uuids,
+                    int32_t device_class, int32_t device_type, int32_t rssi);
+  ~RemoteDeviceProps();
+
+  void set_address(const std::string& address) { address_ = address; }
+
+  const std::string& name() const { return name_; }
+  const std::string& address() const { return address_; }
+  const std::vector<Uuid>& service_uuids() const { return service_uuids_; }
+  int32_t device_class() const { return device_class_; }
+  int32_t device_type() const { return device_type_; }
+  int32_t rssi() const { return rssi_; }
+
+ protected:
+  std::string name_;
+  std::string address_;
+  std::vector<Uuid> service_uuids_;
+  int32_t device_class_ = -1;
+  int32_t device_type_ = -1;
+  int32_t rssi_ = -1;
+};
+
+}  // namespace bluetooth
diff --git a/service/daemon.cc b/service/daemon.cc
index 86a3b5a..439c2c2 100644
--- a/service/daemon.cc
+++ b/service/daemon.cc
@@ -22,6 +22,8 @@
 #include <base/run_loop.h>
 
 #include "service/adapter.h"
+#include "service/hal/bluetooth_av_interface.h"
+#include "service/hal/bluetooth_avrcp_interface.h"
 #include "service/hal/bluetooth_gatt_interface.h"
 #include "service/hal/bluetooth_interface.h"
 #include "service/ipc/ipc_manager.h"
@@ -57,7 +59,7 @@
   // ipc::IPCManager::Delegate implementation:
   void OnIPCHandlerStarted(ipc::IPCManager::Type /* type */) override {
     if (!settings_->EnableOnStart()) return;
-    adapter_->Enable(false /* start_restricted */);
+    adapter_->Enable();
   }
 
   void OnIPCHandlerStopped(ipc::IPCManager::Type /* type */) override {
@@ -69,6 +71,10 @@
 
     if (!hal::BluetoothGattInterface::Initialize()) goto failed;
 
+    if (!hal::BluetoothAvInterface::Initialize()) goto failed;
+
+    if (!hal::BluetoothAvrcpInterface::Initialize()) goto failed;
+
     return true;
 
   failed:
@@ -81,6 +87,10 @@
       hal::BluetoothGattInterface::CleanUp();
     if (hal::BluetoothInterface::IsInitialized())
       hal::BluetoothInterface::CleanUp();
+    if (hal::BluetoothAvInterface::IsInitialized())
+      hal::BluetoothAvInterface::CleanUp();
+    if (hal::BluetoothAvrcpInterface::IsInitialized())
+      hal::BluetoothAvrcpInterface::CleanUp();
   }
 
   void CleanUpBluetoothStack() {
diff --git a/service/example/heart_rate/server_main.cc b/service/example/heart_rate/server_main.cc
index 8ffded6..7423462 100644
--- a/service/example/heart_rate/server_main.cc
+++ b/service/example/heart_rate/server_main.cc
@@ -41,10 +41,7 @@
 std::string kServiceName = "bluetooth-service";
 
 void QuitMessageLoop() {
-  // I don't know why both of these calls are necessary but the message loop
-  // doesn't stop unless I call both. Bug in base::MessageLoop?
   base::RunLoop().Quit();
-  base::MessageLoop::current()->QuitNow();
 }
 
 // Handles the case where the Bluetooth process dies.
@@ -134,7 +131,7 @@
     }
 
     LOG(ERROR) << "Starting Heart Rate server failed asynchronously";
-    main_loop.QuitWhenIdle();
+    base::RunLoop().QuitWhenIdle();
   };
 
   bool advertise =
diff --git a/service/gatt_server_old.cc b/service/gatt_server_old.cc
index e97a6c5..b583d93 100644
--- a/service/gatt_server_old.cc
+++ b/service/gatt_server_old.cc
@@ -23,6 +23,8 @@
 #include <unistd.h>
 
 #include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <base/callback.h>
 #include <algorithm>
 #include <array>
 #include <condition_variable>
@@ -77,8 +79,6 @@
 
 }  // namespace
 
-void DoNothing(uint8_t p) {}
-
 namespace bluetooth {
 namespace gatt {
 
@@ -354,11 +354,11 @@
   // Setup our advertisement. This has no callback.
   g_internal->gatt->advertiser->SetData(0 /* std_inst */, false,
                                         {/*TODO: put inverval 2,2 here*/},
-                                        base::Bind(&DoNothing));
+                                        base::DoNothing());
 
   g_internal->gatt->advertiser->Enable(
       0 /* std_inst */, true, base::Bind(&EnableAdvertisingCallback),
-      0 /* no duration */, 0 /* no maxExtAdvEvent*/, base::Bind(&DoNothing));
+      0 /* no duration */, 0 /* no maxExtAdvEvent*/, base::DoNothing());
 }
 
 void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
@@ -579,7 +579,7 @@
 
   // Setup our advertisement. This has no callback.
   internal_->gatt->advertiser->SetData(0, false, /* beacon, not scan response */
-                                       {}, base::Bind(&DoNothing));
+                                       {}, base::DoNothing());
   // transmit_name,               /* name */
   // 2, 2,                         interval
   // mutable_manufacturer_data,
@@ -605,7 +605,7 @@
 
   // Setup our advertisement. This has no callback.
   internal_->gatt->advertiser->SetData(0, true, /* scan response */
-                                       {}, base::Bind(&DoNothing));
+                                       {}, base::DoNothing());
   // transmit_name,              /* name */
   // false,                      /* no txpower */
   // 2, 2,                        interval
diff --git a/service/hal/bluetooth_av_interface.cc b/service/hal/bluetooth_av_interface.cc
new file mode 100644
index 0000000..68f5bd0
--- /dev/null
+++ b/service/hal/bluetooth_av_interface.cc
@@ -0,0 +1,364 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/hal/bluetooth_av_interface.h"
+
+#include <shared_mutex>
+
+#include <base/logging.h>
+#include <base/memory/ptr_util.h>
+#include <base/observer_list.h>
+
+#include "service/hal/bluetooth_interface.h"
+
+namespace bluetooth {
+namespace hal {
+
+namespace {
+
+BluetoothAvInterface* g_interface = nullptr;
+
+#if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500)
+using shared_mutex_impl = std::shared_mutex;
+#else
+using shared_mutex_impl = std::shared_timed_mutex;
+#endif
+
+// Mutex used by callbacks to access |g_interface|. If we initialize or clean it
+// use unique_lock. If only accessing |g_interface| use shared lock.
+shared_mutex_impl g_instance_lock;
+
+base::ObserverList<BluetoothAvInterface::A2dpSourceObserver>*
+GetA2dpSourceObservers();
+base::ObserverList<BluetoothAvInterface::A2dpSinkObserver>*
+GetA2dpSinkObservers();
+
+#define VERIFY_INTERFACE_OR_RETURN()                                   \
+  do {                                                                 \
+    if (!g_interface) {                                                \
+      LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
+      return;                                                          \
+    }                                                                  \
+  } while (0)
+
+}  // namespace
+
+void SourceConnectionStateCallback(const RawAddress& bd_addr,
+                                   btav_connection_state_t state) {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+
+  for (auto& observer : *GetA2dpSourceObservers()) {
+    observer.ConnectionStateCallback(g_interface, bd_addr, state);
+  }
+}
+
+void SourceAudioStateCallback(const RawAddress& bd_addr,
+                              btav_audio_state_t state) {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetA2dpSourceObservers()) {
+    observer.AudioStateCallback(g_interface, bd_addr, state);
+  }
+}
+
+void SourceAudioConfigCallback(
+    const RawAddress& bd_addr, btav_a2dp_codec_config_t codec_config,
+    std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
+    std::vector<btav_a2dp_codec_config_t> codecs_selectable_capabilities) {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetA2dpSourceObservers()) {
+    observer.AudioConfigCallback(g_interface, bd_addr, codec_config,
+                                 codecs_local_capabilities,
+                                 codecs_selectable_capabilities);
+  }
+}
+
+void SinkConnectionStateCallback(const RawAddress& bd_addr,
+                                 btav_connection_state_t state) {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetA2dpSinkObservers()) {
+    observer.ConnectionStateCallback(g_interface, bd_addr, state);
+  }
+}
+
+void SinkAudioStateCallback(const RawAddress& bd_addr,
+                            btav_audio_state_t state) {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetA2dpSinkObservers()) {
+    observer.AudioStateCallback(g_interface, bd_addr, state);
+  }
+}
+
+void SinkAudioConfigCallback(const RawAddress& bd_addr, uint32_t sample_rate,
+                             uint8_t channel_count) {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetA2dpSinkObservers()) {
+    observer.AudioConfigCallback(g_interface, bd_addr, sample_rate,
+                                 channel_count);
+  }
+}
+
+btav_source_callbacks_t av_source_callbacks = {
+    .size = sizeof(btav_source_callbacks_t),
+    .connection_state_cb = SourceConnectionStateCallback,
+    .audio_state_cb = SourceAudioStateCallback,
+    .audio_config_cb = SourceAudioConfigCallback,
+};
+
+btav_sink_callbacks_t av_sink_callbacks = {
+    .size = sizeof(btav_sink_callbacks_t),
+    .connection_state_cb = SinkConnectionStateCallback,
+    .audio_state_cb = SinkAudioStateCallback,
+    .audio_config_cb = SinkAudioConfigCallback,
+};
+
+class BluetoothAvInterfaceImpl : public BluetoothAvInterface {
+ public:
+  BluetoothAvInterfaceImpl() = default;
+  ~BluetoothAvInterfaceImpl() override {
+    A2dpSinkDisable();
+    A2dpSourceDisable();
+  }
+
+  bool A2dpSourceEnable(
+      std::vector<btav_a2dp_codec_config_t> codec_priorities) override {
+    if (source_enabled_) {
+      return true;
+    }
+
+    // Right now we only support one connected audio device.
+    int max_connected_audio_devices = 1;
+    if (hal_source_iface_->init(
+            &av_source_callbacks, max_connected_audio_devices,
+            std::move(codec_priorities)) != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to initialize HAL A2DP source interface";
+      return false;
+    }
+    source_enabled_ = true;
+    return true;
+  }
+
+  void A2dpSourceDisable() override {
+    if (!source_enabled_) {
+      return;
+    }
+
+    hal_source_iface_->cleanup();
+    source_enabled_ = false;
+  }
+
+  bool A2dpSinkEnable() override {
+    if (sink_enabled_) {
+      return true;
+    }
+    if (hal_sink_iface_->init(&av_sink_callbacks) != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to initialize HAL A2DP sink interface";
+      return false;
+    }
+    sink_enabled_ = true;
+    return true;
+  }
+
+  void A2dpSinkDisable() override {
+    if (!sink_enabled_) {
+      return;
+    }
+    hal_sink_iface_->cleanup();
+    sink_enabled_ = false;
+  }
+
+  void AddA2dpSourceObserver(A2dpSourceObserver* observer) override {
+    a2dp_source_observers_.AddObserver(observer);
+  }
+
+  void RemoveA2dpSourceObserver(A2dpSourceObserver* observer) override {
+    a2dp_source_observers_.RemoveObserver(observer);
+  }
+
+  void AddA2dpSinkObserver(A2dpSinkObserver* observer) override {
+    a2dp_sink_observers_.AddObserver(observer);
+  }
+
+  void RemoveA2dpSinkObserver(A2dpSinkObserver* observer) override {
+    a2dp_sink_observers_.RemoveObserver(observer);
+  }
+
+  const btav_source_interface_t* GetA2dpSourceHALInterface() override {
+    return hal_source_iface_;
+  }
+
+  const btav_sink_interface_t* GetA2dpSinkHALInterface() override {
+    return hal_sink_iface_;
+  }
+
+  bool Initialize() {
+    const bt_interface_t* bt_iface =
+        BluetoothInterface::Get()->GetHALInterface();
+    CHECK(bt_iface);
+
+    const auto* hal_source_iface =
+        reinterpret_cast<const btav_source_interface_t*>(
+            bt_iface->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_ID));
+    if (!hal_source_iface) {
+      LOG(ERROR) << "Failed to obtain A2DP source interface handle";
+      return false;
+    }
+
+    const auto* hal_sink_iface = reinterpret_cast<const btav_sink_interface_t*>(
+        bt_iface->get_profile_interface(BT_PROFILE_ADVANCED_AUDIO_SINK_ID));
+    if (!hal_sink_iface) {
+      LOG(ERROR) << "Failed to obtain A2DP sink interface handle";
+      return false;
+    }
+
+    hal_sink_iface_ = hal_sink_iface;
+    hal_source_iface_ = hal_source_iface;
+
+    // Only initialize the sink interface.
+    return A2dpSinkEnable();
+  }
+
+  base::ObserverList<A2dpSourceObserver>* source_observers() {
+    return &a2dp_source_observers_;
+  }
+
+  base::ObserverList<A2dpSinkObserver>* sink_observers() {
+    return &a2dp_sink_observers_;
+  }
+
+ private:
+  base::ObserverList<A2dpSourceObserver> a2dp_source_observers_;
+  base::ObserverList<A2dpSinkObserver> a2dp_sink_observers_;
+
+  const btav_source_interface_t* hal_source_iface_ = nullptr;
+  const btav_sink_interface_t* hal_sink_iface_ = nullptr;
+
+  bool source_enabled_ = false;
+  bool sink_enabled_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAvInterfaceImpl);
+};
+
+namespace {
+
+base::ObserverList<BluetoothAvInterface::A2dpSourceObserver>*
+GetA2dpSourceObservers() {
+  CHECK(g_interface);
+  return static_cast<BluetoothAvInterfaceImpl*>(g_interface)
+      ->source_observers();
+}
+
+base::ObserverList<BluetoothAvInterface::A2dpSinkObserver>*
+GetA2dpSinkObservers() {
+  CHECK(g_interface);
+  return static_cast<BluetoothAvInterfaceImpl*>(g_interface)->sink_observers();
+}
+
+}  // namespace
+
+void BluetoothAvInterface::A2dpSourceObserver::ConnectionStateCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    btav_connection_state_t state) {
+  // Do nothing.
+}
+
+void BluetoothAvInterface::A2dpSourceObserver::AudioStateCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    btav_audio_state_t state) {
+  // Do nothing.
+}
+
+void BluetoothAvInterface::A2dpSourceObserver::AudioConfigCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    const btav_a2dp_codec_config_t& codec_config,
+    const std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
+    const std::vector<btav_a2dp_codec_config_t>
+        codecs_selectable_capabilities) {
+  // Do nothing.
+}
+
+void BluetoothAvInterface::A2dpSinkObserver::ConnectionStateCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    btav_connection_state_t state) {
+  // Do nothing.
+}
+
+void BluetoothAvInterface::A2dpSinkObserver::AudioStateCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    btav_audio_state_t state) {
+  // Do nothing.
+}
+
+void BluetoothAvInterface::A2dpSinkObserver::AudioConfigCallback(
+    BluetoothAvInterface* iface, const RawAddress& bd_addr,
+    uint32_t sample_rate, uint8_t channel_count) {
+  // Do nothing.
+}
+
+// static
+bool BluetoothAvInterface::Initialize() {
+  std::unique_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(!g_interface);
+
+  auto impl = std::make_unique<BluetoothAvInterfaceImpl>();
+  if (!impl->Initialize()) {
+    LOG(ERROR) << "Failed to initialize BluetoothAvInterface";
+    return false;
+  }
+
+  g_interface = impl.release();
+  return true;
+}
+
+// static
+void BluetoothAvInterface::CleanUp() {
+  std::unique_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(g_interface);
+
+  delete g_interface;
+  g_interface = nullptr;
+}
+
+// static
+bool BluetoothAvInterface::IsInitialized() {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  return g_interface != nullptr;
+}
+
+// static
+void BluetoothAvInterface::InitializeForTesting(
+    BluetoothAvInterface* test_instance) {
+  std::unique_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(test_instance);
+  CHECK(!g_interface);
+
+  g_interface = test_instance;
+}
+
+// static
+BluetoothAvInterface* BluetoothAvInterface::Get() {
+  std::shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(g_interface);
+  return g_interface;
+}
+
+}  // namespace hal
+}  // namespace bluetooth
diff --git a/service/hal/bluetooth_av_interface.h b/service/hal/bluetooth_av_interface.h
new file mode 100644
index 0000000..9346143
--- /dev/null
+++ b/service/hal/bluetooth_av_interface.h
@@ -0,0 +1,96 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <base/macros.h>
+#include <hardware/bluetooth.h>
+#include <hardware/bt_av.h>
+
+#include <vector>
+
+namespace bluetooth {
+namespace hal {
+
+class BluetoothAvInterface {
+ public:
+  class A2dpSourceObserver {
+   public:
+    virtual void ConnectionStateCallback(BluetoothAvInterface* iface,
+                                         const RawAddress& bd_addr,
+                                         btav_connection_state_t state);
+    virtual void AudioStateCallback(BluetoothAvInterface* iface,
+                                    const RawAddress& bd_addr,
+                                    btav_audio_state_t state);
+    virtual void AudioConfigCallback(
+        BluetoothAvInterface* iface, const RawAddress& bd_addr,
+        const btav_a2dp_codec_config_t& codec_config,
+        const std::vector<btav_a2dp_codec_config_t> codecs_local_capabilities,
+        const std::vector<btav_a2dp_codec_config_t>
+            codecs_selectable_capabilities);
+
+   protected:
+    virtual ~A2dpSourceObserver() = default;
+  };
+
+  class A2dpSinkObserver {
+   public:
+    virtual void ConnectionStateCallback(BluetoothAvInterface* iface,
+                                         const RawAddress& bd_addr,
+                                         btav_connection_state_t state);
+    virtual void AudioStateCallback(BluetoothAvInterface* iface,
+                                    const RawAddress& bd_addr,
+                                    btav_audio_state_t state);
+    virtual void AudioConfigCallback(BluetoothAvInterface* iface,
+                                     const RawAddress& bd_addr,
+                                     uint32_t sample_rate,
+                                     uint8_t channel_count);
+
+   protected:
+    virtual ~A2dpSinkObserver() = default;
+  };
+
+  static bool Initialize();
+  static void CleanUp();
+  static bool IsInitialized();
+  static void InitializeForTesting(BluetoothAvInterface* test_instance);
+
+  static BluetoothAvInterface* Get();
+
+  virtual bool A2dpSourceEnable(
+      std::vector<btav_a2dp_codec_config_t> codec_priorities) = 0;
+  virtual void A2dpSourceDisable() = 0;
+  virtual bool A2dpSinkEnable() = 0;
+  virtual void A2dpSinkDisable() = 0;
+
+  virtual void AddA2dpSourceObserver(A2dpSourceObserver* observer) = 0;
+  virtual void RemoveA2dpSourceObserver(A2dpSourceObserver* observer) = 0;
+  virtual void AddA2dpSinkObserver(A2dpSinkObserver* observer) = 0;
+  virtual void RemoveA2dpSinkObserver(A2dpSinkObserver* observer) = 0;
+
+  virtual const btav_source_interface_t* GetA2dpSourceHALInterface() = 0;
+  virtual const btav_sink_interface_t* GetA2dpSinkHALInterface() = 0;
+
+ protected:
+  BluetoothAvInterface() = default;
+  virtual ~BluetoothAvInterface() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAvInterface);
+};
+
+}  // namespace hal
+}  // namespace bluetooth
diff --git a/service/hal/bluetooth_avrcp_interface.cc b/service/hal/bluetooth_avrcp_interface.cc
new file mode 100644
index 0000000..02e7316
--- /dev/null
+++ b/service/hal/bluetooth_avrcp_interface.cc
@@ -0,0 +1,891 @@
+//
+//  Copyright 2015 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/hal/bluetooth_avrcp_interface.h"
+
+#include <mutex>
+#include <shared_mutex>
+
+#include <base/logging.h>
+#include <base/observer_list.h>
+
+#include "service/hal/bluetooth_interface.h"
+#include "service/logging_helpers.h"
+
+using std::lock_guard;
+using std::mutex;
+using std::shared_lock;
+using std::unique_lock;
+#if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500)
+using shared_mutex_impl = std::shared_mutex;
+#else
+using shared_mutex_impl = std::shared_timed_mutex;
+#endif
+
+namespace bluetooth {
+namespace hal {
+
+namespace {
+
+// The global BluetoothAvrcpInterface instance.
+BluetoothAvrcpInterface* g_interface = nullptr;
+
+// Mutex used by callbacks to access |g_interface|. If we initialize or clean it
+// use unique_lock. If only accessing |g_interface| use shared lock.
+// TODO(jpawlowski): this should be just shared_mutex, as we currently don't use
+// timed methods. Change to shared_mutex when we upgrade to C++14
+shared_mutex_impl g_instance_lock;
+
+// Helper for obtaining the observer lists. This is forward declared here
+// and defined below since it depends on BluetoothInterfaceImpl.
+base::ObserverList<BluetoothAvrcpInterface::TargetObserver>*
+GetTargetObservers();
+
+base::ObserverList<BluetoothAvrcpInterface::ControlObserver>*
+GetControlObservers();
+
+#define VERIFY_INTERFACE_OR_RETURN()                                   \
+  do {                                                                 \
+    if (!g_interface) {                                                \
+      LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
+      return;                                                          \
+    }                                                                  \
+  } while (0)
+
+void RemoteFeaturesCallback(const RawAddress& bd_addr,
+                            btrc_remote_features_t features) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.RemoteFeaturesCallback(bd_addr, features);
+  }
+}
+
+void GetPlayStatusCallback(const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetPlayStatusCallback(bd_addr);
+  }
+}
+
+void ListPlayerAppAttrCallback(const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.ListPlayerAppAttrCallback(bd_addr);
+  }
+}
+
+void ListPlayerAppValuesCallback(btrc_player_attr_t attr_id,
+                                 const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.ListPlayerAppValuesCallback(attr_id, bd_addr);
+  }
+}
+
+void GetPlayerAppValueCallback(uint8_t num_attr, btrc_player_attr_t* p_attrs,
+                               const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetPlayerAppValueCallback(num_attr, p_attrs, bd_addr);
+  }
+}
+
+void GetPlayerAppAttrsTextCallback(uint8_t num_attr,
+                                   btrc_player_attr_t* p_attrs,
+                                   const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetPlayerAppAttrsTextCallback(num_attr, p_attrs, bd_addr);
+  }
+}
+
+void GetPlayerAppValuesTextCallback(uint8_t attr_id, uint8_t num_val,
+                                    uint8_t* p_vals,
+                                    const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetPlayerAppValuesTextCallback(attr_id, num_val, p_vals, bd_addr);
+  }
+}
+
+void SetPlayerAppValueCallback(btrc_player_settings_t* p_vals,
+                               const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.SetPlayerAppValueCallback(p_vals, bd_addr);
+  }
+}
+
+void GetElementAttrCallback(uint8_t num_attr, btrc_media_attr_t* p_attrs,
+                            const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetElementAttrCallback(num_attr, p_attrs, bd_addr);
+  }
+}
+
+void RegisterNotificationCallback(btrc_event_id_t event_id, uint32_t param,
+                                  const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.RegisterNotificationCallback(event_id, param, bd_addr);
+  }
+}
+
+void VolumeChangeCallback(uint8_t volume, uint8_t ctype,
+                          const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.VolumeChangeCallback(volume, ctype, bd_addr);
+  }
+}
+
+void PassthroughCmdCallback(int id, int key_state, const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.PassthroughCmdCallback(id, key_state, bd_addr);
+  }
+}
+
+void SetAddressedPlayerCallback(uint16_t player_id, const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.SetAddressedPlayerCallback(player_id, bd_addr);
+  }
+}
+
+void SetBrowsedPlayerCallback(uint16_t player_id, const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.SetBrowsedPlayerCallback(player_id, bd_addr);
+  }
+}
+
+void GetFolderItemsCallback(uint8_t scope, uint32_t start_item,
+                            uint32_t end_item, uint8_t num_attr,
+                            uint32_t* p_attr_ids, const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetFolderItemsCallback(scope, start_item, end_item, num_attr,
+                                    p_attr_ids, bd_addr);
+  }
+}
+
+void ChangePathCallback(uint8_t direction, uint8_t* folder_uid,
+                        const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.ChangePathCallback(direction, folder_uid, bd_addr);
+  }
+}
+
+void GetItemAttrCallback(uint8_t scope, uint8_t* uid, uint16_t uid_counter,
+                         uint8_t num_attr, btrc_media_attr_t* p_attrs,
+                         const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetItemAttrCallback(scope, uid, uid_counter, num_attr, p_attrs,
+                                 bd_addr);
+  }
+}
+
+void PlayItemCallback(uint8_t scope, uint16_t uid_counter, uint8_t* uid,
+                      const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.PlayItemCallback(scope, uid_counter, uid, bd_addr);
+  }
+}
+
+void GetTotalNumOfItemsCallback(uint8_t scope, const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.GetTotalNumOfItemsCallback(scope, bd_addr);
+  }
+}
+
+void SearchCallback(uint16_t charset_id, uint16_t str_len, uint8_t* p_str,
+                    const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.SearchCallback(str_len, p_str, bd_addr);
+  }
+}
+
+void AddToNowPlayingCallback(uint8_t scope, uint8_t* uid, uint16_t uid_counter,
+                             const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetTargetObservers()) {
+    observer.AddToNowPlayingCallback(scope, uid, uid_counter, bd_addr);
+  }
+}
+
+void PassthroughRspCallback(const RawAddress& bd_addr, int id, int key_state) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.PassthroughRspCallback(bd_addr, id, key_state);
+  }
+}
+
+void GroupnavigationRspCallback(int id, int key_state) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.GroupnavigationRspCallback(id, key_state);
+  }
+}
+
+void ConnectionStateCallback(bool rc_connect, bool bt_connect,
+                             const RawAddress& bd_addr) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.ConnectionStateCallback(rc_connect, bt_connect, bd_addr);
+  }
+}
+
+void CtrlGetrcfeaturesCallback(const RawAddress& bd_addr, int features) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlGetrcfeaturesCallback(bd_addr, features);
+  }
+}
+
+void CtrlSetplayerapplicationsettingRspCallback(const RawAddress& bd_addr,
+                                                uint8_t accepted) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlSetplayerapplicationsettingRspCallback(bd_addr, accepted);
+  }
+}
+
+void CtrlPlayerapplicationsettingCallback(
+    const RawAddress& bd_addr, uint8_t num_attr,
+    btrc_player_app_attr_t* app_attrs, uint8_t num_ext_attr,
+    btrc_player_app_ext_attr_t* ext_attrs) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlPlayerapplicationsettingCallback(bd_addr, num_attr, app_attrs,
+                                                  num_ext_attr, ext_attrs);
+  }
+}
+
+void CtrlPlayerapplicationsettingChangedCallback(
+    const RawAddress& bd_addr, const btrc_player_settings_t& vals) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlPlayerapplicationsettingChangedCallback(bd_addr, vals);
+  }
+}
+
+void CtrlSetabsvolCmdCallback(const RawAddress& bd_addr, uint8_t abs_vol,
+                              uint8_t label) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlSetabsvolCmdCallback(bd_addr, abs_vol, label);
+  }
+}
+
+void CtrlRegisternotificationAbsVolCallback(const RawAddress& bd_addr,
+                                            uint8_t label) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlRegisternotificationAbsVolCallback(bd_addr, label);
+  }
+}
+
+void CtrlTrackChangedCallback(const RawAddress& bd_addr, uint8_t num_attr,
+                              btrc_element_attr_val_t* p_attrs) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlTrackChangedCallback(bd_addr, num_attr, p_attrs);
+  }
+}
+
+void CtrlPlayPositionChangedCallback(const RawAddress& bd_addr,
+                                     uint32_t song_len, uint32_t song_pos) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlPlayPositionChangedCallback(bd_addr, song_len, song_pos);
+  }
+}
+
+void CtrlPlayStatusChangedCallback(const RawAddress& bd_addr,
+                                   btrc_play_status_t play_status) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlPlayStatusChangedCallback(bd_addr, play_status);
+  }
+}
+
+void CtrlGetFolderItemsCallback(const RawAddress& bd_addr, btrc_status_t status,
+                                const btrc_folder_items_t* folder_items,
+                                uint8_t count) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlGetFolderItemsCallback(bd_addr, status, folder_items, count);
+  }
+}
+
+void CtrlChangePathCallback(const RawAddress& bd_addr, uint32_t count) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlChangePathCallback(bd_addr, count);
+  }
+}
+
+void CtrlSetBrowsedPlayerCallback(const RawAddress& bd_addr, uint8_t num_items,
+                                  uint8_t depth) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlSetBrowsedPlayerCallback(bd_addr, num_items, depth);
+  }
+}
+
+void CtrlSetAddressedPlayerCallback(const RawAddress& bd_addr, uint8_t status) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VLOG(2) << __func__;
+  VERIFY_INTERFACE_OR_RETURN();
+  for (auto& observer : *GetControlObservers()) {
+    observer.CtrlSetAddressedPlayerCallback(bd_addr, status);
+  }
+}
+
+btrc_callbacks_t target_callbacks = {
+    .size = sizeof(btrc_callbacks_t),
+    .remote_features_cb = RemoteFeaturesCallback,
+    .get_play_status_cb = GetPlayStatusCallback,
+    .list_player_app_attr_cb = ListPlayerAppAttrCallback,
+    .list_player_app_values_cb = ListPlayerAppValuesCallback,
+    .get_player_app_value_cb = GetPlayerAppValueCallback,
+    .get_player_app_attrs_text_cb = GetPlayerAppAttrsTextCallback,
+    .get_player_app_values_text_cb = GetPlayerAppValuesTextCallback,
+    .set_player_app_value_cb = SetPlayerAppValueCallback,
+    .get_element_attr_cb = GetElementAttrCallback,
+    .register_notification_cb = RegisterNotificationCallback,
+    .volume_change_cb = VolumeChangeCallback,
+    .passthrough_cmd_cb = PassthroughCmdCallback,
+    .set_addressed_player_cb = SetAddressedPlayerCallback,
+    .set_browsed_player_cb = SetBrowsedPlayerCallback,
+    .get_folder_items_cb = GetFolderItemsCallback,
+    .change_path_cb = ChangePathCallback,
+    .get_item_attr_cb = GetItemAttrCallback,
+    .play_item_cb = PlayItemCallback,
+    .get_total_num_of_items_cb = GetTotalNumOfItemsCallback,
+    .search_cb = SearchCallback,
+    .add_to_now_playing_cb = AddToNowPlayingCallback,
+};
+
+btrc_ctrl_callbacks_t control_callbacks = {
+    .size = sizeof(btrc_ctrl_callbacks_t),
+    .passthrough_rsp_cb = PassthroughRspCallback,
+    .groupnavigation_rsp_cb = GroupnavigationRspCallback,
+    .connection_state_cb = ConnectionStateCallback,
+    .getrcfeatures_cb = CtrlGetrcfeaturesCallback,
+    .setplayerappsetting_rsp_cb = CtrlSetplayerapplicationsettingRspCallback,
+    .playerapplicationsetting_cb = CtrlPlayerapplicationsettingCallback,
+    .playerapplicationsetting_changed_cb =
+        CtrlPlayerapplicationsettingChangedCallback,
+    .setabsvol_cmd_cb = CtrlSetabsvolCmdCallback,
+    .registernotification_absvol_cb = CtrlRegisternotificationAbsVolCallback,
+    .track_changed_cb = CtrlTrackChangedCallback,
+    .play_position_changed_cb = CtrlPlayPositionChangedCallback,
+    .play_status_changed_cb = CtrlPlayStatusChangedCallback,
+    .get_folder_items_cb = CtrlGetFolderItemsCallback,
+    .change_folder_path_cb = CtrlChangePathCallback,
+    .set_browsed_player_cb = CtrlSetBrowsedPlayerCallback,
+    .set_addressed_player_cb = CtrlSetAddressedPlayerCallback,
+};
+
+}  // namespace
+
+// BluetoothAvrcpInterface implementation for production.
+class BluetoothAvrcpInterfaceImpl : public BluetoothAvrcpInterface {
+ public:
+  BluetoothAvrcpInterfaceImpl() : control_iface_(nullptr) {}
+
+  ~BluetoothAvrcpInterfaceImpl() override {
+    if (control_iface_) control_iface_->cleanup();
+  }
+
+  bool AvrcpControlEnable() override {
+    if (control_enabled_) {
+      return true;
+    }
+
+    if (control_iface_->init(&control_callbacks) != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to initialize HAL AVRCP control interface";
+      return false;
+    }
+
+    control_enabled_ = true;
+    return true;
+  }
+
+  void AvrcpControlDisable() override {
+    if (!control_enabled_) {
+      return;
+    }
+
+    control_iface_->cleanup();
+    control_enabled_ = false;
+  }
+
+  bool AvrcpTargetEnable() override {
+    if (target_enabled_) {
+      return true;
+    }
+
+    if (target_iface_->init(&target_callbacks) != BT_STATUS_SUCCESS) {
+      LOG(ERROR) << "Failed to initialize HAL AVRCP target interface";
+      return false;
+    }
+
+    target_enabled_ = true;
+    return true;
+  }
+
+  void AvrcpTargetDisable() override {
+    if (!target_enabled_) {
+      return;
+    }
+
+    target_iface_->cleanup();
+    target_enabled_ = false;
+  }
+
+  void AddTargetObserver(TargetObserver* observer) override {
+    target_observers_.AddObserver(observer);
+  }
+
+  void RemoveTargetObserver(TargetObserver* observer) override {
+    target_observers_.RemoveObserver(observer);
+  }
+
+  void AddControlObserver(ControlObserver* observer) override {
+    control_observers_.AddObserver(observer);
+  }
+
+  void RemoveControlObserver(ControlObserver* observer) override {
+    control_observers_.RemoveObserver(observer);
+  }
+
+  const btrc_interface_t* GetTargetHALInterface() const override {
+    return target_iface_;
+  }
+
+  const btrc_ctrl_interface_t* GetControlHALInterface() const override {
+    return control_iface_;
+  }
+
+  // Initialize the interface.
+  bool Initialize() {
+    const bt_interface_t* bt_iface =
+        BluetoothInterface::Get()->GetHALInterface();
+    CHECK(bt_iface);
+
+    auto* target_iface = reinterpret_cast<const btrc_interface_t*>(
+        bt_iface->get_profile_interface(BT_PROFILE_AV_RC_ID));
+    if (!target_iface) {
+      LOG(ERROR) << "Failed to obtain HAL AVRCP target interface handle";
+      return false;
+    }
+
+    auto* control_iface = reinterpret_cast<const btrc_ctrl_interface_t*>(
+        bt_iface->get_profile_interface(BT_PROFILE_AV_RC_CTRL_ID));
+    if (!control_iface) {
+      LOG(ERROR) << "Failed to obtain HAL AVRCP control interface handle";
+      return false;
+    }
+
+    control_iface_ = control_iface;
+    target_iface_ = target_iface;
+
+    // Only initialize the control interface.
+    return AvrcpControlEnable();
+  }
+
+  base::ObserverList<TargetObserver>* target_observers() {
+    return &target_observers_;
+  }
+
+  base::ObserverList<ControlObserver>* control_observers() {
+    return &control_observers_;
+  }
+
+ private:
+  // List of observers that are interested in notifications from us.
+  // We're not using a base::ObserverListThreadSafe, which it posts observer
+  // events automatically on the origin threads, as we want to avoid that
+  // overhead and simply forward the events to the upper layer.
+  base::ObserverList<TargetObserver> target_observers_;
+  base::ObserverList<ControlObserver> control_observers_;
+
+  // The HAL handle obtained from the shared library. We hold a weak reference
+  // to this since the actual data resides in the shared Bluetooth library.
+  const btrc_interface_t* target_iface_ = nullptr;
+  const btrc_ctrl_interface_t* control_iface_ = nullptr;
+
+  bool control_enabled_ = false;
+  bool target_enabled_ = false;
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpInterfaceImpl);
+};
+
+namespace {
+
+base::ObserverList<BluetoothAvrcpInterface::TargetObserver>*
+GetTargetObservers() {
+  CHECK(g_interface);
+  return static_cast<BluetoothAvrcpInterfaceImpl*>(g_interface)
+      ->target_observers();
+}
+
+base::ObserverList<BluetoothAvrcpInterface::ControlObserver>*
+GetControlObservers() {
+  CHECK(g_interface);
+  return static_cast<BluetoothAvrcpInterfaceImpl*>(g_interface)
+      ->control_observers();
+}
+
+}  // namespace
+
+void BluetoothAvrcpInterface::TargetObserver::RemoteFeaturesCallback(
+    const RawAddress& bd_addr, btrc_remote_features_t features) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetPlayStatusCallback(
+    const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::ListPlayerAppAttrCallback(
+    const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::ListPlayerAppValuesCallback(
+    btrc_player_attr_t attr_id, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetPlayerAppValueCallback(
+    uint8_t num_attr, btrc_player_attr_t* p_attrs, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetPlayerAppAttrsTextCallback(
+    uint8_t num_attr, btrc_player_attr_t* p_attrs, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetPlayerAppValuesTextCallback(
+    uint8_t attr_id, uint8_t num_val, uint8_t* p_vals,
+    const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::SetPlayerAppValueCallback(
+    btrc_player_settings_t* p_vals, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetElementAttrCallback(
+    uint8_t num_attr, btrc_media_attr_t* p_attrs, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::RegisterNotificationCallback(
+    btrc_event_id_t event_id, uint32_t param, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::VolumeChangeCallback(
+    uint8_t volume, uint8_t ctype, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::PassthroughCmdCallback(
+    int id, int key_state, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::SetAddressedPlayerCallback(
+    uint16_t player_id, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::SetBrowsedPlayerCallback(
+    uint16_t player_id, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetFolderItemsCallback(
+    uint8_t scope, uint32_t start_item, uint32_t end_item, uint8_t num_attr,
+    uint32_t* p_attr_ids, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::ChangePathCallback(
+    uint8_t direction, uint8_t* folder_uid, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetItemAttrCallback(
+    uint8_t scope, uint8_t* uid, uint16_t uid_counter, uint8_t num_attr,
+    btrc_media_attr_t* p_attrs, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::PlayItemCallback(
+    uint8_t scope, uint16_t uid_counter, uint8_t* uid,
+    const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::GetTotalNumOfItemsCallback(
+    uint8_t scope, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::SearchCallback(
+    uint16_t str_len, uint8_t* p_str, const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::TargetObserver::AddToNowPlayingCallback(
+    uint8_t scope, uint8_t* uid, uint16_t uid_counter,
+    const RawAddress& bd_addr) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::PassthroughRspCallback(
+    const RawAddress& /* bd_addr */, int /* id */, int /* key_state */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::GroupnavigationRspCallback(
+    int /* id */, int /* key_state */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::ConnectionStateCallback(
+    bool /* rc_connect */, bool /* bt_connect */,
+    const RawAddress& /* bd_addr */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlGetrcfeaturesCallback(
+    const RawAddress& /* bd_addr */, int /* features */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::
+    CtrlSetplayerapplicationsettingRspCallback(const RawAddress& /* bd_addr */,
+                                               uint8_t /* accepted */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::
+    CtrlPlayerapplicationsettingCallback(
+        const RawAddress& /* bd_addr */, uint8_t /* num_attr */,
+        btrc_player_app_attr_t* /* app_attrs */, uint8_t /* num_ext_attr */,
+        btrc_player_app_ext_attr_t* /* ext_attrs */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::
+    CtrlPlayerapplicationsettingChangedCallback(
+        const RawAddress& /* bd_addr*/,
+        const btrc_player_settings_t& /* vals */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlSetabsvolCmdCallback(
+    const RawAddress& /* bd_addr */, uint8_t /* abs_vol */,
+    uint8_t /* label */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::
+    CtrlRegisternotificationAbsVolCallback(const RawAddress& /* bd_addr */,
+                                           uint8_t /* label */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlTrackChangedCallback(
+    const RawAddress& /*bd_addr */, uint8_t /* num_attr */,
+    btrc_element_attr_val_t* /* p_attrs */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlPlayPositionChangedCallback(
+    const RawAddress& /* bd_addr */, uint32_t /* song_len */,
+    uint32_t /* song_pos */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlPlayStatusChangedCallback(
+    const RawAddress& /* bd_addr */, btrc_play_status_t /* play_status */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlGetFolderItemsCallback(
+    const RawAddress& /* bd_addr */, btrc_status_t /* status */,
+    const btrc_folder_items_t* /*folder_items */, uint8_t /* count */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlChangePathCallback(
+    const RawAddress& /* bd_addr */, uint32_t /* count */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlSetBrowsedPlayerCallback(
+    const RawAddress& /* bd_addr */, uint8_t /* num_items */,
+    uint8_t /* depth */) {
+  // Do nothing.
+}
+
+void BluetoothAvrcpInterface::ControlObserver::CtrlSetAddressedPlayerCallback(
+    const RawAddress& /* bd_addr */, uint8_t /* status */) {
+  // Do nothing.
+}
+
+// static
+bool BluetoothAvrcpInterface::Initialize() {
+  unique_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(!g_interface);
+
+  std::unique_ptr<BluetoothAvrcpInterfaceImpl> impl(
+      new BluetoothAvrcpInterfaceImpl());
+  if (!impl->Initialize()) {
+    LOG(ERROR) << "Failed to initialize BluetoothAvrcpInterface";
+    return false;
+  }
+
+  g_interface = impl.release();
+
+  return true;
+}
+
+// static
+void BluetoothAvrcpInterface::CleanUp() {
+  unique_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(g_interface);
+
+  delete g_interface;
+  g_interface = nullptr;
+}
+
+// static
+bool BluetoothAvrcpInterface::IsInitialized() {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+
+  return g_interface != nullptr;
+}
+
+// static
+BluetoothAvrcpInterface* BluetoothAvrcpInterface::Get() {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(g_interface);
+  return g_interface;
+}
+
+// static
+void BluetoothAvrcpInterface::InitializeForTesting(
+    BluetoothAvrcpInterface* test_instance) {
+  unique_lock<shared_mutex_impl> lock(g_instance_lock);
+  CHECK(test_instance);
+  CHECK(!g_interface);
+
+  g_interface = test_instance;
+}
+
+}  // namespace hal
+}  // namespace bluetooth
diff --git a/service/hal/bluetooth_avrcp_interface.h b/service/hal/bluetooth_avrcp_interface.h
new file mode 100644
index 0000000..08d6989
--- /dev/null
+++ b/service/hal/bluetooth_avrcp_interface.h
@@ -0,0 +1,179 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <base/macros.h>
+#include <hardware/bluetooth.h>
+#include <hardware/bt_rc.h>
+
+namespace bluetooth {
+namespace hal {
+
+class BluetoothAvrcpInterface {
+ public:
+  // The HAL interface doesn't allow registering "user data" that carries
+  // context beyond the callback parameters, forcing implementations to deal
+  // with global variables. The *Observer interface is to redirect these events
+  // to interested parties in an object-oriented manner.
+  class TargetObserver {
+   public:
+    virtual ~TargetObserver() = default;
+
+    virtual void RemoteFeaturesCallback(const RawAddress& bd_addr,
+                                        btrc_remote_features_t features);
+    virtual void GetPlayStatusCallback(const RawAddress& bd_addr);
+    virtual void ListPlayerAppAttrCallback(const RawAddress& bd_addr);
+    virtual void ListPlayerAppValuesCallback(btrc_player_attr_t attr_id,
+                                             const RawAddress& bd_addr);
+    virtual void GetPlayerAppValueCallback(uint8_t num_attr,
+                                           btrc_player_attr_t* p_attrs,
+                                           const RawAddress& bd_addr);
+    virtual void GetPlayerAppAttrsTextCallback(uint8_t num_attr,
+                                               btrc_player_attr_t* p_attrs,
+                                               const RawAddress& bd_addr);
+    virtual void GetPlayerAppValuesTextCallback(uint8_t attr_id,
+                                                uint8_t num_val,
+                                                uint8_t* p_vals,
+                                                const RawAddress& bd_addr);
+    virtual void SetPlayerAppValueCallback(btrc_player_settings_t* p_vals,
+                                           const RawAddress& bd_addr);
+    virtual void GetElementAttrCallback(uint8_t num_attr,
+                                        btrc_media_attr_t* p_attrs,
+                                        const RawAddress& bd_addr);
+    virtual void RegisterNotificationCallback(btrc_event_id_t event_id,
+                                              uint32_t param,
+                                              const RawAddress& bd_addr);
+    virtual void VolumeChangeCallback(uint8_t volume, uint8_t ctype,
+                                      const RawAddress& bd_addr);
+    virtual void PassthroughCmdCallback(int id, int key_state,
+                                        const RawAddress& bd_addr);
+    virtual void SetAddressedPlayerCallback(uint16_t player_id,
+                                            const RawAddress& bd_addr);
+    virtual void SetBrowsedPlayerCallback(uint16_t player_id,
+                                          const RawAddress& bd_addr);
+    virtual void GetFolderItemsCallback(uint8_t scope, uint32_t start_item,
+                                        uint32_t end_item, uint8_t num_attr,
+                                        uint32_t* p_attr_ids,
+                                        const RawAddress& bd_addr);
+    virtual void ChangePathCallback(uint8_t direction, uint8_t* folder_uid,
+                                    const RawAddress& bd_addr);
+    virtual void GetItemAttrCallback(uint8_t scope, uint8_t* uid,
+                                     uint16_t uid_counter, uint8_t num_attr,
+                                     btrc_media_attr_t* p_attrs,
+                                     const RawAddress& bd_addr);
+    virtual void PlayItemCallback(uint8_t scope, uint16_t uid_counter,
+                                  uint8_t* uid, const RawAddress& bd_addr);
+    virtual void GetTotalNumOfItemsCallback(uint8_t scope,
+                                            const RawAddress& bd_addr);
+    virtual void SearchCallback(uint16_t str_len, uint8_t* p_str,
+                                const RawAddress& bd_addr);
+    virtual void AddToNowPlayingCallback(uint8_t scope, uint8_t* uid,
+                                         uint16_t uid_counter,
+                                         const RawAddress& bd_addr);
+  };
+
+  class ControlObserver {
+   public:
+    virtual ~ControlObserver() = default;
+
+    virtual void PassthroughRspCallback(const RawAddress& bd_addr, int id,
+                                        int key_state);
+    virtual void GroupnavigationRspCallback(int id, int key_state);
+    virtual void ConnectionStateCallback(bool rc_connect, bool bt_connect,
+                                         const RawAddress& bd_addr);
+    virtual void CtrlGetrcfeaturesCallback(const RawAddress& bd_addr,
+                                           int features);
+    virtual void CtrlSetplayerapplicationsettingRspCallback(
+        const RawAddress& bd_addr, uint8_t accepted);
+    virtual void CtrlPlayerapplicationsettingCallback(
+        const RawAddress& bd_addr, uint8_t num_attr,
+        btrc_player_app_attr_t* app_attrs, uint8_t num_ext_attr,
+        btrc_player_app_ext_attr_t* ext_attrs);
+    virtual void CtrlPlayerapplicationsettingChangedCallback(
+        const RawAddress& bd_addr, const btrc_player_settings_t& p_vals);
+    virtual void CtrlSetabsvolCmdCallback(const RawAddress& bd_addr,
+                                          uint8_t abs_vol, uint8_t label);
+    virtual void CtrlRegisternotificationAbsVolCallback(
+        const RawAddress& bd_addr, uint8_t label);
+    virtual void CtrlTrackChangedCallback(const RawAddress& bd_addr,
+                                          uint8_t num_attr,
+                                          btrc_element_attr_val_t* p_attrs);
+    virtual void CtrlPlayPositionChangedCallback(const RawAddress& bd_addr,
+                                                 uint32_t song_len,
+                                                 uint32_t song_pos);
+    virtual void CtrlPlayStatusChangedCallback(const RawAddress& bd_addr,
+                                               btrc_play_status_t play_status);
+    virtual void CtrlGetFolderItemsCallback(
+        const RawAddress& bd_addr, btrc_status_t status,
+        const btrc_folder_items_t* folder_items, uint8_t count);
+    virtual void CtrlChangePathCallback(const RawAddress& bd_addr,
+                                        uint32_t count);
+    virtual void CtrlSetBrowsedPlayerCallback(const RawAddress& bd_addr,
+                                              uint8_t num_items, uint8_t depth);
+    virtual void CtrlSetAddressedPlayerCallback(const RawAddress& bd_addr,
+                                                uint8_t status);
+  };
+
+  // Initialize and clean up the BluetoothInterface singleton. Returns false if
+  // the underlying HAL interface failed to initialize, and true on success.
+  static bool Initialize();
+
+  // Shuts down and cleans up the interface. CleanUp must be called on the same
+  // thread that called Initialize.
+  static void CleanUp();
+
+  // Returns true if the interface was initialized and a global singleton has
+  // been created.
+  static bool IsInitialized();
+
+  // Initialize for testing. Use this to inject a test version of
+  // BluetoothAvrcpInterface. To be used from unit tests only.
+  static void InitializeForTesting(BluetoothAvrcpInterface* test_instance);
+
+  // Returns the BluetoothAvrcpInterface singleton. If the interface has
+  // not been initialized, returns nullptr. This method is thread-safe, in that
+  // it will block if the internal lock is being held by another thread. Don't
+  // call this re-entrantly from an observer event as this may cause a deadlock.
+  static BluetoothAvrcpInterface* Get();
+
+  virtual bool AvrcpControlEnable() = 0;
+  virtual void AvrcpControlDisable() = 0;
+  virtual bool AvrcpTargetEnable() = 0;
+  virtual void AvrcpTargetDisable() = 0;
+
+  // Thread-safety is guaranteed by ObserverList.
+  virtual void AddTargetObserver(TargetObserver* observer) = 0;
+  virtual void RemoveTargetObserver(TargetObserver* observer) = 0;
+
+  // Thread-safety is guaranteed by ObserverList.
+  virtual void AddControlObserver(ControlObserver* observer) = 0;
+  virtual void RemoveControlObserver(ControlObserver* observer) = 0;
+
+  // The HAL module pointers provided by the shared Bluetooth library
+  virtual const btrc_interface_t* GetTargetHALInterface() const = 0;
+  virtual const btrc_ctrl_interface_t* GetControlHALInterface() const = 0;
+
+ protected:
+  BluetoothAvrcpInterface() = default;
+  virtual ~BluetoothAvrcpInterface() = default;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpInterface);
+};
+
+}  // namespace hal
+}  // namespace bluetooth
diff --git a/service/hal/bluetooth_gatt_interface.cc b/service/hal/bluetooth_gatt_interface.cc
index 35b295b..d61a238 100644
--- a/service/hal/bluetooth_gatt_interface.cc
+++ b/service/hal/bluetooth_gatt_interface.cc
@@ -148,7 +148,7 @@
   LOG(INFO) << __func__ << " - conn_id: " << conn_id << " - status: " << status
             << " - registered: " << registered << " - handle: " << handle;
   FOR_EACH_CLIENT_OBSERVER(RegisterForNotificationCallback(
-      g_interface, conn_id, status, registered, handle));
+      g_interface, conn_id, registered, status, handle));
 }
 
 void NotifyCallback(int conn_id, const btgatt_notify_params_t& p_data) {
@@ -594,7 +594,7 @@
 
 void BluetoothGattInterface::ClientObserver::RegisterForNotificationCallback(
     BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
-    int /* status */, int /* registered */, uint16_t /* handle */) {
+    int /* registered */, int /* status */, uint16_t /* handle */) {
   // Do nothing
 }
 
diff --git a/service/hal/bluetooth_gatt_interface.h b/service/hal/bluetooth_gatt_interface.h
index 08b0e9b..ccd0ae9 100644
--- a/service/hal/bluetooth_gatt_interface.h
+++ b/service/hal/bluetooth_gatt_interface.h
@@ -81,8 +81,8 @@
                                         int conn_id, int status);
 
     virtual void RegisterForNotificationCallback(
-        BluetoothGattInterface* gatt_iface, int conn_id, int status,
-        int registered, uint16_t handle);
+        BluetoothGattInterface* gatt_iface, int conn_id, int registered,
+        int status, uint16_t handle);
 
     virtual void NotifyCallback(BluetoothGattInterface* gatt_iface, int conn_id,
                                 const btgatt_notify_params_t& p_data);
diff --git a/service/hal/bluetooth_interface.cc b/service/hal/bluetooth_interface.cc
index 9296966..5ca220c 100644
--- a/service/hal/bluetooth_interface.cc
+++ b/service/hal/bluetooth_interface.cc
@@ -98,6 +98,13 @@
       status, remote_bd_addr, num_properties, properties));
 }
 
+void DeviceFoundCallback(int num_properties, bt_property_t* properties) {
+  shared_lock<shared_mutex_impl> lock(g_instance_lock);
+  VERIFY_INTERFACE_OR_RETURN();
+  VLOG(1) << " Device found.";
+  FOR_EACH_BLUETOOTH_OBSERVER(DeviceFoundCallback(num_properties, properties));
+}
+
 void DiscoveryStateChangedCallback(bt_discovery_state_t state) {
   shared_lock<shared_mutex_impl> lock(g_instance_lock);
   VERIFY_INTERFACE_OR_RETURN();
@@ -190,7 +197,7 @@
     AdapterStateChangedCallback,
     AdapterPropertiesCallback,
     RemoteDevicePropertiesCallback,
-    nullptr, /* device_found_cb */
+    DeviceFoundCallback,
     DiscoveryStateChangedCallback,
     PinRequestCallback,
     SSPRequestCallback,
@@ -247,7 +254,7 @@
 
     // Initialize the Bluetooth interface. Set up the adapter (Bluetooth DM) API
     // callbacks.
-    status = hal_iface_->init(&bt_callbacks);
+    status = hal_iface_->init(&bt_callbacks, false, false);
     if (status != BT_STATUS_SUCCESS) {
       LOG(ERROR) << "Failed to initialize Bluetooth stack";
       return false;
@@ -309,6 +316,11 @@
   // Do nothing.
 }
 
+void BluetoothInterface::Observer::DeviceFoundCallback(
+    int /* num_properties */, bt_property_t* /* properties */) {
+  // Do nothing.
+}
+
 void BluetoothInterface::Observer::DiscoveryStateChangedCallback(
     bt_discovery_state_t /* state */) {
   // Do nothing.
diff --git a/service/hal/bluetooth_interface.h b/service/hal/bluetooth_interface.h
index 897835f..a1c8e62 100644
--- a/service/hal/bluetooth_interface.h
+++ b/service/hal/bluetooth_interface.h
@@ -57,6 +57,8 @@
                                                 RawAddress* remote_bd_addr,
                                                 int num_properties,
                                                 bt_property_t* properties);
+    virtual void DeviceFoundCallback(int num_properties,
+                                     bt_property_t* properties);
     virtual void DiscoveryStateChangedCallback(bt_discovery_state_t state);
     virtual void PinRequestCallback(RawAddress* remote_bd_addr,
                                     bt_bdname_t* bd_name, uint32_t cod,
diff --git a/service/hal/fake_bluetooth_av_interface.cc b/service/hal/fake_bluetooth_av_interface.cc
new file mode 100644
index 0000000..39a6331
--- /dev/null
+++ b/service/hal/fake_bluetooth_av_interface.cc
@@ -0,0 +1,151 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include "service/hal/fake_bluetooth_av_interface.h"
+
+namespace bluetooth {
+namespace hal {
+namespace {
+
+// The global test handler instances. We have to have globals since the HAL
+// interface methods all have to be global and their signatures don't allow us
+// to pass in user_data.
+std::shared_ptr<FakeBluetoothAvInterface::TestA2dpSinkHandler>
+    g_a2dp_sink_handler;
+
+bt_status_t FakeInit(btav_sink_callbacks_t* callbacks) {
+  return BT_STATUS_SUCCESS;
+}
+
+bt_status_t FakeConnect(const RawAddress& bd_addr) {
+  if (g_a2dp_sink_handler) return g_a2dp_sink_handler->Connect(bd_addr);
+  return BT_STATUS_FAIL;
+}
+
+bt_status_t FakeDisconnect(const RawAddress& bd_addr) {
+  if (g_a2dp_sink_handler) return g_a2dp_sink_handler->Disconnect(bd_addr);
+  return BT_STATUS_FAIL;
+}
+
+void FakeCleanup(void) {}
+
+void FakeSetAudioFocusState(int focus_state) {
+  if (g_a2dp_sink_handler)
+    return g_a2dp_sink_handler->SetAudioFocusState(focus_state);
+}
+
+void FakeSetAudioTrackGain(float gain) {
+  if (g_a2dp_sink_handler) return g_a2dp_sink_handler->SetAudioTrackGain(gain);
+}
+
+btav_source_interface_t fake_a2dp_source_interface = {
+    .size = sizeof(btav_source_interface_t),
+    .init = nullptr,
+    .connect = nullptr,
+    .disconnect = nullptr,
+    .config_codec = nullptr,
+    .cleanup = nullptr,
+};
+
+btav_sink_interface_t fake_a2dp_sink_interface = {
+    .size = sizeof(btav_sink_interface_t),
+    .init = FakeInit,
+    .connect = FakeConnect,
+    .disconnect = FakeDisconnect,
+    .cleanup = FakeCleanup,
+    .set_audio_focus_state = FakeSetAudioFocusState,
+    .set_audio_track_gain = FakeSetAudioTrackGain,
+};
+
+}  // namespace
+
+FakeBluetoothAvInterface::FakeBluetoothAvInterface(
+    std::shared_ptr<TestA2dpSinkHandler> a2dp_sink_handler) {
+  CHECK(!g_a2dp_sink_handler);
+
+  if (a2dp_sink_handler) g_a2dp_sink_handler = a2dp_sink_handler;
+}
+
+FakeBluetoothAvInterface::~FakeBluetoothAvInterface() {
+  g_a2dp_sink_handler = nullptr;
+}
+
+void FakeBluetoothAvInterface::NotifyConnectionState(
+    const RawAddress& bda, btav_connection_state_t state) {
+  for (auto& observer : a2dp_sink_observers_) {
+    observer.ConnectionStateCallback(this, bda, state);
+  }
+}
+void FakeBluetoothAvInterface::NotifyAudioState(const RawAddress& bda,
+                                                btav_audio_state_t state) {
+  for (auto& observer : a2dp_sink_observers_) {
+    observer.AudioStateCallback(this, bda, state);
+  }
+}
+void FakeBluetoothAvInterface::NotifyAudioConfig(const RawAddress& bda,
+                                                 uint32_t sample_rate,
+                                                 uint8_t channel_count) {
+  for (auto& observer : a2dp_sink_observers_) {
+    observer.AudioConfigCallback(this, bda, sample_rate, channel_count);
+  }
+}
+
+bool FakeBluetoothAvInterface::A2dpSourceEnable(
+    std::vector<btav_a2dp_codec_config_t> codec_priorities) {
+  return true;
+}
+
+void FakeBluetoothAvInterface::A2dpSourceDisable() {}
+
+bool FakeBluetoothAvInterface::A2dpSinkEnable() { return true; }
+
+void FakeBluetoothAvInterface::A2dpSinkDisable() {}
+
+void FakeBluetoothAvInterface::AddA2dpSourceObserver(
+    A2dpSourceObserver* observer) {
+  CHECK(observer);
+  a2dp_source_observers_.AddObserver(observer);
+}
+
+void FakeBluetoothAvInterface::RemoveA2dpSourceObserver(
+    A2dpSourceObserver* observer) {
+  CHECK(observer);
+  a2dp_source_observers_.RemoveObserver(observer);
+}
+
+void FakeBluetoothAvInterface::AddA2dpSinkObserver(A2dpSinkObserver* observer) {
+  CHECK(observer);
+  a2dp_sink_observers_.AddObserver(observer);
+}
+
+void FakeBluetoothAvInterface::RemoveA2dpSinkObserver(
+    A2dpSinkObserver* observer) {
+  CHECK(observer);
+  a2dp_sink_observers_.RemoveObserver(observer);
+}
+
+const btav_source_interface_t*
+FakeBluetoothAvInterface::GetA2dpSourceHALInterface() {
+  return &fake_a2dp_source_interface;
+}
+
+const btav_sink_interface_t*
+FakeBluetoothAvInterface::GetA2dpSinkHALInterface() {
+  return &fake_a2dp_sink_interface;
+}
+
+}  // namespace hal
+}  // namespace bluetooth
diff --git a/service/hal/fake_bluetooth_av_interface.h b/service/hal/fake_bluetooth_av_interface.h
new file mode 100644
index 0000000..c979434
--- /dev/null
+++ b/service/hal/fake_bluetooth_av_interface.h
@@ -0,0 +1,82 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <base/macros.h>
+#include <base/observer_list.h>
+
+#include "service/hal/bluetooth_av_interface.h"
+
+namespace bluetooth {
+namespace hal {
+
+class FakeBluetoothAvInterface : public BluetoothAvInterface {
+ public:
+  // Handles HAL Bluetooth A2DP sink API calls for testing. Test code can
+  // provide a fake or mock implementation of this and all calls will be routed
+  // to it.
+  class TestA2dpSinkHandler {
+   public:
+    virtual bt_status_t Connect(RawAddress bda) = 0;
+    virtual bt_status_t Disconnect(RawAddress bda) = 0;
+    virtual void SetAudioFocusState(int focus_state) = 0;
+    virtual void SetAudioTrackGain(float gain) = 0;
+
+   protected:
+    virtual ~TestA2dpSinkHandler() = default;
+  };
+
+  // Constructs the fake with the given handlers. Implementations can
+  // provide their own handlers or simply pass "nullptr" for the default
+  // behavior in which BT_STATUS_FAIL will be returned from all calls.
+  FakeBluetoothAvInterface(
+      std::shared_ptr<TestA2dpSinkHandler> a2dp_sink_handler);
+  ~FakeBluetoothAvInterface();
+
+  // The methods below can be used to notify observers with certain events and
+  // given parameters.
+
+  // A2DP sink callbacks
+  void NotifyConnectionState(const RawAddress& bda,
+                             btav_connection_state_t state);
+  void NotifyAudioState(const RawAddress& bda, btav_audio_state_t state);
+  void NotifyAudioConfig(const RawAddress& bda, uint32_t sample_rate,
+                         uint8_t channel_count);
+
+  // BluetoothAvInterface overrides:
+  bool A2dpSourceEnable(
+      std::vector<btav_a2dp_codec_config_t> codec_priorities) override;
+  void A2dpSourceDisable() override;
+  bool A2dpSinkEnable() override;
+  void A2dpSinkDisable() override;
+  void AddA2dpSourceObserver(A2dpSourceObserver* observer) override;
+  void RemoveA2dpSourceObserver(A2dpSourceObserver* observer) override;
+  void AddA2dpSinkObserver(A2dpSinkObserver* observer) override;
+  void RemoveA2dpSinkObserver(A2dpSinkObserver* observer) override;
+  const btav_source_interface_t* GetA2dpSourceHALInterface() override;
+  const btav_sink_interface_t* GetA2dpSinkHALInterface() override;
+
+ private:
+  base::ObserverList<A2dpSourceObserver> a2dp_source_observers_;
+  base::ObserverList<A2dpSinkObserver> a2dp_sink_observers_;
+  std::shared_ptr<TestA2dpSinkHandler> scanner_handler_;
+
+  DISALLOW_COPY_AND_ASSIGN(FakeBluetoothAvInterface);
+};
+
+}  // namespace hal
+}  // namespace bluetooth
diff --git a/service/hal/fake_bluetooth_interface.cc b/service/hal/fake_bluetooth_interface.cc
index eb550e7..f1d03ad 100644
--- a/service/hal/fake_bluetooth_interface.cc
+++ b/service/hal/fake_bluetooth_interface.cc
@@ -23,7 +23,7 @@
 
 FakeBluetoothInterface::Manager g_hal_manager;
 
-int FakeHALEnable(bool start_restricted) {
+int FakeHALEnable() {
   return g_hal_manager.enable_succeed ? BT_STATUS_SUCCESS : BT_STATUS_FAIL;
 }
 
@@ -74,6 +74,7 @@
     nullptr, /* interop_database_clear */
     nullptr, /* interop_database_add */
     nullptr, /* get_avrcp_service */
+    nullptr, /* obfuscate_address */
 };
 
 }  // namespace
diff --git a/service/ipc/binder/bluetooth_a2dp_sink_binder_server.cc b/service/ipc/binder/bluetooth_a2dp_sink_binder_server.cc
new file mode 100644
index 0000000..1609aa8
--- /dev/null
+++ b/service/ipc/binder/bluetooth_a2dp_sink_binder_server.cc
@@ -0,0 +1,222 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+#include "service/ipc/binder/bluetooth_a2dp_sink_binder_server.h"
+
+#include <base/logging.h>
+
+#include "service/adapter.h"
+
+using android::String16;
+using android::String8;
+using android::binder::Status;
+
+using android::bluetooth::IBluetoothA2dpSinkCallback;
+
+namespace ipc {
+namespace binder {
+
+BluetoothA2dpSinkBinderServer::BluetoothA2dpSinkBinderServer(
+    bluetooth::Adapter* adapter)
+    : adapter_(adapter) {
+  CHECK(adapter);
+}
+
+Status BluetoothA2dpSinkBinderServer::Register(
+    const android::sp<IBluetoothA2dpSinkCallback>& callback,
+    bool* _aidl_return) {
+  auto factory = adapter_->GetA2dpSinkFactory();
+  *_aidl_return = RegisterInstanceBase(callback, factory);
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::Unregister() {
+  UnregisterAllBase();
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::Enable(bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto a2dp_sink = GetA2dpSink();
+  if (!a2dp_sink) {
+    LOG(ERROR) << "Failed to get A2DP sink instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!a2dp_sink->Enable()) {
+    LOG(ERROR) << "Failed to enable";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::Disable(bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto a2dp_sink = GetA2dpSink();
+  if (!a2dp_sink) {
+    LOG(ERROR) << "Failed to get A2DP sink instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  a2dp_sink->Disable();
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::Connect(const String16& device_address,
+                                              bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto a2dp_sink = GetA2dpSink();
+  if (!a2dp_sink) {
+    LOG(ERROR) << "Failed to get A2DP sink instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!a2dp_sink->Connect(String8(device_address).string())) {
+    LOG(ERROR) << "Failed to connect";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::Disconnect(const String16& device_address,
+                                                 bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto a2dp_sink = GetA2dpSink();
+  if (!a2dp_sink) {
+    LOG(ERROR) << "Failed to get A2DP sink instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!a2dp_sink->Disconnect(String8(device_address).string())) {
+    LOG(ERROR) << "Failed to connect";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::SetAudioFocusState(int focus_state,
+                                                         bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto a2dp_sink = GetA2dpSink();
+  if (!a2dp_sink) {
+    LOG(ERROR) << "Failed to get A2DP instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  a2dp_sink->SetAudioFocusState(focus_state);
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothA2dpSinkBinderServer::SetAudioTrackGain(float gain,
+                                                        bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto a2dp_sink = GetA2dpSink();
+  if (!a2dp_sink) {
+    LOG(ERROR) << "Failed to get A2DP instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  a2dp_sink->SetAudioTrackGain(gain);
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+void BluetoothA2dpSinkBinderServer::OnConnectionState(
+    const std::string& device_address, int state) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto cb = GetA2dpSinkCallback();
+  if (!cb.get()) {
+    LOG(WARNING) << "Callback for this GattServer was deleted.";
+    return;
+  }
+
+  cb->OnConnectionState(String16(device_address.c_str()), state);
+}
+
+void BluetoothA2dpSinkBinderServer::OnAudioState(
+    const std::string& device_address, int state) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto cb = GetA2dpSinkCallback();
+  if (!cb.get()) {
+    LOG(WARNING) << "Callback for this GattServer was deleted.";
+    return;
+  }
+
+  cb->OnAudioState(String16(device_address.c_str()), state);
+}
+
+void BluetoothA2dpSinkBinderServer::OnAudioConfig(
+    const std::string& device_address, uint32_t sample_rate,
+    uint8_t channel_count) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto cb = GetA2dpSinkCallback();
+  if (!cb.get()) {
+    LOG(WARNING) << "Callback for this GattServer was deleted.";
+    return;
+  }
+
+  cb->OnAudioConfig(String16(device_address.c_str()), sample_rate,
+                    channel_count);
+}
+
+bool BluetoothA2dpSinkBinderServer::HasInstance() {
+  return GetA2dpSink() != nullptr;
+}
+
+android::sp<IBluetoothA2dpSinkCallback>
+BluetoothA2dpSinkBinderServer::GetA2dpSinkCallback() {
+  auto cb = GetCallback(bluetooth::A2dpSink::kSingletonInstanceId);
+  return android::sp<IBluetoothA2dpSinkCallback>(
+      static_cast<IBluetoothA2dpSinkCallback*>(cb.get()));
+}
+
+std::shared_ptr<bluetooth::A2dpSink>
+BluetoothA2dpSinkBinderServer::GetA2dpSink() {
+  return std::static_pointer_cast<bluetooth::A2dpSink>(
+      GetInstance(bluetooth::A2dpSink::kSingletonInstanceId));
+}
+
+void BluetoothA2dpSinkBinderServer::OnRegisterInstanceImpl(
+    bluetooth::BLEStatus status, android::sp<IInterface> callback,
+    bluetooth::BluetoothInstance* instance) {
+  VLOG(1) << __func__ << " instance ID: " << instance->GetInstanceId()
+          << " status: " << status;
+  bluetooth::A2dpSink* a2dp_sink = static_cast<bluetooth::A2dpSink*>(instance);
+  a2dp_sink->SetDelegate(this);
+
+  android::sp<IBluetoothA2dpSinkCallback> cb(
+      static_cast<IBluetoothA2dpSinkCallback*>(callback.get()));
+  cb->OnRegistered(status);
+}
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h b/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h
new file mode 100644
index 0000000..e18af54
--- /dev/null
+++ b/service/ipc/binder/bluetooth_a2dp_sink_binder_server.h
@@ -0,0 +1,86 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <map>
+#include <string>
+
+#include <base/macros.h>
+
+#include <android/bluetooth/BnBluetoothA2dpSink.h>
+#include <android/bluetooth/IBluetoothA2dpSinkCallback.h>
+
+#include "service/a2dp_sink.h"
+#include "service/ipc/binder/interface_with_instances_base.h"
+
+namespace bluetooth {
+class Adapter;
+}  // namespace bluetooth
+
+namespace ipc {
+namespace binder {
+
+class BluetoothA2dpSinkBinderServer
+    : public InterfaceWithInstancesBase,
+      public android::bluetooth::BnBluetoothA2dpSink,
+      public bluetooth::A2dpSink::Delegate {
+ public:
+  explicit BluetoothA2dpSinkBinderServer(bluetooth::Adapter* adapter);
+  ~BluetoothA2dpSinkBinderServer() override = default;
+
+  // IBluetoothA2dpSink implementation:
+  android::binder::Status Register(
+      const android::sp<android::bluetooth::IBluetoothA2dpSinkCallback>&
+          callback,
+      bool* _aidl_return) override;
+  android::binder::Status Enable(bool* _aidl_return) override;
+  android::binder::Status Disable(bool* _aidl_return) override;
+  android::binder::Status Unregister() override;
+  android::binder::Status Connect(const android::String16& device_address,
+                                  bool* _aidl_return) override;
+  android::binder::Status Disconnect(const android::String16& device_address,
+                                     bool* _aidl_return) override;
+  android::binder::Status SetAudioFocusState(int state,
+                                             bool* _aidl_return) override;
+  android::binder::Status SetAudioTrackGain(float gain,
+                                            bool* _aidl_return) override;
+
+  // bluetooth::bluetooth::A2dpSink::Delegate implementation:
+  void OnConnectionState(const std::string& device_address, int state) override;
+  void OnAudioState(const std::string& device_address, int state) override;
+  void OnAudioConfig(const std::string& device_address, uint32_t sample_rate,
+                     uint8_t channel_count) override;
+
+  bool HasInstance();
+
+ private:
+  android::sp<android::bluetooth::IBluetoothA2dpSinkCallback>
+  GetA2dpSinkCallback();
+  std::shared_ptr<bluetooth::A2dpSink> GetA2dpSink();
+
+  // InterfaceWithInstancesBase override:
+  void OnRegisterInstanceImpl(bluetooth::BLEStatus status,
+                              android::sp<IInterface> callback,
+                              bluetooth::BluetoothInstance* instance) override;
+
+  bluetooth::Adapter* adapter_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothA2dpSinkBinderServer);
+};
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_a2dp_source_binder_server.cc b/service/ipc/binder/bluetooth_a2dp_source_binder_server.cc
new file mode 100644
index 0000000..51e6dff
--- /dev/null
+++ b/service/ipc/binder/bluetooth_a2dp_source_binder_server.cc
@@ -0,0 +1,226 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+#include "service/ipc/binder/bluetooth_a2dp_source_binder_server.h"
+
+#include <base/logging.h>
+
+#include "service/adapter.h"
+
+#define AIDL_RET(value)      \
+  do {                       \
+    *_aidl_return = (value); \
+    return Status::ok();     \
+  } while (0)
+
+#define TRY_GET_SOURCE()                                   \
+  ({                                                       \
+    auto source = GetA2dpSource();                         \
+    if (!source) {                                         \
+      LOG(ERROR) << __func__ << ": "                       \
+                 << "Failed to get A2DP source interface"; \
+      AIDL_RET(false);                                     \
+    }                                                      \
+    source;                                                \
+  })
+
+#define TRY_GET_CB()                                          \
+  ({                                                          \
+    auto cb = GetA2dpSourceCallback();                        \
+    if (!cb.get()) {                                          \
+      LOG(WARNING) << "Callback for A2DP SOURCE was deleted"; \
+      return;                                                 \
+    }                                                         \
+    cb;                                                       \
+  })
+
+#define TRY_RET(expr, msg) \
+  do {                     \
+    if (!(expr)) {         \
+      LOG(ERROR) << msg;   \
+      AIDL_RET(false);     \
+    }                      \
+    AIDL_RET(true);        \
+  } while (0)
+
+#define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
+
+using android::String16;
+using android::String8;
+using android::binder::Status;
+using android::bluetooth::BluetoothA2dpCodecConfig;
+using android::bluetooth::IBluetoothA2dpSourceCallback;
+
+using LockGuard = std::lock_guard<std::mutex>;
+
+namespace ipc {
+namespace binder {
+
+namespace {
+
+std::vector<bluetooth::A2dpCodecConfig> A2dpCodecsFromBinder(
+    const std::vector<BluetoothA2dpCodecConfig>& codecs) {
+  std::vector<bluetooth::A2dpCodecConfig> ret;
+  ret.reserve(codecs.size());
+  for (const auto& config : codecs) {
+    ret.push_back(config);
+  }
+
+  return ret;
+}
+
+std::vector<BluetoothA2dpCodecConfig> A2dpCodecsToBinder(
+    const std::vector<bluetooth::A2dpCodecConfig>& codecs) {
+  std::vector<BluetoothA2dpCodecConfig> ret;
+  ret.reserve(codecs.size());
+  for (const auto& config : codecs) {
+    ret.push_back(config);
+  }
+
+  return ret;
+}
+
+}  // namespace
+
+BluetoothA2dpSourceBinderServer::BluetoothA2dpSourceBinderServer(
+    bluetooth::Adapter* adapter)
+    : adapter_(adapter) {
+  CHECK(adapter);
+}
+
+BluetoothA2dpSourceBinderServer::~BluetoothA2dpSourceBinderServer() = default;
+
+bool BluetoothA2dpSourceBinderServer::HasInstance() {
+  return GetA2dpSource() != nullptr;
+}
+
+Status BluetoothA2dpSourceBinderServer::Register(
+    const android::sp<IBluetoothA2dpSourceCallback>& callback,
+    bool* _aidl_return) {
+  auto factory = adapter_->GetA2dpSourceFactory();
+  *_aidl_return = RegisterInstanceBase(callback, factory);
+  return Status::ok();
+}
+
+Status BluetoothA2dpSourceBinderServer::Unregister() {
+  UnregisterAllBase();
+  return Status::ok();
+}
+
+Status BluetoothA2dpSourceBinderServer::Enable(
+    const std::vector<android::bluetooth::BluetoothA2dpCodecConfig>&
+        codec_priorities,
+    bool* _aidl_return) {
+  auto codec_priorities_non_binder = A2dpCodecsFromBinder(codec_priorities);
+
+  LockGuard lock(*maps_lock());
+  auto a2dp_source = TRY_GET_SOURCE();
+  TRY_RET_FUNC(a2dp_source->Enable(codec_priorities_non_binder));
+}
+
+Status BluetoothA2dpSourceBinderServer::Disable(bool* _aidl_return) {
+  LockGuard lock(*maps_lock());
+  auto a2dp_source = TRY_GET_SOURCE();
+  a2dp_source->Disable();
+  AIDL_RET(true);
+}
+
+Status BluetoothA2dpSourceBinderServer::Connect(const String16& device_address,
+                                                bool* _aidl_return) {
+  LockGuard lock(*maps_lock());
+  auto a2dp_source = TRY_GET_SOURCE();
+  TRY_RET_FUNC(a2dp_source->Connect(String8(device_address).string()));
+}
+
+Status BluetoothA2dpSourceBinderServer::Disconnect(
+    const String16& device_address, bool* _aidl_return) {
+  LockGuard lock(*maps_lock());
+  auto a2dp_source = TRY_GET_SOURCE();
+  TRY_RET_FUNC(a2dp_source->Disconnect(String8(device_address).string()));
+}
+
+Status BluetoothA2dpSourceBinderServer::ConfigCodec(
+    const android::String16& device_address,
+    const std::vector<android::bluetooth::BluetoothA2dpCodecConfig>&
+        codec_preferences,
+    bool* _aidl_return) {
+  auto codec_preferences_non_binder = A2dpCodecsFromBinder(codec_preferences);
+
+  LockGuard lock(*maps_lock());
+  auto a2dp_source = TRY_GET_SOURCE();
+  TRY_RET_FUNC(a2dp_source->ConfigCodec(String8(device_address).string(),
+                                        codec_preferences_non_binder));
+}
+
+void BluetoothA2dpSourceBinderServer::OnConnectionState(
+    const std::string& device_address, int state) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnConnectionState(String16(device_address.c_str()), state);
+}
+
+void BluetoothA2dpSourceBinderServer::OnAudioState(
+    const std::string& device_address, int state) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnAudioState(String16(device_address.c_str()), state);
+}
+
+void BluetoothA2dpSourceBinderServer::OnAudioConfig(
+    const std::string& device_address, bluetooth::A2dpCodecConfig codec_config,
+    const std::vector<bluetooth::A2dpCodecConfig>& codecs_local_capabilities,
+    const std::vector<bluetooth::A2dpCodecConfig>&
+        codecs_selectable_capabilities) {
+  auto binder_codecs_local_capabilities =
+      A2dpCodecsToBinder(codecs_local_capabilities);
+  auto binder_codecs_selectable_capabilities =
+      A2dpCodecsToBinder(codecs_selectable_capabilities);
+
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnAudioConfig(String16(device_address.c_str()), codec_config,
+                    binder_codecs_local_capabilities,
+                    binder_codecs_selectable_capabilities);
+}
+
+android::sp<IBluetoothA2dpSourceCallback>
+BluetoothA2dpSourceBinderServer::GetA2dpSourceCallback() {
+  auto cb = GetCallback(bluetooth::A2dpSource::kSingletonInstanceId);
+  return android::sp<IBluetoothA2dpSourceCallback>(
+      static_cast<IBluetoothA2dpSourceCallback*>(cb.get()));
+}
+
+std::shared_ptr<bluetooth::A2dpSource>
+BluetoothA2dpSourceBinderServer::GetA2dpSource() {
+  return std::static_pointer_cast<bluetooth::A2dpSource>(
+      GetInstance(bluetooth::A2dpSource::kSingletonInstanceId));
+}
+
+void BluetoothA2dpSourceBinderServer::OnRegisterInstanceImpl(
+    bluetooth::BLEStatus status, android::sp<IInterface> callback,
+    bluetooth::BluetoothInstance* instance) {
+  VLOG(1) << __func__ << " instance ID: " << instance->GetInstanceId()
+          << " status: " << status;
+  bluetooth::A2dpSource* a2dp_source =
+      static_cast<bluetooth::A2dpSource*>(instance);
+  a2dp_source->SetDelegate(this);
+
+  android::sp<IBluetoothA2dpSourceCallback> cb(
+      static_cast<IBluetoothA2dpSourceCallback*>(callback.get()));
+  cb->OnRegistered(status);
+}
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_a2dp_source_binder_server.h b/service/ipc/binder/bluetooth_a2dp_source_binder_server.h
new file mode 100644
index 0000000..160a38a
--- /dev/null
+++ b/service/ipc/binder/bluetooth_a2dp_source_binder_server.h
@@ -0,0 +1,95 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include <base/macros.h>
+
+#include <android/bluetooth/BnBluetoothA2dpSource.h>
+#include <android/bluetooth/IBluetoothA2dpSourceCallback.h>
+
+#include "service/a2dp_source.h"
+#include "service/ipc/binder/interface_with_instances_base.h"
+
+namespace bluetooth {
+class Adapter;
+}  // namespace bluetooth
+
+namespace ipc {
+namespace binder {
+
+class BluetoothA2dpSourceBinderServer
+    : public InterfaceWithInstancesBase,
+      public android::bluetooth::BnBluetoothA2dpSource,
+      public bluetooth::A2dpSource::Delegate {
+ public:
+  explicit BluetoothA2dpSourceBinderServer(bluetooth::Adapter* adapter);
+  ~BluetoothA2dpSourceBinderServer() override;
+
+  bool HasInstance();
+
+  // IBluetoothA2dpSource implementation:
+  android::binder::Status Register(
+      const android::sp<android::bluetooth::IBluetoothA2dpSourceCallback>&
+          callback,
+      bool* _aidl_return) override;
+  android::binder::Status Unregister() override;
+  android::binder::Status Enable(
+      const std::vector<android::bluetooth::BluetoothA2dpCodecConfig>&
+          codec_priorities,
+      bool* _aidl_return) override;
+  android::binder::Status Disable(bool* _aidl_return) override;
+  android::binder::Status Connect(const android::String16& device_address,
+                                  bool* _aidl_return) override;
+  android::binder::Status Disconnect(const android::String16& device_address,
+                                     bool* _aidl_return) override;
+  android::binder::Status ConfigCodec(
+      const android::String16& device_address,
+      const std::vector<android::bluetooth::BluetoothA2dpCodecConfig>&
+          codec_preferences,
+      bool* _aidl_return) override;
+
+ private:
+  // bluetooth::bluetooth::A2dpSource::Delegate implementation:
+  void OnConnectionState(const std::string& device_address, int state) override;
+  void OnAudioState(const std::string& device_address, int state) override;
+  void OnAudioConfig(
+      const std::string& device_address,
+      bluetooth::A2dpCodecConfig codec_config,
+      const std::vector<bluetooth::A2dpCodecConfig>& codecs_local_capabilities,
+      const std::vector<bluetooth::A2dpCodecConfig>&
+          codecs_selectable_capabilities) override;
+
+  android::sp<android::bluetooth::IBluetoothA2dpSourceCallback>
+  GetA2dpSourceCallback();
+  std::shared_ptr<bluetooth::A2dpSource> GetA2dpSource();
+
+  // InterfaceWithInstancesBase override:
+  void OnRegisterInstanceImpl(bluetooth::BLEStatus status,
+                              android::sp<IInterface> callback,
+                              bluetooth::BluetoothInstance* instance) override;
+
+  bluetooth::Adapter* const adapter_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothA2dpSourceBinderServer);
+};
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_avrcp_control_binder_server.cc b/service/ipc/binder/bluetooth_avrcp_control_binder_server.cc
new file mode 100644
index 0000000..d816859
--- /dev/null
+++ b/service/ipc/binder/bluetooth_avrcp_control_binder_server.cc
@@ -0,0 +1,236 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+#include "service/ipc/binder/bluetooth_avrcp_control_binder_server.h"
+
+#include <string>
+
+#include "base/logging.h"
+
+#include "service/adapter.h"
+
+using android::String16;
+using android::String8;
+using android::binder::Status;
+using android::bluetooth::IBluetoothAvrcpControlCallback;
+
+namespace ipc {
+namespace binder {
+
+namespace {
+const int kInvalidInstanceId = -1;
+}  // namespace
+
+BluetoothAvrcpControlBinderServer::BluetoothAvrcpControlBinderServer(
+    bluetooth::Adapter* adapter)
+    : adapter_(adapter) {
+  CHECK(adapter_);
+}
+
+Status BluetoothAvrcpControlBinderServer::Register(
+    const android::sp<IBluetoothAvrcpControlCallback>& callback,
+    bool* _aidl_return) {
+  VLOG(2) << __func__;
+
+  bluetooth::AvrcpControlFactory* gatt_client_factory =
+      adapter_->GetAvrcpControlFactory();
+
+  *_aidl_return = RegisterInstanceBase(callback, gatt_client_factory);
+  return Status::ok();
+}
+
+Status BluetoothAvrcpControlBinderServer::Unregister(int32_t id) {
+  VLOG(2) << __func__;
+  UnregisterInstanceBase(id);
+  return Status::ok();
+}
+
+Status BluetoothAvrcpControlBinderServer::UnregisterAll() {
+  VLOG(2) << __func__;
+  UnregisterAllBase();
+  return Status::ok();
+}
+
+Status BluetoothAvrcpControlBinderServer::Enable(int32_t id,
+                                                 bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto avrcp_control = GetAvrcpControl(id);
+  if (!avrcp_control) {
+    LOG(ERROR) << "Failed to get avrcp control instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!avrcp_control->Enable()) {
+    LOG(ERROR) << "Failed to enable";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothAvrcpControlBinderServer::Disable(int32_t id,
+                                                  bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto avrcp_control = GetAvrcpControl(id);
+  if (!avrcp_control) {
+    LOG(ERROR) << "Failed to get avrcp control instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  avrcp_control->Disable();
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+Status BluetoothAvrcpControlBinderServer::SendPassThroughCommand(
+    int32_t id, const String16& device_address, int32_t key_code,
+    bool key_pressed, bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto avrcp_control = GetAvrcpControl(id);
+  if (!avrcp_control) {
+    LOG(ERROR) << "Failed to get avrcp control instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!avrcp_control->SendPassThroughCommand(String8(device_address).string(),
+                                             key_code, key_pressed)) {
+    LOG(ERROR) << "Failed to send pass through command";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+android::binder::Status BluetoothAvrcpControlBinderServer::SetAbsVolumeResponse(
+    int32_t id, const android::String16& device_address, int32_t abs_vol,
+    int32_t label, bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto avrcp_control = GetAvrcpControl(id);
+  if (!avrcp_control) {
+    LOG(ERROR) << "Failed to get avrcp control instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!avrcp_control->SetAbsVolumeResponse(String8(device_address).string(),
+                                           abs_vol, label)) {
+    LOG(ERROR) << "Failed to send set absolute volume response";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+android::binder::Status
+BluetoothAvrcpControlBinderServer::RegisterForAbsVolumeCallbackResponse(
+    int32_t id, const android::String16& device_address, int32_t response_type,
+    int32_t abs_vol, int32_t label, bool* _aidl_return) {
+  std::lock_guard<std::mutex> lock(*maps_lock());
+  auto avrcp_control = GetAvrcpControl(id);
+  if (!avrcp_control) {
+    LOG(ERROR) << "Failed to get avrcp control instance";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+
+  if (!avrcp_control->RegisterForAbsVolumeCallbackResponse(
+          String8(device_address).string(), response_type, abs_vol, label)) {
+    LOG(ERROR)
+        << "Failed to send register for absolute volume callback response";
+    *_aidl_return = false;
+    return Status::ok();
+  }
+  *_aidl_return = true;
+  return Status::ok();
+}
+
+void BluetoothAvrcpControlBinderServer::OnConnectionState(
+    bool rc_connect, bool bt_connect, const std::string& device_address) {
+  auto func = [rc_connect, bt_connect, &device_address](IInterface* cb) {
+    auto avrcp_control_cb = static_cast<IBluetoothAvrcpControlCallback*>(cb);
+    avrcp_control_cb->OnConnectionState(rc_connect, bt_connect,
+                                        String16(device_address.c_str()));
+  };
+
+  ForEachCallback(func);
+}
+
+void BluetoothAvrcpControlBinderServer::OnTrackChanged(
+    const std::string& device_address, const bluetooth::AvrcpMediaAttr& attr) {
+  auto binder_attr = android::bluetooth::BluetoothAvrcpMediaAttr(attr);
+
+  auto func = [&device_address, &binder_attr](IInterface* cb) {
+    auto avrcp_control_cb = static_cast<IBluetoothAvrcpControlCallback*>(cb);
+    avrcp_control_cb->OnTrackChanged(String16(device_address.c_str()),
+                                     binder_attr);
+  };
+
+  ForEachCallback(func);
+}
+
+void BluetoothAvrcpControlBinderServer::OnSetAbsVolumeRequest(
+    const std::string& device_address, int32_t abs_vol, int32_t label) {
+  auto addr_s16 = String16(device_address.c_str(), device_address.size());
+  auto func = [&addr_s16, abs_vol, label](IInterface* cb) {
+    auto avrcp_control_cb = static_cast<IBluetoothAvrcpControlCallback*>(cb);
+    avrcp_control_cb->OnSetAbsVolumeRequest(addr_s16, abs_vol, label);
+  };
+
+  ForEachCallback(func);
+}
+
+void BluetoothAvrcpControlBinderServer::OnRegisterForAbsVolumeCallbackRequest(
+    const std::string& device_address, int32_t label) {
+  auto addr_s16 = String16(device_address.c_str(), device_address.size());
+  auto func = [&addr_s16, label](IInterface* cb) {
+    auto avrcp_control_cb = static_cast<IBluetoothAvrcpControlCallback*>(cb);
+    avrcp_control_cb->OnRegisterForAbsVolumeCallbackRequest(addr_s16, label);
+  };
+
+  ForEachCallback(func);
+}
+
+std::shared_ptr<bluetooth::AvrcpControl>
+BluetoothAvrcpControlBinderServer::GetAvrcpControl(int id) {
+  return std::static_pointer_cast<bluetooth::AvrcpControl>(GetInstance(id));
+}
+
+void BluetoothAvrcpControlBinderServer::OnRegisterInstanceImpl(
+    bluetooth::BLEStatus status, android::sp<IInterface> callback,
+    bluetooth::BluetoothInstance* instance) {
+  VLOG(1) << __func__ << " client ID: " << instance->GetInstanceId()
+          << " status: " << status;
+
+  bluetooth::AvrcpControl* avrcp_control =
+      static_cast<bluetooth::AvrcpControl*>(instance);
+  avrcp_control->SetDelegate(this);
+
+  android::sp<IBluetoothAvrcpControlCallback> cb(
+      static_cast<IBluetoothAvrcpControlCallback*>(callback.get()));
+  cb->OnRegistered(status, (status == bluetooth::BLE_STATUS_SUCCESS)
+                               ? instance->GetInstanceId()
+                               : kInvalidInstanceId);
+}
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_avrcp_control_binder_server.h b/service/ipc/binder/bluetooth_avrcp_control_binder_server.h
new file mode 100644
index 0000000..11cf1f3
--- /dev/null
+++ b/service/ipc/binder/bluetooth_avrcp_control_binder_server.h
@@ -0,0 +1,89 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <map>
+#include <string>
+
+#include "base/macros.h"
+
+#include "android/bluetooth/BnBluetoothAvrcpControl.h"
+#include "android/bluetooth/IBluetoothAvrcpControlCallback.h"
+
+#include "service/avrcp_control.h"
+#include "service/ipc/binder/interface_with_instances_base.h"
+
+namespace bluetooth {
+class Adapter;
+}  // namespace bluetooth
+
+namespace ipc {
+namespace binder {
+
+class BluetoothAvrcpControlBinderServer
+    : public InterfaceWithInstancesBase,
+      public android::bluetooth::BnBluetoothAvrcpControl,
+      public bluetooth::AvrcpControl::Delegate {
+ public:
+  explicit BluetoothAvrcpControlBinderServer(bluetooth::Adapter* adapter);
+  ~BluetoothAvrcpControlBinderServer() override = default;
+
+  // IBluetoothAvrcpControl implementation:
+  android::binder::Status Register(
+      const android::sp<::android::bluetooth::IBluetoothAvrcpControlCallback>&
+          callback,
+      bool* _aidl_return) override;
+  android::binder::Status Unregister(int32_t id) override;
+  android::binder::Status UnregisterAll() override;
+  android::binder::Status Enable(int32_t id, bool* _aidl_return) override;
+  android::binder::Status Disable(int32_t id, bool* _aidl_return) override;
+  android::binder::Status SendPassThroughCommand(
+      int32_t id, const android::String16& device_address, int32_t key_code,
+      bool key_pressed, bool* _aidl_return) override;
+  android::binder::Status SetAbsVolumeResponse(
+      int32_t id, const android::String16& device_address, int32_t abs_vol,
+      int32_t label, bool* _aidl_return) override;
+  android::binder::Status RegisterForAbsVolumeCallbackResponse(
+      int32_t id, const android::String16& device_address,
+      int32_t response_type, int32_t abs_vol, int32_t label,
+      bool* _aidl_return) override;
+
+ private:
+  // bluetooth::bluetooth::AvrcpControl::Delegate implementation:
+  void OnConnectionState(bool rc_connect, bool bt_connect,
+                         const std::string& device_address) override;
+  void OnTrackChanged(const std::string& device_address,
+                      const bluetooth::AvrcpMediaAttr& attr) override;
+  void OnSetAbsVolumeRequest(const std::string& device_address, int32_t abs_vol,
+                             int32_t label) override;
+  void OnRegisterForAbsVolumeCallbackRequest(const std::string& device_address,
+                                             int32_t label) override;
+
+  // InterfaceWithInstancesBase override:
+  void OnRegisterInstanceImpl(bluetooth::BLEStatus status,
+                              android::sp<IInterface> callback,
+                              bluetooth::BluetoothInstance* instance) override;
+
+  std::shared_ptr<bluetooth::AvrcpControl> GetAvrcpControl(int id);
+
+  bluetooth::Adapter* adapter_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpControlBinderServer);
+};
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_avrcp_target_binder_server.cc b/service/ipc/binder/bluetooth_avrcp_target_binder_server.cc
new file mode 100644
index 0000000..1652b10
--- /dev/null
+++ b/service/ipc/binder/bluetooth_avrcp_target_binder_server.cc
@@ -0,0 +1,339 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+#include "service/ipc/binder/bluetooth_avrcp_target_binder_server.h"
+
+#include <string>
+
+#include "base/logging.h"
+
+#include "service/adapter.h"
+
+#define AIDL_RET(value)      \
+  do {                       \
+    *_aidl_return = (value); \
+    return Status::ok();     \
+  } while (0)
+
+#define TRY_GET_TARGET()                                    \
+  ({                                                        \
+    auto target = GetAvrcpTarget();                         \
+    if (!target) {                                          \
+      LOG(ERROR) << __func__ << ": "                        \
+                 << "Failed to get AVRCP target interface"; \
+      AIDL_RET(false);                                      \
+    }                                                       \
+    target;                                                 \
+  })
+
+#define TRY_GET_CB()                                           \
+  ({                                                           \
+    auto cb = GetAvrcpTargetCallback();                        \
+    if (!cb.get()) {                                           \
+      LOG(WARNING) << "Callback for AVRCP target was deleted"; \
+      return;                                                  \
+    }                                                          \
+    cb;                                                        \
+  })
+
+#define TRY_RET(expr, msg) \
+  do {                     \
+    if (!(expr)) {         \
+      LOG(ERROR) << msg;   \
+      AIDL_RET(false);     \
+    }                      \
+    AIDL_RET(true);        \
+  } while (0)
+
+#define TRY_RET_FUNC(expr) TRY_RET(expr, __func__ << " failed")
+
+using android::String16;
+using android::String8;
+using android::binder::Status;
+using android::bluetooth::BluetoothAvrcpIntValue;
+using android::bluetooth::IBluetoothAvrcpTargetCallback;
+
+using LockGuard = std::lock_guard<std::mutex>;
+
+namespace ipc {
+namespace binder {
+
+BluetoothAvrcpTargetBinderServer::BluetoothAvrcpTargetBinderServer(
+    bluetooth::Adapter* adapter)
+    : adapter_(adapter) {
+  CHECK(adapter_);
+}
+
+BluetoothAvrcpTargetBinderServer::~BluetoothAvrcpTargetBinderServer() = default;
+
+bool BluetoothAvrcpTargetBinderServer::HasInstance() {
+  return GetAvrcpTarget() != nullptr;
+}
+
+Status BluetoothAvrcpTargetBinderServer::Register(
+    const android::sp<IBluetoothAvrcpTargetCallback>& callback,
+    bool* _aidl_return) {
+  VLOG(2) << __func__;
+
+  bluetooth::AvrcpTargetFactory* gatt_client_factory =
+      adapter_->GetAvrcpTargetFactory();
+
+  *_aidl_return = RegisterInstanceBase(callback, gatt_client_factory);
+  return Status::ok();
+}
+
+Status BluetoothAvrcpTargetBinderServer::Unregister(int32_t id) {
+  VLOG(2) << __func__;
+  UnregisterInstanceBase(id);
+  return Status::ok();
+}
+
+Status BluetoothAvrcpTargetBinderServer::UnregisterAll() {
+  VLOG(2) << __func__;
+  UnregisterAllBase();
+  return Status::ok();
+}
+
+Status BluetoothAvrcpTargetBinderServer::Enable(bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  TRY_RET_FUNC(avrcp_target->Enable());
+}
+
+Status BluetoothAvrcpTargetBinderServer::Disable(bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  avrcp_target->Disable();
+  AIDL_RET(true);
+}
+
+Status BluetoothAvrcpTargetBinderServer::GetPlayStatusResponse(
+    const android::String16& addr, int32_t play_status, int32_t song_len,
+    int32_t song_pos, bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  TRY_RET_FUNC(avrcp_target->GetPlayStatusResponse(
+      String8(addr).string(), play_status, song_len, song_pos));
+}
+
+Status BluetoothAvrcpTargetBinderServer::ListPlayerAppAttrResponse(
+    const android::String16& addr, const std::vector<int32_t>& attrs,
+    bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  TRY_RET_FUNC(
+      avrcp_target->ListPlayerAppAttrResponse(String8(addr).string(), attrs));
+}
+
+Status BluetoothAvrcpTargetBinderServer::GetPlayerAppValueResponse(
+    const android::String16& addr,
+    const std::vector<::android::bluetooth::BluetoothAvrcpIntValue>& values,
+    bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  std::vector<bluetooth::AvrcpIntValue> non_binder;
+  non_binder.reserve(values.size());
+  for (const auto& val : values) {
+    non_binder.push_back(val);
+  }
+  TRY_RET_FUNC(avrcp_target->GetPlayerAppValueResponse(String8(addr).string(),
+                                                       non_binder));
+}
+
+Status BluetoothAvrcpTargetBinderServer::GetPlayerAppAttrTextResponse(
+    const android::String16& addr,
+    const std::vector<::android::bluetooth::BluetoothAvrcpStringValue>& attrs,
+    bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  std::vector<bluetooth::AvrcpStringValue> non_binder;
+  non_binder.reserve(attrs.size());
+  for (const auto& val : attrs) {
+    non_binder.push_back(val);
+  }
+  TRY_RET_FUNC(avrcp_target->GetPlayerAppAttrTextResponse(
+      String8(addr).string(), non_binder));
+}
+
+Status BluetoothAvrcpTargetBinderServer::GetPlayerAppValueTextResponse(
+    const android::String16& addr,
+    const std::vector<::android::bluetooth::BluetoothAvrcpStringValue>& values,
+    bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  std::vector<bluetooth::AvrcpStringValue> non_binder;
+  non_binder.reserve(values.size());
+  for (const auto& val : values) {
+    non_binder.push_back(val);
+  }
+  TRY_RET_FUNC(avrcp_target->GetPlayerAppValueTextResponse(
+      String8(addr).string(), non_binder));
+}
+
+Status BluetoothAvrcpTargetBinderServer::GetElementAttrResponse(
+    const android::String16& addr,
+    const std::vector<::android::bluetooth::BluetoothAvrcpStringValue>& attrs,
+    bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  std::vector<bluetooth::AvrcpStringValue> non_binder;
+  non_binder.reserve(attrs.size());
+  for (const auto& val : attrs) {
+    non_binder.push_back(val);
+  }
+  TRY_RET_FUNC(
+      avrcp_target->GetElementAttrResponse(String8(addr).string(), non_binder));
+}
+
+Status BluetoothAvrcpTargetBinderServer::SetPlayerAppValueResponse(
+    const android::String16& addr, int32_t rsp_status, bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  TRY_RET_FUNC(avrcp_target->SetPlayerAppValueResponse(String8(addr).string(),
+                                                       rsp_status));
+}
+
+Status BluetoothAvrcpTargetBinderServer::RegisterNotificationResponse(
+    int32_t event_id, int32_t type,
+    const ::android::bluetooth::BluetoothAvrcpRegisterNotificationResponse&
+        param,
+    bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  TRY_RET_FUNC(
+      avrcp_target->RegisterNotificationResponse(event_id, type, param));
+}
+
+Status BluetoothAvrcpTargetBinderServer::SetVolume(int32_t volume,
+                                                   bool* _aidl_return) {
+  auto avrcp_target = TRY_GET_TARGET();
+  TRY_RET_FUNC(avrcp_target->SetVolume(volume));
+}
+
+void BluetoothAvrcpTargetBinderServer::OnGetRemoteFeatures(
+    const std::string& addr, int32_t features) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnGetRemoteFeatures(String16(addr.data(), addr.size()), features);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnGetPlayStatus(
+    const std::string& addr) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnGetPlayStatus(String16(addr.data(), addr.size()));
+}
+
+void BluetoothAvrcpTargetBinderServer::OnListPlayerAppAttr(
+    const std::string& addr) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnListPlayerAppAttr(String16(addr.data(), addr.size()));
+}
+
+void BluetoothAvrcpTargetBinderServer::OnListPlayerAppValues(
+    const std::string& addr, int32_t attr_id) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnListPlayerAppValues(String16(addr.data(), addr.size()), attr_id);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnGetPlayerAppValue(
+    const std::string& addr, const std::vector<int32_t>& attrs) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnGetPlayerAppValue(String16(addr.data(), addr.size()), attrs);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnGetPlayerAppAttrsText(
+    const std::string& addr, const std::vector<int32_t>& attrs) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnGetPlayerAppAttrsText(String16(addr.data(), addr.size()), attrs);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnGetPlayerAppValuesText(
+    const std::string& addr, int32_t attr_id,
+    const std::vector<int32_t>& values) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnGetPlayerAppValuesText(String16(addr.data(), addr.size()), attr_id,
+                               values);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnSetPlayerAppValue(
+    const std::string& addr,
+    const std::vector<bluetooth::AvrcpIntValue>& values) {
+  std::vector<BluetoothAvrcpIntValue> binder_values;
+  binder_values.reserve(values.size());
+  for (const auto& val : values) {
+    binder_values.push_back(val);
+  }
+
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnSetPlayerAppValue(String16(addr.data(), addr.size()), binder_values);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnGetElementAttrs(
+    const std::string& addr, const std::vector<int32_t>& attrs) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnGetElementAttrs(String16(addr.data(), addr.size()), attrs);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnRegisterNotification(
+    const std::string& addr, int32_t event_id, uint32_t param) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnRegisterNotification(String16(addr.data(), addr.size()), event_id,
+                             param);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnVolumeChange(const std::string& addr,
+                                                      int32_t volume,
+                                                      int32_t ctype) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnVolumeChange(String16(addr.data(), addr.size()), volume, ctype);
+}
+
+void BluetoothAvrcpTargetBinderServer::OnPassThroughCommand(
+    const std::string& addr, int32_t id, int32_t key_state) {
+  LockGuard lock(*maps_lock());
+  auto cb = TRY_GET_CB();
+  cb->OnPassThroughCommand(String16(addr.data(), addr.size()), id, key_state);
+}
+
+android::sp<IBluetoothAvrcpTargetCallback>
+BluetoothAvrcpTargetBinderServer::GetAvrcpTargetCallback() {
+  auto cb = GetCallback(bluetooth::AvrcpTarget::kSingletonInstanceId);
+  return android::sp<IBluetoothAvrcpTargetCallback>(
+      static_cast<IBluetoothAvrcpTargetCallback*>(cb.get()));
+}
+
+std::shared_ptr<bluetooth::AvrcpTarget>
+BluetoothAvrcpTargetBinderServer::GetAvrcpTarget() {
+  return std::static_pointer_cast<bluetooth::AvrcpTarget>(
+      GetInstance(bluetooth::AvrcpTarget::kSingletonInstanceId));
+}
+
+void BluetoothAvrcpTargetBinderServer::OnRegisterInstanceImpl(
+    bluetooth::BLEStatus status, android::sp<IInterface> callback,
+    bluetooth::BluetoothInstance* instance) {
+  VLOG(1) << __func__ << " client ID: " << instance->GetInstanceId()
+          << " status: " << status;
+
+  bluetooth::AvrcpTarget* avrcp_target =
+      static_cast<bluetooth::AvrcpTarget*>(instance);
+  avrcp_target->SetDelegate(this);
+
+  android::sp<IBluetoothAvrcpTargetCallback> cb(
+      static_cast<IBluetoothAvrcpTargetCallback*>(callback.get()));
+  cb->OnRegistered(status);
+}
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_avrcp_target_binder_server.h b/service/ipc/binder/bluetooth_avrcp_target_binder_server.h
new file mode 100644
index 0000000..9d2bba0
--- /dev/null
+++ b/service/ipc/binder/bluetooth_avrcp_target_binder_server.h
@@ -0,0 +1,131 @@
+//
+//  Copyright (C) 2017 Google, Inc.
+//
+//  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.
+//
+
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+
+#include "android/bluetooth/BnBluetoothAvrcpTarget.h"
+#include "android/bluetooth/IBluetoothAvrcpTargetCallback.h"
+
+#include "service/avrcp_target.h"
+#include "service/ipc/binder/interface_with_instances_base.h"
+
+namespace bluetooth {
+class Adapter;
+}  // namespace bluetooth
+
+namespace ipc {
+namespace binder {
+
+class BluetoothAvrcpTargetBinderServer
+    : public InterfaceWithInstancesBase,
+      public android::bluetooth::BnBluetoothAvrcpTarget,
+      public bluetooth::AvrcpTarget::Delegate {
+ public:
+  explicit BluetoothAvrcpTargetBinderServer(bluetooth::Adapter* adapter);
+  ~BluetoothAvrcpTargetBinderServer() override;
+
+  bool HasInstance();
+
+  // IBluetoothAvrcpTarget implementation:
+  android::binder::Status Register(
+      const android::sp<android::bluetooth::IBluetoothAvrcpTargetCallback>&
+          callback,
+      bool* _aidl_return) override;
+  android::binder::Status Unregister(int32_t id) override;
+  android::binder::Status UnregisterAll() override;
+  android::binder::Status Enable(bool* _aidl_return) override;
+  android::binder::Status Disable(bool* _aidl_return) override;
+  android::binder::Status GetPlayStatusResponse(const android::String16& addr,
+                                                int32_t play_status,
+                                                int32_t song_len,
+                                                int32_t song_pos,
+                                                bool* _aidl_return) override;
+  android::binder::Status ListPlayerAppAttrResponse(
+      const android::String16& addr, const std::vector<int32_t>& attrs,
+      bool* _aidl_return) override;
+  android::binder::Status GetPlayerAppValueResponse(
+      const android::String16& addr,
+      const std::vector<android::bluetooth::BluetoothAvrcpIntValue>& values,
+      bool* _aidl_return) override;
+  android::binder::Status GetPlayerAppAttrTextResponse(
+      const android::String16& addr,
+      const std::vector<android::bluetooth::BluetoothAvrcpStringValue>& attrs,
+      bool* _aidl_return) override;
+  android::binder::Status GetPlayerAppValueTextResponse(
+      const android::String16& addr,
+      const std::vector<android::bluetooth::BluetoothAvrcpStringValue>& values,
+      bool* _aidl_return) override;
+  android::binder::Status GetElementAttrResponse(
+      const android::String16& addr,
+      const std::vector<android::bluetooth::BluetoothAvrcpStringValue>& attrs,
+      bool* _aidl_return) override;
+  android::binder::Status SetPlayerAppValueResponse(
+      const android::String16& addr, int32_t rsp_status,
+      bool* _aidl_return) override;
+  android::binder::Status RegisterNotificationResponse(
+      int32_t event_id, int32_t type,
+      const android::bluetooth::BluetoothAvrcpRegisterNotificationResponse&
+          param,
+      bool* _aidl_return) override;
+  android::binder::Status SetVolume(int32_t volume,
+                                    bool* _aidl_return) override;
+
+ private:
+  // bluetooth::bluetooth::AvrcpTarget::Delegate implementation:
+  void OnGetRemoteFeatures(const std::string& addr, int32_t features) override;
+  void OnGetPlayStatus(const std::string& addr) override;
+  void OnListPlayerAppAttr(const std::string& addr) override;
+  void OnListPlayerAppValues(const std::string& addr, int32_t attr_id) override;
+  void OnGetPlayerAppValue(const std::string& addr,
+                           const std::vector<int32_t>& attrs) override;
+  void OnGetPlayerAppAttrsText(const std::string& addr,
+                               const std::vector<int32_t>& attrs) override;
+  void OnGetPlayerAppValuesText(const std::string& addr, int32_t attr_id,
+                                const std::vector<int32_t>& values) override;
+  void OnSetPlayerAppValue(
+      const std::string& addr,
+      const std::vector<bluetooth::AvrcpIntValue>& values) override;
+  void OnGetElementAttrs(const std::string& addr,
+                         const std::vector<int32_t>& attrs) override;
+  void OnRegisterNotification(const std::string& addr, int32_t event_id,
+                              uint32_t param) override;
+  void OnVolumeChange(const std::string& addr, int32_t volume,
+                      int32_t ctype) override;
+  void OnPassThroughCommand(const std::string& addr, int32_t id,
+                            int32_t key_state) override;
+
+  // InterfaceWithInstancesBase override:
+  void OnRegisterInstanceImpl(bluetooth::BLEStatus status,
+                              android::sp<IInterface> callback,
+                              bluetooth::BluetoothInstance* instance) override;
+
+  android::sp<android::bluetooth::IBluetoothAvrcpTargetCallback>
+  GetAvrcpTargetCallback();
+  std::shared_ptr<bluetooth::AvrcpTarget> GetAvrcpTarget();
+
+  bluetooth::Adapter* const adapter_;  // weak
+
+  DISALLOW_COPY_AND_ASSIGN(BluetoothAvrcpTargetBinderServer);
+};
+
+}  // namespace binder
+}  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_binder_server.cc b/service/ipc/binder/bluetooth_binder_server.cc
index 2d32cee..097abb7 100644
--- a/service/ipc/binder/bluetooth_binder_server.cc
+++ b/service/ipc/binder/bluetooth_binder_server.cc
@@ -18,6 +18,10 @@
 
 #include <base/logging.h>
 
+#include "service/ipc/binder/bluetooth_a2dp_sink_binder_server.h"
+#include "service/ipc/binder/bluetooth_a2dp_source_binder_server.h"
+#include "service/ipc/binder/bluetooth_avrcp_control_binder_server.h"
+#include "service/ipc/binder/bluetooth_avrcp_target_binder_server.h"
 #include "service/ipc/binder/bluetooth_gatt_client_binder_server.h"
 #include "service/ipc/binder/bluetooth_gatt_server_binder_server.h"
 #include "service/ipc/binder/bluetooth_le_advertiser_binder_server.h"
@@ -60,10 +64,9 @@
   return Status::ok();
 }
 
-Status BluetoothBinderServer::Enable(bool start_restricted,
-                                     bool* _aidl_return) {
+Status BluetoothBinderServer::Enable(bool* _aidl_return) {
   VLOG(2) << __func__;
-  *_aidl_return = adapter_->Enable(start_restricted);
+  *_aidl_return = adapter_->Enable();
   return Status::ok();
 }
 
@@ -107,6 +110,59 @@
   return Status::ok();
 }
 
+Status BluetoothBinderServer::SetScanMode(int32_t scan_mode,
+                                          bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return = adapter_->SetScanMode(scan_mode);
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::SetScanEnable(bool scan_enable,
+                                            bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return = adapter_->SetScanEnable(scan_enable);
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::SspReply(
+    const ::android::String16& device_address, int32_t variant, bool accept,
+    int32_t passkey, bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return = adapter_->SspReply(String8(device_address).string(), variant,
+                                     accept, passkey);
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::CreateBond(
+    const ::android::String16& device_address, int32_t transport,
+    bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return =
+      adapter_->CreateBond(String8(device_address).string(), transport);
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::GetBondedDevices(bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return = adapter_->GetBondedDevices();
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::RemoveBond(
+    const ::android::String16& device_address, bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return = adapter_->RemoveBond(String8(device_address).string());
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::GetRemoteDeviceProperties(
+    const ::android::String16& device_address, bool* _aidl_return) {
+  VLOG(2) << __func__;
+  *_aidl_return =
+      adapter_->GetRemoteDeviceProperties(String8(device_address).string());
+  return Status::ok();
+}
+
 Status BluetoothBinderServer::RegisterCallback(
     const ::android::sp<IBluetoothCallback>& callback) {
   VLOG(2) << __func__;
@@ -136,6 +192,52 @@
   return Status::ok();
 }
 
+Status BluetoothBinderServer::GetA2dpSinkInterface(
+    ::android::sp<IBluetoothA2dpSink>* _aidl_return) {
+  VLOG(2) << __func__;
+
+  if (!adapter_->IsEnabled()) {
+    LOG(ERROR) << "Cannot obtain IBluetoothA2dpSink interface while disabled";
+    *_aidl_return = nullptr;
+    return Status::ok();
+  }
+
+  if (!a2dp_sink_interface_.get())
+    a2dp_sink_interface_ = new BluetoothA2dpSinkBinderServer(adapter_);
+
+  if (a2dp_sink_interface_->HasInstance()) {
+    LOG(ERROR) << "Only one A2dpSink interface allowed at a time";
+    *_aidl_return = nullptr;
+    return Status::ok();
+  }
+
+  *_aidl_return = a2dp_sink_interface_;
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::GetA2dpSourceInterface(
+    ::android::sp<IBluetoothA2dpSource>* _aidl_return) {
+  VLOG(2) << __func__;
+
+  if (!adapter_->IsEnabled()) {
+    LOG(ERROR) << "Cannot obtain IBluetoothA2dpSource interface while disabled";
+    *_aidl_return = nullptr;
+    return Status::ok();
+  }
+
+  if (!a2dp_source_interface_.get())
+    a2dp_source_interface_ = new BluetoothA2dpSourceBinderServer(adapter_);
+
+  if (a2dp_source_interface_->HasInstance()) {
+    LOG(ERROR) << "Only one A2dpSource interface allowed at a time";
+    *_aidl_return = nullptr;
+    return Status::ok();
+  }
+
+  *_aidl_return = a2dp_source_interface_;
+  return Status::ok();
+}
+
 Status BluetoothBinderServer::GetLowEnergyInterface(
     ::android::sp<IBluetoothLowEnergy>* _aidl_return) {
   VLOG(2) << __func__;
@@ -222,6 +324,48 @@
   return Status::ok();
 }
 
+Status BluetoothBinderServer::GetAvrcpControlInterface(
+    ::android::sp<IBluetoothAvrcpControl>* _aidl_return) {
+  VLOG(2) << __func__;
+
+  if (!adapter_->IsEnabled()) {
+    LOG(ERROR)
+        << "Cannot obtain IBluetoothAvrcpControl interface while disabled";
+    *_aidl_return = NULL;
+    return Status::ok();
+  }
+
+  if (!avrcp_control_interface_.get())
+    avrcp_control_interface_ = new BluetoothAvrcpControlBinderServer(adapter_);
+
+  *_aidl_return = avrcp_control_interface_;
+  return Status::ok();
+}
+
+Status BluetoothBinderServer::GetAvrcpTargetInterface(
+    ::android::sp<IBluetoothAvrcpTarget>* _aidl_return) {
+  VLOG(2) << __func__;
+
+  if (!adapter_->IsEnabled()) {
+    LOG(ERROR)
+        << "Cannot obtain IBluetoothAvrcpTarget interface while disabled";
+    *_aidl_return = NULL;
+    return Status::ok();
+  }
+
+  if (!avrcp_target_interface_.get())
+    avrcp_target_interface_ = new BluetoothAvrcpTargetBinderServer(adapter_);
+
+  if (avrcp_target_interface_->HasInstance()) {
+    LOG(ERROR) << "Only one AVRCP target interface allowed at a time";
+    *_aidl_return = nullptr;
+    return Status::ok();
+  }
+
+  *_aidl_return = avrcp_target_interface_;
+  return Status::ok();
+}
+
 android::status_t BluetoothBinderServer::dump(
     int fd, const android::Vector<android::String16>& args) {
   VLOG(2) << __func__ << " called with fd " << fd;
@@ -249,5 +393,97 @@
   });
 }
 
+void BluetoothBinderServer::OnDeviceConnectionStateChanged(
+    bluetooth::Adapter* adapter, const std::string& device_address,
+    bool connected) {
+  CHECK_EQ(adapter, adapter_);
+  auto addr_s16 = String16(device_address.c_str(), device_address.size());
+  callbacks_.ForEach([&addr_s16, connected](IBluetoothCallback* callback) {
+    callback->OnDeviceConnectionStateChanged(addr_s16, connected);
+  });
+}
+
+void BluetoothBinderServer::OnScanEnableChanged(bluetooth::Adapter* adapter,
+                                                bool scan_enabled) {
+  CHECK_EQ(adapter, adapter_);
+  callbacks_.ForEach([scan_enabled](IBluetoothCallback* callback) {
+    callback->OnScanEnableChanged(scan_enabled);
+  });
+}
+
+void BluetoothBinderServer::OnSspRequest(bluetooth::Adapter* adapter,
+                                         const std::string& device_address,
+                                         const std::string& device_name,
+                                         int cod, int pairing_variant,
+                                         int pass_key) {
+  CHECK_EQ(adapter, adapter_);
+  VLOG(2) << "Received ssp request: device_address: " << device_address
+          << ", device_name: " << device_name << ", cod: " << cod
+          << ", pairing_variant: " << pairing_variant
+          << ", pass_key: " << pass_key;
+
+  android::String16 addr_s16(device_address.c_str());
+  android::String16 name_s16(device_name.c_str());
+  callbacks_.ForEach([&addr_s16, &name_s16, cod, pairing_variant,
+                      pass_key](IBluetoothCallback* callback) {
+    callback->OnSspRequest(addr_s16, name_s16, cod, pairing_variant, pass_key);
+  });
+}
+
+void BluetoothBinderServer::OnBondStateChanged(
+    bluetooth::Adapter* adapter, int status, const std::string& device_address,
+    int state) {
+  CHECK_EQ(adapter, adapter_);
+  VLOG(2) << "Received " << __func__ << " "
+          << "status: " << status << ", device_address: " << device_address
+          << ", state: " << state;
+  android::String16 addr_s16(device_address.c_str(), device_address.size());
+  callbacks_.ForEach([status, &addr_s16, state](IBluetoothCallback* callback) {
+    callback->OnBondStateChanged(status, addr_s16, state);
+  });
+}
+
+void BluetoothBinderServer::OnGetBondedDevices(
+    bluetooth::Adapter* adapter, int status,
+    const std::vector<std::string>& bonded_devices) {
+  CHECK_EQ(adapter, adapter_);
+  VLOG(2) << "Received " << __func__;
+  std::vector<android::String16> devices_s16;
+  devices_s16.reserve(bonded_devices.size());
+  for (const auto& device : bonded_devices)
+    devices_s16.emplace_back(device.c_str(), device.size());
+
+  callbacks_.ForEach([status, &devices_s16](IBluetoothCallback* callback) {
+    callback->OnGetBondedDevices(status, devices_s16);
+  });
+}
+
+void BluetoothBinderServer::OnGetRemoteDeviceProperties(
+    bluetooth::Adapter* adapter, int status, const std::string& device_address,
+    const bluetooth::RemoteDeviceProps& properties) {
+  CHECK_EQ(adapter, adapter_);
+  VLOG(2) << "Received " << __func__ << " "
+          << "status: " << status << ", device_address: " << device_address;
+  android::String16 addr_s16(device_address.c_str(), device_address.size());
+  auto binder_props =
+      android::bluetooth::BluetoothRemoteDeviceProps(properties);
+  callbacks_.ForEach(
+      [status, &addr_s16, &binder_props](IBluetoothCallback* callback) {
+        callback->OnGetRemoteDeviceProperties(status, addr_s16, binder_props);
+      });
+}
+
+void BluetoothBinderServer::OnDeviceFound(
+    bluetooth::Adapter* adapter,
+    const bluetooth::RemoteDeviceProps& properties) {
+  CHECK_EQ(adapter, adapter_);
+  VLOG(2) << "Received " << __func__ << " ";
+  auto binder_props =
+      android::bluetooth::BluetoothRemoteDeviceProps(properties);
+  callbacks_.ForEach([&binder_props](IBluetoothCallback* callback) {
+    callback->OnDeviceFound(binder_props);
+  });
+}
+
 }  // namespace binder
 }  // namespace ipc
diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h
index b03a815..7131e8b 100644
--- a/service/ipc/binder/bluetooth_binder_server.h
+++ b/service/ipc/binder/bluetooth_binder_server.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2015 Google, Inc.
+//  Copyright (C) 2015 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -24,14 +24,18 @@
 #include <utils/Vector.h>
 
 #include <android/bluetooth/BnBluetooth.h>
+#include <android/bluetooth/IBluetoothA2dpSink.h>
+#include <android/bluetooth/IBluetoothA2dpSource.h>
+#include <android/bluetooth/IBluetoothAvrcpControl.h>
+#include <android/bluetooth/IBluetoothAvrcpTarget.h>
 #include <android/bluetooth/IBluetoothCallback.h>
 #include <android/bluetooth/IBluetoothGattClient.h>
 #include <android/bluetooth/IBluetoothGattServer.h>
 #include <android/bluetooth/IBluetoothLeAdvertiser.h>
 #include <android/bluetooth/IBluetoothLeScanner.h>
 #include <android/bluetooth/IBluetoothLowEnergy.h>
-#include <bluetooth/uuid.h>
 
+#include "bluetooth/uuid.h"
 #include "service/adapter.h"
 #include "service/ipc/binder/remote_callback_list.h"
 
@@ -39,16 +43,24 @@
 using android::binder::Status;
 
 using android::bluetooth::BnBluetooth;
+using android::bluetooth::IBluetoothA2dpSink;
+using android::bluetooth::IBluetoothA2dpSource;
+using android::bluetooth::IBluetoothAvrcpControl;
+using android::bluetooth::IBluetoothAvrcpTarget;
 using android::bluetooth::IBluetoothCallback;
 using android::bluetooth::IBluetoothGattClient;
 using android::bluetooth::IBluetoothGattServer;
-using android::bluetooth::IBluetoothLowEnergy;
 using android::bluetooth::IBluetoothLeAdvertiser;
 using android::bluetooth::IBluetoothLeScanner;
+using android::bluetooth::IBluetoothLowEnergy;
 
 namespace ipc {
 namespace binder {
 
+class BluetoothA2dpSinkBinderServer;
+class BluetoothA2dpSourceBinderServer;
+class BluetoothAvrcpTargetBinderServer;
+
 // Implements the server side of the IBluetooth Binder interface.
 class BluetoothBinderServer : public BnBluetooth,
                               public bluetooth::Adapter::Observer {
@@ -59,7 +71,7 @@
   // IBluetooth overrides:
   Status IsEnabled(bool* _aidl_return) override;
   Status GetState(int32_t* _aidl_return) override;
-  Status Enable(bool start_restricted, bool* _aidl_return) override;
+  Status Enable(bool* _aidl_return) override;
   Status EnableNoAutoConnect(bool* _aidl_return) override;
   Status Disable(bool* _aidl_return) override;
 
@@ -68,12 +80,27 @@
       ::std::vector<::android::bluetooth::UUID>* _aidl_return) override;
   Status SetName(const ::android::String16& name, bool* _aidl_return) override;
   Status GetName(::android::String16* _aidl_return) override;
+  Status SetScanMode(int32_t scan_mode, bool* _aidl_return) override;
+  Status SetScanEnable(bool scan_enable, bool* _aidl_return) override;
+  Status SspReply(const ::android::String16& device_address, int32_t variant,
+                  bool accept, int32_t passkey, bool* _aidl_return) override;
+  Status CreateBond(const ::android::String16& device_address,
+                    int32_t transport, bool* _aidl_return) override;
+  Status GetBondedDevices(bool* _aidl_return) override;
+  Status RemoveBond(const ::android::String16& device_address,
+                    bool* _aidl_return) override;
+  Status GetRemoteDeviceProperties(const ::android::String16& device_address,
+                                   bool* _aidl_return) override;
 
   Status RegisterCallback(
       const ::android::sp<IBluetoothCallback>& callback) override;
   Status UnregisterCallback(
       const ::android::sp<IBluetoothCallback>& callback) override;
   Status IsMultiAdvertisementSupported(bool* _aidl_return) override;
+  Status GetA2dpSinkInterface(
+      ::android::sp<IBluetoothA2dpSink>* _aidl_return) override;
+  Status GetA2dpSourceInterface(
+      ::android::sp<IBluetoothA2dpSource>* _aidl_return) override;
   Status GetLowEnergyInterface(
       ::android::sp<IBluetoothLowEnergy>* _aidl_return) override;
   Status GetLeAdvertiserInterface(
@@ -84,6 +111,10 @@
       ::android::sp<IBluetoothGattClient>* _aidl_return) override;
   Status GetGattServerInterface(
       ::android::sp<IBluetoothGattServer>* _aidl_return) override;
+  Status GetAvrcpControlInterface(
+      ::android::sp<IBluetoothAvrcpControl>* _aidl_return) override;
+  Status GetAvrcpTargetInterface(
+      ::android::sp<IBluetoothAvrcpTarget>* _aidl_return) override;
 
   android::status_t dump(
       int fd, const android::Vector<android::String16>& args) override;
@@ -93,10 +124,43 @@
                              bluetooth::AdapterState prev_state,
                              bluetooth::AdapterState new_state) override;
 
+  void OnDeviceConnectionStateChanged(bluetooth::Adapter* adapter,
+                                      const std::string& device_address,
+                                      bool connected) override;
+
+  void OnScanEnableChanged(bluetooth::Adapter* adapter,
+                           bool scan_enabled) override;
+
+  void OnSspRequest(bluetooth::Adapter* adapter,
+                    const std::string& device_address,
+                    const std::string& device_name, int cod,
+                    int pairing_variant, int pass_key) override;
+
+  void OnBondStateChanged(bluetooth::Adapter* adapter, int status,
+                          const std::string& device_address,
+                          int state) override;
+  void OnGetBondedDevices(
+      bluetooth::Adapter* adapter, int status,
+      const std::vector<std::string>& bonded_devices) override;
+  void OnGetRemoteDeviceProperties(
+      bluetooth::Adapter* adapter, int status,
+      const std::string& device_address,
+      const bluetooth::RemoteDeviceProps& properties) override;
+  void OnDeviceFound(bluetooth::Adapter* adapter,
+                     const bluetooth::RemoteDeviceProps& properties) override;
+
  private:
   bluetooth::Adapter* adapter_;  // weak
   RemoteCallbackList<IBluetoothCallback> callbacks_;
 
+  // The IBluetoothA2dpSink interface handle. This is lazily initialized on the
+  // first call to GetA2dpSinkInterface().
+  android::sp<BluetoothA2dpSinkBinderServer> a2dp_sink_interface_;
+
+  // The IBluetoothA2dpSource interface handle. This is lazily initialized on
+  // the first call to GetA2dpSourceInterface().
+  android::sp<BluetoothA2dpSourceBinderServer> a2dp_source_interface_;
+
   // The IBluetoothLowEnergy interface handle. This is lazily initialized on the
   // first call to GetLowEnergyInterface().
   android::sp<IBluetoothLowEnergy> low_energy_interface_;
@@ -117,6 +181,14 @@
   // the first call to GetGattServerInterface().
   android::sp<IBluetoothGattServer> gatt_server_interface_;
 
+  // The IBluetoothAvrcpControl interface handle. This is lazily initialized on
+  // the first call to GetAvrcpControlInterface().
+  android::sp<IBluetoothAvrcpControl> avrcp_control_interface_;
+
+  // The IBluetoothAvrcpTarget interface handle. This is lazily initialized on
+  // the first call to GetAvrcpTargetInterface().
+  android::sp<BluetoothAvrcpTargetBinderServer> avrcp_target_interface_;
+
   DISALLOW_COPY_AND_ASSIGN(BluetoothBinderServer);
 };
 
diff --git a/service/ipc/binder/interface_with_instances_base.cc b/service/ipc/binder/interface_with_instances_base.cc
index ba24657..1716bbd 100644
--- a/service/ipc/binder/interface_with_instances_base.cc
+++ b/service/ipc/binder/interface_with_instances_base.cc
@@ -86,6 +86,16 @@
   id_to_instance_.clear();
 }
 
+void InterfaceWithInstancesBase::ForEachCallback(
+    const std::function<void(IInterface*)>& func) {
+  VLOG(2) << __func__;
+  std::lock_guard<std::mutex> lock(maps_lock_);
+  for (auto& pair : id_to_instance_) {
+    auto cb = id_to_cb_.Get(pair.first);
+    func(cb.get());
+  }
+}
+
 android::sp<IInterface> InterfaceWithInstancesBase::GetCallback(
     int instance_id) {
   return id_to_cb_.Get(instance_id);
diff --git a/service/ipc/binder/interface_with_instances_base.h b/service/ipc/binder/interface_with_instances_base.h
index 90224b6..05f2817 100644
--- a/service/ipc/binder/interface_with_instances_base.h
+++ b/service/ipc/binder/interface_with_instances_base.h
@@ -1,5 +1,5 @@
 //
-//  Copyright 2015 Google, Inc.
+//  Copyright (C) 2015 Google, Inc.
 //
 //  Licensed under the Apache License, Version 2.0 (the "License");
 //  you may not use this file except in compliance with the License.
@@ -20,8 +20,8 @@
 #include <unordered_map>
 
 #include <base/macros.h>
-#include <bluetooth/uuid.h>
 
+#include "bluetooth/uuid.h"
 #include "service/bluetooth_instance.h"
 #include "service/ipc/binder/remote_callback_map.h"
 
@@ -57,6 +57,8 @@
   // Unregisters all registered instances.
   void UnregisterAllBase();
 
+  void ForEachCallback(const std::function<void(IInterface*)>& func);
+
   // Returns a handle to the lock used to synchronize access to the internal
   // data structures. Subclasses should acquire this before accessing the maps.
   std::mutex* maps_lock() { return &maps_lock_; }
diff --git a/service/ipc/ipc_handler_linux.cc b/service/ipc/ipc_handler_linux.cc
index 7fe724e..ebfae12 100644
--- a/service/ipc/ipc_handler_linux.cc
+++ b/service/ipc/ipc_handler_linux.cc
@@ -89,7 +89,7 @@
             sizeof(address.sun_path) - 1);
     if (bind(server_socket.get(), (struct sockaddr*)&address, sizeof(address)) <
         0) {
-      LOG(ERROR) << "Failed to bind IPC socket to address: " << strerror(errno);
+      PLOG(ERROR) << "Failed to bind IPC socket to address";
       return false;
     }
 
@@ -141,7 +141,7 @@
 
   int status = listen(socket_.get(), SOMAXCONN);
   if (status < 0) {
-    LOG(ERROR) << "Failed to listen on domain socket: " << strerror(errno);
+    PLOG(ERROR) << "Failed to listen on domain socket";
     origin_task_runner_->PostTask(
         FROM_HERE, base::Bind(&IPCHandlerLinux::ShutDownOnOriginThread, this));
     return;
@@ -158,7 +158,7 @@
   while (keep_running_.load()) {
     int client_socket = accept4(socket_.get(), nullptr, nullptr, SOCK_NONBLOCK);
     if (client_socket < 0) {
-      LOG(ERROR) << "Failed to accept client connection: " << strerror(errno);
+      PLOG(ERROR) << "Failed to accept client connection";
       continue;
     }
 
diff --git a/service/ipc/ipc_handler_linux.h b/service/ipc/ipc_handler_linux.h
index 21c71d2..7cd6efa 100644
--- a/service/ipc/ipc_handler_linux.h
+++ b/service/ipc/ipc_handler_linux.h
@@ -17,7 +17,6 @@
 #pragma once
 
 #include <atomic>
-
 #include <base/files/file_path.h>
 #include <base/files/scoped_file.h>
 #include <base/macros.h>
diff --git a/service/low_energy_advertiser.cc b/service/low_energy_advertiser.cc
index 4f4bff9..7bc5f25 100644
--- a/service/low_energy_advertiser.cc
+++ b/service/low_energy_advertiser.cc
@@ -16,14 +16,16 @@
 
 #include "service/low_energy_advertiser.h"
 
-#include <base/bind.h>
-#include <base/logging.h>
-
 #include "service/adapter.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 #include "stack/include/hcidefs.h"
 
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <base/callback.h>
+#include <base/logging.h>
+
 using std::lock_guard;
 using std::mutex;
 
@@ -53,7 +55,7 @@
       ms = kAdvertisingIntervalLowMs;
       break;
     case AdvertiseSettings::MODE_LOW_POWER:
-    // Fall through
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     default:
       ms = kAdvertisingIntervalHighMs;
       break;
@@ -77,7 +79,7 @@
       power = -7;
       break;
     case AdvertiseSettings::TX_POWER_LEVEL_HIGH:
-    // Fall through
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     default:
       power = 1;
       break;
@@ -113,8 +115,6 @@
   out_params->scan_request_notification_enable = 0;
 }
 
-void DoNothing(uint8_t status) {}
-
 }  // namespace
 
 // LowEnergyAdvertiser implementation
@@ -133,8 +133,7 @@
 
   // Stop advertising and ignore the result.
   hal::BluetoothGattInterface::Get()->GetAdvertiserHALInterface()->Enable(
-      advertiser_id_, false, base::Bind(&DoNothing), 0, 0,
-      base::Bind(&DoNothing));
+      advertiser_id_, false, base::DoNothing(), 0, 0, base::DoNothing());
   hal::BluetoothGattInterface::Get()->GetAdvertiserHALInterface()->Unregister(
       advertiser_id_);
 }
diff --git a/service/low_energy_scanner.cc b/service/low_energy_scanner.cc
index 1527563..82f3ab4 100644
--- a/service/low_energy_scanner.cc
+++ b/service/low_energy_scanner.cc
@@ -16,14 +16,15 @@
 
 #include "service/low_energy_scanner.h"
 
-#include <base/bind.h>
-#include <base/logging.h>
-
 #include "service/adapter.h"
 #include "service/logging_helpers.h"
 #include "stack/include/bt_types.h"
 #include "stack/include/hcidefs.h"
 
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/logging.h>
+
 using std::lock_guard;
 using std::mutex;
 
diff --git a/service/test/a2dp_sink_unittest.cc b/service/test/a2dp_sink_unittest.cc
new file mode 100644
index 0000000..06fb88e
--- /dev/null
+++ b/service/test/a2dp_sink_unittest.cc
@@ -0,0 +1,271 @@
+//
+//  Copyright 2017 Google, Inc.
+//
+//  Licensed under the Apache License, Version 2.0 (the "License");
+//  you may not use this file except in compliance with the License.
+//  You may obtain a copy of the License at:
+//
+//  http://www.apache.org/licenses/LICENSE-2.0
+//
+//  Unless required by applicable law or agreed to in writing, software
+//  distributed under the License is distributed on an "AS IS" BASIS,
+//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+//  See the License for the specific language governing permissions and
+//  limitations under the License.
+//
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "service/a2dp_sink.h"
+#include "service/hal/fake_bluetooth_av_interface.h"
+
+using ::testing::_;
+using ::testing::Return;
+
+namespace bluetooth {
+namespace {
+
+class MockA2dpSinkHandler
+    : public hal::FakeBluetoothAvInterface::TestA2dpSinkHandler {
+ public:
+  MockA2dpSinkHandler() = default;
+  ~MockA2dpSinkHandler() override = default;
+
+  MOCK_METHOD1(Connect, bt_status_t(RawAddress));
+  MOCK_METHOD1(Disconnect, bt_status_t(RawAddress));
+  MOCK_METHOD1(SetAudioFocusState, void(int));
+  MOCK_METHOD1(SetAudioTrackGain, void(float));
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(MockA2dpSinkHandler);
+};
+
+class TestDelegate : public A2dpSink::Delegate {
+ public:
+  TestDelegate() = default;
+  ~TestDelegate() override = default;
+
+  struct RequestData {
+    std::string device_address;
+    int state = -1;
+    uint32_t sample_rate = 0;
+    uint8_t channel_count = 0;
+    int count = 0;
+  };
+
+  // A2dpSink::Delegate implementation:
+  void OnConnectionState(const std::string& device_address,
+                         int state) override {
+    ++connection_state_.count;
+    connection_state_.device_address = device_address;
+    connection_state_.state = state;
+  }
+  void OnAudioState(const std::string& device_address, int state) override {
+    ++audio_state_.count;
+    audio_state_.device_address = device_address;
+    audio_state_.state = state;
+  }
+  void OnAudioConfig(const std::string& device_address, uint32_t sample_rate,
+                     uint8_t channel_count) override {
+    ++audio_config_.count;
+    audio_config_.device_address = device_address;
+    audio_config_.sample_rate = sample_rate;
+    audio_config_.channel_count = channel_count;
+  }
+
+  const RequestData& connection_state() const { return connection_state_; }
+  const RequestData& audio_state() const { return audio_state_; }
+  const RequestData& audio_config() const { return audio_config_; }
+
+ private:
+  RequestData connection_state_;
+  RequestData audio_state_;
+  RequestData audio_config_;
+};
+
+class A2dpSinkTest : public ::testing::Test {
+ public:
+  A2dpSinkTest() = default;
+  ~A2dpSinkTest() override = default;
+
+  void SetUp() override {
+    mock_handler_.reset(new MockA2dpSinkHandler());
+    fake_hal_av_iface_ = new hal::FakeBluetoothAvInterface(mock_handler_);
+    hal::BluetoothAvInterface::InitializeForTesting(fake_hal_av_iface_);
+    factory_.reset(new A2dpSinkFactory());
+  }
+
+  void TearDown() override {
+    factory_.reset();
+    hal::BluetoothAvInterface::CleanUp();
+  }
+
+ protected:
+  hal::FakeBluetoothAvInterface* fake_hal_av_iface_;
+  std::shared_ptr<MockA2dpSinkHandler> mock_handler_;
+  std::unique_ptr<A2dpSinkFactory> factory_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(A2dpSinkTest);
+};
+
+class A2dpSinkPostRegisterTest : public A2dpSinkTest {
+ public:
+  A2dpSinkPostRegisterTest() = default;
+  ~A2dpSinkPostRegisterTest() override = default;
+
+  void SetUp() override {
+    A2dpSinkTest::SetUp();
+    Uuid uuid = Uuid::GetRandom();
+    auto callback = [&](BLEStatus status, const Uuid& in_uuid,
+                        std::unique_ptr<BluetoothInstance> in_client) {
+      CHECK(in_uuid == uuid);
+      CHECK(in_client.get());
+      CHECK(status == BLE_STATUS_SUCCESS);
+
+      a2dp_sink_ = std::unique_ptr<A2dpSink>(
+          static_cast<A2dpSink*>(in_client.release()));
+    };
+
+    factory_->RegisterInstance(uuid, callback);
+  }
+
+  void TearDown() override {
+    a2dp_sink_ = nullptr;
+    A2dpSinkTest::TearDown();
+  }
+
+ protected:
+  void Connect(const std::string& addr) {
+    RawAddress hal_addr;
+    ASSERT_TRUE(RawAddress::FromString(addr, hal_addr));
+
+    EXPECT_CALL(*mock_handler_, Connect(hal_addr))
+        .WillOnce(Return(BT_STATUS_SUCCESS));
+
+    EXPECT_TRUE(a2dp_sink_->Connect(addr));
+  }
+
+  void Disconnect(const std::string& addr) {
+    RawAddress hal_addr;
+    ASSERT_TRUE(RawAddress::FromString(addr, hal_addr));
+
+    EXPECT_CALL(*mock_handler_, Disconnect(hal_addr))
+        .WillOnce(Return(BT_STATUS_SUCCESS));
+
+    EXPECT_TRUE(a2dp_sink_->Disconnect(addr));
+  }
+
+  std::unique_ptr<A2dpSink> a2dp_sink_;
+
+ private:
+  DISALLOW_COPY_AND_ASSIGN(A2dpSinkPostRegisterTest);
+};
+
+TEST_F(A2dpSinkTest, RegisterA2dpSink) {
+  // These will be asynchronously populate with a result when the callback
+  // executes.
+  BLEStatus status = BLE_STATUS_SUCCESS;
+  Uuid cb_uuid;
+  std::unique_ptr<A2dpSink> a2dp_sink;
+  int callback_count = 0;
+
+  auto callback = [&](BLEStatus in_status, const Uuid& uuid,
+                      std::unique_ptr<BluetoothInstance> in_a2dp_sink) {
+    status = in_status;
+    cb_uuid = uuid;
+    a2dp_sink = std::unique_ptr<A2dpSink>(
+        static_cast<A2dpSink*>(in_a2dp_sink.release()));
+    callback_count++;
+  };
+
+  Uuid uuid0 = Uuid::GetRandom();
+
+  // This should always succeed.
+  EXPECT_TRUE(factory_->RegisterInstance(uuid0, callback));
+  EXPECT_EQ(1, callback_count);
+
+  testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
+
+  ASSERT_TRUE(a2dp_sink.get() !=
+              nullptr);  // Assert to terminate in case of error
+  EXPECT_EQ(BLE_STATUS_SUCCESS, status);
+  EXPECT_EQ(bluetooth::A2dpSink::kSingletonInstanceId,
+            a2dp_sink->GetInstanceId());
+  EXPECT_EQ(uuid0, a2dp_sink->GetAppIdentifier());
+  EXPECT_EQ(uuid0, cb_uuid);
+
+  testing::Mock::VerifyAndClearExpectations(mock_handler_.get());
+}
+
+TEST_F(A2dpSinkPostRegisterTest, Connect) {
+  static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
+  Connect(kTestAddr);
+  Disconnect(kTestAddr);
+}
+
+TEST_F(A2dpSinkPostRegisterTest, SetAudioFocusState) {
+  static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
+  static const int kFocusState = 2;
+  Connect(kTestAddr);
+
+  EXPECT_CALL(*mock_handler_, SetAudioFocusState(kFocusState));
+  a2dp_sink_->SetAudioFocusState(kFocusState);
+
+  Disconnect(kTestAddr);
+}
+
+TEST_F(A2dpSinkPostRegisterTest, SetAudioTrackGain) {
+  static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
+  static const float kTrackGain = 0.5;
+  Connect(kTestAddr);
+
+  EXPECT_CALL(*mock_handler_, SetAudioTrackGain(kTrackGain));
+  a2dp_sink_->SetAudioTrackGain(kTrackGain);
+
+  Disconnect(kTestAddr);
+}
+
+TEST_F(A2dpSinkPostRegisterTest, CallbackTest) {
+  static const char kTestAddr[] = "AA:BB:CC:DD:EE:FF";
+  RawAddress hal_addr;
+  ASSERT_TRUE(RawAddress::FromString(kTestAddr, hal_addr));
+
+  TestDelegate delegate;
+  a2dp_sink_->SetDelegate(&delegate);
+  Connect(kTestAddr);
+
+  // OnConnectionState
+  const int kConnectionState = 2;
+  EXPECT_EQ(0, delegate.connection_state().count);
+  fake_hal_av_iface_->NotifyConnectionState(
+      hal_addr, static_cast<btav_connection_state_t>(kConnectionState));
+  EXPECT_EQ(1, delegate.connection_state().count);
+  EXPECT_EQ(kTestAddr, delegate.connection_state().device_address);
+  EXPECT_EQ(kConnectionState, delegate.connection_state().state);
+
+  // OnAudioState
+  const int kAudioState = 1;
+  EXPECT_EQ(0, delegate.audio_state().count);
+  fake_hal_av_iface_->NotifyAudioState(
+      hal_addr, static_cast<btav_audio_state_t>(kAudioState));
+  EXPECT_EQ(1, delegate.audio_state().count);
+  EXPECT_EQ(kTestAddr, delegate.audio_state().device_address);
+  EXPECT_EQ(kAudioState, delegate.audio_state().state);
+
+  // OnAudioConfig
+  const uint32_t kSampleRate = 44100;
+  const uint32_t kChannelCount = 2;
+  EXPECT_EQ(0, delegate.audio_config().count);
+  fake_hal_av_iface_->NotifyAudioConfig(hal_addr, kSampleRate, kChannelCount);
+  EXPECT_EQ(1, delegate.audio_config().count);
+  EXPECT_EQ(kTestAddr, delegate.audio_config().device_address);
+  EXPECT_EQ(kSampleRate, delegate.audio_config().sample_rate);
+  EXPECT_EQ(kChannelCount, delegate.audio_config().channel_count);
+
+  Disconnect(kTestAddr);
+}
+
+}  // namespace
+}  // namespace bluetooth
diff --git a/service/test/adapter_unittest.cc b/service/test/adapter_unittest.cc
index e6f5d10..b1cedc1 100644
--- a/service/test/adapter_unittest.cc
+++ b/service/test/adapter_unittest.cc
@@ -124,12 +124,12 @@
   EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState());
 
   // Enable fails at HAL level
-  EXPECT_FALSE(adapter_->Enable(false));
+  EXPECT_FALSE(adapter_->Enable());
   EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, adapter_->GetState());
 
   // Enable success
   fake_hal_manager_->enable_succeed = true;
-  EXPECT_TRUE(adapter_->Enable(false));
+  EXPECT_TRUE(adapter_->Enable());
 
   // Should have received a state update.
   EXPECT_EQ(bluetooth::ADAPTER_STATE_OFF, observer.prev_state());
@@ -137,7 +137,7 @@
 
   // Enable fails because not disabled
   EXPECT_EQ(bluetooth::ADAPTER_STATE_TURNING_ON, adapter_->GetState());
-  EXPECT_FALSE(adapter_->Enable(false));
+  EXPECT_FALSE(adapter_->Enable());
 
   // Adapter state updates properly
   fake_hal_iface_->NotifyAdapterStateChanged(BT_STATE_ON);
@@ -148,7 +148,7 @@
   EXPECT_EQ(bluetooth::ADAPTER_STATE_ON, observer.cur_state());
 
   // Enable fails because already enabled
-  EXPECT_FALSE(adapter_->Enable(false));
+  EXPECT_FALSE(adapter_->Enable());
 }
 
 TEST_F(AdapterTest, Disable) {
diff --git a/service/test/mock_adapter.h b/service/test/mock_adapter.h
index 4b93792..b652026 100644
--- a/service/test/mock_adapter.h
+++ b/service/test/mock_adapter.h
@@ -32,16 +32,29 @@
   MOCK_METHOD1(RemoveObserver, void(Observer*));
   MOCK_CONST_METHOD0(GetState, AdapterState());
   MOCK_CONST_METHOD0(IsEnabled, bool());
-  MOCK_METHOD1(Enable, bool(bool));
+  MOCK_METHOD0(Enable, bool());
   MOCK_METHOD0(Disable, bool());
   MOCK_CONST_METHOD0(GetName, std::string());
   MOCK_METHOD1(SetName, bool(const std::string&));
   MOCK_CONST_METHOD0(GetAddress, std::string());
+  MOCK_METHOD1(SetScanMode, bool(int));
+  MOCK_METHOD1(SetScanEnable, bool(bool));
+  MOCK_METHOD4(SspReply, bool(const std::string&, int, bool, int32_t));
+  MOCK_METHOD2(CreateBond,
+               bool(const std::string& device_address, int transport));
   MOCK_METHOD0(IsMultiAdvertisementSupported, bool());
   MOCK_METHOD1(IsDeviceConnected, bool(const std::string&));
   MOCK_METHOD0(GetTotalNumberOfTrackableAdvertisements, int());
   MOCK_METHOD0(IsOffloadedFilteringSupported, bool());
   MOCK_METHOD0(IsOffloadedScanBatchingSupported, bool());
+  MOCK_METHOD0(GetBondedDevices, bool());
+  MOCK_METHOD1(RemoveBond, bool(const std::string&));
+  MOCK_METHOD1(GetRemoteDeviceProperties,
+               bool(const std::string& device_address));
+  MOCK_CONST_METHOD0(GetA2dpSinkFactory, A2dpSinkFactory*());
+  MOCK_CONST_METHOD0(GetA2dpSourceFactory, A2dpSourceFactory*());
+  MOCK_CONST_METHOD0(GetAvrcpControlFactory, AvrcpControlFactory*());
+  MOCK_CONST_METHOD0(GetAvrcpTargetFactory, AvrcpTargetFactory*());
   MOCK_CONST_METHOD0(GetLowEnergyClientFactory, LowEnergyClientFactory*());
   MOCK_CONST_METHOD0(GetLeAdvertiserFactory, LowEnergyAdvertiserFactory*());
   MOCK_CONST_METHOD0(GetLeScannerFactory, LowEnergyScannerFactory*());
diff --git a/stack/Android.bp b/stack/Android.bp
index 03e2c94..f7f5a45 100644
--- a/stack/Android.bp
+++ b/stack/Android.bp
@@ -1,3 +1,9 @@
+crypto_toolbox_srcs = [
+    "crypto_toolbox/aes.cc",
+    "crypto_toolbox/aes_cmac.cc",
+    "crypto_toolbox/crypto_toolbox.cc",
+]
+
 // Bluetooth stack static library for target
 // ========================================================
 cc_library_static {
@@ -40,7 +46,8 @@
         "system/bt/bta/sys",
         "system/bt/utils/include",
     ],
-    srcs: [
+    cflags: ["-Wno-implicit-fallthrough"],
+    srcs: crypto_toolbox_srcs + [
         "a2dp/a2dp_aac.cc",
         "a2dp/a2dp_aac_decoder.cc",
         "a2dp/a2dp_aac_encoder.cc",
@@ -57,6 +64,7 @@
         "a2dp/a2dp_vendor_aptx_hd_encoder.cc",
         "a2dp/a2dp_vendor_ldac.cc",
         "a2dp/a2dp_vendor_ldac_abr.cc",
+        "a2dp/a2dp_vendor_ldac_decoder.cc",
         "a2dp/a2dp_vendor_ldac_encoder.cc",
         "avct/avct_api.cc",
         "avct/avct_bcb_act.cc",
@@ -91,6 +99,7 @@
         "btm/btm_ble_adv_filter.cc",
         "btm/btm_ble_batchscan.cc",
         "btm/btm_ble_bgconn.cc",
+        "btm/btm_ble_connection_establishment.cc",
         "btm/btm_ble_cont_energy.cc",
         "btm/btm_ble_gap.cc",
         "btm/btm_ble_multi_adv.cc",
@@ -108,6 +117,7 @@
         "gap/gap_ble.cc",
         "gap/gap_conn.cc",
         "gatt/att_protocol.cc",
+        "gatt/connection_manager.cc",
         "gatt/gatt_api.cc",
         "gatt/gatt_attr.cc",
         "gatt/gatt_auth.cc",
@@ -130,13 +140,6 @@
         "l2cap/l2c_main.cc",
         "l2cap/l2c_utils.cc",
         "l2cap/l2cap_client.cc",
-        "mcap/mca_api.cc",
-        "mcap/mca_cact.cc",
-        "mcap/mca_csm.cc",
-        "mcap/mca_dact.cc",
-        "mcap/mca_dsm.cc",
-        "mcap/mca_l2c.cc",
-        "mcap/mca_main.cc",
         "pan/pan_api.cc",
         "pan/pan_main.cc",
         "pan/pan_utils.cc",
@@ -155,19 +158,16 @@
         "sdp/sdp_main.cc",
         "sdp/sdp_server.cc",
         "sdp/sdp_utils.cc",
-        "smp/aes.cc",
         "smp/p_256_curvepara.cc",
         "smp/p_256_ecc_pp.cc",
         "smp/p_256_multprecision.cc",
         "smp/smp_act.cc",
         "smp/smp_api.cc",
         "smp/smp_br_main.cc",
-        "smp/smp_cmac.cc",
         "smp/smp_keys.cc",
         "smp/smp_l2c.cc",
         "smp/smp_main.cc",
         "smp/smp_utils.cc",
-        "srvc/srvc_battery.cc",
         "srvc/srvc_dis.cc",
         "srvc/srvc_eng.cc",
     ],
@@ -178,12 +178,11 @@
     shared_libs: [
         "libcutils",
         "liblog",
-        "libstatslog",
     ],
     required: [
         "libldacBT_enc",
         "libldacBT_abr",
-    ]
+    ],
 }
 
 // Bluetooth stack unit tests for target
@@ -191,6 +190,7 @@
 cc_test {
     name: "net_test_stack",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     local_include_dirs: [
         "include",
     ],
@@ -202,6 +202,7 @@
         "test/stack_a2dp_test.cc",
     ],
     shared_libs: [
+        "libcrypto",
         "libhidlbase",
         "liblog",
         "libprotobuf-cpp-lite",
@@ -211,6 +212,7 @@
     static_libs: [
         "libbt-bta",
         "libbt-stack",
+        "libbt-common",
         "libbt-sbc-decoder",
         "libbt-sbc-encoder",
         "libFraunhoferAAC",
@@ -225,53 +227,60 @@
 }
 
 cc_test {
-  name: "net_test_stack_rfcomm",
-  defaults: ["fluoride_defaults"],
-  host_supported: true,
-  local_include_dirs: [
-      "include",
-      "btm",
-      "l2cap",
-      "smp",
-      "rfcomm",
-      "test/common",
-  ],
-  include_dirs: [
-      "system/bt",
-      "system/bt/internal_include",
-      "system/bt/btcore/include",
-      "system/bt/hci/include",
-      "system/bt/utils/include",
-  ],
-  srcs: [
-      "rfcomm/port_api.cc",
-      "rfcomm/port_rfc.cc",
-      "rfcomm/port_utils.cc",
-      "rfcomm/rfc_l2cap_if.cc",
-      "rfcomm/rfc_mx_fsm.cc",
-      "rfcomm/rfc_port_fsm.cc",
-      "rfcomm/rfc_port_if.cc",
-      "rfcomm/rfc_ts_frames.cc",
-      "rfcomm/rfc_utils.cc",
-      "test/common/mock_btm_layer.cc",
-      "test/common/mock_btu_layer.cc",
-      "test/common/mock_l2cap_layer.cc",
-      "test/common/stack_test_packet_utils.cc",
-      "test/rfcomm/stack_rfcomm_test.cc",
-      "test/rfcomm/stack_rfcomm_test_main.cc",
-      "test/rfcomm/stack_rfcomm_test_utils.cc",
-      "test/rfcomm/stack_rfcomm_test_utils_test.cc",
-  ],
-  shared_libs: [
-      "libcutils",
-      "libprotobuf-cpp-lite",
-  ],
-  static_libs: [
-      "liblog",
-      "libgmock",
-      "libosi",
-      "libbt-protos-lite",
-  ],
+    name: "net_test_stack_rfcomm",
+    defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
+    host_supported: true,
+    local_include_dirs: [
+        "include",
+        "btm",
+        "l2cap",
+        "smp",
+        "rfcomm",
+        "test/common",
+    ],
+    include_dirs: [
+        "system/bt",
+        "system/bt/internal_include",
+        "system/bt/btcore/include",
+        "system/bt/hci/include",
+        "system/bt/utils/include",
+    ],
+    srcs: [
+        "rfcomm/port_api.cc",
+        "rfcomm/port_rfc.cc",
+        "rfcomm/port_utils.cc",
+        "rfcomm/rfc_l2cap_if.cc",
+        "rfcomm/rfc_mx_fsm.cc",
+        "rfcomm/rfc_port_fsm.cc",
+        "rfcomm/rfc_port_if.cc",
+        "rfcomm/rfc_ts_frames.cc",
+        "rfcomm/rfc_utils.cc",
+        "test/common/mock_btm_layer.cc",
+        "test/common/mock_btsnoop_module.cc",
+        "test/common/mock_btu_layer.cc",
+        "test/common/mock_l2cap_layer.cc",
+        "test/common/stack_test_packet_utils.cc",
+        "test/rfcomm/stack_rfcomm_test.cc",
+        "test/rfcomm/stack_rfcomm_test_main.cc",
+        "test/rfcomm/stack_rfcomm_test_utils.cc",
+        "test/rfcomm/stack_rfcomm_test_utils_test.cc",
+    ],
+    shared_libs: [
+        "libcutils",
+        "libprotobuf-cpp-lite",
+        "libcrypto",
+    ],
+    static_libs: [
+        "liblog",
+        "libgmock",
+        "libosi",
+        "libbt-common",
+        "libbt-protos-lite",
+    ],
+    sanitize: {
+        cfi: false,
+    },
 }
 
 // Bluetooth stack smp unit tests for target
@@ -279,6 +288,7 @@
 cc_test {
     name: "net_test_stack_smp",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     local_include_dirs: [
         "include",
         "btm",
@@ -292,15 +302,15 @@
         "system/bt/hci/include",
         "system/bt/utils/include",
     ],
-    srcs: [
+    srcs: crypto_toolbox_srcs + [
         "smp/smp_keys.cc",
-        "smp/aes.cc",
         "smp/p_256_curvepara.cc",
         "smp/p_256_ecc_pp.cc",
         "smp/p_256_multprecision.cc",
         "smp/smp_api.cc",
         "smp/smp_main.cc",
         "smp/smp_utils.cc",
+        "test/crypto_toolbox_test.cc",
         "test/stack_smp_test.cc",
     ],
     shared_libs: [
@@ -313,12 +323,12 @@
     ],
 }
 
-
 // Bluetooth stack multi-advertising unit tests for target
 // ========================================================
 cc_test {
     name: "net_test_stack_multi_adv",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     local_include_dirs: [
         "include",
         "btm",
@@ -353,6 +363,7 @@
 cc_test {
     name: "net_test_stack_ad_parser",
     defaults: ["fluoride_defaults"],
+    test_suites: ["device-tests"],
     local_include_dirs: [
         "include",
     ],
@@ -391,6 +402,7 @@
         "libprotobuf-cpp-lite",
     ],
     static_libs: [
+        "libbt-common",
         "libbluetooth-types",
         "libgmock",
         "libosi",
@@ -400,3 +412,37 @@
         cfi: false,
     },
 }
+
+// Bluetooth stack connection multiplexing
+// ========================================================
+cc_test {
+    name: "net_test_gatt_conn_multiplexing",
+    defaults: ["fluoride_defaults"],
+    local_include_dirs: [
+        "include",
+        "btm",
+    ],
+    include_dirs: [
+        "system/bt",
+        "system/bt/internal_include",
+        "system/bt/btcore/include",
+        "system/bt/hci/include",
+        "system/bt/internal_include",
+        "system/bt/utils/include",
+    ],
+    srcs: [
+        "gatt/connection_manager.cc",
+        "test/gatt_connection_manager_test.cc",
+    ],
+    shared_libs: [
+        "libcutils",
+    ],
+    static_libs: [
+        "libbluetooth-types",
+        "liblog",
+        "libgmock",
+    ],
+    sanitize: {
+        cfi: false,
+    },
+}
diff --git a/stack/BUILD.gn b/stack/BUILD.gn
index 6f3c55a..00680c8 100644
--- a/stack/BUILD.gn
+++ b/stack/BUILD.gn
@@ -14,6 +14,22 @@
 #  limitations under the License.
 #
 
+static_library("crypto_toolbox") {
+  sources = [
+    "crypto_toolbox/crypto_toolbox.cc",
+    "crypto_toolbox/aes.cc",
+    "crypto_toolbox/aes_cmac.cc",
+  ]
+
+  include_dirs = [
+    "//",
+  ]
+
+  deps = [
+    "//third_party/libchrome:base",
+  ]
+}
+
 static_library("stack") {
   sources = [
     "a2dp/a2dp_aac.cc",
@@ -32,6 +48,7 @@
     "a2dp/a2dp_vendor_aptx_hd_encoder.cc",
     "a2dp/a2dp_vendor_ldac.cc",
     "a2dp/a2dp_vendor_ldac_abr.cc",
+    "a2dp/a2dp_vendor_ldac_decoder.cc",
     "a2dp/a2dp_vendor_ldac_encoder.cc",
     "avct/avct_api.cc",
     "avct/avct_bcb_act.cc",
@@ -83,6 +100,7 @@
     "gap/gap_ble.cc",
     "gap/gap_conn.cc",
     "gatt/att_protocol.cc",
+    "gatt/connection_manager.cc",
     "gatt/gatt_api.cc",
     "gatt/gatt_attr.cc",
     "gatt/gatt_auth.cc",
@@ -105,13 +123,6 @@
     "l2cap/l2c_main.cc",
     "l2cap/l2c_utils.cc",
     "l2cap/l2cap_client.cc",
-    "mcap/mca_api.cc",
-    "mcap/mca_cact.cc",
-    "mcap/mca_csm.cc",
-    "mcap/mca_dact.cc",
-    "mcap/mca_dsm.cc",
-    "mcap/mca_l2c.cc",
-    "mcap/mca_main.cc",
     "pan/pan_api.cc",
     "pan/pan_main.cc",
     "pan/pan_utils.cc",
@@ -130,19 +141,16 @@
     "sdp/sdp_main.cc",
     "sdp/sdp_server.cc",
     "sdp/sdp_utils.cc",
-    "smp/aes.cc",
     "smp/p_256_curvepara.cc",
     "smp/p_256_ecc_pp.cc",
     "smp/p_256_multprecision.cc",
     "smp/smp_act.cc",
     "smp/smp_api.cc",
     "smp/smp_br_main.cc",
-    "smp/smp_cmac.cc",
     "smp/smp_keys.cc",
     "smp/smp_l2c.cc",
     "smp/smp_main.cc",
     "smp/smp_utils.cc",
-    "srvc/srvc_battery.cc",
     "srvc/srvc_dis.cc",
     "srvc/srvc_eng.cc",
   ]
@@ -162,6 +170,8 @@
     "sdp",
     "smp",
     "srvc",
+    "//linux_include",
+    "//internal_include",
     "//btcore/include",
     "//vnd/include",
     "//vnd/ble",
@@ -179,6 +189,7 @@
   ]
 
   deps = [
+    ":crypto_toolbox",
     "//types",
     "//third_party/libchrome:base",
     "//third_party/libldac:libldacBT_enc",
@@ -226,6 +237,7 @@
     "//btcore",
     "//device",
     "//embdrv/sbc",
+    "//embdrv/g722",
     "//hci",
     "//types",
     "//main:bluetooth",
@@ -234,6 +246,77 @@
   ]
 }
 
+executable("net_test_stack_crypto_toolbox") {
+  testonly = true
+  sources = [
+    "test/crypto_toolbox_test.cc",
+  ]
+
+  include_dirs = [
+    "//",
+  ]
+
+  deps = [
+    ":crypto_toolbox",
+    "//third_party/googletest:gmock_main",
+    "//third_party/libchrome:base",
+  ]
+}
+
+executable("net_test_stack_smp") {
+  testonly = true
+  sources = [
+        "smp/p_256_curvepara.cc",
+        "smp/p_256_ecc_pp.cc",
+        "smp/p_256_multprecision.cc",
+        "smp/smp_keys.cc",
+        "smp/smp_api.cc",
+        "smp/smp_main.cc",
+        "smp/smp_utils.cc",
+        "test/stack_smp_test.cc",
+  ]
+
+  include_dirs = [
+    "//",
+    "//linux_include",
+    "//internal_include",
+    "//btcore/include",
+    "//hci/include",
+    "//utils/include",
+    "//bta/include",
+    "//bta/sys",
+    "//btcore/include",
+    "//embdrv/sbc/encoder/include",
+    "//hci/include",
+    "//internal_include",
+    "//stack/a2dp",
+    "//stack/l2cap",
+    "//stack/btm",
+    "//stack/include",
+    "//third_party/tinyxml2",
+    "//udrv/include",
+    "//utils/include",
+    "//vnd/include"
+  ]
+
+  libs = [
+    "-ldl",
+    "-lpthread",
+    "-lresolv",
+    "-lrt",
+    "-lz",
+    "-latomic",
+  ]
+
+  deps = [
+    ":crypto_toolbox",
+    "//osi",
+    "//types",
+    "//third_party/googletest:gmock_main",
+    "//third_party/libchrome:base",
+  ]
+}
+
 executable("net_test_stack_multi_adv") {
   testonly = true
   sources = [
diff --git a/stack/a2dp/a2dp_aac.cc b/stack/a2dp/a2dp_aac.cc
index 7792631..df641be 100644
--- a/stack/a2dp/a2dp_aac.cc
+++ b/stack/a2dp/a2dp_aac.cc
@@ -191,7 +191,18 @@
                   (*(p_codec_info + 2) & A2DP_AAC_BIT_RATE_MASK2);
   p_codec_info += 3;
 
-  if (is_capability) return A2DP_SUCCESS;
+  if (is_capability) {
+    // NOTE: The checks here are very liberal. We should be using more
+    // pedantic checks specific to the SRC or SNK as specified in the spec.
+    if (A2DP_BitsSet(p_ie->objectType) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_OBJ_TYPE;
+    if (A2DP_BitsSet(p_ie->sampleRate) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_SAMP_FREQ;
+    if (A2DP_BitsSet(p_ie->channelMode) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_CH_MODE;
+
+    return A2DP_SUCCESS;
+  }
 
   if (A2DP_BitsSet(p_ie->objectType) != A2DP_SET_ONE_BIT)
     return A2DP_BAD_OBJ_TYPE;
@@ -391,6 +402,21 @@
   return -1;
 }
 
+int A2DP_GetTrackBitsPerSampleAac(const uint8_t* p_codec_info) {
+  tA2DP_AAC_CIE aac_cie;
+
+  // Check whether the codec info contains valid data
+  tA2DP_STATUS a2dp_status = A2DP_ParseInfoAac(&aac_cie, p_codec_info, false);
+  if (a2dp_status != A2DP_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+              a2dp_status);
+    return -1;
+  }
+
+  // NOTE: The bits per sample never changes for AAC
+  return 16;
+}
+
 int A2DP_GetTrackChannelCountAac(const uint8_t* p_codec_info) {
   tA2DP_AAC_CIE aac_cie;
 
@@ -1324,6 +1350,7 @@
          sizeof(ota_codec_peer_config_));
   return false;
 }
+
 bool A2dpCodecConfigAacBase::setPeerCodecCapabilities(
     const uint8_t* p_peer_codec_capabilities) {
   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
@@ -1415,7 +1442,7 @@
   return true;
 }
 
-period_ms_t A2dpCodecConfigAacSink::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigAacSink::encoderIntervalMs() const {
   // TODO: This method applies only to Source codecs
   return 0;
 }
diff --git a/stack/a2dp/a2dp_aac_encoder.cc b/stack/a2dp/a2dp_aac_encoder.cc
index 43b6181..f6c68a6 100644
--- a/stack/a2dp/a2dp_aac_encoder.cc
+++ b/stack/a2dp/a2dp_aac_encoder.cc
@@ -27,6 +27,7 @@
 
 #include "a2dp_aac.h"
 #include "bt_common.h"
+#include "common/time_util.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
@@ -37,12 +38,6 @@
 // A2DP AAC encoder interval in milliseconds
 #define A2DP_AAC_ENCODER_INTERVAL_MS 20
 
-/*
- * 2DH5 payload size of:
- * 679 bytes - (4 bytes L2CAP Header + 12 bytes AVDTP Header)
- */
-#define MAX_2MBPS_AVDTP_MTU 663
-
 // offset
 #if (BTA_AV_CO_CP_SCMS_T == TRUE)
 #define A2DP_AAC_OFFSET (AVDT_MEDIA_OFFSET + 1)
@@ -131,7 +126,8 @@
     aacEncClose(&a2dp_aac_encoder_cb.aac_handle);
   memset(&a2dp_aac_encoder_cb, 0, sizeof(a2dp_aac_encoder_cb));
 
-  a2dp_aac_encoder_cb.stats.session_start_us = time_get_os_boottime_us();
+  a2dp_aac_encoder_cb.stats.session_start_us =
+      bluetooth::common::time_get_os_boottime_us();
 
   a2dp_aac_encoder_cb.read_callback = read_callback;
   a2dp_aac_encoder_cb.enqueue_callback = enqueue_callback;
@@ -483,7 +479,7 @@
   a2dp_aac_encoder_cb.aac_feeding_state.counter = 0;
 }
 
-period_ms_t a2dp_aac_get_encoder_interval_ms(void) {
+uint64_t a2dp_aac_get_encoder_interval_ms(void) {
   return A2DP_AAC_ENCODER_INTERVAL_MS;
 }
 
@@ -694,7 +690,7 @@
   return true;
 }
 
-period_ms_t A2dpCodecConfigAacSource::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigAacSource::encoderIntervalMs() const {
   return a2dp_aac_get_encoder_interval_ms();
 }
 
diff --git a/stack/a2dp/a2dp_codec_config.cc b/stack/a2dp/a2dp_codec_config.cc
index 47856fe..edf7e0c 100644
--- a/stack/a2dp/a2dp_codec_config.cc
+++ b/stack/a2dp/a2dp_codec_config.cc
@@ -129,7 +129,10 @@
       codec_config = new A2dpCodecConfigAptxHd(codec_priority);
       break;
     case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
-      codec_config = new A2dpCodecConfigLdac(codec_priority);
+      codec_config = new A2dpCodecConfigLdacSource(codec_priority);
+      break;
+    case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
+      codec_config = new A2dpCodecConfigLdacSink(codec_priority);
       break;
     case BTAV_A2DP_CODEC_INDEX_MAX:
       break;
@@ -188,6 +191,8 @@
           codec_config[4];  // blk_len | subbands | Alloc Method
       p_a2dp_offload->codec_info[1] = codec_config[5];  // Min bit pool
       p_a2dp_offload->codec_info[2] = codec_config[6];  // Max bit pool
+      p_a2dp_offload->codec_info[3] =
+          codec_config[3];  // Sample freq | channel mode
       break;
     case A2DP_MEDIA_CT_AAC:
       p_a2dp_offload->codec_info[0] = codec_config[3];  // object type
@@ -220,13 +225,18 @@
               p_a2dp_offload->codec_info[6] =
                   A2DP_LDAC_QUALITY_LOW;  // Low birate
               break;
-            case 3:  // fall through
+            case 3:
+              FALLTHROUGH_INTENDED; /* FALLTHROUGH */
             default:
               p_a2dp_offload->codec_info[6] =
                   A2DP_LDAC_QUALITY_ABR_OFFLOAD;  // ABR in offload
               break;
           }
         }
+        p_a2dp_offload->codec_info[7] =
+            codec_config[10];  // LDAC specific channel mode
+        LOG_VERBOSE(LOG_TAG, "%s: Ldac specific channelmode =%d", __func__,
+                    p_a2dp_offload->codec_info[7]);
       }
       break;
     default:
@@ -668,6 +678,11 @@
   return iter->second;
 }
 
+bool A2dpCodecs::isSupportedCodec(btav_a2dp_codec_index_t codec_index) {
+  std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
+  return indexed_codecs_.find(codec_index) != indexed_codecs_.end();
+}
+
 bool A2dpCodecs::setCodecConfig(const uint8_t* p_peer_codec_info,
                                 bool is_capability,
                                 uint8_t* p_result_codec_config,
@@ -1214,6 +1229,26 @@
   return -1;
 }
 
+int A2DP_GetTrackBitsPerSample(const uint8_t* p_codec_info) {
+  tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
+
+  LOG_VERBOSE(LOG_TAG, "%s: codec_type = 0x%x", __func__, codec_type);
+
+  switch (codec_type) {
+    case A2DP_MEDIA_CT_SBC:
+      return A2DP_GetTrackBitsPerSampleSbc(p_codec_info);
+    case A2DP_MEDIA_CT_AAC:
+      return A2DP_GetTrackBitsPerSampleAac(p_codec_info);
+    case A2DP_MEDIA_CT_NON_A2DP:
+      return A2DP_VendorGetTrackBitsPerSample(p_codec_info);
+    default:
+      break;
+  }
+
+  LOG_ERROR(LOG_TAG, "%s: unsupported codec type 0x%x", __func__, codec_type);
+  return -1;
+}
+
 int A2DP_GetTrackChannelCount(const uint8_t* p_codec_info) {
   tA2DP_CODEC_TYPE codec_type = A2DP_GetCodecType(p_codec_info);
 
diff --git a/stack/a2dp/a2dp_sbc.cc b/stack/a2dp/a2dp_sbc.cc
index bef5bf9..4c48993 100644
--- a/stack/a2dp/a2dp_sbc.cc
+++ b/stack/a2dp/a2dp_sbc.cc
@@ -197,7 +197,22 @@
     return A2DP_BAD_MAX_BITPOOL;
   }
 
-  if (is_capability) return A2DP_SUCCESS;
+  if (is_capability) {
+    // NOTE: The checks here are very liberal. We should be using more
+    // pedantic checks specific to the SRC or SNK as specified in the spec.
+    if (A2DP_BitsSet(p_ie->samp_freq) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_SAMP_FREQ;
+    if (A2DP_BitsSet(p_ie->ch_mode) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_CH_MODE;
+    if (A2DP_BitsSet(p_ie->block_len) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_BLOCK_LEN;
+    if (A2DP_BitsSet(p_ie->num_subbands) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_SUBBANDS;
+    if (A2DP_BitsSet(p_ie->alloc_method) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_ALLOC_METHOD;
+
+    return A2DP_SUCCESS;
+  }
 
   if (A2DP_BitsSet(p_ie->samp_freq) != A2DP_SET_ONE_BIT)
     return A2DP_BAD_SAMP_FREQ;
@@ -468,6 +483,20 @@
   return -1;
 }
 
+int A2DP_GetTrackBitsPerSampleSbc(const uint8_t* p_codec_info) {
+  tA2DP_SBC_CIE sbc_cie;
+
+  tA2DP_STATUS a2dp_status = A2DP_ParseInfoSbc(&sbc_cie, p_codec_info, false);
+  if (a2dp_status != A2DP_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+              a2dp_status);
+    return -1;
+  }
+
+  // NOTE: The bits per sample never changes for SBC
+  return 16;
+}
+
 int A2DP_GetTrackChannelCountSbc(const uint8_t* p_codec_info) {
   tA2DP_SBC_CIE sbc_cie;
 
@@ -840,8 +869,8 @@
 
 A2dpCodecConfigSbcSource::A2dpCodecConfigSbcSource(
     btav_a2dp_codec_priority_t codec_priority)
-    : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC, "SBC",
-                             codec_priority, true) {
+    : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SOURCE_SBC,
+                             A2DP_CodecIndexStrSbc(), codec_priority, true) {
   // Compute the local capability
   if (a2dp_sbc_source_caps.samp_freq & A2DP_SBC_IE_SAMP_FREQ_44) {
     codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
@@ -1525,8 +1554,9 @@
 
 A2dpCodecConfigSbcSink::A2dpCodecConfigSbcSink(
     btav_a2dp_codec_priority_t codec_priority)
-    : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SINK_SBC, "SBC(Sink)",
-                             codec_priority, false) {}
+    : A2dpCodecConfigSbcBase(BTAV_A2DP_CODEC_INDEX_SINK_SBC,
+                             A2DP_CodecIndexStrSbcSink(), codec_priority,
+                             false) {}
 
 A2dpCodecConfigSbcSink::~A2dpCodecConfigSbcSink() {}
 
@@ -1555,7 +1585,7 @@
   return false;
 }
 
-period_ms_t A2dpCodecConfigSbcSink::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigSbcSink::encoderIntervalMs() const {
   // TODO: This method applies only to Source codecs
   return 0;
 }
diff --git a/stack/a2dp/a2dp_sbc_encoder.cc b/stack/a2dp/a2dp_sbc_encoder.cc
index bd09989..aac7e6d 100644
--- a/stack/a2dp/a2dp_sbc_encoder.cc
+++ b/stack/a2dp/a2dp_sbc_encoder.cc
@@ -28,6 +28,7 @@
 #include "a2dp_sbc.h"
 #include "a2dp_sbc_up_sample.h"
 #include "bt_common.h"
+#include "common/time_util.h"
 #include "embdrv/sbc/encoder/include/sbc_encoder.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
@@ -43,11 +44,6 @@
 
 #define A2DP_SBC_NON_EDR_MAX_RATE 229
 
-/*
- * 2DH5 payload size of:
- * 679 bytes - (4 bytes L2CAP Header + 12 bytes AVDTP Header)
- */
-#define MAX_2MBPS_AVDTP_MTU 663
 #define A2DP_SBC_MAX_PCM_ITER_NUM_PER_TICK 3
 
 #define A2DP_SBC_MAX_HQ_FRAME_SIZE_44_1 119
@@ -142,7 +138,8 @@
                            a2dp_source_enqueue_callback_t enqueue_callback) {
   memset(&a2dp_sbc_encoder_cb, 0, sizeof(a2dp_sbc_encoder_cb));
 
-  a2dp_sbc_encoder_cb.stats.session_start_us = time_get_os_boottime_us();
+  a2dp_sbc_encoder_cb.stats.session_start_us =
+      bluetooth::common::time_get_os_boottime_us();
 
   a2dp_sbc_encoder_cb.read_callback = read_callback;
   a2dp_sbc_encoder_cb.enqueue_callback = enqueue_callback;
@@ -399,7 +396,7 @@
   a2dp_sbc_encoder_cb.feeding_state.aa_feed_residue = 0;
 }
 
-period_ms_t a2dp_sbc_get_encoder_interval_ms(void) {
+uint64_t a2dp_sbc_get_encoder_interval_ms(void) {
   return A2DP_SBC_ENCODER_INTERVAL_MS;
 }
 
@@ -860,7 +857,7 @@
 
   switch (p_encoder_params->s16ChannelMode) {
     case SBC_MONO:
-    /* FALLTHROUGH */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case SBC_DUAL:
       frame_len = A2DP_SBC_FRAME_HEADER_SIZE_BYTES +
                   ((uint32_t)(A2DP_SBC_SCALE_FACTOR_BITS *
@@ -909,7 +906,7 @@
   return p_encoder_params->u16BitRate * 1000;
 }
 
-period_ms_t A2dpCodecConfigSbcSource::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigSbcSource::encoderIntervalMs() const {
   return a2dp_sbc_get_encoder_interval_ms();
 }
 
diff --git a/stack/a2dp/a2dp_vendor.cc b/stack/a2dp/a2dp_vendor.cc
index 1a6dcc2..bcea13d 100644
--- a/stack/a2dp/a2dp_vendor.cc
+++ b/stack/a2dp/a2dp_vendor.cc
@@ -54,24 +54,33 @@
   return false;
 }
 
-bool A2DP_IsVendorSinkCodecValid(UNUSED_ATTR const uint8_t* p_codec_info) {
-  // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
-  // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+bool A2DP_IsVendorSinkCodecValid(const uint8_t* p_codec_info) {
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
   // Add checks based on <vendor_id, codec_id>
   // NOTE: Should be done only for local Sink codecs.
 
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_IsVendorSinkCodecValidLdac(p_codec_info);
+  }
+
   return false;
 }
 
-bool A2DP_IsVendorPeerSourceCodecValid(
-    UNUSED_ATTR const uint8_t* p_codec_info) {
-  // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
-  // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+bool A2DP_IsVendorPeerSourceCodecValid(const uint8_t* p_codec_info) {
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
   // Add checks based on <vendor_id, codec_id>
   // NOTE: Should be done only for local Sink codecs.
 
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_IsVendorPeerSourceCodecValidLdac(p_codec_info);
+  }
+
   return false;
 }
 
@@ -101,24 +110,33 @@
   return false;
 }
 
-bool A2DP_IsVendorSinkCodecSupported(UNUSED_ATTR const uint8_t* p_codec_info) {
-  // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
-  // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+bool A2DP_IsVendorSinkCodecSupported(const uint8_t* p_codec_info) {
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
   // Add checks based on <vendor_id, codec_id>
   // NOTE: Should be done only for local Sink codecs.
 
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_IsVendorSinkCodecSupportedLdac(p_codec_info);
+  }
+
   return false;
 }
 
-bool A2DP_IsVendorPeerSourceCodecSupported(
-    UNUSED_ATTR const uint8_t* p_codec_info) {
-  // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
-  // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+bool A2DP_IsVendorPeerSourceCodecSupported(const uint8_t* p_codec_info) {
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
   // Add checks based on <vendor_id, codec_id> and peer codec capabilities
   // NOTE: Should be done only for local Sink codecs.
 
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_IsPeerSourceCodecSupportedLdac(p_codec_info);
+  }
+
   return false;
 }
 
@@ -170,7 +188,7 @@
   return true;
 }
 
-const char* A2DP_VendorCodecName(UNUSED_ATTR const uint8_t* p_codec_info) {
+const char* A2DP_VendorCodecName(const uint8_t* p_codec_info) {
   uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
   uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
@@ -328,6 +346,32 @@
   return -1;
 }
 
+int A2DP_VendorGetTrackBitsPerSample(const uint8_t* p_codec_info) {
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+
+  // Check for aptX
+  if (vendor_id == A2DP_APTX_VENDOR_ID &&
+      codec_id == A2DP_APTX_CODEC_ID_BLUETOOTH) {
+    return A2DP_VendorGetTrackBitsPerSampleAptx(p_codec_info);
+  }
+
+  // Check for aptX-HD
+  if (vendor_id == A2DP_APTX_HD_VENDOR_ID &&
+      codec_id == A2DP_APTX_HD_CODEC_ID_BLUETOOTH) {
+    return A2DP_VendorGetTrackBitsPerSampleAptxHd(p_codec_info);
+  }
+
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_VendorGetTrackBitsPerSampleLdac(p_codec_info);
+  }
+
+  // Add checks based on <vendor_id, codec_id>
+
+  return -1;
+}
+
 int A2DP_VendorGetTrackChannelCount(const uint8_t* p_codec_info) {
   uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
   uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
@@ -354,14 +398,18 @@
   return -1;
 }
 
-int A2DP_VendorGetSinkTrackChannelType(
-    UNUSED_ATTR const uint8_t* p_codec_info) {
-  // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
-  // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+int A2DP_VendorGetSinkTrackChannelType(const uint8_t* p_codec_info) {
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
   // Add checks based on <vendor_id, codec_id>
   // NOTE: Should be done only for local Sink codecs.
 
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_VendorGetSinkTrackChannelTypeLdac(p_codec_info);
+  }
+
   return -1;
 }
 
@@ -453,7 +501,17 @@
 
 const tA2DP_DECODER_INTERFACE* A2DP_VendorGetDecoderInterface(
     const uint8_t* p_codec_info) {
-  // We do not support vendor codecs for decoding right now.
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+
+  // Add checks based on <vendor_id, codec_id>
+  // NOTE: Should be done only for local Sink codecs.
+
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_VendorGetDecoderInterfaceLdac(p_codec_info);
+  }
+
   return NULL;
 }
 
@@ -511,10 +569,16 @@
 }
 
 btav_a2dp_codec_index_t A2DP_VendorSinkCodecIndex(const uint8_t* p_codec_info) {
-  // uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
-  // uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
+  uint32_t vendor_id = A2DP_VendorCodecGetVendorId(p_codec_info);
+  uint16_t codec_id = A2DP_VendorCodecGetCodecId(p_codec_info);
 
   // Add checks based on <vendor_id, codec_id>
+  // NOTE: Should be done only for local Sink codecs.
+
+  // Check for LDAC
+  if (vendor_id == A2DP_LDAC_VENDOR_ID && codec_id == A2DP_LDAC_CODEC_ID) {
+    return A2DP_VendorSinkCodecIndexLdac(p_codec_info);
+  }
 
   return BTAV_A2DP_CODEC_INDEX_MAX;
 }
@@ -533,6 +597,8 @@
       return A2DP_VendorCodecIndexStrAptxHd();
     case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
       return A2DP_VendorCodecIndexStrLdac();
+    case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
+      return A2DP_VendorCodecIndexStrLdacSink();
     // Add a switch statement for each vendor-specific codec
     case BTAV_A2DP_CODEC_INDEX_MAX:
       break;
@@ -556,6 +622,8 @@
       return A2DP_VendorInitCodecConfigAptxHd(p_cfg);
     case BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC:
       return A2DP_VendorInitCodecConfigLdac(p_cfg);
+    case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
+      return A2DP_VendorInitCodecConfigLdacSink(p_cfg);
     // Add a switch statement for each vendor-specific codec
     case BTAV_A2DP_CODEC_INDEX_MAX:
       break;
diff --git a/stack/a2dp/a2dp_vendor_aptx.cc b/stack/a2dp/a2dp_vendor_aptx.cc
index 7017f06..e3e844d 100644
--- a/stack/a2dp/a2dp_vendor_aptx.cc
+++ b/stack/a2dp/a2dp_vendor_aptx.cc
@@ -155,7 +155,16 @@
   p_ie->sampleRate = *p_codec_info & 0xF0;
   p_codec_info++;
 
-  if (is_capability) return A2DP_SUCCESS;
+  if (is_capability) {
+    // NOTE: The checks here are very liberal. We should be using more
+    // pedantic checks specific to the SRC or SNK as specified in the spec.
+    if (A2DP_BitsSet(p_ie->sampleRate) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_SAMP_FREQ;
+    if (A2DP_BitsSet(p_ie->channelMode) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_CH_MODE;
+
+    return A2DP_SUCCESS;
+  }
 
   if (A2DP_BitsSet(p_ie->sampleRate) != A2DP_SET_ONE_BIT)
     return A2DP_BAD_SAMP_FREQ;
@@ -304,6 +313,21 @@
   return -1;
 }
 
+int A2DP_VendorGetTrackBitsPerSampleAptx(const uint8_t* p_codec_info) {
+  tA2DP_APTX_CIE aptx_cie;
+
+  // Check whether the codec info contains valid data
+  tA2DP_STATUS a2dp_status = A2DP_ParseInfoAptx(&aptx_cie, p_codec_info, false);
+  if (a2dp_status != A2DP_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+              a2dp_status);
+    return -1;
+  }
+
+  // NOTE: The bits per sample never changes for aptX
+  return 16;
+}
+
 int A2DP_VendorGetTrackChannelCountAptx(const uint8_t* p_codec_info) {
   tA2DP_APTX_CIE aptx_cie;
 
@@ -419,8 +443,8 @@
 
 A2dpCodecConfigAptx::A2dpCodecConfigAptx(
     btav_a2dp_codec_priority_t codec_priority)
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX, "aptX",
-                      codec_priority) {
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX,
+                      A2DP_VendorCodecIndexStrAptx(), codec_priority) {
   // Compute the local capability
   if (a2dp_aptx_source_caps.sampleRate & A2DP_APTX_SAMPLERATE_44100) {
     codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
diff --git a/stack/a2dp/a2dp_vendor_aptx_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
index 0252935..0d605c0 100644
--- a/stack/a2dp/a2dp_vendor_aptx_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_encoder.cc
@@ -26,6 +26,7 @@
 #include "a2dp_vendor.h"
 #include "a2dp_vendor_aptx.h"
 #include "bt_common.h"
+#include "common/time_util.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
@@ -174,7 +175,8 @@
     a2dp_source_enqueue_callback_t enqueue_callback) {
   memset(&a2dp_aptx_encoder_cb, 0, sizeof(a2dp_aptx_encoder_cb));
 
-  a2dp_aptx_encoder_cb.stats.session_start_us = time_get_os_boottime_us();
+  a2dp_aptx_encoder_cb.stats.session_start_us =
+      bluetooth::common::time_get_os_boottime_us();
 
   a2dp_aptx_encoder_cb.read_callback = read_callback;
   a2dp_aptx_encoder_cb.enqueue_callback = enqueue_callback;
@@ -369,7 +371,7 @@
   aptx_init_framing_params(&a2dp_aptx_encoder_cb.framing_params);
 }
 
-period_ms_t a2dp_vendor_aptx_get_encoder_interval_ms(void) {
+uint64_t a2dp_vendor_aptx_get_encoder_interval_ms(void) {
   return a2dp_aptx_encoder_cb.framing_params.sleep_time_ns / (1000 * 1000);
 }
 
@@ -480,7 +482,7 @@
   return pcm_bytes_encoded;
 }
 
-period_ms_t A2dpCodecConfigAptx::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigAptx::encoderIntervalMs() const {
   return a2dp_vendor_aptx_get_encoder_interval_ms();
 }
 
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd.cc b/stack/a2dp/a2dp_vendor_aptx_hd.cc
index 798e4fd..9e19d5f 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd.cc
@@ -171,7 +171,16 @@
   p_ie->acl_sprint_reserved2 = *(p_codec_info++);
   p_ie->acl_sprint_reserved3 = *(p_codec_info++);
 
-  if (is_capability) return A2DP_SUCCESS;
+  if (is_capability) {
+    // NOTE: The checks here are very liberal. We should be using more
+    // pedantic checks specific to the SRC or SNK as specified in the spec.
+    if (A2DP_BitsSet(p_ie->sampleRate) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_SAMP_FREQ;
+    if (A2DP_BitsSet(p_ie->channelMode) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_CH_MODE;
+
+    return A2DP_SUCCESS;
+  }
 
   if (A2DP_BitsSet(p_ie->sampleRate) != A2DP_SET_ONE_BIT)
     return A2DP_BAD_SAMP_FREQ;
@@ -319,6 +328,22 @@
   return -1;
 }
 
+int A2DP_VendorGetTrackBitsPerSampleAptxHd(const uint8_t* p_codec_info) {
+  tA2DP_APTX_HD_CIE aptx_hd_cie;
+
+  // Check whether the codec info contains valid data
+  tA2DP_STATUS a2dp_status =
+      A2DP_ParseInfoAptxHd(&aptx_hd_cie, p_codec_info, false);
+  if (a2dp_status != A2DP_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+              a2dp_status);
+    return -1;
+  }
+
+  // NOTE: The bits per sample never changes for aptX-HD
+  return 24;
+}
+
 int A2DP_VendorGetTrackChannelCountAptxHd(const uint8_t* p_codec_info) {
   tA2DP_APTX_HD_CIE aptx_hd_cie;
 
@@ -436,8 +461,8 @@
 
 A2dpCodecConfigAptxHd::A2dpCodecConfigAptxHd(
     btav_a2dp_codec_priority_t codec_priority)
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD, "aptX-HD",
-                      codec_priority) {
+    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_APTX_HD,
+                      A2DP_VendorCodecIndexStrAptxHd(), codec_priority) {
   // Compute the local capability
   if (a2dp_aptx_hd_source_caps.sampleRate & A2DP_APTX_HD_SAMPLERATE_44100) {
     codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
diff --git a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
index d72ec5a..fb782dd 100644
--- a/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_aptx_hd_encoder.cc
@@ -26,6 +26,7 @@
 #include "a2dp_vendor.h"
 #include "a2dp_vendor_aptx_hd.h"
 #include "bt_common.h"
+#include "common/time_util.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
@@ -174,7 +175,8 @@
     a2dp_source_enqueue_callback_t enqueue_callback) {
   memset(&a2dp_aptx_hd_encoder_cb, 0, sizeof(a2dp_aptx_hd_encoder_cb));
 
-  a2dp_aptx_hd_encoder_cb.stats.session_start_us = time_get_os_boottime_us();
+  a2dp_aptx_hd_encoder_cb.stats.session_start_us =
+      bluetooth::common::time_get_os_boottime_us();
 
   a2dp_aptx_hd_encoder_cb.read_callback = read_callback;
   a2dp_aptx_hd_encoder_cb.enqueue_callback = enqueue_callback;
@@ -353,7 +355,7 @@
   aptx_hd_init_framing_params(&a2dp_aptx_hd_encoder_cb.framing_params);
 }
 
-period_ms_t a2dp_vendor_aptx_hd_get_encoder_interval_ms(void) {
+uint64_t a2dp_vendor_aptx_hd_get_encoder_interval_ms(void) {
   return a2dp_aptx_hd_encoder_cb.framing_params.sleep_time_ns / (1000 * 1000);
 }
 
@@ -477,7 +479,7 @@
   return pcm_bytes_encoded;
 }
 
-period_ms_t A2dpCodecConfigAptxHd::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigAptxHd::encoderIntervalMs() const {
   return a2dp_vendor_aptx_hd_get_encoder_interval_ms();
 }
 
diff --git a/stack/a2dp/a2dp_vendor_ldac.cc b/stack/a2dp/a2dp_vendor_ldac.cc
index 266db81..4949e74 100644
--- a/stack/a2dp/a2dp_vendor_ldac.cc
+++ b/stack/a2dp/a2dp_vendor_ldac.cc
@@ -31,6 +31,7 @@
 
 #include <base/logging.h>
 #include "a2dp_vendor.h"
+#include "a2dp_vendor_ldac_decoder.h"
 #include "a2dp_vendor_ldac_encoder.h"
 #include "bt_utils.h"
 #include "btif_av_co.h"
@@ -60,6 +61,19 @@
     (BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 | BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24 |
      BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32)};
 
+/* LDAC Sink codec capabilities */
+static const tA2DP_LDAC_CIE a2dp_ldac_sink_caps = {
+    A2DP_LDAC_VENDOR_ID,  // vendorId
+    A2DP_LDAC_CODEC_ID,   // codecId
+    // sampleRate
+    (A2DP_LDAC_SAMPLING_FREQ_44100 | A2DP_LDAC_SAMPLING_FREQ_48000 |
+     A2DP_LDAC_SAMPLING_FREQ_88200 | A2DP_LDAC_SAMPLING_FREQ_96000),
+    // channelMode
+    (A2DP_LDAC_CHANNEL_MODE_DUAL | A2DP_LDAC_CHANNEL_MODE_STEREO),
+    // bits_per_sample
+    (BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16 | BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24 |
+     BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32)};
+
 /* Default LDAC codec configuration */
 static const tA2DP_LDAC_CIE a2dp_ldac_default_config = {
     A2DP_LDAC_VENDOR_ID,                // vendorId
@@ -78,6 +92,12 @@
     a2dp_vendor_ldac_send_frames,
     a2dp_vendor_ldac_set_transmit_queue_length};
 
+static const tA2DP_DECODER_INTERFACE a2dp_decoder_interface_ldac = {
+    a2dp_vendor_ldac_decoder_init,
+    a2dp_vendor_ldac_decoder_cleanup,
+    a2dp_vendor_ldac_decoder_decode_packet,
+};
+
 UNUSED_ATTR static tA2DP_STATUS A2DP_CodecInfoMatchesCapabilityLdac(
     const tA2DP_LDAC_CIE* p_cap, const uint8_t* p_codec_info,
     bool is_peer_codec_info);
@@ -162,7 +182,16 @@
   p_ie->sampleRate = *p_codec_info++ & A2DP_LDAC_SAMPLING_FREQ_MASK;
   p_ie->channelMode = *p_codec_info++ & A2DP_LDAC_CHANNEL_MODE_MASK;
 
-  if (is_capability) return A2DP_SUCCESS;
+  if (is_capability) {
+    // NOTE: The checks here are very liberal. We should be using more
+    // pedantic checks specific to the SRC or SNK as specified in the spec.
+    if (A2DP_BitsSet(p_ie->sampleRate) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_SAMP_FREQ;
+    if (A2DP_BitsSet(p_ie->channelMode) == A2DP_SET_ZERO_BIT)
+      return A2DP_BAD_CH_MODE;
+
+    return A2DP_SUCCESS;
+  }
 
   if (A2DP_BitsSet(p_ie->sampleRate) != A2DP_SET_ONE_BIT)
     return A2DP_BAD_SAMP_FREQ;
@@ -199,6 +228,22 @@
          (A2DP_ParseInfoLdac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
 }
 
+bool A2DP_IsVendorSinkCodecValidLdac(const uint8_t* p_codec_info) {
+  tA2DP_LDAC_CIE cfg_cie;
+
+  /* Use a liberal check when parsing the codec info */
+  return (A2DP_ParseInfoLdac(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) ||
+         (A2DP_ParseInfoLdac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
+}
+
+bool A2DP_IsVendorPeerSourceCodecValidLdac(const uint8_t* p_codec_info) {
+  tA2DP_LDAC_CIE cfg_cie;
+
+  /* Use a liberal check when parsing the codec info */
+  return (A2DP_ParseInfoLdac(&cfg_cie, p_codec_info, false) == A2DP_SUCCESS) ||
+         (A2DP_ParseInfoLdac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
+}
+
 bool A2DP_IsVendorPeerSinkCodecValidLdac(const uint8_t* p_codec_info) {
   tA2DP_LDAC_CIE cfg_cie;
 
@@ -207,6 +252,15 @@
          (A2DP_ParseInfoLdac(&cfg_cie, p_codec_info, true) == A2DP_SUCCESS);
 }
 
+bool A2DP_IsVendorSinkCodecSupportedLdac(const uint8_t* p_codec_info) {
+  return A2DP_CodecInfoMatchesCapabilityLdac(&a2dp_ldac_sink_caps, p_codec_info,
+                                             false) == A2DP_SUCCESS;
+}
+bool A2DP_IsPeerSourceCodecSupportedLdac(const uint8_t* p_codec_info) {
+  return A2DP_CodecInfoMatchesCapabilityLdac(&a2dp_ldac_sink_caps, p_codec_info,
+                                             true) == A2DP_SUCCESS;
+}
+
 // Checks whether A2DP LDAC codec configuration matches with a device's codec
 // capabilities. |p_cap| is the LDAC codec configuration. |p_codec_info| is
 // the device's codec capabilities.
@@ -361,6 +415,35 @@
   return -1;
 }
 
+int A2DP_VendorGetTrackBitsPerSampleLdac(const uint8_t* p_codec_info) {
+  tA2DP_LDAC_CIE ldac_cie;
+
+  // Check whether the codec info contains valid data
+  tA2DP_STATUS a2dp_status = A2DP_ParseInfoLdac(&ldac_cie, p_codec_info, false);
+  if (a2dp_status != A2DP_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+              a2dp_status);
+    return -1;
+  }
+
+#if 1
+  return 32;
+#else
+  // TODO : Implement proc to care about bit per sample in A2DP_ParseInfoLdac()
+
+  switch (ldac_cie.bits_per_sample) {
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
+      return 16;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_24:
+      return 24;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_32:
+      return 32;
+    case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE:
+      return -1;
+  }
+#endif
+}
+
 int A2DP_VendorGetTrackChannelCountLdac(const uint8_t* p_codec_info) {
   tA2DP_LDAC_CIE ldac_cie;
 
@@ -384,6 +467,29 @@
   return -1;
 }
 
+int A2DP_VendorGetSinkTrackChannelTypeLdac(const uint8_t* p_codec_info) {
+  tA2DP_LDAC_CIE ldac_cie;
+
+  // Check whether the codec info contains valid data
+  tA2DP_STATUS a2dp_status = A2DP_ParseInfoLdac(&ldac_cie, p_codec_info, false);
+  if (a2dp_status != A2DP_SUCCESS) {
+    LOG_ERROR(LOG_TAG, "%s: cannot decode codec information: %d", __func__,
+              a2dp_status);
+    return -1;
+  }
+
+  switch (ldac_cie.channelMode) {
+    case A2DP_LDAC_CHANNEL_MODE_MONO:
+      return 1;
+    case A2DP_LDAC_CHANNEL_MODE_DUAL:
+      return 3;
+    case A2DP_LDAC_CHANNEL_MODE_STEREO:
+      return 3;
+  }
+
+  return -1;
+}
+
 int A2DP_VendorGetChannelModeCodeLdac(const uint8_t* p_codec_info) {
   tA2DP_LDAC_CIE ldac_cie;
 
@@ -483,6 +589,13 @@
   return &a2dp_encoder_interface_ldac;
 }
 
+const tA2DP_DECODER_INTERFACE* A2DP_VendorGetDecoderInterfaceLdac(
+    const uint8_t* p_codec_info) {
+  if (!A2DP_IsVendorSinkCodecValidLdac(p_codec_info)) return NULL;
+
+  return &a2dp_decoder_interface_ldac;
+}
+
 bool A2DP_VendorAdjustCodecLdac(uint8_t* p_codec_info) {
   tA2DP_LDAC_CIE cfg_cie;
 
@@ -498,8 +611,15 @@
   return BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC;
 }
 
+btav_a2dp_codec_index_t A2DP_VendorSinkCodecIndexLdac(
+    UNUSED_ATTR const uint8_t* p_codec_info) {
+  return BTAV_A2DP_CODEC_INDEX_SINK_LDAC;
+}
+
 const char* A2DP_VendorCodecIndexStrLdac(void) { return "LDAC"; }
 
+const char* A2DP_VendorCodecIndexStrLdacSink(void) { return "LDAC SINK"; }
+
 bool A2DP_VendorInitCodecConfigLdac(AvdtpSepConfig* p_cfg) {
   if (A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_ldac_source_caps,
                          p_cfg->codec_info) != A2DP_SUCCESS) {
@@ -517,6 +637,11 @@
   return true;
 }
 
+bool A2DP_VendorInitCodecConfigLdacSink(AvdtpSepConfig* p_cfg) {
+  return A2DP_BuildInfoLdac(AVDT_MEDIA_TYPE_AUDIO, &a2dp_ldac_sink_caps,
+                            p_cfg->codec_info) == A2DP_SUCCESS;
+}
+
 UNUSED_ATTR static void build_codec_config(const tA2DP_LDAC_CIE& config_cie,
                                            btav_a2dp_codec_config_t* result) {
   if (config_cie.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100)
@@ -542,10 +667,11 @@
   }
 }
 
-A2dpCodecConfigLdac::A2dpCodecConfigLdac(
+A2dpCodecConfigLdacSource::A2dpCodecConfigLdacSource(
     btav_a2dp_codec_priority_t codec_priority)
-    : A2dpCodecConfig(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC, "LDAC",
-                      codec_priority) {
+    : A2dpCodecConfigLdacBase(BTAV_A2DP_CODEC_INDEX_SOURCE_LDAC,
+                              A2DP_VendorCodecIndexStrLdac(), codec_priority,
+                              true) {
   // Compute the local capability
   if (a2dp_ldac_source_caps.sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
     codec_local_capability_.sample_rate |= BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
@@ -578,9 +704,9 @@
   }
 }
 
-A2dpCodecConfigLdac::~A2dpCodecConfigLdac() {}
+A2dpCodecConfigLdacSource::~A2dpCodecConfigLdacSource() {}
 
-bool A2dpCodecConfigLdac::init() {
+bool A2dpCodecConfigLdacSource::init() {
   if (!isValid()) return false;
 
   // Load the encoder
@@ -592,7 +718,7 @@
   return true;
 }
 
-bool A2dpCodecConfigLdac::useRtpHeaderMarkerBit() const { return false; }
+bool A2dpCodecConfigLdacSource::useRtpHeaderMarkerBit() const { return false; }
 
 //
 // Selects the best sample rate from |sampleRate|.
@@ -822,15 +948,17 @@
   return false;
 }
 
-bool A2dpCodecConfigLdac::setCodecConfig(const uint8_t* p_peer_codec_info,
-                                         bool is_capability,
-                                         uint8_t* p_result_codec_config) {
+bool A2dpCodecConfigLdacBase::setCodecConfig(const uint8_t* p_peer_codec_info,
+                                             bool is_capability,
+                                             uint8_t* p_result_codec_config) {
   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
   tA2DP_LDAC_CIE peer_info_cie;
   tA2DP_LDAC_CIE result_config_cie;
   uint8_t channelMode;
   uint8_t sampleRate;
   btav_a2dp_codec_bits_per_sample_t bits_per_sample;
+  const tA2DP_LDAC_CIE* p_a2dp_ldac_caps =
+      (is_source_) ? &a2dp_ldac_source_caps : &a2dp_ldac_sink_caps;
 
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_config = codec_config_;
@@ -860,13 +988,13 @@
   // Build the preferred configuration
   //
   memset(&result_config_cie, 0, sizeof(result_config_cie));
-  result_config_cie.vendorId = a2dp_ldac_source_caps.vendorId;
-  result_config_cie.codecId = a2dp_ldac_source_caps.codecId;
+  result_config_cie.vendorId = p_a2dp_ldac_caps->vendorId;
+  result_config_cie.codecId = p_a2dp_ldac_caps->codecId;
 
   //
   // Select the sample frequency
   //
-  sampleRate = a2dp_ldac_source_caps.sampleRate & peer_info_cie.sampleRate;
+  sampleRate = p_a2dp_ldac_caps->sampleRate & peer_info_cie.sampleRate;
   codec_config_.sample_rate = BTAV_A2DP_CODEC_SAMPLE_RATE_NONE;
   switch (codec_user_config_.sample_rate) {
     case BTAV_A2DP_CODEC_SAMPLE_RATE_44100:
@@ -910,6 +1038,7 @@
         codec_capability_.sample_rate = codec_user_config_.sample_rate;
         codec_config_.sample_rate = codec_user_config_.sample_rate;
       }
+      break;
     case BTAV_A2DP_CODEC_SAMPLE_RATE_16000:
     case BTAV_A2DP_CODEC_SAMPLE_RATE_24000:
     case BTAV_A2DP_CODEC_SAMPLE_RATE_NONE:
@@ -985,8 +1114,7 @@
     LOG_ERROR(LOG_TAG,
               "%s: cannot match sample frequency: local caps = 0x%x "
               "peer info = 0x%x",
-              __func__, a2dp_ldac_source_caps.sampleRate,
-              peer_info_cie.sampleRate);
+              __func__, p_a2dp_ldac_caps->sampleRate, peer_info_cie.sampleRate);
     goto fail;
   }
 
@@ -995,7 +1123,7 @@
   //
   // NOTE: this information is NOT included in the LDAC A2DP codec description
   // that is sent OTA.
-  bits_per_sample = a2dp_ldac_source_caps.bits_per_sample;
+  bits_per_sample = p_a2dp_ldac_caps->bits_per_sample;
   codec_config_.bits_per_sample = BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE;
   switch (codec_user_config_.bits_per_sample) {
     case BTAV_A2DP_CODEC_BITS_PER_SAMPLE_16:
@@ -1030,7 +1158,7 @@
   do {
     // Compute the selectable capability
     codec_selectable_capability_.bits_per_sample =
-        a2dp_ldac_source_caps.bits_per_sample;
+        p_a2dp_ldac_caps->bits_per_sample;
 
     if (codec_config_.bits_per_sample != BTAV_A2DP_CODEC_BITS_PER_SAMPLE_NONE)
       break;
@@ -1040,7 +1168,7 @@
 
     // No user preference - the the codec audio config
     if (select_audio_bits_per_sample(&codec_audio_config_,
-                                     a2dp_ldac_source_caps.bits_per_sample,
+                                     p_a2dp_ldac_caps->bits_per_sample,
                                      &result_config_cie, &codec_config_)) {
       break;
     }
@@ -1052,7 +1180,7 @@
     }
 
     // No user preference - use the best match
-    if (select_best_bits_per_sample(a2dp_ldac_source_caps.bits_per_sample,
+    if (select_best_bits_per_sample(p_a2dp_ldac_caps->bits_per_sample,
                                     &result_config_cie, &codec_config_)) {
       break;
     }
@@ -1069,7 +1197,7 @@
   //
   // Select the channel mode
   //
-  channelMode = a2dp_ldac_source_caps.channelMode & peer_info_cie.channelMode;
+  channelMode = p_a2dp_ldac_caps->channelMode & peer_info_cie.channelMode;
   codec_config_.channel_mode = BTAV_A2DP_CODEC_CHANNEL_MODE_NONE;
   switch (codec_user_config_.channel_mode) {
     case BTAV_A2DP_CODEC_CHANNEL_MODE_MONO:
@@ -1148,7 +1276,7 @@
     LOG_ERROR(LOG_TAG,
               "%s: cannot match channel mode: local caps = 0x%x "
               "peer info = 0x%x",
-              __func__, a2dp_ldac_source_caps.channelMode,
+              __func__, p_a2dp_ldac_caps->channelMode,
               peer_info_cie.channelMode);
     goto fail;
   }
@@ -1200,12 +1328,14 @@
   return false;
 }
 
-bool A2dpCodecConfigLdac::setPeerCodecCapabilities(
+bool A2dpCodecConfigLdacBase::setPeerCodecCapabilities(
     const uint8_t* p_peer_codec_capabilities) {
   std::lock_guard<std::recursive_mutex> lock(codec_mutex_);
   tA2DP_LDAC_CIE peer_info_cie;
   uint8_t channelMode;
   uint8_t sampleRate;
+  const tA2DP_LDAC_CIE* p_a2dp_ldac_caps =
+      (is_source_) ? &a2dp_ldac_source_caps : &a2dp_ldac_sink_caps;
 
   // Save the internal state
   btav_a2dp_codec_config_t saved_codec_selectable_capability =
@@ -1223,7 +1353,7 @@
   }
 
   // Compute the selectable capability - sample rate
-  sampleRate = a2dp_ldac_source_caps.sampleRate & peer_info_cie.sampleRate;
+  sampleRate = p_a2dp_ldac_caps->sampleRate & peer_info_cie.sampleRate;
   if (sampleRate & A2DP_LDAC_SAMPLING_FREQ_44100) {
     codec_selectable_capability_.sample_rate |=
         BTAV_A2DP_CODEC_SAMPLE_RATE_44100;
@@ -1251,10 +1381,10 @@
 
   // Compute the selectable capability - bits per sample
   codec_selectable_capability_.bits_per_sample =
-      a2dp_ldac_source_caps.bits_per_sample;
+      p_a2dp_ldac_caps->bits_per_sample;
 
   // Compute the selectable capability - channel mode
-  channelMode = a2dp_ldac_source_caps.channelMode & peer_info_cie.channelMode;
+  channelMode = p_a2dp_ldac_caps->channelMode & peer_info_cie.channelMode;
   if (channelMode & A2DP_LDAC_CHANNEL_MODE_MONO) {
     codec_selectable_capability_.channel_mode |=
         BTAV_A2DP_CODEC_CHANNEL_MODE_MONO;
@@ -1280,3 +1410,46 @@
          sizeof(ota_codec_peer_capability_));
   return false;
 }
+
+A2dpCodecConfigLdacSink::A2dpCodecConfigLdacSink(
+    btav_a2dp_codec_priority_t codec_priority)
+    : A2dpCodecConfigLdacBase(BTAV_A2DP_CODEC_INDEX_SINK_LDAC,
+                              A2DP_VendorCodecIndexStrLdacSink(),
+                              codec_priority, false) {}
+
+A2dpCodecConfigLdacSink::~A2dpCodecConfigLdacSink() {}
+
+bool A2dpCodecConfigLdacSink::init() {
+  if (!isValid()) return false;
+
+  // Load the decoder
+  if (!A2DP_VendorLoadDecoderLdac()) {
+    LOG_ERROR(LOG_TAG, "%s: cannot load the decoder", __func__);
+    return false;
+  }
+
+  return true;
+}
+
+uint64_t A2dpCodecConfigLdacSink::encoderIntervalMs() const {
+  // TODO: This method applies only to Source codecs
+  return 0;
+}
+
+int A2dpCodecConfigLdacSink::getEffectiveMtu() const {
+  // TODO: This method applies only to Source codecs
+  return 0;
+}
+
+bool A2dpCodecConfigLdacSink::useRtpHeaderMarkerBit() const {
+  // TODO: This method applies only to Source codecs
+  return false;
+}
+
+bool A2dpCodecConfigLdacSink::updateEncoderUserConfig(
+    UNUSED_ATTR const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
+    UNUSED_ATTR bool* p_restart_input, UNUSED_ATTR bool* p_restart_output,
+    UNUSED_ATTR bool* p_config_updated) {
+  // TODO: This method applies only to Source codecs
+  return false;
+}
diff --git a/stack/a2dp/a2dp_vendor_ldac_decoder.cc b/stack/a2dp/a2dp_vendor_ldac_decoder.cc
new file mode 100644
index 0000000..444af34
--- /dev/null
+++ b/stack/a2dp/a2dp_vendor_ldac_decoder.cc
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "a2dp_vendor_ldac_decoder"
+#define ATRACE_TAG ATRACE_TAG_AUDIO
+
+#include "a2dp_vendor_ldac_decoder.h"
+
+#ifndef OS_GENERIC
+#include <cutils/trace.h>
+#endif
+#include <dlfcn.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <ldacBT.h>
+
+#include "a2dp_vendor.h"
+#include "a2dp_vendor_ldac.h"
+#include "bt_common.h"
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+
+//
+// Decoder for LDAC Source Codec
+//
+
+//
+// The LDAC decoder shared library, and the functions to use
+//
+static const char* LDAC_DECODER_LIB_NAME = "libldacBT_dec.so";
+static void* ldac_decoder_lib_handle = NULL;
+
+static const char* LDAC_GET_HANDLE_NAME = "ldacBT_get_handle";
+typedef HANDLE_LDAC_BT (*tLDAC_GET_HANDLE)(void);
+
+static const char* LDAC_FREE_HANDLE_NAME = "ldacBT_free_handle";
+typedef void (*tLDAC_FREE_HANDLE)(HANDLE_LDAC_BT hLdacParam);
+
+static const char* LDAC_CLOSE_HANDLE_NAME = "ldacBT_close_handle";
+typedef void (*tLDAC_CLOSE_HANDLE)(HANDLE_LDAC_BT hLdacParam);
+
+static const char* LDAC_GET_VERSION_NAME = "ldacBT_get_version";
+typedef int (*tLDAC_GET_VERSION)(void);
+
+static const char* LDAC_GET_BITRATE_NAME = "ldacBT_get_bitrate";
+typedef int (*tLDAC_GET_BITRATE)(HANDLE_LDAC_BT hLdacParam);
+
+static const char* LDAC_GET_SAMPLING_FREQ_NAME = "ldacBT_get_sampling_freq";
+typedef int (*tLDAC_GET_SAMPLING_FREQ)(HANDLE_LDAC_BT hLdacParam);
+
+static const char* LDAC_INIT_HANDLE_DECODE_NAME = "ldacBT_init_handle_decode";
+typedef int (*tLDAC_INIT_HANDLE_DECODE)(HANDLE_LDAC_BT hLdacParam, int cm,
+                                        int sf, int var0, int var1, int var2);
+
+static const char* LDAC_DECODE_NAME = "ldacBT_decode";
+typedef int (*tLDAC_DECODE)(HANDLE_LDAC_BT hLdacBt, unsigned char* p_bs,
+                            unsigned char* p_pcm, LDACBT_SMPL_FMT_T fmt,
+                            int bs_bytes, int* used_bytes, int* wrote_bytes);
+
+static const char* LDAC_GET_ERROR_CODE_NAME = "ldacBT_get_error_code";
+typedef int (*tLDAC_GET_ERROR_CODE)(HANDLE_LDAC_BT hLdacParam);
+
+static tLDAC_GET_HANDLE ldac_get_handle_func;
+static tLDAC_FREE_HANDLE ldac_free_handle_func;
+static tLDAC_CLOSE_HANDLE ldac_close_handle_func;
+static tLDAC_GET_VERSION ldac_get_version_func;
+static tLDAC_GET_BITRATE ldac_get_bitrate_func;
+static tLDAC_GET_SAMPLING_FREQ ldac_get_sampling_freq_func;
+static tLDAC_INIT_HANDLE_DECODE ldac_init_handle_decode_func;
+static tLDAC_DECODE ldac_decode_func;
+static tLDAC_GET_ERROR_CODE ldac_get_error_code_func;
+
+// offset
+#if (BTA_AV_CO_CP_SCMS_T == TRUE)
+#define A2DP_LDAC_OFFSET (AVDT_MEDIA_OFFSET + A2DP_LDAC_MPL_HDR_LEN + 1)
+#else
+#define A2DP_LDAC_OFFSET (AVDT_MEDIA_OFFSET + A2DP_LDAC_MPL_HDR_LEN)
+#endif
+
+typedef struct {
+  uint32_t sample_rate;
+  uint8_t channel_mode;
+  uint8_t bits_per_sample;
+  int pcm_wlength;
+  LDACBT_SMPL_FMT_T pcm_fmt;
+} tA2DP_LDAC_DECODER_PARAMS;
+
+typedef struct {
+  bool use_SCMS_T;
+  bool is_peer_edr;          // True if the peer device supports EDR
+  bool peer_supports_3mbps;  // True if the peer device supports 3Mbps EDR
+  uint16_t peer_mtu;         // MTU of the A2DP peer
+  uint32_t timestamp;        // Timestamp for the A2DP frames
+
+  HANDLE_LDAC_BT ldac_handle;
+  bool has_ldac_handle;  // True if ldac_handle is valid
+  unsigned char* decode_buf;
+  decoded_data_callback_t decode_callback;
+} tA2DP_LDAC_DECODER_CB;
+
+static tA2DP_LDAC_DECODER_CB a2dp_ldac_decoder_cb;
+
+static void* load_func(const char* func_name) {
+  void* func_ptr = dlsym(ldac_decoder_lib_handle, func_name);
+  if (func_ptr == NULL) {
+    LOG_ERROR(LOG_TAG,
+              "%s: cannot find function '%s' in the decoder library: %s",
+              __func__, func_name, dlerror());
+    A2DP_VendorUnloadDecoderLdac();
+    return NULL;
+  }
+  return func_ptr;
+}
+
+bool A2DP_VendorLoadDecoderLdac(void) {
+  if (ldac_decoder_lib_handle != NULL) return true;  // Already loaded
+
+  // Initialize the control block
+  memset(&a2dp_ldac_decoder_cb, 0, sizeof(a2dp_ldac_decoder_cb));
+
+  // Open the decoder library
+  ldac_decoder_lib_handle = dlopen(LDAC_DECODER_LIB_NAME, RTLD_NOW);
+  if (ldac_decoder_lib_handle == NULL) {
+    LOG_ERROR(LOG_TAG, "%s: cannot open LDAC decoder library %s: %s", __func__,
+              LDAC_DECODER_LIB_NAME, dlerror());
+    return false;
+  }
+
+  // Load all functions
+  ldac_get_handle_func = (tLDAC_GET_HANDLE)load_func(LDAC_GET_HANDLE_NAME);
+  if (ldac_get_handle_func == NULL) return false;
+  ldac_free_handle_func = (tLDAC_FREE_HANDLE)load_func(LDAC_FREE_HANDLE_NAME);
+  if (ldac_free_handle_func == NULL) return false;
+  ldac_close_handle_func =
+      (tLDAC_CLOSE_HANDLE)load_func(LDAC_CLOSE_HANDLE_NAME);
+  if (ldac_close_handle_func == NULL) return false;
+  ldac_get_version_func = (tLDAC_GET_VERSION)load_func(LDAC_GET_VERSION_NAME);
+  if (ldac_get_version_func == NULL) return false;
+  ldac_get_bitrate_func = (tLDAC_GET_BITRATE)load_func(LDAC_GET_BITRATE_NAME);
+  if (ldac_get_bitrate_func == NULL) return false;
+  ldac_get_sampling_freq_func =
+      (tLDAC_GET_SAMPLING_FREQ)load_func(LDAC_GET_SAMPLING_FREQ_NAME);
+  if (ldac_get_sampling_freq_func == NULL) return false;
+  ldac_init_handle_decode_func =
+      (tLDAC_INIT_HANDLE_DECODE)load_func(LDAC_INIT_HANDLE_DECODE_NAME);
+  if (ldac_init_handle_decode_func == NULL) return false;
+  ldac_decode_func = (tLDAC_DECODE)load_func(LDAC_DECODE_NAME);
+  if (ldac_decode_func == NULL) return false;
+  ldac_get_error_code_func =
+      (tLDAC_GET_ERROR_CODE)load_func(LDAC_GET_ERROR_CODE_NAME);
+  if (ldac_get_error_code_func == NULL) return false;
+
+  return true;
+}
+
+void A2DP_VendorUnloadDecoderLdac(void) {
+  // Cleanup any LDAC-related state
+  if (a2dp_ldac_decoder_cb.has_ldac_handle && ldac_free_handle_func != NULL)
+    ldac_free_handle_func(a2dp_ldac_decoder_cb.ldac_handle);
+  memset(&a2dp_ldac_decoder_cb, 0, sizeof(a2dp_ldac_decoder_cb));
+
+  ldac_get_handle_func = NULL;
+  ldac_free_handle_func = NULL;
+  ldac_close_handle_func = NULL;
+  ldac_get_version_func = NULL;
+  ldac_get_bitrate_func = NULL;
+  ldac_get_sampling_freq_func = NULL;
+  ldac_init_handle_decode_func = NULL;
+  ldac_decode_func = NULL;
+  ldac_get_error_code_func = NULL;
+
+  if (ldac_decoder_lib_handle != NULL) {
+    dlclose(ldac_decoder_lib_handle);
+    ldac_decoder_lib_handle = NULL;
+  }
+}
+
+bool a2dp_vendor_ldac_decoder_init(decoded_data_callback_t decode_callback) {
+  if (a2dp_ldac_decoder_cb.has_ldac_handle)
+    ldac_free_handle_func(a2dp_ldac_decoder_cb.ldac_handle);
+  memset(&a2dp_ldac_decoder_cb, 0, sizeof(a2dp_ldac_decoder_cb));
+
+  a2dp_vendor_ldac_decoder_cleanup();
+
+  a2dp_ldac_decoder_cb.ldac_handle = ldac_get_handle_func();
+  a2dp_ldac_decoder_cb.has_ldac_handle = true;
+  a2dp_ldac_decoder_cb.decode_buf = static_cast<unsigned char*>(
+      osi_malloc(sizeof(a2dp_ldac_decoder_cb.decode_buf[0]) * LDACBT_MAX_LSU *
+                 LDAC_PRCNCH * sizeof(int)));
+  a2dp_ldac_decoder_cb.decode_callback = decode_callback;
+
+  // initialize
+  ldac_init_handle_decode_func(a2dp_ldac_decoder_cb.ldac_handle,
+                               LDACBT_CHANNEL_MODE_STEREO, 96000, 0, 0, 0);
+  return true;
+}
+
+void a2dp_vendor_ldac_decoder_cleanup(void) {
+  if (a2dp_ldac_decoder_cb.has_ldac_handle)
+    ldac_free_handle_func(a2dp_ldac_decoder_cb.ldac_handle);
+  memset(&a2dp_ldac_decoder_cb, 0, sizeof(a2dp_ldac_decoder_cb));
+}
+
+bool a2dp_vendor_ldac_decoder_decode_packet(BT_HDR* p_buf) {
+  unsigned char* pBuffer =
+      reinterpret_cast<unsigned char*>(p_buf->data + p_buf->offset);
+  //  unsigned int bufferSize = p_buf->len;
+  unsigned int bytesValid = p_buf->len;
+  int err;
+  LDACBT_SMPL_FMT_T fmt;
+  int bs_bytes, used_bytes, wrote_bytes, frame_number;
+
+  fmt = LDACBT_SMPL_FMT_S32;
+  frame_number = (int)pBuffer[0];
+  pBuffer++;
+  bs_bytes = (int)bytesValid - 1;
+  bytesValid -= 1;
+  LOG_VERBOSE(LOG_TAG, "%s:INPUT size : %d, frame : %d", __func__, bs_bytes,
+              frame_number);
+
+  while (bytesValid > 0) {
+#if 0
+    err = ldacDecoder_Fill(a2dp_ldac_decoder_cb.ldac_handle,
+                               &pBuffer, &bufferSize, &bytesValid);
+    if (err != LDACBT_ERR_NONE) {
+      LOG_ERROR(LOG_TAG, "%s: ldacDecoder_Fill failed: 0x%x", __func__,
+                static_cast<unsigned>(err));
+      return false;
+    }
+#endif
+    while (true) {
+      // Todo : implement LDAC Buffer Control Operation instead of
+      // ldac_decode_func().
+      err = ldac_decode_func(a2dp_ldac_decoder_cb.ldac_handle, pBuffer,
+                             a2dp_ldac_decoder_cb.decode_buf, fmt, bs_bytes,
+                             &used_bytes, &wrote_bytes);
+      //      if (err == LDAC_DEC_NOT_ENOUGH_FRAMES) {
+      //        break;
+      //      }
+      if (LDACBT_ERROR(err)) {
+        err = ldac_get_error_code_func(a2dp_ldac_decoder_cb.ldac_handle);
+        LOG_ERROR(LOG_TAG, "%s: ldacDecoder_DecodeFrame failed: %d:%d:%d",
+                  __func__, LDACBT_API_ERR(err), LDACBT_HANDLE_ERR(err),
+                  LDACBT_BLOCK_ERR(err));
+        if (LDACBT_FATAL(err)) {
+          break;
+        }
+      }
+
+      if (wrote_bytes > 0) {
+        size_t frame_len = (size_t)wrote_bytes;
+        a2dp_ldac_decoder_cb.decode_callback(
+            reinterpret_cast<uint8_t*>(a2dp_ldac_decoder_cb.decode_buf),
+            frame_len);
+      }
+      pBuffer += used_bytes;
+      bs_bytes -= used_bytes;
+      if (bs_bytes <= 1) {
+        bytesValid = 0;
+        break;
+      }
+    }
+  }
+
+  return true;
+}
diff --git a/stack/a2dp/a2dp_vendor_ldac_encoder.cc b/stack/a2dp/a2dp_vendor_ldac_encoder.cc
index 21d5e72..ca6c2fc 100644
--- a/stack/a2dp/a2dp_vendor_ldac_encoder.cc
+++ b/stack/a2dp/a2dp_vendor_ldac_encoder.cc
@@ -33,6 +33,7 @@
 #include "a2dp_vendor_ldac.h"
 #include "a2dp_vendor_ldac_abr.h"
 #include "bt_common.h"
+#include "common/time_util.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
@@ -285,7 +286,8 @@
     a2dp_ldac_abr_free_handle(a2dp_ldac_encoder_cb.ldac_abr_handle);
   memset(&a2dp_ldac_encoder_cb, 0, sizeof(a2dp_ldac_encoder_cb));
 
-  a2dp_ldac_encoder_cb.stats.session_start_us = time_get_os_boottime_us();
+  a2dp_ldac_encoder_cb.stats.session_start_us =
+      bluetooth::common::time_get_os_boottime_us();
 
   a2dp_ldac_encoder_cb.read_callback = read_callback;
   a2dp_ldac_encoder_cb.enqueue_callback = enqueue_callback;
@@ -313,7 +315,7 @@
                                   &restart_output, &config_updated);
 }
 
-bool A2dpCodecConfigLdac::updateEncoderUserConfig(
+bool A2dpCodecConfigLdacSource::updateEncoderUserConfig(
     const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params, bool* p_restart_input,
     bool* p_restart_output, bool* p_config_updated) {
   a2dp_ldac_encoder_cb.is_peer_edr = p_peer_params->is_peer_edr;
@@ -533,7 +535,7 @@
   a2dp_ldac_encoder_cb.ldac_feeding_state.counter = 0;
 }
 
-period_ms_t a2dp_vendor_ldac_get_encoder_interval_ms(void) {
+uint64_t a2dp_vendor_ldac_get_encoder_interval_ms(void) {
   return A2DP_LDAC_ENCODER_INTERVAL_MS;
 }
 
@@ -759,15 +761,15 @@
   a2dp_ldac_encoder_cb.TxQueueLength = transmit_queue_length;
 }
 
-period_ms_t A2dpCodecConfigLdac::encoderIntervalMs() const {
+uint64_t A2dpCodecConfigLdacSource::encoderIntervalMs() const {
   return a2dp_vendor_ldac_get_encoder_interval_ms();
 }
 
-int A2dpCodecConfigLdac::getEffectiveMtu() const {
+int A2dpCodecConfigLdacSource::getEffectiveMtu() const {
   return a2dp_ldac_encoder_cb.TxAaMtuSize;
 }
 
-void A2dpCodecConfigLdac::debug_codec_dump(int fd) {
+void A2dpCodecConfigLdacSource::debug_codec_dump(int fd) {
   a2dp_ldac_encoder_stats_t* stats = &a2dp_ldac_encoder_cb.stats;
   tA2DP_LDAC_ENCODER_PARAMS* p_encoder_params =
       &a2dp_ldac_encoder_cb.ldac_encoder_params;
diff --git a/stack/avct/avct_api.cc b/stack/avct/avct_api.cc
index 5ced71f..51e2daf 100644
--- a/stack/avct/avct_api.cc
+++ b/stack/avct/avct_api.cc
@@ -56,7 +56,8 @@
   AVCT_TRACE_API("AVCT_Register");
 
   /* register PSM with L2CAP */
-  L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl);
+  L2CA_Register(AVCT_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_appl,
+                true /* enable_snoop */);
 
   /* set security level */
   BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVCTP, sec_mask, AVCT_PSM, 0,
@@ -68,7 +69,8 @@
   memset(&avct_cb, 0, sizeof(tAVCT_CB));
 
   /* Include the browsing channel which uses eFCR */
-  L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl);
+  L2CA_Register(AVCT_BR_PSM, (tL2CAP_APPL_INFO*)&avct_l2c_br_appl,
+                true /*enable_snoop*/);
 
   /* AVCTP browsing channel uses the same security service as AVCTP control
    * channel */
diff --git a/stack/avct/avct_lcb_act.cc b/stack/avct/avct_lcb_act.cc
index faa098b..eec049d 100644
--- a/stack/avct/avct_lcb_act.cc
+++ b/stack/avct/avct_lcb_act.cc
@@ -53,6 +53,12 @@
   uint8_t pkt_type;
   BT_HDR* p_ret;
 
+  if (p_buf->len < 1) {
+    osi_free(p_buf);
+    p_ret = NULL;
+    return p_ret;
+  }
+
   /* parse the message header */
   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
   pkt_type = AVCT_PKT_TYPE(p);
diff --git a/stack/avdt/avdt_api.cc b/stack/avdt/avdt_api.cc
index 43954b4..9350c31 100644
--- a/stack/avdt/avdt_api.cc
+++ b/stack/avdt/avdt_api.cc
@@ -90,7 +90,8 @@
  ******************************************************************************/
 void AVDT_Register(AvdtpRcb* p_reg, tAVDT_CTRL_CBACK* p_cback) {
   /* register PSM with L2CAP */
-  L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl);
+  L2CA_Register(AVDT_PSM, (tL2CAP_APPL_INFO*)&avdt_l2c_appl,
+                true /* enable_snoop */);
 
   /* set security level */
   BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_AVDTP, p_reg->sec_mask,
@@ -1212,6 +1213,8 @@
 }
 
 void stack_debug_avdtp_api_dump(int fd) {
+  if (appl_trace_level < BT_TRACE_LEVEL_DEBUG) return;
+
   dprintf(fd, "\nAVDTP Stack State:\n");
   dprintf(fd, "  AVDTP signalling L2CAP channel MTU: %d\n",
           avdtp_cb.rcb.ctrl_mtu);
@@ -1219,6 +1222,9 @@
 
   for (size_t i = 0; i < AVDT_NUM_LINKS; i++) {
     const AvdtpCcb& ccb = avdtp_cb.ccb[i];
+    if (ccb.peer_addr.IsEmpty()) {
+      continue;
+    }
     dprintf(fd, "\n  Channel control block: %zu peer: %s\n", i,
             ccb.peer_addr.ToString().c_str());
     dprintf(fd, "    Allocated: %s\n", ccb.allocated ? "true" : "false");
@@ -1235,6 +1241,9 @@
 
     for (size_t i = 0; i < AVDT_NUM_SEPS; i++) {
       const AvdtpScb& scb = ccb.scb[i];
+      if (!scb.in_use) {
+        continue;
+      }
       dprintf(fd, "\n    Stream control block: %zu\n", i);
       dprintf(fd, "      SEP codec: %s\n",
               A2DP_CodecName(scb.stream_config.cfg.codec_info));
diff --git a/stack/avdt/avdt_ccb_act.cc b/stack/avdt/avdt_ccb_act.cc
index 52f3857..3059d8a 100644
--- a/stack/avdt/avdt_ccb_act.cc
+++ b/stack/avdt/avdt_ccb_act.cc
@@ -122,7 +122,7 @@
   if (i == AVDT_NUM_SEPS) {
     alarm_cancel(p_ccb->ret_ccb_timer);
     alarm_cancel(p_ccb->rsp_ccb_timer);
-    period_ms_t interval_ms = avdtp_cb.rcb.idle_tout * 1000;
+    uint64_t interval_ms = avdtp_cb.rcb.idle_tout * 1000;
     alarm_set_on_mloop(p_ccb->idle_ccb_timer, interval_ms,
                        avdt_ccb_idle_ccb_timer_timeout, p_ccb);
   }
@@ -780,7 +780,7 @@
     /* restart ret timer */
     alarm_cancel(p_ccb->idle_ccb_timer);
     alarm_cancel(p_ccb->rsp_ccb_timer);
-    period_ms_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
+    uint64_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
     alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
                        avdt_ccb_ret_ccb_timer_timeout, p_ccb);
   }
diff --git a/stack/avdt/avdt_msg.cc b/stack/avdt/avdt_msg.cc
index cf517d1..853f369 100644
--- a/stack/avdt/avdt_msg.cc
+++ b/stack/avdt/avdt_msg.cc
@@ -586,6 +586,10 @@
     /* parse individual information elements with additional parameters */
     switch (elem) {
       case AVDT_CAT_RECOV:
+        if ((p_end - p) < 3) {
+          err = AVDT_ERR_PAYLOAD;
+          break;
+        }
         p_cfg->recov_type = *p++;
         p_cfg->recov_mrws = *p++;
         p_cfg->recov_mnmp = *p++;
@@ -617,6 +621,10 @@
         break;
 
       case AVDT_CAT_HDRCMP:
+        if ((p_end - p) < 1) {
+          err = AVDT_ERR_PAYLOAD;
+          break;
+        }
         p_cfg->hdrcmp_mask = *p++;
         break;
 
@@ -1135,13 +1143,13 @@
             (sig == AVDT_SIG_SECURITY) || (avdtp_cb.rcb.ret_tout == 0)) {
           alarm_cancel(p_ccb->idle_ccb_timer);
           alarm_cancel(p_ccb->ret_ccb_timer);
-          period_ms_t interval_ms = avdtp_cb.rcb.sig_tout * 1000;
+          uint64_t interval_ms = avdtp_cb.rcb.sig_tout * 1000;
           alarm_set_on_mloop(p_ccb->rsp_ccb_timer, interval_ms,
                              avdt_ccb_rsp_ccb_timer_timeout, p_ccb);
         } else if (sig != AVDT_SIG_DELAY_RPT) {
           alarm_cancel(p_ccb->idle_ccb_timer);
           alarm_cancel(p_ccb->rsp_ccb_timer);
-          period_ms_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
+          uint64_t interval_ms = avdtp_cb.rcb.ret_tout * 1000;
           alarm_set_on_mloop(p_ccb->ret_ccb_timer, interval_ms,
                              avdt_ccb_ret_ccb_timer_timeout, p_ccb);
         }
@@ -1191,6 +1199,14 @@
 
   /* parse the message header */
   p = (uint8_t*)(p_buf + 1) + p_buf->offset;
+
+  /* Check if is valid length */
+  if (p_buf->len < 1) {
+    android_errorWriteLog(0x534e4554, "78287084");
+    osi_free(p_buf);
+    p_ret = NULL;
+    return p_ret;
+  }
   AVDT_MSG_PRS_PKT_TYPE(p, pkt_type);
 
   /* quick sanity check on length */
@@ -1499,8 +1515,8 @@
   uint8_t pkt_type;
   uint8_t msg_type;
   uint8_t sig = 0;
-  tAVDT_MSG msg;
-  AvdtpSepConfig cfg;
+  tAVDT_MSG msg{};
+  AvdtpSepConfig cfg{};
   uint8_t err;
   uint8_t evt = 0;
   uint8_t scb_hdl;
diff --git a/stack/avdt/avdt_scb.cc b/stack/avdt/avdt_scb.cc
index eacdf83..c1c0de4 100644
--- a/stack/avdt/avdt_scb.cc
+++ b/stack/avdt/avdt_scb.cc
@@ -894,7 +894,7 @@
   }
 
   uint8_t index = hdl - 1;
-  size_t i = index / AVDT_NUM_LINKS;
+  size_t i = index / AVDT_NUM_SEPS;
   size_t j = index % AVDT_NUM_SEPS;
 
   AvdtpScb* p_scb = &avdtp_cb.ccb[i].scb[j];
diff --git a/stack/avrc/avrc_pars_ct.cc b/stack/avrc/avrc_pars_ct.cc
index 2b77618..80dc882 100644
--- a/stack/avrc/avrc_pars_ct.cc
+++ b/stack/avrc/avrc_pars_ct.cc
@@ -184,6 +184,16 @@
       break;
 
     case AVRC_EVT_ADDR_PLAYER_CHANGE:
+      min_len += 4;
+      if (len < min_len) goto length_error;
+      BE_STREAM_TO_UINT16(p_rsp->param.addr_player.player_id, p_stream);
+      BE_STREAM_TO_UINT16(p_rsp->param.addr_player.uid_counter, p_stream);
+      break;
+
+    case AVRC_EVT_PLAY_POS_CHANGED:
+      min_len += 4;
+      if (len < min_len) goto length_error;
+      BE_STREAM_TO_UINT32(p_rsp->param.play_pos, p_stream);
       break;
 
     case AVRC_EVT_UIDS_CHANGE:
@@ -191,7 +201,6 @@
 
     case AVRC_EVT_TRACK_REACHED_END:
     case AVRC_EVT_TRACK_REACHED_START:
-    case AVRC_EVT_PLAY_POS_CHANGED:
     case AVRC_EVT_BATTERY_STATUS_CHANGE:
     case AVRC_EVT_SYSTEM_STATUS_CHANGE:
     default:
@@ -442,7 +451,7 @@
           set_br_pl_rsp->charset_id, set_br_pl_rsp->folder_depth);
 
       set_br_pl_rsp->p_folders = (tAVRC_NAME*)osi_malloc(
-          set_br_pl_rsp->num_items * sizeof(tAVRC_NAME));
+          set_br_pl_rsp->folder_depth * sizeof(tAVRC_NAME));
 
       /* Read each of the folder in the depth */
       for (uint32_t i = 0; i < set_br_pl_rsp->folder_depth; i++) {
diff --git a/stack/avrc/avrc_pars_tg.cc b/stack/avrc/avrc_pars_tg.cc
index c0504ee..22471bd 100644
--- a/stack/avrc/avrc_pars_tg.cc
+++ b/stack/avrc/avrc_pars_tg.cc
@@ -135,15 +135,16 @@
       if (!AVRC_IS_VALID_CAP_ID(p_result->get_caps.capability_id))
         status = AVRC_STS_BAD_PARAM;
       else if (len != 1)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       break;
 
     case AVRC_PDU_LIST_PLAYER_APP_ATTR: /* 0x11 */
       /* no additional parameters */
-      if (len != 0) status = AVRC_STS_INTERNAL_ERR;
+      if (len != 0) return AVRC_STS_INTERNAL_ERR;
       break;
 
     case AVRC_PDU_LIST_PLAYER_APP_VALUES: /* 0x12 */
+      if (len == 0) return AVRC_STS_INTERNAL_ERR;
       p_result->list_app_values.attr_id = *p++;
       if (!AVRC_IS_VALID_ATTRIBUTE(p_result->list_app_values.attr_id))
         status = AVRC_STS_BAD_PARAM;
@@ -153,6 +154,7 @@
 
     case AVRC_PDU_GET_CUR_PLAYER_APP_VALUE: /* 0x13 */
     case AVRC_PDU_GET_PLAYER_APP_ATTR_TEXT: /* 0x15 */
+      if (len == 0) return AVRC_STS_INTERNAL_ERR;
       BE_STREAM_TO_UINT8(p_result->get_cur_app_val.num_attr, p);
       if (len != (p_result->get_cur_app_val.num_attr + 1)) {
         status = AVRC_STS_INTERNAL_ERR;
@@ -177,6 +179,7 @@
       break;
 
     case AVRC_PDU_SET_PLAYER_APP_VALUE: /* 0x14 */
+      if (len == 0) return AVRC_STS_INTERNAL_ERR;
       BE_STREAM_TO_UINT8(p_result->set_app_val.num_val, p);
       size_needed = sizeof(tAVRC_APP_SETTING);
       if (p_buf && (len == ((p_result->set_app_val.num_val << 1) + 1))) {
@@ -208,7 +211,7 @@
 
     case AVRC_PDU_GET_PLAYER_APP_VALUE_TEXT: /* 0x16 */
       if (len < 3)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT8(p_result->get_app_val_txt.attr_id, p);
         if (!AVRC_IS_VALID_ATTRIBUTE(p_result->get_app_val_txt.attr_id))
@@ -240,7 +243,7 @@
 
     case AVRC_PDU_INFORM_DISPLAY_CHARSET: /* 0x17 */
       if (len < 3)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT8(p_result->inform_charset.num_id, p);
         if ((len - 1 /* num_id */) != p_result->inform_charset.num_id * 2)
@@ -258,7 +261,7 @@
 
     case AVRC_PDU_INFORM_BATTERY_STAT_OF_CT: /* 0x18 */
       if (len != 1)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         p_result->inform_battery_status.battery_status = *p++;
         if (!AVRC_IS_VALID_BATTERY_STATUS(
@@ -269,7 +272,7 @@
 
     case AVRC_PDU_GET_ELEMENT_ATTR: /* 0x20 */
       if (len < 9)                  /* UID/8 and num_attr/1 */
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT32(u32, p);
         BE_STREAM_TO_UINT32(u32_2, p);
@@ -293,12 +296,12 @@
 
     case AVRC_PDU_GET_PLAY_STATUS: /* 0x30 */
       /* no additional parameters */
-      if (len != 0) status = AVRC_STS_INTERNAL_ERR;
+      if (len != 0) return AVRC_STS_INTERNAL_ERR;
       break;
 
     case AVRC_PDU_REGISTER_NOTIFICATION: /* 0x31 */
       if (len != 5)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else {
         BE_STREAM_TO_UINT8(p_result->reg_notif.event_id, p);
         BE_STREAM_TO_UINT32(p_result->reg_notif.param, p);
@@ -307,21 +310,21 @@
 
     case AVRC_PDU_SET_ABSOLUTE_VOLUME: /* 0x50 */
       if (len != 1)
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       else
         p_result->volume.volume = *p++;
       break;
 
     case AVRC_PDU_REQUEST_CONTINUATION_RSP: /* 0x40 */
       if (len != 1) {
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       }
       BE_STREAM_TO_UINT8(p_result->continu.target_pdu, p);
       break;
 
     case AVRC_PDU_ABORT_CONTINUATION_RSP: /* 0x41 */
       if (len != 1) {
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       }
       BE_STREAM_TO_UINT8(p_result->abort.target_pdu, p);
       break;
@@ -330,14 +333,14 @@
       if (len != 2) {
         AVRC_TRACE_ERROR("AVRC_PDU_SET_ADDRESSED_PLAYER length is incorrect:%d",
                          len);
-        status = AVRC_STS_INTERNAL_ERR;
+        return AVRC_STS_INTERNAL_ERR;
       }
       BE_STREAM_TO_UINT16(p_result->addr_player.player_id, p);
       break;
 
     case AVRC_PDU_PLAY_ITEM:          /* 0x74 */
     case AVRC_PDU_ADD_TO_NOW_PLAYING: /* 0x90 */
-      if (len != (AVRC_UID_SIZE + 3)) status = AVRC_STS_INTERNAL_ERR;
+      if (len != (AVRC_UID_SIZE + 3)) return AVRC_STS_INTERNAL_ERR;
       BE_STREAM_TO_UINT8(p_result->play_item.scope, p);
       if (p_result->play_item.scope > AVRC_SCOPE_NOW_PLAYING) {
         status = AVRC_STS_BAD_SCOPE;
diff --git a/stack/bnep/bnep_api.cc b/stack/bnep/bnep_api.cc
index 0e7b692..809d0b2 100644
--- a/stack/bnep/bnep_api.cc
+++ b/stack/bnep/bnep_api.cc
@@ -340,7 +340,7 @@
   p_bcb = &(bnep_cb.bcb[handle - 1]);
   /* Check MTU size */
   if (p_buf->len > BNEP_MTU_SIZE) {
-    BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", p_buf->len,
+    BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, p_buf->len,
                      BNEP_MTU_SIZE);
     osi_free(p_buf);
     return (BNEP_MTU_EXCEDED);
@@ -349,7 +349,7 @@
   /* Check if the packet should be filtered out */
   p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
   if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
-                             p_data) != BNEP_SUCCESS) {
+                             p_data, p_buf->len) != BNEP_SUCCESS) {
     /*
     ** If packet is filtered and ext headers are present
     ** drop the data and forward the ext headers
@@ -361,6 +361,11 @@
       org_len = p_buf->len;
       new_len = 0;
       do {
+        if ((new_len + 2) > org_len) {
+          osi_free(p_buf);
+          return BNEP_IGNORE_CMD;
+        }
+
         ext = *p_data++;
         length = *p_data++;
         p_data += length;
@@ -437,7 +442,7 @@
 
   /* Check MTU size. Consider the possibility of having extension headers */
   if (len > BNEP_MTU_SIZE) {
-    BNEP_TRACE_ERROR("BNEP_Write() length %d exceeded MTU %d", len,
+    BNEP_TRACE_ERROR("%s length %d exceeded MTU %d", __func__, len,
                      BNEP_MTU_SIZE);
     return (BNEP_MTU_EXCEDED);
   }
@@ -448,7 +453,7 @@
 
   /* Check if the packet should be filtered out */
   if (bnep_is_packet_allowed(p_bcb, p_dest_addr, protocol, fw_ext_present,
-                             p_data) != BNEP_SUCCESS) {
+                             p_data, len) != BNEP_SUCCESS) {
     /*
     ** If packet is filtered and ext headers are present
     ** drop the data and forward the ext headers
@@ -461,6 +466,10 @@
       new_len = 0;
       p = p_data;
       do {
+        if ((new_len + 2) > org_len) {
+          return BNEP_IGNORE_CMD;
+        }
+
         ext = *p_data++;
         length = *p_data++;
         p_data += length;
diff --git a/stack/bnep/bnep_int.h b/stack/bnep/bnep_int.h
index 2587147..5bba15d 100644
--- a/stack/bnep/bnep_int.h
+++ b/stack/bnep/bnep_int.h
@@ -229,7 +229,7 @@
 extern tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
                                            const RawAddress& p_dest_addr,
                                            uint16_t protocol,
-                                           bool fw_ext_present,
-                                           uint8_t* p_data);
+                                           bool fw_ext_present, uint8_t* p_data,
+                                           uint16_t org_len);
 
 #endif
diff --git a/stack/bnep/bnep_main.cc b/stack/bnep/bnep_main.cc
index ae6c51b..265ec79 100644
--- a/stack/bnep/bnep_main.cc
+++ b/stack/bnep/bnep_main.cc
@@ -94,7 +94,8 @@
   bnep_cb.reg_info.pL2CA_CongestionStatus_Cb = bnep_congestion_ind;
 
   /* Now, register with L2CAP */
-  if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info)) {
+  if (!L2CA_Register(BT_PSM_BNEP, &bnep_cb.reg_info,
+                     false /* enable_snoop */)) {
     BNEP_TRACE_ERROR("BNEP - Registration failed");
     return BNEP_SECURITY_FAIL;
   }
diff --git a/stack/bnep/bnep_utils.cc b/stack/bnep/bnep_utils.cc
index 48fd5d1..ac74ce0 100644
--- a/stack/bnep/bnep_utils.cc
+++ b/stack/bnep/bnep_utils.cc
@@ -22,10 +22,10 @@
  *
  ******************************************************************************/
 
-#include <cutils/log.h>
-
+#include <log/log.h>
 #include <stdio.h>
 #include <string.h>
+
 #include "bnep_int.h"
 #include "bt_common.h"
 #include "bt_types.h"
@@ -1259,23 +1259,33 @@
 tBNEP_RESULT bnep_is_packet_allowed(tBNEP_CONN* p_bcb,
                                     const RawAddress& p_dest_addr,
                                     uint16_t protocol, bool fw_ext_present,
-                                    uint8_t* p_data) {
+                                    uint8_t* p_data, uint16_t org_len) {
   if (p_bcb->rcvd_num_filters) {
     uint16_t i, proto;
 
     /* Findout the actual protocol to check for the filtering */
     proto = protocol;
     if (proto == BNEP_802_1_P_PROTOCOL) {
+      uint16_t new_len = 0;
       if (fw_ext_present) {
         uint8_t len, ext;
         /* parse the extension headers and findout actual protocol */
         do {
+          if ((new_len + 2) > org_len) {
+            return BNEP_IGNORE_CMD;
+          }
+
           ext = *p_data++;
           len = *p_data++;
           p_data += len;
 
+          new_len += (len + 2);
+
         } while (ext & 0x80);
       }
+      if ((new_len + 4) > org_len) {
+        return BNEP_IGNORE_CMD;
+      }
       p_data += 2;
       BE_STREAM_TO_UINT16(proto, p_data);
     }
diff --git a/stack/btm/ble_advertiser_hci_interface.cc b/stack/btm/ble_advertiser_hci_interface.cc
index 574ef71..dddf8d4 100644
--- a/stack/btm/ble_advertiser_hci_interface.cc
+++ b/stack/btm/ble_advertiser_hci_interface.cc
@@ -17,11 +17,6 @@
  ******************************************************************************/
 
 #include "ble_advertiser_hci_interface.h"
-#include <base/callback.h>
-#include <base/location.h>
-#include <base/logging.h>
-#include <queue>
-#include <utility>
 #include "btm_api.h"
 #include "btm_ble_api.h"
 #include "btm_int_types.h"
@@ -29,6 +24,14 @@
 #include "hcidefs.h"
 #include "log/log.h"
 
+#include <queue>
+#include <utility>
+
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/location.h>
+#include <base/logging.h>
+
 #define BTM_BLE_MULTI_ADV_SET_RANDOM_ADDR_LEN 8
 #define BTM_BLE_MULTI_ADV_ENB_LEN 3
 #define BTM_BLE_MULTI_ADV_SET_PARAM_LEN 24
@@ -43,11 +46,11 @@
 
 using status_cb = BleAdvertiserHciInterface::status_cb;
 
-using hci_cmd_cb = base::Callback<void(uint8_t* /* return_parameters */,
-                                       uint16_t /* return_parameters_length*/)>;
-extern void btu_hcif_send_cmd_with_cb(
-    const tracked_objects::Location& posted_from, uint16_t opcode,
-    uint8_t* params, uint8_t params_len, hci_cmd_cb cb);
+using hci_cmd_cb = base::OnceCallback<void(
+    uint8_t* /* return_parameters */, uint16_t /* return_parameters_length*/)>;
+extern void btu_hcif_send_cmd_with_cb(const base::Location& posted_from,
+                                      uint16_t opcode, uint8_t* params,
+                                      uint8_t params_len, hci_cmd_cb cb);
 
 namespace {
 BleAdvertiserHciInterface* instance = nullptr;
@@ -92,9 +95,8 @@
 }
 
 class BleAdvertiserVscHciInterfaceImpl : public BleAdvertiserHciInterface {
-  void SendAdvCmd(const tracked_objects::Location& posted_from,
-                  uint8_t param_len, uint8_t* param_buf,
-                  status_cb command_complete) {
+  void SendAdvCmd(const base::Location& posted_from, uint8_t param_len,
+                  uint8_t* param_buf, status_cb command_complete) {
     btu_hcif_send_cmd_with_cb(posted_from, HCI_BLE_MULTI_ADV_OCF, param_buf,
                               param_len,
                               base::Bind(&btm_ble_multi_adv_vsc_cmpl_cback,
@@ -321,7 +323,7 @@
 }
 
 class BleAdvertiserLegacyHciInterfaceImpl : public BleAdvertiserHciInterface {
-  void SendAdvCmd(const tracked_objects::Location& posted_from, uint16_t opcode,
+  void SendAdvCmd(const base::Location& posted_from, uint16_t opcode,
                   uint8_t* param_buf, uint8_t param_buf_len,
                   status_cb command_complete) {
     btu_hcif_send_cmd_with_cb(
@@ -510,7 +512,7 @@
 };
 
 class BleAdvertiserHciExtendedImpl : public BleAdvertiserHciInterface {
-  void SendAdvCmd(const tracked_objects::Location& posted_from, uint16_t opcode,
+  void SendAdvCmd(const base::Location& posted_from, uint16_t opcode,
                   uint8_t* param_buf, uint8_t param_buf_len,
                   status_cb command_complete) {
     btu_hcif_send_cmd_with_cb(
diff --git a/stack/btm/ble_advertiser_hci_interface.h b/stack/btm/ble_advertiser_hci_interface.h
index c08bb86..24e501d 100644
--- a/stack/btm/ble_advertiser_hci_interface.h
+++ b/stack/btm/ble_advertiser_hci_interface.h
@@ -19,10 +19,11 @@
 #ifndef BLE_ADVERTISER_HCI_INTERFACE_H
 #define BLE_ADVERTISER_HCI_INTERFACE_H
 
-#include <base/bind.h>
 #include <vector>
 #include "stack/include/bt_types.h"
 
+#include <base/callback.h>
+
 /* This class is an abstraction of HCI commands used for managing
  * advertisements. Please see VSC HCI SPEC at
  * https://static.googleusercontent.com/media/source.android.com/en//devices/Android-6.0-Bluetooth-HCI-Reqs.pdf
diff --git a/stack/btm/btm_acl.cc b/stack/btm/btm_acl.cc
index ee2530a..dcb2fb4 100644
--- a/stack/btm/btm_acl.cc
+++ b/stack/btm/btm_acl.cc
@@ -45,6 +45,7 @@
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/metrics.h"
 #include "device/include/controller.h"
 #include "device/include/interop.h"
 #include "hcidefs.h"
@@ -163,8 +164,8 @@
       break;
 
     case BTM_BLE_ADDR_STATIC:
-      conn_addr = p_dev_rec->ble.static_addr;
-      *p_addr_type = p_dev_rec->ble.static_addr_type;
+      conn_addr = p_dev_rec->ble.identity_addr;
+      *p_addr_type = p_dev_rec->ble.identity_addr_type;
       break;
 
     default:
@@ -537,9 +538,7 @@
                            tBTM_CMPL_CB* p_cb) {
   tACL_CONN* p;
   tBTM_SEC_DEV_REC* p_dev_rec = NULL;
-#if (BTM_SCO_INCLUDED == TRUE)
   bool is_sco_active;
-#endif
   tBTM_STATUS status;
   tBTM_PM_MODE pwr_mode;
   tBTM_PM_PWR_MD settings;
@@ -567,12 +566,10 @@
   if (interop_match_addr(INTEROP_DISABLE_ROLE_SWITCH, &remote_bd_addr))
     return BTM_DEV_BLACKLISTED;
 
-#if (BTM_SCO_INCLUDED == TRUE)
   /* Check if there is any SCO Active on this BD Address */
   is_sco_active = btm_is_sco_active_by_bdaddr(remote_bd_addr);
 
   if (is_sco_active) return (BTM_NO_RESOURCES);
-#endif
 
   /* Ignore role switch request if the previous request was not completed */
   if (p->switch_role_state != BTM_ACL_SWKEY_STATE_IDLE) {
@@ -892,6 +889,11 @@
         if (p_acl_cb->transport == BT_TRANSPORT_BR_EDR) {
           btm_read_remote_features(p_acl_cb->hci_handle);
         }
+        bluetooth::common::LogRemoteVersionInfo(
+            handle, status, p_acl_cb->lmp_version, p_acl_cb->manufacturer,
+            p_acl_cb->lmp_subversion);
+      } else {
+        bluetooth::common::LogRemoteVersionInfo(handle, status, 0, 0, 0);
       }
 
       if (p_acl_cb->transport == BT_TRANSPORT_LE) {
diff --git a/stack/btm/btm_ble.cc b/stack/btm/btm_ble.cc
index 0c4bdd9..3f67876 100644
--- a/stack/btm/btm_ble.cc
+++ b/stack/btm/btm_ble.cc
@@ -43,15 +43,10 @@
 #include "l2c_int.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "smp_api.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
 
-extern bool aes_cipher_msg_auth_code(BT_OCTET16 key, uint8_t* input,
-                                     uint16_t length, uint16_t tlen,
-                                     uint8_t* p_signature);
 extern void gatt_notify_phy_updated(uint8_t status, uint16_t handle,
                                     uint8_t tx_phy, uint8_t rx_phy);
-extern void btm_ble_advertiser_notify_terminated_legacy(
-    uint8_t status, uint16_t connection_handle);
 
 /******************************************************************************/
 /* External Function to be called by other modules                            */
@@ -185,8 +180,7 @@
         break;
 
       case BTM_BLE_KEY_TYPE_ER:
-        memcpy(p_devcb->ble_encryption_key_value, p_key->er,
-               sizeof(BT_OCTET16));
+        p_devcb->ble_encryption_key_value = p_key->er;
         break;
 
       default:
@@ -196,54 +190,16 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         BTM_GetDeviceEncRoot
- *
- * Description      This function is called to read the local device encryption
- *                  root.
- *
- * Returns          void
- *                  the local device ER is copied into ble_encr_key_value
- *
- ******************************************************************************/
-void BTM_GetDeviceEncRoot(BT_OCTET16 ble_encr_key_value) {
-  BTM_TRACE_DEBUG("%s", __func__);
-  memcpy(ble_encr_key_value, btm_cb.devcb.ble_encryption_key_value,
-         BT_OCTET16_LEN);
+/** Returns local device encryption root (ER) */
+const Octet16& BTM_GetDeviceEncRoot() {
+  return btm_cb.devcb.ble_encryption_key_value;
 }
 
-/*******************************************************************************
- *
- * Function         BTM_GetDeviceIDRoot
- *
- * Description      This function is called to read the local device identity
- *                  root.
- *
- * Returns          void
- *                  the local device IR is copied into irk
- *
- ******************************************************************************/
-void BTM_GetDeviceIDRoot(BT_OCTET16 irk) {
-  BTM_TRACE_DEBUG("BTM_GetDeviceIDRoot ");
+/** Returns local device identity root (IR). */
+const Octet16& BTM_GetDeviceIDRoot() { return btm_cb.devcb.id_keys.irk; }
 
-  memcpy(irk, btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN);
-}
-
-/*******************************************************************************
- *
- * Function         BTM_GetDeviceDHK
- *
- * Description      This function is called to read the local device DHK.
- *
- * Returns          void
- *                  the local device DHK is copied into dhk
- *
- ******************************************************************************/
-void BTM_GetDeviceDHK(BT_OCTET16 dhk) {
-  BTM_TRACE_DEBUG("BTM_GetDeviceDHK");
-  memcpy(dhk, btm_cb.devcb.id_keys.dhk, BT_OCTET16_LEN);
-}
+/** Return local device DHK. */
+const Octet16& BTM_GetDeviceDHK() { return btm_cb.devcb.id_keys.dhk; }
 
 /*******************************************************************************
  *
@@ -476,8 +432,8 @@
   memset(&oob, 0, sizeof(tSMP_SC_OOB_DATA));
 
   oob.peer_oob_data.present = true;
-  memcpy(&oob.peer_oob_data.randomizer, p_r, BT_OCTET16_LEN);
-  memcpy(&oob.peer_oob_data.commitment, p_c, BT_OCTET16_LEN);
+  memcpy(&oob.peer_oob_data.randomizer, p_r, OCTET16_LEN);
+  memcpy(&oob.peer_oob_data.commitment, p_c, OCTET16_LEN);
   oob.peer_oob_data.addr_rcvd_from.type = p_dev_rec->ble.ble_addr_type;
   oob.peer_oob_data.addr_rcvd_from.bda = bd_addr;
 
@@ -514,7 +470,7 @@
       new_param = true;
     }
 
-    if (new_param && p_ble_cb->conn_state == BLE_BG_CONN) {
+    if (new_param && btm_ble_get_conn_st() == BLE_CONNECTING) {
       btm_ble_suspend_bg_conn();
     }
   } else {
@@ -796,6 +752,7 @@
 tBTM_STATUS BTM_SetBleDataLength(const RawAddress& bd_addr,
                                  uint16_t tx_pdu_length) {
   tACL_CONN* p_acl = btm_bda_to_acl(bd_addr, BT_TRANSPORT_LE);
+  uint16_t tx_time = BTM_BLE_DATA_TX_TIME_MAX_LEGACY;
 
   if (p_acl == NULL) {
     BTM_TRACE_ERROR("%s: Wrong mode: no LE link exist or LE not supported",
@@ -820,9 +777,10 @@
   else if (tx_pdu_length < BTM_BLE_DATA_SIZE_MIN)
     tx_pdu_length = BTM_BLE_DATA_SIZE_MIN;
 
-  /* 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);
+  if (controller_get_interface()->get_bt_version()->hci_version >= HCI_PROTO_VERSION_5_0)
+    tx_time = BTM_BLE_DATA_TX_TIME_MAX;
+
+  btsnd_hcic_ble_set_data_length(p_acl->hci_handle, tx_pdu_length, tx_time);
 
   return BTM_SUCCESS;
 }
@@ -1086,13 +1044,13 @@
  *                  p_callback : Pointer to the callback function.
  *                  p_ref_data : Pointer to be returned along with the callback.
  *
- * Returns          true if link already meets the required security; otherwise
- *                  false.
+ * Returns          Returns  - L2CAP LE Connection Response Result Code.
  *
  ******************************************************************************/
-bool btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm,
-                             bool is_originator, tBTM_SEC_CALLBACK* p_callback,
-                             void* p_ref_data) {
+tL2CAP_LE_RESULT_CODE btm_ble_start_sec_check(const RawAddress& bd_addr,
+                                              uint16_t psm, bool is_originator,
+                                              tBTM_SEC_CALLBACK* p_callback,
+                                              void* p_ref_data) {
   /* Find the service record for the PSM */
   tBTM_SEC_SERV_REC* p_serv_rec = btm_sec_find_first_serv(is_originator, psm);
 
@@ -1101,20 +1059,45 @@
   if (!p_serv_rec) {
     BTM_TRACE_WARNING("%s PSM: %d no application registerd", __func__, psm);
     (*p_callback)(&bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_MODE_UNSUPPORTED);
-    return false;
+    return L2CAP_LE_RESULT_NO_PSM;
+  }
+  uint8_t sec_flag = 0;
+  BTM_GetSecurityFlagsByTransport(bd_addr, &sec_flag, BT_TRANSPORT_LE);
+
+  if (!is_originator) {
+    if ((p_serv_rec->security_flags & BTM_SEC_IN_ENCRYPT) &&
+        !(sec_flag & BTM_SEC_ENCRYPTED)) {
+      BTM_TRACE_ERROR(
+          "%s: L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP. service "
+          "security_flags=0x%x, "
+          "sec_flag=0x%x",
+          __func__, p_serv_rec->security_flags, sec_flag);
+      return L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP;
+    } else if ((p_serv_rec->security_flags & BTM_SEC_IN_AUTHENTICATE) &&
+               !(sec_flag &
+                 (BTM_SEC_LINK_KEY_AUTHED | BTM_SEC_AUTHENTICATED))) {
+      BTM_TRACE_ERROR(
+          "%s: L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION. service "
+          "security_flags=0x%x, "
+          "sec_flag=0x%x",
+          __func__, p_serv_rec->security_flags, sec_flag);
+      return L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION;
+    }
+    /* TODO: When security is required, then must check that the key size of our
+       service is equal or smaller than the incoming connection key size. */
   }
 
   tBTM_SEC_ACTION sec_act = btm_ble_determine_security_act(
       is_originator, bd_addr, p_serv_rec->security_flags);
 
   tBTM_BLE_SEC_ACT ble_sec_act = BTM_BLE_SEC_NONE;
-  bool status = false;
+  tL2CAP_LE_RESULT_CODE result = L2CAP_LE_RESULT_CONN_OK;
 
   switch (sec_act) {
     case BTM_SEC_OK:
       BTM_TRACE_DEBUG("%s Security met", __func__);
       p_callback(&bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_SUCCESS);
-      status = true;
+      result = L2CAP_LE_RESULT_CONN_OK;
       break;
 
     case BTM_SEC_ENCRYPT:
@@ -1137,14 +1120,14 @@
       break;
   }
 
-  if (ble_sec_act == BTM_BLE_SEC_NONE) return status;
+  if (ble_sec_act == BTM_BLE_SEC_NONE) return result;
 
   tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
   p_lcb->sec_act = sec_act;
   BTM_SetEncryption(bd_addr, BT_TRANSPORT_LE, p_callback, p_ref_data,
                     ble_sec_act);
 
-  return false;
+  return L2CAP_LE_RESULT_CONN_OK;
 }
 
 /*******************************************************************************
@@ -1178,7 +1161,7 @@
       if (op_code == HCI_BLE_RAND)
         params.param_len = BT_OCTET8_LEN;
       else
-        params.param_len = BT_OCTET16_LEN;
+        params.param_len = OCTET16_LEN;
 
       /* Fetch return info from HCI event message */
       memcpy(p_dest, p, params.param_len);
@@ -1279,7 +1262,6 @@
                          tBTM_LE_KEY_VALUE* p_keys, bool pass_to_application) {
   tBTM_SEC_DEV_REC* p_rec;
   tBTM_LE_EVT_DATA cb_data;
-  uint8_t i;
 
   BTM_TRACE_DEBUG("btm_sec_save_le_key key_type=0x%x pass_to_application=%d",
                   key_type, pass_to_application);
@@ -1293,7 +1275,7 @@
 
     switch (key_type) {
       case BTM_LE_KEY_PENC:
-        memcpy(p_rec->ble.keys.pltk, p_keys->penc_key.ltk, BT_OCTET16_LEN);
+        p_rec->ble.keys.pltk = p_keys->penc_key.ltk;
         memcpy(p_rec->ble.keys.rand, p_keys->penc_key.rand, BT_OCTET8_LEN);
         p_rec->ble.keys.sec_level = p_keys->penc_key.sec_level;
         p_rec->ble.keys.ediv = p_keys->penc_key.ediv;
@@ -1310,28 +1292,24 @@
         break;
 
       case BTM_LE_KEY_PID:
-        for (i = 0; i < BT_OCTET16_LEN; i++) {
-          p_rec->ble.keys.irk[i] = p_keys->pid_key.irk[i];
-        }
-
-        // memcpy( p_rec->ble.keys.irk, p_keys->pid_key, BT_OCTET16_LEN); todo
-        // will crash the system
-        p_rec->ble.static_addr = p_keys->pid_key.static_addr;
-        p_rec->ble.static_addr_type = p_keys->pid_key.addr_type;
+        p_rec->ble.keys.irk = p_keys->pid_key.irk;
+        p_rec->ble.identity_addr = p_keys->pid_key.identity_addr;
+        p_rec->ble.identity_addr_type = p_keys->pid_key.identity_addr_type;
         p_rec->ble.key_type |= BTM_LE_KEY_PID;
         BTM_TRACE_DEBUG(
             "%s: BTM_LE_KEY_PID key_type=0x%x save peer IRK, change bd_addr=%s "
-            "to static_addr=%s",
+            "to id_addr=%s id_addr_type=0x%x",
             __func__, p_rec->ble.key_type, p_rec->bd_addr.ToString().c_str(),
-            p_keys->pid_key.static_addr.ToString().c_str());
-        /* update device record address as static address */
-        p_rec->bd_addr = p_keys->pid_key.static_addr;
+            p_keys->pid_key.identity_addr.ToString().c_str(),
+            p_keys->pid_key.identity_addr_type);
+        /* update device record address as identity address */
+        p_rec->bd_addr = p_keys->pid_key.identity_addr;
         /* combine DUMO device security record if needed */
         btm_consolidate_dev(p_rec);
         break;
 
       case BTM_LE_KEY_PCSRK:
-        memcpy(p_rec->ble.keys.pcsrk, p_keys->pcsrk_key.csrk, BT_OCTET16_LEN);
+        p_rec->ble.keys.pcsrk = p_keys->pcsrk_key.csrk;
         p_rec->ble.keys.srk_sec_level = p_keys->pcsrk_key.sec_level;
         p_rec->ble.keys.counter = p_keys->pcsrk_key.counter;
         p_rec->ble.key_type |= BTM_LE_KEY_PCSRK;
@@ -1349,7 +1327,7 @@
         break;
 
       case BTM_LE_KEY_LENC:
-        memcpy(p_rec->ble.keys.lltk, p_keys->lenc_key.ltk, BT_OCTET16_LEN);
+        p_rec->ble.keys.lltk = p_keys->lenc_key.ltk;
         p_rec->ble.keys.div = p_keys->lenc_key.div; /* update DIV */
         p_rec->ble.keys.sec_level = p_keys->lenc_key.sec_level;
         p_rec->ble.keys.key_size = p_keys->lenc_key.key_size;
@@ -1363,7 +1341,7 @@
         break;
 
       case BTM_LE_KEY_LCSRK: /* local CSRK has been delivered */
-        memcpy(p_rec->ble.keys.lcsrk, p_keys->lcsrk_key.csrk, BT_OCTET16_LEN);
+        p_rec->ble.keys.lcsrk = p_keys->lcsrk_key.csrk;
         p_rec->ble.keys.div = p_keys->lcsrk_key.div; /* update DIV */
         p_rec->ble.keys.local_csrk_sec_level = p_keys->lcsrk_key.sec_level;
         p_rec->ble.keys.local_counter = p_keys->lcsrk_key.counter;
@@ -1556,6 +1534,7 @@
       }
     /* if salve role then fall through to call SMP_Pair below which will send a
        sec_request to request the master to encrypt the link */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case BTM_BLE_SEC_ENCRYPT_NO_MITM:
     case BTM_BLE_SEC_ENCRYPT_MITM:
       auth_req = (sec_act == BTM_BLE_SEC_ENCRYPT_NO_MITM)
@@ -1602,7 +1581,6 @@
 void btm_ble_ltk_request(uint16_t handle, uint8_t rand[8], uint16_t ediv) {
   tBTM_CB* p_cb = &btm_cb;
   tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle);
-  BT_OCTET8 dummy_stk = {0};
 
   BTM_TRACE_DEBUG("btm_ble_ltk_request");
 
@@ -1611,23 +1589,17 @@
   memcpy(p_cb->enc_rand, rand, BT_OCTET8_LEN);
 
   if (p_dev_rec != NULL) {
-    if (!smp_proc_ltk_request(p_dev_rec->bd_addr))
-      btm_ble_ltk_request_reply(p_dev_rec->bd_addr, false, dummy_stk);
+    if (!smp_proc_ltk_request(p_dev_rec->bd_addr)) {
+      btm_ble_ltk_request_reply(p_dev_rec->bd_addr, false, Octet16{0});
+    }
   }
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_start_encrypt
- *
- * Description      This function is called to start LE encryption.
- *
- *
- * Returns          BTM_SUCCESS if encryption was started successfully
- *
- ******************************************************************************/
+/** This function is called to start LE encryption.
+ * Returns BTM_SUCCESS if encryption was started successfully
+ */
 tBTM_STATUS btm_ble_start_encrypt(const RawAddress& bda, bool use_stk,
-                                  BT_OCTET16 stk) {
+                                  Octet16* p_stk) {
   tBTM_CB* p_cb = &btm_cb;
   tBTM_SEC_DEV_REC* p_rec = btm_find_dev(bda);
   BT_OCTET8 dummy_rand = {0};
@@ -1647,7 +1619,7 @@
   p_cb->enc_handle = p_rec->ble_hci_handle;
 
   if (use_stk) {
-    btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, dummy_rand, 0, stk);
+    btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, dummy_rand, 0, *p_stk);
   } else if (p_rec->ble.key_type & BTM_LE_KEY_PENC) {
     btsnd_hcic_ble_start_enc(p_rec->ble_hci_handle, p_rec->ble.keys.rand,
                              p_rec->ble.keys.ediv, p_rec->ble.keys.pltk);
@@ -1717,7 +1689,7 @@
  *
  ******************************************************************************/
 void btm_ble_ltk_request_reply(const RawAddress& bda, bool use_stk,
-                               BT_OCTET16 stk) {
+                               const Octet16& stk) {
   tBTM_SEC_DEV_REC* p_rec = btm_find_dev(bda);
   tBTM_CB* p_cb = &btm_cb;
 
@@ -1914,126 +1886,6 @@
 }
 
 /*****************************************************************************
- *  Function        btm_ble_conn_complete
- *
- *  Description     LE connection complete.
- *
- *****************************************************************************/
-void btm_ble_conn_complete(uint8_t* p, UNUSED_ATTR uint16_t evt_len,
-                           bool enhanced) {
-#if (BLE_PRIVACY_SPT == TRUE)
-  uint8_t peer_addr_type;
-#endif
-  RawAddress local_rpa, peer_rpa;
-  uint8_t role, status, bda_type;
-  uint16_t handle;
-  RawAddress bda;
-  uint16_t conn_interval, conn_latency, conn_timeout;
-  bool match = false;
-
-  STREAM_TO_UINT8(status, p);
-  STREAM_TO_UINT16(handle, p);
-  STREAM_TO_UINT8(role, p);
-  STREAM_TO_UINT8(bda_type, p);
-  STREAM_TO_BDADDR(bda, p);
-
-  if (status == 0) {
-    if (enhanced) {
-      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);
-    handle = HCID_GET_HANDLE(handle);
-
-#if (BLE_PRIVACY_SPT == TRUE)
-    peer_addr_type = bda_type;
-    match = btm_identity_addr_to_random_pseudo(&bda, &bda_type, true);
-
-    /* possiblly receive connection complete with resolvable random while
-       the device has been paired */
-    if (!match && BTM_BLE_IS_RESOLVE_BDA(bda)) {
-      tBTM_SEC_DEV_REC* match_rec = btm_ble_resolve_random_addr(bda);
-      if (match_rec) {
-        LOG_INFO(LOG_TAG, "%s matched and resolved random address", __func__);
-        match = true;
-        match_rec->ble.active_addr_type = BTM_BLE_ADDR_RRA;
-        match_rec->ble.cur_rand_addr = bda;
-        if (!btm_ble_init_pseudo_addr(match_rec, bda)) {
-          /* assign the original address to be the current report address */
-          bda = match_rec->ble.pseudo_addr;
-        } else {
-          bda = match_rec->bd_addr;
-        }
-      } else {
-        LOG_INFO(LOG_TAG, "%s unable to match and resolve random address",
-                 __func__);
-      }
-    }
-#endif
-
-    btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type,
-                      match);
-
-    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
-  } else {
-    role = HCI_ROLE_UNKNOWN;
-    if (status != HCI_ERR_ADVERTISING_TIMEOUT) {
-      btm_ble_set_conn_st(BLE_CONN_IDLE);
-#if (BLE_PRIVACY_SPT == TRUE)
-      btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
-#endif
-    } else {
-#if (BLE_PRIVACY_SPT == TRUE)
-      btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
-      btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, true);
-#endif
-    }
-  }
-
-  btm_ble_update_mode_operation(role, &bda, status);
-
-  if (role == HCI_ROLE_SLAVE)
-    btm_ble_advertiser_notify_terminated_legacy(status, handle);
-}
-
-/*****************************************************************************
- * Function btm_ble_create_ll_conn_complete
- *
- * Description LE connection complete.
- *
- *****************************************************************************/
-void btm_ble_create_ll_conn_complete(uint8_t status) {
-  if (status == HCI_SUCCESS) return;
-
-  btm_ble_set_conn_st(BLE_CONN_IDLE);
-  btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
-
-  LOG(WARNING) << "LE Create Connection attempt failed, status="
-               << loghex(status);
-
-  if (status == HCI_ERR_COMMAND_DISALLOWED) {
-    /* There is already either direct connect, or whitelist connection
-     * pending, but we don't know which one, or to which state should we
-     * transition now. This can be triggered only in case of rare race
-     * condition. Crash to recover. */
-    LOG(FATAL) << "LE Create Connection - command disallowed";
-  }
-}
-/*****************************************************************************
  *  Function        btm_proc_smp_cback
  *
  *  Description     This function is the SMP callback handler.
@@ -2062,8 +1914,8 @@
       case SMP_OOB_REQ_EVT:
       case SMP_NC_REQ_EVT:
       case SMP_SC_OOB_REQ_EVT:
-        /* fall through */
         p_dev_rec->sec_flags |= BTM_SEC_LE_AUTHENTICATED;
+        FALLTHROUGH_INTENDED; /* FALLTHROUGH */
 
       case SMP_SEC_REQUEST_EVT:
         if (event == SMP_SEC_REQUEST_EVT &&
@@ -2074,7 +1926,7 @@
         btm_cb.pairing_bda = bd_addr;
         p_dev_rec->sec_state = BTM_SEC_STATE_AUTHENTICATING;
         btm_cb.pairing_flags |= BTM_PAIR_FLAGS_LE_ACTIVE;
-      /* fall through */
+        FALLTHROUGH_INTENDED; /* FALLTHROUGH */
 
       case SMP_COMPLT_EVT:
         if (btm_cb.api.p_le_callback) {
@@ -2184,45 +2036,42 @@
   tBTM_SEC_DEV_REC* p_rec = btm_find_dev(bd_addr);
 
   BTM_TRACE_DEBUG("%s", __func__);
-  bool ret = false;
   if (p_rec == NULL) {
     BTM_TRACE_ERROR("%s-data signing can not be done from unknown device",
                     __func__);
-  } else {
-    uint8_t* p_mac = (uint8_t*)signature;
-    uint8_t* pp;
-    uint8_t* p_buf = (uint8_t*)osi_malloc(len + 4);
-
-    BTM_TRACE_DEBUG("%s-Start to generate Local CSRK", __func__);
-    pp = p_buf;
-    /* prepare plain text */
-    if (p_text) {
-      memcpy(p_buf, p_text, len);
-      pp = (p_buf + len);
-    }
-
-    UINT32_TO_STREAM(pp, p_rec->ble.keys.local_counter);
-    UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
-
-    ret = aes_cipher_msg_auth_code(p_rec->ble.keys.lcsrk, p_buf,
-                                   (uint16_t)(len + 4), BTM_CMAC_TLEN_SIZE,
-                                   p_mac);
-    if (ret) {
-      btm_ble_increment_sign_ctr(bd_addr, true);
-    }
-
-    BTM_TRACE_DEBUG("%s p_mac = %d", __func__, p_mac);
-    BTM_TRACE_DEBUG(
-        "p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = "
-        "0x%02x",
-        *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
-    BTM_TRACE_DEBUG(
-        "p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = "
-        "0x%02x",
-        *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
-    osi_free(p_buf);
+    return false;
   }
-  return ret;
+
+  uint8_t* p_mac = (uint8_t*)signature;
+  uint8_t* pp;
+  uint8_t* p_buf = (uint8_t*)osi_malloc(len + 4);
+
+  BTM_TRACE_DEBUG("%s-Start to generate Local CSRK", __func__);
+  pp = p_buf;
+  /* prepare plain text */
+  if (p_text) {
+    memcpy(p_buf, p_text, len);
+    pp = (p_buf + len);
+  }
+
+  UINT32_TO_STREAM(pp, p_rec->ble.keys.local_counter);
+  UINT32_TO_STREAM(p_mac, p_rec->ble.keys.local_counter);
+
+  crypto_toolbox::aes_cmac(p_rec->ble.keys.lcsrk, p_buf, (uint16_t)(len + 4),
+                           BTM_CMAC_TLEN_SIZE, p_mac);
+  btm_ble_increment_sign_ctr(bd_addr, true);
+
+  BTM_TRACE_DEBUG("%s p_mac = %d", __func__, p_mac);
+  BTM_TRACE_DEBUG(
+      "p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = "
+      "0x%02x",
+      *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
+  BTM_TRACE_DEBUG(
+      "p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = "
+      "0x%02x",
+      *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
+  osi_free(p_buf);
+  return true;
 }
 
 /*******************************************************************************
@@ -2256,12 +2105,11 @@
     BTM_TRACE_DEBUG("%s rcv_cnt=%d >= expected_cnt=%d", __func__, counter,
                     p_rec->ble.keys.counter);
 
-    if (aes_cipher_msg_auth_code(p_rec->ble.keys.pcsrk, p_orig, len,
-                                 BTM_CMAC_TLEN_SIZE, p_mac)) {
-      if (memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0) {
-        btm_ble_increment_sign_ctr(bd_addr, false);
-        verified = true;
-      }
+    crypto_toolbox::aes_cmac(p_rec->ble.keys.pcsrk, p_orig, len,
+                             BTM_CMAC_TLEN_SIZE, p_mac);
+    if (memcmp(p_mac, p_comp, BTM_CMAC_TLEN_SIZE) == 0) {
+      btm_ble_increment_sign_ctr(bd_addr, false);
+      verified = true;
     }
   }
   return verified;
@@ -2395,16 +2243,7 @@
 /*******************************************************************************
  *  Utility functions for LE device IR/ER generation
  ******************************************************************************/
-/*******************************************************************************
- *
- * Function         btm_notify_new_key
- *
- * Description      This function is to notify application new keys have been
- *                  generated.
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is to notify application new keys have been generated. */
 static void btm_notify_new_key(uint8_t key_type) {
   tBTM_BLE_LOCAL_KEYS* p_local_keys = NULL;
 
@@ -2432,112 +2271,67 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_process_irk
- *
- * Description      This function is called when IRK is generated, store it in
- *                  local control block.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void btm_ble_process_irk(tSMP_ENC* p) {
-  BTM_TRACE_DEBUG("btm_ble_process_irk");
-  if (p && p->opcode == HCI_BLE_ENCRYPT) {
-    memcpy(btm_cb.devcb.id_keys.irk, p->param_buf, BT_OCTET16_LEN);
-    btm_notify_new_key(BTM_BLE_KEY_TYPE_ID);
+/** implementation of btm_ble_reset_id */
+static void btm_ble_reset_id_impl(const Octet16& rand1, const Octet16& rand2) {
+  /* Regenerate Identity Root */
+  btm_cb.devcb.id_keys.ir = rand1;
+  uint8_t btm_ble_dhk_pt = 0x03;
+
+  /* generate DHK= Eir({0x03, 0x00, 0x00 ...}) */
+  btm_cb.devcb.id_keys.dhk =
+      crypto_toolbox::aes_128(btm_cb.devcb.id_keys.ir, &btm_ble_dhk_pt, 1);
+
+  uint8_t btm_ble_irk_pt = 0x01;
+  /* IRK = D1(IR, 1) */
+  btm_cb.devcb.id_keys.irk =
+      crypto_toolbox::aes_128(btm_cb.devcb.id_keys.ir, &btm_ble_irk_pt, 1);
+
+  btm_notify_new_key(BTM_BLE_KEY_TYPE_ID);
 
 #if (BLE_PRIVACY_SPT == TRUE)
-    /* if privacy is enabled, new RPA should be calculated */
-    if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
-      btm_gen_resolvable_private_addr(base::Bind(&btm_gen_resolve_paddr_low));
-    }
-#endif
-  } else {
-    BTM_TRACE_ERROR("Generating IRK exception.");
+  /* if privacy is enabled, new RPA should be calculated */
+  if (btm_cb.ble_ctr_cb.privacy_mode != BTM_PRIVACY_NONE) {
+    btm_gen_resolvable_private_addr(base::Bind(&btm_gen_resolve_paddr_low));
   }
+#endif
 
   /* proceed generate ER */
-  btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand1) {
-    memcpy(&btm_cb.devcb.ble_encryption_key_value[0], rand1, BT_OCTET8_LEN);
-
-    btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand2) {
-      memcpy(&btm_cb.devcb.ble_encryption_key_value[8], rand2, BT_OCTET8_LEN);
-      btm_notify_new_key(BTM_BLE_KEY_TYPE_ER);
-    }));
-
-  }));
+  btm_cb.devcb.ble_encryption_key_value = rand2;
+  btm_notify_new_key(BTM_BLE_KEY_TYPE_ER);
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_process_dhk
- *
- * Description      This function is called when DHK is calculated, store it in
- *                  local control block, and proceed to generate ER, a 128-bits
- *                  random number.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void btm_ble_process_dhk(tSMP_ENC* p) {
-  uint8_t btm_ble_irk_pt = 0x01;
-  tSMP_ENC output;
+struct reset_id_data {
+  Octet16 rand1;
+  Octet16 rand2;
+};
 
-  BTM_TRACE_DEBUG("btm_ble_process_dhk");
-
-  if (p && p->opcode == HCI_BLE_ENCRYPT) {
-    memcpy(btm_cb.devcb.id_keys.dhk, p->param_buf, BT_OCTET16_LEN);
-    BTM_TRACE_DEBUG("BLE DHK generated.");
-
-    /* IRK = D1(IR, 1) */
-    if (!SMP_Encrypt(btm_cb.devcb.id_keys.ir, BT_OCTET16_LEN, &btm_ble_irk_pt,
-                     1, &output)) {
-      /* reset all identity root related key */
-      memset(&btm_cb.devcb.id_keys, 0, sizeof(tBTM_BLE_LOCAL_ID_KEYS));
-    } else {
-      btm_ble_process_irk(&output);
-    }
-  } else {
-    /* reset all identity root related key */
-    memset(&btm_cb.devcb.id_keys, 0, sizeof(tBTM_BLE_LOCAL_ID_KEYS));
-  }
-}
-
-/*******************************************************************************
- *
- * Function         btm_ble_reset_id
- *
- * Description      This function is called to reset LE device identity.
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is called to reset LE device identity. */
 void btm_ble_reset_id(void) {
   BTM_TRACE_DEBUG("btm_ble_reset_id");
 
-  /* Regenerate Identity Root*/
+  /* In order to reset identity, we need four random numbers. Make four nested
+   * calls to generate them first, then proceed to perform the actual reset in
+   * btm_ble_reset_id_impl. */
   btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand) {
-    BTM_TRACE_DEBUG("btm_ble_process_ir1");
-    memcpy(btm_cb.devcb.id_keys.ir, rand, BT_OCTET8_LEN);
-
-    btsnd_hcic_ble_rand(base::Bind([](BT_OCTET8 rand) {
-      uint8_t btm_ble_dhk_pt = 0x03;
-      tSMP_ENC output;
-
-      BTM_TRACE_DEBUG("btm_ble_process_ir2");
-
-      /* remembering in control block */
-      memcpy(&btm_cb.devcb.id_keys.ir[8], rand, BT_OCTET8_LEN);
-      /* generate DHK= Eir({0x03, 0x00, 0x00 ...}) */
-
-      SMP_Encrypt(btm_cb.devcb.id_keys.ir, BT_OCTET16_LEN, &btm_ble_dhk_pt, 1,
-                  &output);
-      btm_ble_process_dhk(&output);
-
-      BTM_TRACE_DEBUG("BLE IR generated.");
-    }));
+    reset_id_data tmp;
+    memcpy(tmp.rand1.data(), rand, BT_OCTET8_LEN);
+    btsnd_hcic_ble_rand(base::Bind(
+        [](reset_id_data tmp, BT_OCTET8 rand) {
+          memcpy(tmp.rand1.data() + 8, rand, BT_OCTET8_LEN);
+          btsnd_hcic_ble_rand(base::Bind(
+              [](reset_id_data tmp, BT_OCTET8 rand) {
+                memcpy(tmp.rand2.data(), rand, BT_OCTET8_LEN);
+                btsnd_hcic_ble_rand(base::Bind(
+                    [](reset_id_data tmp, BT_OCTET8 rand) {
+                      memcpy(tmp.rand2.data() + 8, rand, BT_OCTET8_LEN);
+                      // when all random numbers are ready, do the actual reset.
+                      btm_ble_reset_id_impl(tmp.rand1, tmp.rand2);
+                    },
+                    tmp));
+              },
+              tmp));
+        },
+        tmp));
   }));
 }
 
@@ -2549,11 +2343,6 @@
   bool 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);
diff --git a/stack/btm/btm_ble_addr.cc b/stack/btm/btm_ble_addr.cc
index 2d0acc6..000066e 100644
--- a/stack/btm/btm_ble_addr.cc
+++ b/stack/btm/btm_ble_addr.cc
@@ -33,88 +33,66 @@
 #include "hcimsgs.h"
 
 #include "btm_ble_int.h"
-#include "smp_api.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
 
-/*******************************************************************************
- *
- * Function         btm_gen_resolve_paddr_cmpl
- *
- * Description      This is callback functioin when resolvable private address
- *                  generation is complete.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void btm_gen_resolve_paddr_cmpl(tSMP_ENC* p) {
-  tBTM_LE_RANDOM_CB* p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
-  BTM_TRACE_EVENT("btm_gen_resolve_paddr_cmpl");
+/* This function generates Resolvable Private Address (RPA) from Identity
+ * Resolving Key |irk| and |random|*/
+RawAddress generate_rpa_from_irk_and_rand(const Octet16& irk,
+                                          BT_OCTET8 random) {
+  random[2] &= (~BLE_RESOLVE_ADDR_MASK);
+  random[2] |= BLE_RESOLVE_ADDR_MSB;
 
-  if (p) {
-    /* set hash to be LSB of rpAddress */
-    p_cb->private_addr.address[5] = p->param_buf[0];
-    p_cb->private_addr.address[4] = p->param_buf[1];
-    p_cb->private_addr.address[3] = p->param_buf[2];
-    /* set it to controller */
-    btm_ble_set_random_address(p_cb->private_addr);
+  RawAddress address;
+  address.address[2] = random[0];
+  address.address[1] = random[1];
+  address.address[0] = random[2];
 
-    p_cb->own_addr_type = BLE_ADDR_RANDOM;
+  /* encrypt with IRK */
+  Octet16 p = crypto_toolbox::aes_128(irk, random, 3);
 
-    /* start a periodical timer to refresh random addr */
-    period_ms_t interval_ms = BTM_BLE_PRIVATE_ADDR_INT_MS;
-#if (BTM_BLE_CONFORMANCE_TESTING == TRUE)
-    interval_ms = btm_cb.ble_ctr_cb.rpa_tout * 1000;
-#endif
-    alarm_set_on_mloop(p_cb->refresh_raddr_timer, interval_ms,
-                       btm_ble_refresh_raddr_timer_timeout, NULL);
-  } else {
-    /* random address set failure */
-    BTM_TRACE_DEBUG("set random address failed");
-  }
+  /* set hash to be LSB of rpAddress */
+  address.address[5] = p[0];
+  address.address[4] = p[1];
+  address.address[3] = p[2];
+  return address;
 }
-/*******************************************************************************
- *
- * Function         btm_gen_resolve_paddr_low
- *
- * Description      This function is called when random address has generate the
- *                  random number base for low 3 byte bd address.
- *
- * Returns          void
- *
- ******************************************************************************/
-void btm_gen_resolve_paddr_low(BT_OCTET8 rand) {
+
+/** This function is called when random address for local controller was
+ * generated */
+void btm_gen_resolve_paddr_low(const RawAddress& address) {
   tBTM_LE_RANDOM_CB* p_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
-  tSMP_ENC output;
 
   BTM_TRACE_EVENT("btm_gen_resolve_paddr_low");
-  rand[2] &= (~BLE_RESOLVE_ADDR_MASK);
-  rand[2] |= BLE_RESOLVE_ADDR_MSB;
 
-  p_cb->private_addr.address[2] = rand[0];
-  p_cb->private_addr.address[1] = rand[1];
-  p_cb->private_addr.address[0] = rand[2];
+  p_cb->private_addr = address;
 
-  /* encrypt with ur IRK */
-  if (!SMP_Encrypt(btm_cb.devcb.id_keys.irk, BT_OCTET16_LEN, rand, 3,
-                   &output)) {
-    btm_gen_resolve_paddr_cmpl(NULL);
-  } else {
-    btm_gen_resolve_paddr_cmpl(&output);
-  }
+  /* set it to controller */
+  btm_ble_set_random_address(p_cb->private_addr);
+
+  p_cb->own_addr_type = BLE_ADDR_RANDOM;
+
+  /* start a periodical timer to refresh random addr */
+  uint64_t interval_ms = BTM_BLE_PRIVATE_ADDR_INT_MS;
+#if (BTM_BLE_CONFORMANCE_TESTING == TRUE)
+  interval_ms = btm_cb.ble_ctr_cb.rpa_tout * 1000;
+#endif
+  alarm_set_on_mloop(p_cb->refresh_raddr_timer, interval_ms,
+                     btm_ble_refresh_raddr_timer_timeout, NULL);
 }
-/*******************************************************************************
- *
- * Function         btm_gen_resolvable_private_addr
- *
- * Description      This function generate a resolvable private address.
- *
- * Returns          void
- *
- ******************************************************************************/
-void btm_gen_resolvable_private_addr(base::Callback<void(BT_OCTET8)> cb) {
+
+/** This function generate a resolvable private address using local IRK */
+void btm_gen_resolvable_private_addr(
+    base::Callback<void(const RawAddress&)> cb) {
   BTM_TRACE_EVENT("%s", __func__);
   /* generate 3B rand as BD LSB, SRK with it, get BD MSB */
-  btsnd_hcic_ble_rand(std::move(cb));
+  btsnd_hcic_ble_rand(base::Bind(
+      [](base::Callback<void(const RawAddress&)> cb, BT_OCTET8 random) {
+        const Octet16& irk = BTM_GetDeviceIDRoot();
+        cb.Run(generate_rpa_from_irk_and_rand(irk, random));
+      },
+      std::move(cb)));
 }
+
 /*******************************************************************************
  *
  * Function         btm_gen_non_resolve_paddr_cmpl
@@ -169,33 +147,6 @@
 /*******************************************************************************
  *  Utility functions for Random address resolving
  ******************************************************************************/
-/*******************************************************************************
- *
- * Function         btm_ble_proc_resolve_x
- *
- * Description      This function compares the X with random address 3 MSO bytes
- *                  to find a match.
- *
- * Returns          true on match, false otherwise
- *
- ******************************************************************************/
-static bool btm_ble_proc_resolve_x(const tSMP_ENC& encrypt_output,
-                                   const RawAddress& random_bda) {
-  BTM_TRACE_EVENT("btm_ble_proc_resolve_x");
-
-  /* compare the hash with 3 LSB of bd address */
-  uint8_t comp[3];
-  comp[0] = random_bda.address[5];
-  comp[1] = random_bda.address[4];
-  comp[2] = random_bda.address[3];
-
-  if (!memcmp(encrypt_output.param_buf, comp, 3)) {
-    BTM_TRACE_EVENT("match is found");
-    return true;
-  }
-
-  return false;
-}
 
 /*******************************************************************************
  *
@@ -217,71 +168,56 @@
   return false;
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_addr_resolvable
- *
- * Description      This function checks if a RPA is resolvable by the device
- *                  key.
- *
- * Returns          true is resolvable; false otherwise.
- *
- ******************************************************************************/
+/* Return true if given Resolvable Privae Address |rpa| matches Identity
+ * Resolving Key |irk| */
+static bool rpa_matches_irk(const RawAddress& rpa, const Octet16& irk) {
+  /* use the 3 MSB of bd address as prand */
+  uint8_t rand[3];
+  rand[0] = rpa.address[2];
+  rand[1] = rpa.address[1];
+  rand[2] = rpa.address[0];
+
+  /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
+  Octet16 x = crypto_toolbox::aes_128(irk, &rand[0], 3);
+
+  rand[0] = rpa.address[5];
+  rand[1] = rpa.address[4];
+  rand[2] = rpa.address[3];
+
+  if (memcmp(x.data(), &rand[0], 3) == 0) {
+    // match
+    return true;
+  }
+  // not a match
+  return false;
+}
+
+/** This function checks if a RPA is resolvable by the device key.
+ *  Returns true is resolvable; false otherwise.
+ */
 bool btm_ble_addr_resolvable(const RawAddress& rpa,
                              tBTM_SEC_DEV_REC* p_dev_rec) {
-  bool rt = false;
+  if (!BTM_BLE_IS_RESOLVE_BDA(rpa)) return false;
 
-  if (!BTM_BLE_IS_RESOLVE_BDA(rpa)) return rt;
-
-  uint8_t rand[3];
-  tSMP_ENC output;
   if ((p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) &&
       (p_dev_rec->ble.key_type & BTM_LE_KEY_PID)) {
     BTM_TRACE_DEBUG("%s try to resolve", __func__);
-    /* use the 3 MSB of bd address as prand */
-    rand[0] = rpa.address[2];
-    rand[1] = rpa.address[1];
-    rand[2] = rpa.address[0];
 
-    /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
-    SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN, &rand[0], 3, &output);
-
-    rand[0] = rpa.address[5];
-    rand[1] = rpa.address[4];
-    rand[2] = rpa.address[3];
-
-    if (!memcmp(output.param_buf, &rand[0], 3)) {
+    if (rpa_matches_irk(rpa, p_dev_rec->ble.keys.irk)) {
       btm_ble_init_pseudo_addr(p_dev_rec, rpa);
-      rt = true;
+      return true;
     }
   }
-  return rt;
+  return false;
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_match_random_bda
- *
- * Description      This function match the random address to the appointed
- *                  device record, starting from calculating IRK. If the record
- *                  index exceeds the maximum record number, matching failed and
- *                  send a callback.
- *
- * Returns          None.
- *
- ******************************************************************************/
+/** This function match the random address to the appointed device record,
+ * starting from calculating IRK. If the record index exceeds the maximum record
+ * number, matching failed and send a callback. */
 static bool btm_ble_match_random_bda(void* data, void* context) {
-  RawAddress* random_bda = (RawAddress*)context;
-  /* use the 3 MSB of bd address as prand */
-
-  uint8_t rand[3];
-  rand[0] = random_bda->address[2];
-  rand[1] = random_bda->address[1];
-  rand[2] = random_bda->address[0];
-
   BTM_TRACE_EVENT("%s next iteration", __func__);
+  RawAddress* random_bda = (RawAddress*)context;
 
-  tSMP_ENC output;
   tBTM_SEC_DEV_REC* p_dev_rec = static_cast<tBTM_SEC_DEV_REC*>(data);
 
   BTM_TRACE_DEBUG("sec_flags = %02x device_type = %d", p_dev_rec->sec_flags,
@@ -291,22 +227,20 @@
       !(p_dev_rec->ble.key_type & BTM_LE_KEY_PID))
     return true;
 
-  /* generate X = E irk(R0, R1, R2) and R is random address 3 LSO */
-  SMP_Encrypt(p_dev_rec->ble.keys.irk, BT_OCTET16_LEN, &rand[0], 3, &output);
-  // if it was match, finish iteration, otherwise continue
-  return !btm_ble_proc_resolve_x(output, *random_bda);
+  if (rpa_matches_irk(*random_bda, p_dev_rec->ble.keys.irk)) {
+    BTM_TRACE_EVENT("match is found");
+    // if it was match, finish iteration, otherwise continue
+    return false;
+  }
+
+  // not a match, continue iteration
+  return true;
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_resolve_random_addr
- *
- * Description      This function is called to resolve a random address.
- *
- * Returns          pointer to the security record of the device whom a random
- *                  address is matched to.
- *
- ******************************************************************************/
+/** This function is called to resolve a random address.
+ * Returns pointer to the security record of the device whom a random address is
+ * matched to.
+ */
 tBTM_SEC_DEV_REC* btm_ble_resolve_random_addr(const RawAddress& random_bda) {
   BTM_TRACE_EVENT("%s", __func__);
 
@@ -326,13 +260,7 @@
 /*******************************************************************************
  *  address mapping between pseudo address and real connection address
  ******************************************************************************/
-/*******************************************************************************
- *
- * Function         btm_find_dev_by_identity_addr
- *
- * Description      find the security record whose LE static address is matching
- *
- ******************************************************************************/
+/** Find the security record whose LE identity address is matching */
 tBTM_SEC_DEV_REC* btm_find_dev_by_identity_addr(const RawAddress& bd_addr,
                                                 uint8_t addr_type) {
 #if (BLE_PRIVACY_SPT == TRUE)
@@ -341,12 +269,12 @@
        node = list_next(node)) {
     tBTM_SEC_DEV_REC* p_dev_rec =
         static_cast<tBTM_SEC_DEV_REC*>(list_node(node));
-    if (p_dev_rec->ble.static_addr == bd_addr) {
-      if ((p_dev_rec->ble.static_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
+    if (p_dev_rec->ble.identity_addr == bd_addr) {
+      if ((p_dev_rec->ble.identity_addr_type & (~BLE_ADDR_TYPE_ID_BIT)) !=
           (addr_type & (~BLE_ADDR_TYPE_ID_BIT)))
         BTM_TRACE_WARNING(
             "%s find pseudo->random match with diff addr type: %d vs %d",
-            __func__, p_dev_rec->ble.static_addr_type, addr_type);
+            __func__, p_dev_rec->ble.identity_addr_type, addr_type);
 
       /* found the match */
       return p_dev_rec;
@@ -399,16 +327,16 @@
  *
  ******************************************************************************/
 bool btm_random_pseudo_to_identity_addr(RawAddress* random_pseudo,
-                                        uint8_t* p_static_addr_type) {
+                                        uint8_t* p_identity_addr_type) {
 #if (BLE_PRIVACY_SPT == TRUE)
   tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(*random_pseudo);
 
   if (p_dev_rec != NULL) {
     if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
-      *p_static_addr_type = p_dev_rec->ble.static_addr_type;
-      *random_pseudo = p_dev_rec->ble.static_addr;
+      *p_identity_addr_type = p_dev_rec->ble.identity_addr_type;
+      *random_pseudo = p_dev_rec->ble.identity_addr;
       if (controller_get_interface()->supports_ble_privacy())
-        *p_static_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+        *p_identity_addr_type |= BLE_ADDR_TYPE_ID_BIT;
       return true;
     }
   }
@@ -458,10 +386,10 @@
 
   if (p_acl != NULL) {
     if (rra_type == BTM_BLE_ADDR_PSEUDO) {
-      /* use static address, resolvable_private_addr is empty */
+      /* use identity address, resolvable_private_addr is empty */
       if (rra_dummy) {
-        p_acl->active_remote_addr_type = p_sec_rec->ble.static_addr_type;
-        p_acl->active_remote_addr = p_sec_rec->ble.static_addr;
+        p_acl->active_remote_addr_type = p_sec_rec->ble.identity_addr_type;
+        p_acl->active_remote_addr = p_sec_rec->ble.identity_addr;
       } else {
         p_acl->active_remote_addr_type = BLE_ADDR_RANDOM;
         p_acl->active_remote_addr = rpa;
diff --git a/stack/btm/btm_ble_adv_filter.cc b/stack/btm/btm_ble_adv_filter.cc
index 54e038e..f69f1a2 100644
--- a/stack/btm/btm_ble_adv_filter.cc
+++ b/stack/btm/btm_ble_adv_filter.cc
@@ -18,11 +18,6 @@
 
 #define LOG_TAG "bt_btm_ble"
 
-#include <base/bind.h>
-#include <string.h>
-#include <algorithm>
-#include <vector>
-
 #include "bt_target.h"
 
 #include "bt_types.h"
@@ -34,6 +29,13 @@
 #include "hcidefs.h"
 #include "hcimsgs.h"
 
+#include <string.h>
+#include <algorithm>
+#include <vector>
+
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+
 using base::Bind;
 using bluetooth::Uuid;
 
@@ -594,8 +596,6 @@
   memset(&btm_ble_adv_filt_cb.cur_filter_target, 0, sizeof(tBLE_BD_ADDR));
 }
 
-void DoNothing(uint8_t a, uint8_t b, uint8_t c) {}
-
 void BTM_LE_PF_set(tBTM_BLE_PF_FILT_INDEX filt_index,
                    std::vector<ApcfCommand> commands,
                    tBTM_BLE_PF_CFG_CBACK cb) {
@@ -620,7 +620,8 @@
         target_addr.bda = cmd.address;
         target_addr.type = cmd.addr_type;
 
-        BTM_LE_PF_addr_filter(action, filt_index, target_addr, Bind(DoNothing));
+        BTM_LE_PF_addr_filter(action, filt_index, target_addr,
+                              base::DoNothing());
         break;
       }
 
@@ -632,24 +633,24 @@
       case BTM_BLE_PF_SRVC_SOL_UUID: {
         BTM_LE_PF_uuid_filter(action, filt_index, cmd.type, cmd.uuid,
                               BTM_BLE_PF_LOGIC_AND, cmd.uuid_mask,
-                              Bind(DoNothing));
+                              base::DoNothing());
         break;
       }
 
       case BTM_BLE_PF_LOCAL_NAME: {
-        BTM_LE_PF_local_name(action, filt_index, cmd.name, Bind(DoNothing));
+        BTM_LE_PF_local_name(action, filt_index, cmd.name, base::DoNothing());
         break;
       }
 
       case BTM_BLE_PF_MANU_DATA: {
         BTM_LE_PF_manu_data(action, filt_index, cmd.company, cmd.company_mask,
-                            cmd.data, cmd.data_mask, Bind(DoNothing));
+                            cmd.data, cmd.data_mask, base::DoNothing());
         break;
       }
 
       case BTM_BLE_PF_SRVC_DATA_PATTERN: {
         BTM_LE_PF_srvc_data_pattern(action, filt_index, cmd.data, cmd.data_mask,
-                                    Bind(DoNothing));
+                                    base::DoNothing());
         break;
       }
 
diff --git a/stack/btm/btm_ble_bgconn.cc b/stack/btm/btm_ble_bgconn.cc
index 952e953..73256c8 100644
--- a/stack/btm/btm_ble_bgconn.cc
+++ b/stack/btm/btm_ble_bgconn.cc
@@ -23,50 +23,45 @@
  ******************************************************************************/
 
 #include <base/logging.h>
-#include <string.h>
 #include <unordered_map>
 
 #include "bt_types.h"
-#include "bt_utils.h"
 #include "btm_int.h"
 #include "btu.h"
 #include "device/include/controller.h"
 #include "hcimsgs.h"
 #include "l2c_int.h"
-#include "osi/include/allocator.h"
-#include "osi/include/osi.h"
 
-#ifndef BTM_BLE_SCAN_PARAM_TOUT
-#define BTM_BLE_SCAN_PARAM_TOUT 50 /* 50 seconds */
-#endif
-
-static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state);
-static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state);
+extern void btm_send_hci_create_connection(
+    uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy,
+    uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own,
+    uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency,
+    uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len,
+    uint8_t phy);
+extern void btm_ble_create_conn_cancel();
 
 // Unfortunately (for now?) we have to maintain a copy of the device whitelist
 // on the host to determine if a device is pending to be connected or not. This
 // controls whether the host should keep trying to scan for whitelisted
 // peripherals or not.
 // TODO: Move all of this to controller/le/background_list or similar?
-typedef struct background_connection_t {
+struct BackgroundConnection {
   RawAddress address;
   uint8_t addr_type;
-
   bool in_controller_wl;
   uint8_t addr_type_in_wl;
-
   bool pending_removal;
-} background_connection_t;
+};
 
 struct BgConnHash {
-  bool operator()(const RawAddress& x) const {
+  std::size_t operator()(const RawAddress& x) const {
     const uint8_t* a = x.address;
     return a[0] ^ (a[1] << 8) ^ (a[2] << 16) ^ (a[3] << 24) ^ a[4] ^
            (a[5] << 8);
   }
 };
 
-static std::unordered_map<RawAddress, background_connection_t, BgConnHash>
+static std::unordered_map<RawAddress, BackgroundConnection, BgConnHash>
     background_connections;
 
 static void background_connection_add(uint8_t addr_type,
@@ -74,9 +69,9 @@
   auto map_iter = background_connections.find(address);
   if (map_iter == background_connections.end()) {
     background_connections[address] =
-        background_connection_t{address, addr_type, false, 0, false};
+        BackgroundConnection{address, addr_type, false, 0, false};
   } else {
-    background_connection_t* connection = &map_iter->second;
+    BackgroundConnection* connection = &map_iter->second;
     connection->addr_type = addr_type;
     connection->pending_removal = false;
   }
@@ -97,7 +92,7 @@
 
 static bool background_connections_pending() {
   for (auto& map_el : background_connections) {
-    background_connection_t* connection = &map_el.second;
+    BackgroundConnection* connection = &map_el.second;
     if (connection->pending_removal) continue;
     const bool connected =
         BTM_IsAclConnectionUp(connection->address, BT_TRANSPORT_LE);
@@ -155,18 +150,42 @@
  *
  ******************************************************************************/
 void btm_ble_bgconn_cancel_if_disconnected(const RawAddress& bd_addr) {
-  if (btm_cb.ble_ctr_cb.conn_state != BLE_BG_CONN) return;
+  if (btm_ble_get_conn_st() != BLE_CONNECTING) return;
 
   auto map_it = background_connections.find(bd_addr);
   if (map_it != background_connections.end()) {
-    background_connection_t* connection = &map_it->second;
+    BackgroundConnection* connection = &map_it->second;
     if (!connection->in_controller_wl && !connection->pending_removal &&
         !BTM_IsAclConnectionUp(bd_addr, BT_TRANSPORT_LE)) {
-      btm_ble_start_auto_conn(false);
+      btm_ble_stop_auto_conn();
     }
   }
 }
 
+bool BTM_BackgroundConnectAddressKnown(const RawAddress& address) {
+  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(address);
+
+  //  not a known device, or a classic device, we assume public address
+  if (p_dev_rec == NULL || (p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) == 0)
+    return true;
+
+  // bonded device with identity address known
+  if (p_dev_rec->ble.identity_addr != address &&
+      !p_dev_rec->ble.identity_addr.IsEmpty()) {
+    return true;
+  }
+
+  // Public address, Random Static, or Random Non-Resolvable Address known
+  if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC ||
+      !BTM_BLE_IS_RESOLVE_BDA(address)) {
+    return true;
+  }
+
+  // Only Resolvable Private Address (RPA) is known, we don't allow it into
+  // the background connection procedure.
+  return false;
+}
+
 /*******************************************************************************
  *
  * Function         btm_add_dev_to_controller
@@ -175,33 +194,34 @@
  ******************************************************************************/
 bool btm_add_dev_to_controller(bool to_add, const RawAddress& bd_addr) {
   tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bd_addr);
-  bool started = false;
 
   if (p_dev_rec != NULL && p_dev_rec->device_type & BT_DEVICE_TYPE_BLE) {
     if (to_add) {
-      if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC ||
-          !BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
+      if (p_dev_rec->ble.identity_addr != bd_addr &&
+          !p_dev_rec->ble.identity_addr.IsEmpty()) {
+        background_connection_add(p_dev_rec->ble.identity_addr_type,
+                                  p_dev_rec->ble.identity_addr);
+      } else {
         background_connection_add(p_dev_rec->ble.ble_addr_type, bd_addr);
-        started = true;
-        p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
-      } else if (p_dev_rec->ble.static_addr != bd_addr &&
-                 !p_dev_rec->ble.static_addr.IsEmpty()) {
-        background_connection_add(p_dev_rec->ble.static_addr_type,
-                                  p_dev_rec->ble.static_addr);
-        started = true;
-        p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
-      }
-    } else {
-      if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_PUBLIC ||
-          !BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
-        background_connection_remove(bd_addr);
-        started = true;
+
+        if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
+            BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
+          LOG(INFO) << __func__ << " addig RPA into white list";
+        }
       }
 
-      if (!p_dev_rec->ble.static_addr.IsEmpty() &&
-          p_dev_rec->ble.static_addr != bd_addr) {
-        background_connection_remove(p_dev_rec->ble.static_addr);
-        started = true;
+      p_dev_rec->ble.in_controller_list |= BTM_WHITE_LIST_BIT;
+    } else {
+      if (!p_dev_rec->ble.identity_addr.IsEmpty() &&
+          p_dev_rec->ble.identity_addr != bd_addr) {
+        background_connection_remove(p_dev_rec->ble.identity_addr);
+      } else {
+        background_connection_remove(bd_addr);
+
+        if (p_dev_rec->ble.ble_addr_type == BLE_ADDR_RANDOM &&
+            BTM_BLE_IS_RESOLVE_BDA(bd_addr)) {
+          LOG(INFO) << __func__ << " removing RPA from white list";
+        }
       }
 
       p_dev_rec->ble.in_controller_list &= ~BTM_WHITE_LIST_BIT;
@@ -209,15 +229,29 @@
   } else {
     /* not a known device, i.e. attempt to connect to device never seen before
      */
-    started = true;
     if (to_add)
       background_connection_add(BLE_ADDR_PUBLIC, bd_addr);
     else
       background_connection_remove(bd_addr);
   }
 
-  return started;
+  return true;
 }
+
+/** White list add complete */
+void wl_add_complete(uint8_t* p_data, uint16_t /* evt_len */) {
+  uint8_t status;
+  STREAM_TO_UINT8(status, p_data);
+  VLOG(2) << __func__ << ": status=" << loghex(status);
+}
+
+/** White list element remove complete */
+void wl_remove_complete(uint8_t* p_data, uint16_t /* evt_len */) {
+  uint8_t status;
+  STREAM_TO_UINT8(status, p_data);
+  VLOG(2) << __func__ << ": status=" << loghex(status);
+}
+
 /*******************************************************************************
  *
  * Function         btm_execute_wl_dev_operation
@@ -229,20 +263,22 @@
   // handle removals first to avoid filling up controller's white list
   for (auto map_it = background_connections.begin();
        map_it != background_connections.end();) {
-    background_connection_t* connection = &map_it->second;
+    BackgroundConnection* connection = &map_it->second;
     if (connection->pending_removal) {
-      btsnd_hcic_ble_remove_from_white_list(connection->addr_type_in_wl,
-                                            connection->address);
+      btsnd_hcic_ble_remove_from_white_list(
+          connection->addr_type_in_wl, connection->address,
+          base::BindOnce(&wl_remove_complete));
       map_it = background_connections.erase(map_it);
     } else
       ++map_it;
   }
   for (auto& map_el : background_connections) {
-    background_connection_t* connection = &map_el.second;
+    BackgroundConnection* connection = &map_el.second;
     const bool connected =
         BTM_IsAclConnectionUp(connection->address, BT_TRANSPORT_LE);
     if (!connection->in_controller_wl && !connected) {
-      btsnd_hcic_ble_add_white_list(connection->addr_type, connection->address);
+      btsnd_hcic_ble_add_white_list(connection->addr_type, connection->address,
+                                    base::BindOnce(&wl_add_complete));
       connection->in_controller_wl = true;
       connection->addr_type_in_wl = connection->addr_type;
     } else if (connection->in_controller_wl && connected) {
@@ -250,8 +286,9 @@
          connection between two LE addresses. Not all controllers handle this
          correctly, therefore we must make sure connected devices are not in
          the white list when bg connection attempt is active. */
-      btsnd_hcic_ble_remove_from_white_list(connection->addr_type_in_wl,
-                                            connection->address);
+      btsnd_hcic_ble_remove_from_white_list(
+          connection->addr_type_in_wl, connection->address,
+          base::BindOnce(&wl_remove_complete));
       connection->in_controller_wl = false;
     }
   }
@@ -260,58 +297,6 @@
 
 /*******************************************************************************
  *
- * Function         btm_update_dev_to_white_list
- *
- * Description      This function adds or removes a device into/from
- *                  the white list.
- *
- ******************************************************************************/
-bool btm_update_dev_to_white_list(bool to_add, const RawAddress& bd_addr) {
-  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
-
-  if (to_add &&
-      background_connections_count() ==
-          controller_get_interface()->get_ble_white_list_size()) {
-    BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__);
-    return false;
-  }
-
-  btm_suspend_wl_activity(p_cb->wl_state);
-  btm_add_dev_to_controller(to_add, bd_addr);
-  btm_resume_wl_activity(p_cb->wl_state);
-  return true;
-}
-
-/*******************************************************************************
- *
- * Function         btm_ble_clear_white_list
- *
- * Description      This function clears the white list.
- *
- ******************************************************************************/
-void btm_ble_clear_white_list(void) {
-  BTM_TRACE_EVENT("btm_ble_clear_white_list");
-  btsnd_hcic_ble_clear_white_list();
-  background_connections_clear();
-}
-
-/*******************************************************************************
- *
- * Function         btm_ble_clear_white_list_complete
- *
- * Description      Indicates white list cleared.
- *
- ******************************************************************************/
-void btm_ble_clear_white_list_complete(uint8_t* p_data,
-                                       UNUSED_ATTR uint16_t evt_len) {
-  uint8_t status;
-
-  STREAM_TO_UINT8(status, p_data);
-  BTM_TRACE_EVENT("%s status=%d", __func__, status);
-}
-
-/*******************************************************************************
- *
  * Function         btm_ble_white_list_init
  *
  * Description      Initialize white list size
@@ -321,98 +306,44 @@
   BTM_TRACE_DEBUG("%s white_list_size = %d", __func__, white_list_size);
 }
 
-/*******************************************************************************
- *
- * Function         btm_ble_add_2_white_list_complete
- *
- * Description      White list element added
- *
- ******************************************************************************/
-void btm_ble_add_2_white_list_complete(uint8_t status) {
-  BTM_TRACE_EVENT("%s status=%d", __func__, status);
-}
-
-/*******************************************************************************
- *
- * Function         btm_ble_remove_from_white_list_complete
- *
- * Description      White list element removal complete
- *
- ******************************************************************************/
-void btm_ble_remove_from_white_list_complete(uint8_t* p,
-                                             UNUSED_ATTR uint16_t evt_len) {
-  BTM_TRACE_EVENT("%s status=%d", __func__, *p);
-}
-
-void btm_ble_create_conn_cancel_complete(uint8_t* p) {
-  uint8_t status;
-  STREAM_TO_UINT8(status, p);
-
-  if (status == HCI_ERR_COMMAND_DISALLOWED) {
-    /* This is a sign that logic around keeping connection state is broken */
-    LOG(ERROR)
-        << "Attempt to cancel LE connection, when no connection is pending.";
-    if (btm_ble_get_conn_st() == BLE_CONN_CANCEL) {
-      btm_ble_set_conn_st(BLE_CONN_IDLE);
-      btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, nullptr, status);
-    }
-  }
-}
-
-void btm_send_hci_create_connection(
-    uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy,
-    uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own,
-    uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency,
-    uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len,
-    uint8_t initiating_phys) {
-  if (controller_get_interface()->supports_ble_extended_advertising()) {
-    EXT_CONN_PHY_CFG phy_cfg[3];  // maximum three phys
-
-    int phy_cnt =
-        std::bitset<std::numeric_limits<uint8_t>::digits>(initiating_phys)
-            .count();
-
-    LOG_ASSERT(phy_cnt < 3) << "More than three phys provided";
-    // TODO(jpawlowski): tune parameters for different transports
-    for (int i = 0; i < phy_cnt; i++) {
-      phy_cfg[i].scan_int = scan_int;
-      phy_cfg[i].scan_win = scan_win;
-      phy_cfg[i].conn_int_min = conn_int_min;
-      phy_cfg[i].conn_int_max = conn_int_max;
-      phy_cfg[i].conn_latency = conn_latency;
-      phy_cfg[i].sup_timeout = conn_timeout;
-      phy_cfg[i].min_ce_len = min_ce_len;
-      phy_cfg[i].max_ce_len = max_ce_len;
-    }
-
-    addr_type_peer &= ~BLE_ADDR_TYPE_ID_BIT;
-    btsnd_hcic_ble_ext_create_conn(init_filter_policy, addr_type_own,
-                                   addr_type_peer, bda_peer, initiating_phys,
-                                   phy_cfg);
-  } else {
-    btsnd_hcic_ble_create_ll_conn(scan_int, scan_win, init_filter_policy,
-                                  addr_type_peer, bda_peer, addr_type_own,
-                                  conn_int_min, conn_int_max, conn_latency,
-                                  conn_timeout, min_ce_len, max_ce_len);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         btm_ble_start_auto_conn
- *
- * Description      This function is to start/stop auto connection procedure.
- *
- * Parameters       start: true to start; false to stop.
- *
- * Returns          void
- *
- ******************************************************************************/
-bool btm_ble_start_auto_conn(bool start) {
+bool BTM_SetLeConnectionModeToFast() {
+  VLOG(2) << __func__;
   tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
-  bool exec = true;
-  uint16_t scan_int;
-  uint16_t scan_win;
+  if ((p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF &&
+       p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ||
+      (p_cb->scan_int == BTM_BLE_SCAN_SLOW_INT_1 &&
+       p_cb->scan_win == BTM_BLE_SCAN_SLOW_WIN_1)) {
+    p_cb->scan_int = BTM_BLE_SCAN_FAST_INT;
+    p_cb->scan_win = BTM_BLE_SCAN_FAST_WIN;
+    return true;
+  }
+  return false;
+}
+
+void BTM_SetLeConnectionModeToSlow() {
+  VLOG(2) << __func__;
+  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
+  if ((p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF &&
+       p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF) ||
+      (p_cb->scan_int == BTM_BLE_SCAN_FAST_INT &&
+       p_cb->scan_win == BTM_BLE_SCAN_FAST_WIN)) {
+    p_cb->scan_int = BTM_BLE_SCAN_SLOW_INT_1;
+    p_cb->scan_win = BTM_BLE_SCAN_SLOW_WIN_1;
+  }
+}
+
+/** This function is to start auto connection procedure */
+bool btm_ble_start_auto_conn() {
+  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
+
+  BTM_TRACE_EVENT("%s", __func__);
+
+  uint16_t scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF)
+                          ? BTM_BLE_SCAN_SLOW_INT_1
+                          : p_cb->scan_int;
+  uint16_t scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF)
+                          ? BTM_BLE_SCAN_SLOW_WIN_1
+                          : p_cb->scan_win;
   uint8_t own_addr_type = p_cb->addr_mgnt_cb.own_addr_type;
   uint8_t peer_addr_type = BLE_ADDR_PUBLIC;
 
@@ -420,63 +351,60 @@
   if (controller_get_interface()->supports_ble_2m_phy()) phy |= PHY_LE_2M;
   if (controller_get_interface()->supports_ble_coded_phy()) phy |= PHY_LE_CODED;
 
-  BTM_TRACE_EVENT("%s start=%d", __func__, start);
-
-  if (start) {
-    if (p_cb->conn_state == BLE_CONN_IDLE && background_connections_pending() &&
-        btm_ble_topology_check(BTM_BLE_STATE_INIT) && l2cu_can_allocate_lcb()) {
-      p_cb->wl_state |= BTM_BLE_WL_INIT;
-
-      btm_execute_wl_dev_operation();
-
-#if (BLE_PRIVACY_SPT == TRUE)
-      btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT);
-#endif
-      scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF)
-                     ? BTM_BLE_SCAN_SLOW_INT_1
-                     : p_cb->scan_int;
-      scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF)
-                     ? BTM_BLE_SCAN_SLOW_WIN_1
-                     : p_cb->scan_win;
-
-#if (BLE_PRIVACY_SPT == TRUE)
-      if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE &&
-          controller_get_interface()->supports_ble_privacy()) {
-        own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
-        peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
-      }
-#endif
-
-      btm_send_hci_create_connection(
-          scan_int,                       /* uint16_t scan_int      */
-          scan_win,                       /* uint16_t scan_win      */
-          0x01,                           /* uint8_t white_list     */
-          peer_addr_type,                 /* uint8_t addr_type_peer */
-          RawAddress::kEmpty,             /* BD_ADDR bda_peer     */
-          own_addr_type,                  /* uint8_t addr_type_own */
-          BTM_BLE_CONN_INT_MIN_DEF,       /* uint16_t conn_int_min  */
-          BTM_BLE_CONN_INT_MAX_DEF,       /* uint16_t conn_int_max  */
-          BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* uint16_t conn_latency  */
-          BTM_BLE_CONN_TIMEOUT_DEF,       /* uint16_t conn_timeout  */
-          0,                              /* uint16_t min_len       */
-          0,                              /* uint16_t max_len       */
-          phy);
-      btm_ble_set_conn_st(BLE_BG_CONN);
-    } else {
-      exec = false;
-    }
-  } else {
-    if (p_cb->conn_state == BLE_BG_CONN) {
-      btsnd_hcic_ble_create_conn_cancel();
-      btm_ble_set_conn_st(BLE_CONN_CANCEL);
-      p_cb->wl_state &= ~BTM_BLE_WL_INIT;
-    } else {
-      BTM_TRACE_DEBUG("conn_st = %d, not in auto conn state, cannot stop",
-                      p_cb->conn_state);
-      exec = false;
-    }
+  if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
+    LOG(INFO) << "initate background connection fail, topology limitation";
+    return false;
   }
-  return exec;
+
+  if (btm_ble_get_conn_st() != BLE_CONN_IDLE ||
+      !background_connections_pending() || !l2cu_can_allocate_lcb()) {
+    return false;
+  }
+
+  p_cb->wl_state |= BTM_BLE_WL_INIT;
+
+  btm_execute_wl_dev_operation();
+
+#if (BLE_PRIVACY_SPT == TRUE)
+  btm_ble_enable_resolving_list_for_platform(BTM_BLE_RL_INIT);
+  if (btm_cb.ble_ctr_cb.rl_state != BTM_BLE_RL_IDLE &&
+      controller_get_interface()->supports_ble_privacy()) {
+    own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+    peer_addr_type |= BLE_ADDR_TYPE_ID_BIT;
+  }
+#endif
+
+  btm_send_hci_create_connection(
+      scan_int,                       /* uint16_t scan_int      */
+      scan_win,                       /* uint16_t scan_win      */
+      0x01,                           /* uint8_t white_list     */
+      peer_addr_type,                 /* uint8_t addr_type_peer */
+      RawAddress::kEmpty,             /* BD_ADDR bda_peer     */
+      own_addr_type,                  /* uint8_t addr_type_own */
+      BTM_BLE_CONN_INT_MIN_DEF,       /* uint16_t conn_int_min  */
+      BTM_BLE_CONN_INT_MAX_DEF,       /* uint16_t conn_int_max  */
+      BTM_BLE_CONN_SLAVE_LATENCY_DEF, /* uint16_t conn_latency  */
+      BTM_BLE_CONN_TIMEOUT_DEF,       /* uint16_t conn_timeout  */
+      0,                              /* uint16_t min_len       */
+      0,                              /* uint16_t max_len       */
+      phy);
+  return true;
+}
+
+/** This function is to stop auto connection procedure */
+bool btm_ble_stop_auto_conn() {
+  BTM_TRACE_EVENT("%s", __func__);
+
+  if (btm_ble_get_conn_st() != BLE_CONNECTING) {
+    BTM_TRACE_DEBUG("conn_st = %d, not in auto conn state, cannot stop",
+                    btm_ble_get_conn_st());
+    return false;
+  }
+
+  btm_ble_create_conn_cancel();
+
+  btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_INIT;
+  return true;
 }
 
 /*******************************************************************************
@@ -493,38 +421,9 @@
  ******************************************************************************/
 bool btm_ble_suspend_bg_conn(void) {
   BTM_TRACE_EVENT("%s", __func__);
+  return btm_ble_stop_auto_conn();
+}
 
-  if (btm_cb.ble_ctr_cb.bg_conn_type == BTM_BLE_CONN_AUTO)
-    return btm_ble_start_auto_conn(false);
-
-  return false;
-}
-/*******************************************************************************
- *
- * Function         btm_suspend_wl_activity
- *
- * Description      This function is to suspend white list related activity
- *
- * Returns          none.
- *
- ******************************************************************************/
-static void btm_suspend_wl_activity(tBTM_BLE_WL_STATE wl_state) {
-  if (wl_state & BTM_BLE_WL_INIT) {
-    btm_ble_start_auto_conn(false);
-  }
-}
-/*******************************************************************************
- *
- * Function         btm_resume_wl_activity
- *
- * Description      This function is to resume white list related activity
- *
- * Returns          none.
- *
- ******************************************************************************/
-static void btm_resume_wl_activity(tBTM_BLE_WL_STATE wl_state) {
-  btm_ble_resume_bg_conn();
-}
 /*******************************************************************************
  *
  * Function         btm_ble_resume_bg_conn
@@ -537,113 +436,49 @@
  * Returns          none.
  *
  ******************************************************************************/
-bool btm_ble_resume_bg_conn(void) {
-  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
-  if (p_cb->bg_conn_type == BTM_BLE_CONN_AUTO) {
-    return btm_ble_start_auto_conn(true);
+bool btm_ble_resume_bg_conn(void) { return btm_ble_start_auto_conn(); }
+
+/** Adds the device into white list. Returns false if white list is full and
+ * device can't be added, true otherwise. */
+bool BTM_WhiteListAdd(const RawAddress& address) {
+  VLOG(1) << __func__ << ": " << address;
+
+  if (background_connections_count() ==
+      controller_get_interface()->get_ble_white_list_size()) {
+    BTM_TRACE_ERROR("%s Whitelist full, unable to add device", __func__);
+    return false;
   }
 
-  return false;
-}
-/*******************************************************************************
- *
- * Function         btm_ble_get_conn_st
- *
- * Description      This function get BLE connection state
- *
- * Returns          connection state
- *
- ******************************************************************************/
-tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) {
-  return btm_cb.ble_ctr_cb.conn_state;
-}
-/*******************************************************************************
- *
- * Function         btm_ble_set_conn_st
- *
- * Description      This function set BLE connection state
- *
- * Returns          None.
- *
- ******************************************************************************/
-void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st) {
-  btm_cb.ble_ctr_cb.conn_state = new_st;
-
-  if (new_st == BLE_BG_CONN || new_st == BLE_DIR_CONN)
-    btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
-  else
-    btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
-}
-
-/*******************************************************************************
- *
- * Function         btm_ble_enqueue_direct_conn_req
- *
- * Description      This function enqueue the direct connection request
- *
- * Returns          None.
- *
- ******************************************************************************/
-void btm_ble_enqueue_direct_conn_req(void* p_param) {
-  tBTM_BLE_CONN_REQ* p =
-      (tBTM_BLE_CONN_REQ*)osi_malloc(sizeof(tBTM_BLE_CONN_REQ));
-
-  p->p_param = p_param;
-
-  fixed_queue_enqueue(btm_cb.ble_ctr_cb.conn_pending_q, p);
-}
-/*******************************************************************************
- *
- * Function         btm_ble_dequeue_direct_conn_req
- *
- * Description      This function dequeues the direct connection request
- *
- * Returns          None.
- *
- ******************************************************************************/
-void btm_ble_dequeue_direct_conn_req(const RawAddress& 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 (rem_bda == p_lcb->remote_bd_addr) {
-      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;
-    }
+  if (btm_cb.ble_ctr_cb.wl_state & BTM_BLE_WL_INIT) {
+    btm_ble_stop_auto_conn();
   }
+  btm_add_dev_to_controller(true, address);
+  btm_ble_resume_bg_conn();
+  return true;
 }
-/*******************************************************************************
- *
- * Function         btm_send_pending_direct_conn
- *
- * Description      This function send the pending direct connection request in
- *                  queue
- *
- * Returns          true if started, false otherwise
- *
- ******************************************************************************/
-bool btm_send_pending_direct_conn(void) {
-  tBTM_BLE_CONN_REQ* p_req;
-  bool rt = false;
 
-  p_req = (tBTM_BLE_CONN_REQ*)fixed_queue_try_dequeue(
-      btm_cb.ble_ctr_cb.conn_pending_q);
-  if (p_req != NULL) {
-    tL2C_LCB* p_lcb = (tL2C_LCB*)(p_req->p_param);
-    /* Ignore entries that might have been released while queued. */
-    if (p_lcb->in_use) rt = l2cble_init_direct_conn(p_lcb);
-    osi_free(p_req);
+/** Removes the device from white list */
+void BTM_WhiteListRemove(const RawAddress& address) {
+  VLOG(1) << __func__ << ": " << address;
+  if (btm_cb.ble_ctr_cb.wl_state & BTM_BLE_WL_INIT) {
+    btm_ble_stop_auto_conn();
   }
+  btm_add_dev_to_controller(false, address);
+  btm_ble_resume_bg_conn();
+}
 
-  return rt;
+/** clear white list complete */
+void wl_clear_complete(uint8_t* p_data, uint16_t /* evt_len */) {
+  uint8_t status;
+  STREAM_TO_UINT8(status, p_data);
+  VLOG(2) << __func__ << ": status=" << loghex(status);
+}
+
+/** Clear the whitelist, end any pending whitelist connections */
+void BTM_WhiteListClear() {
+  VLOG(1) << __func__;
+  if (!controller_get_interface()->supports_ble()) return;
+  btm_ble_stop_auto_conn();
+  btsnd_hcic_ble_clear_white_list(base::BindOnce(&wl_clear_complete));
+  background_connections_clear();
 }
diff --git a/stack/btm/btm_ble_bgconn.h b/stack/btm/btm_ble_bgconn.h
new file mode 100644
index 0000000..45ab2ec
--- /dev/null
+++ b/stack/btm/btm_ble_bgconn.h
@@ -0,0 +1,40 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "types/raw_address.h"
+
+/** Adds the device into white list. Returns false if white list is full and
+ * device can't be added, true otherwise. */
+extern bool BTM_WhiteListAdd(const RawAddress& address);
+
+/** Removes the device from white list */
+extern void BTM_WhiteListRemove(const RawAddress& address);
+
+/** Clear the whitelist, end any pending whitelist connections */
+extern void BTM_WhiteListClear();
+
+/* Use fast scan window/interval for LE connection establishment.
+ * This does not send any requests to controller, instead it changes the
+ * parameters that will be used after next add/remove request.
+ * Returns true, if the change is scheduled, false otherwise. */
+extern bool BTM_SetLeConnectionModeToFast();
+
+/* Use slow scan window/interval for LE connection establishment.
+ * This does not send any requests to controller, instead it changes the
+ * parameters that will be used after next add/remove request */
+extern void BTM_SetLeConnectionModeToSlow();
\ No newline at end of file
diff --git a/stack/btm/btm_ble_connection_establishment.cc b/stack/btm/btm_ble_connection_establishment.cc
new file mode 100644
index 0000000..c0d7791
--- /dev/null
+++ b/stack/btm/btm_ble_connection_establishment.cc
@@ -0,0 +1,254 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
+#include <frameworks/base/core/proto/android/bluetooth/hci/enums.pb.h>
+
+#include "bt_types.h"
+#include "btm_int.h"
+#include "common/metrics.h"
+#include "device/include/controller.h"
+#include "l2c_int.h"
+#include "stack/gatt/connection_manager.h"
+#include "stack/include/hcimsgs.h"
+
+extern void btm_ble_advertiser_notify_terminated_legacy(
+    uint8_t status, uint16_t connection_handle);
+
+/** This function get BLE connection state */
+tBTM_BLE_CONN_ST btm_ble_get_conn_st(void) {
+  return btm_cb.ble_ctr_cb.conn_state;
+}
+
+/** This function set BLE connection state */
+void btm_ble_set_conn_st(tBTM_BLE_CONN_ST new_st) {
+  btm_cb.ble_ctr_cb.conn_state = new_st;
+
+  if (new_st == BLE_CONNECTING)
+    btm_ble_set_topology_mask(BTM_BLE_STATE_INIT_BIT);
+  else
+    btm_ble_clear_topology_mask(BTM_BLE_STATE_INIT_BIT);
+}
+
+void btm_send_hci_create_connection(
+    uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy,
+    uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own,
+    uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency,
+    uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len,
+    uint8_t initiating_phys) {
+  if (controller_get_interface()->supports_ble_extended_advertising()) {
+    EXT_CONN_PHY_CFG phy_cfg[3];  // maximum three phys
+
+    int phy_cnt =
+        std::bitset<std::numeric_limits<uint8_t>::digits>(initiating_phys)
+            .count();
+
+    LOG_ASSERT(phy_cnt <= 3) << "More than three phys provided";
+    // TODO(jpawlowski): tune parameters for different transports
+    for (int i = 0; i < phy_cnt; i++) {
+      phy_cfg[i].scan_int = scan_int;
+      phy_cfg[i].scan_win = scan_win;
+      phy_cfg[i].conn_int_min = conn_int_min;
+      phy_cfg[i].conn_int_max = conn_int_max;
+      phy_cfg[i].conn_latency = conn_latency;
+      phy_cfg[i].sup_timeout = conn_timeout;
+      phy_cfg[i].min_ce_len = min_ce_len;
+      phy_cfg[i].max_ce_len = max_ce_len;
+    }
+
+    addr_type_peer &= ~BLE_ADDR_TYPE_ID_BIT;
+    btsnd_hcic_ble_ext_create_conn(init_filter_policy, addr_type_own,
+                                   addr_type_peer, bda_peer, initiating_phys,
+                                   phy_cfg);
+  } else {
+    btsnd_hcic_ble_create_ll_conn(scan_int, scan_win, init_filter_policy,
+                                  addr_type_peer, bda_peer, addr_type_own,
+                                  conn_int_min, conn_int_max, conn_latency,
+                                  conn_timeout, min_ce_len, max_ce_len);
+  }
+
+  btm_ble_set_conn_st(BLE_CONNECTING);
+}
+
+/** LE connection complete. */
+void btm_ble_create_ll_conn_complete(uint8_t status) {
+  if (status == HCI_SUCCESS) return;
+
+  LOG(WARNING) << "LE Create Connection attempt failed, status="
+               << loghex(status);
+
+  if (status == HCI_ERR_COMMAND_DISALLOWED) {
+    btm_ble_set_conn_st(BLE_CONNECTING);
+    LOG(ERROR) << "LE Create Connection - command disallowed";
+  } else {
+    btm_ble_set_conn_st(BLE_CONN_IDLE);
+    btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, NULL, status);
+  }
+}
+
+/** LE connection complete. */
+void btm_ble_conn_complete(uint8_t* p, UNUSED_ATTR uint16_t evt_len,
+                           bool enhanced) {
+#if (BLE_PRIVACY_SPT == TRUE)
+  uint8_t peer_addr_type;
+#endif
+  RawAddress local_rpa, peer_rpa;
+  uint8_t role, status, bda_type;
+  uint16_t handle;
+  RawAddress bda;
+  uint16_t conn_interval, conn_latency, conn_timeout;
+  bool match = false;
+
+  STREAM_TO_UINT8(status, p);
+  STREAM_TO_UINT16(handle, p);
+  STREAM_TO_UINT8(role, p);
+  STREAM_TO_UINT8(bda_type, p);
+  STREAM_TO_BDADDR(bda, p);
+  if (enhanced) {
+    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);
+  handle = HCID_GET_HANDLE(handle);
+
+  uint32_t hci_ble_event =
+      enhanced ? android::bluetooth::hci::BLE_EVT_ENHANCED_CONN_COMPLETE_EVT
+               : android::bluetooth::hci::BLE_EVT_CONN_COMPLETE_EVT;
+
+  if (status == HCI_SUCCESS) {
+#if (BLE_PRIVACY_SPT == TRUE)
+    peer_addr_type = bda_type;
+    bool addr_is_rpa =
+        (peer_addr_type == BLE_ADDR_RANDOM && BTM_BLE_IS_RESOLVE_BDA(bda));
+
+    /* We must translate whatever address we received into the "pseudo" address.
+     * i.e. if we bonded with device that was using RPA for first connection,
+     * "pseudo" address is equal to this RPA. If it later decides to use Public
+     * address, or Random Static Address, we convert it into the "pseudo"
+     * address here. */
+    if (!addr_is_rpa || peer_addr_type & BLE_ADDR_TYPE_ID_BIT) {
+      match = btm_identity_addr_to_random_pseudo(&bda, &bda_type, true);
+    }
+
+    /* possiblly receive connection complete with resolvable random while
+       the device has been paired */
+    if (!match && addr_is_rpa) {
+      tBTM_SEC_DEV_REC* match_rec = btm_ble_resolve_random_addr(bda);
+      if (match_rec) {
+        LOG(INFO) << __func__ << ": matched and resolved random address";
+        match = true;
+        match_rec->ble.active_addr_type = BTM_BLE_ADDR_RRA;
+        match_rec->ble.cur_rand_addr = bda;
+        if (!btm_ble_init_pseudo_addr(match_rec, bda)) {
+          /* assign the original address to be the current report address */
+          bda = match_rec->ble.pseudo_addr;
+        } else {
+          bda = match_rec->bd_addr;
+        }
+      } else {
+        LOG(INFO) << __func__ << ": unable to match and resolve random address";
+      }
+    }
+#endif
+    // Log for the HCI success case after resolving Bluetooth address
+    bluetooth::common::LogLinkLayerConnectionEvent(
+        &bda, handle, android::bluetooth::DIRECTION_UNKNOWN,
+        android::bluetooth::LINK_TYPE_ACL, android::bluetooth::hci::CMD_UNKNOWN,
+        android::bluetooth::hci::EVT_BLE_META, hci_ble_event, status,
+        android::bluetooth::hci::STATUS_UNKNOWN);
+
+    if (role == HCI_ROLE_MASTER) {
+      btm_ble_set_conn_st(BLE_CONN_IDLE);
+    }
+
+    connection_manager::on_connection_complete(bda);
+    btm_ble_connected(bda, handle, HCI_ENCRYPT_MODE_DISABLED, role, bda_type,
+                      match);
+
+    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
+  } else {
+    // Log for non HCI success case
+    bluetooth::common::LogLinkLayerConnectionEvent(
+        &bda, handle, android::bluetooth::DIRECTION_UNKNOWN,
+        android::bluetooth::LINK_TYPE_ACL, android::bluetooth::hci::CMD_UNKNOWN,
+        android::bluetooth::hci::EVT_BLE_META, hci_ble_event, status,
+        android::bluetooth::hci::STATUS_UNKNOWN);
+
+    role = HCI_ROLE_UNKNOWN;
+    if (status != HCI_ERR_ADVERTISING_TIMEOUT) {
+      btm_ble_set_conn_st(BLE_CONN_IDLE);
+#if (BLE_PRIVACY_SPT == TRUE)
+      btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
+#endif
+    } else {
+#if (BLE_PRIVACY_SPT == TRUE)
+      btm_cb.ble_ctr_cb.inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
+      btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, true);
+#endif
+    }
+  }
+
+  btm_ble_update_mode_operation(role, &bda, status);
+
+  if (role == HCI_ROLE_SLAVE)
+    btm_ble_advertiser_notify_terminated_legacy(status, handle);
+}
+
+void btm_ble_create_conn_cancel() {
+  btsnd_hcic_ble_create_conn_cancel();
+  btm_ble_set_conn_st(BLE_CONN_CANCEL);
+}
+
+void btm_ble_create_conn_cancel_complete(uint8_t* p) {
+  uint8_t status;
+  STREAM_TO_UINT8(status, p);
+  if (status != HCI_SUCCESS) {
+    // Only log errors to prevent log spam due to whitelist connections
+    bluetooth::common::LogLinkLayerConnectionEvent(
+        nullptr, bluetooth::common::kUnknownConnectionHandle,
+        android::bluetooth::DIRECTION_OUTGOING,
+        android::bluetooth::LINK_TYPE_ACL,
+        android::bluetooth::hci::CMD_BLE_CREATE_CONN_CANCEL,
+        android::bluetooth::hci::EVT_COMMAND_COMPLETE,
+        android::bluetooth::hci::BLE_EVT_UNKNOWN, status,
+        android::bluetooth::hci::STATUS_UNKNOWN);
+  }
+
+  if (status == HCI_ERR_COMMAND_DISALLOWED) {
+    /* This is a sign that logic around keeping connection state is broken */
+    LOG(ERROR)
+        << "Attempt to cancel LE connection, when no connection is pending.";
+    if (btm_ble_get_conn_st() == BLE_CONN_CANCEL) {
+      btm_ble_set_conn_st(BLE_CONN_IDLE);
+      btm_ble_update_mode_operation(HCI_ROLE_UNKNOWN, nullptr, status);
+    }
+  }
+}
diff --git a/stack/btm/btm_ble_gap.cc b/stack/btm/btm_ble_gap.cc
index 1f8263f..c46acf0 100644
--- a/stack/btm/btm_ble_gap.cc
+++ b/stack/btm/btm_ble_gap.cc
@@ -58,7 +58,10 @@
 
 #define BTM_EXT_BLE_RMT_NAME_TIMEOUT_MS (30 * 1000)
 #define MIN_ADV_LENGTH 2
-#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE 9
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN 9
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_L_RELEASE \
+  BTM_VSC_CHIP_CAPABILITY_RSP_LEN
+#define BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE 15
 
 namespace {
 
@@ -452,7 +455,7 @@
       btm_cb.ble_ctr_cb.scan_activity |= BTM_LE_OBSERVE_ACTIVE;
       if (duration != 0) {
         /* start observer timer */
-        period_ms_t duration_ms = duration * 1000;
+        uint64_t duration_ms = duration * 1000;
         alarm_set_on_mloop(btm_cb.ble_ctr_cb.observer_timer, duration_ms,
                            btm_ble_observer_timer_timeout, NULL);
       }
@@ -495,6 +498,7 @@
     BTM_TRACE_DEBUG("%s: Status = 0x%02x (0 is success)", __func__, status);
     return;
   }
+  CHECK(p_vcs_cplt_params->param_len > BTM_VSC_CHIP_CAPABILITY_RSP_LEN);
   STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.adv_inst_max, p);
   STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.rpa_offloading, p);
   STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.tot_scan_results_strg, p);
@@ -512,9 +516,10 @@
 
   if (btm_cb.cmn_ble_vsc_cb.version_supported >=
       BTM_VSC_CHIP_CAPABILITY_M_VERSION) {
+    CHECK(p_vcs_cplt_params->param_len >= BTM_VSC_CHIP_CAPABILITY_RSP_LEN_M_RELEASE);
     STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.total_trackable_advertisers, p);
-    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
-    STREAM_TO_UINT16(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
+    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.extended_scan_support, p);
+    STREAM_TO_UINT8(btm_cb.cmn_ble_vsc_cb.debug_logging_supported, p);
   }
   btm_cb.cmn_ble_vsc_cb.values_read = true;
 
@@ -696,59 +701,6 @@
 #endif
 }
 
-/**
- * Set BLE connectable mode to auto connect
- */
-void BTM_BleStartAutoConn() {
-  BTM_TRACE_EVENT("%s", __func__);
-  if (!controller_get_interface()->supports_ble()) return;
-
-  if (btm_cb.ble_ctr_cb.bg_conn_type != BTM_BLE_CONN_AUTO) {
-    btm_ble_start_auto_conn(true);
-    btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_AUTO;
-  }
-}
-
-/*******************************************************************************
- *
- * Function         BTM_BleClearBgConnDev
- *
- * Description      This function is called to clear the whitelist,
- *                  end any pending whitelist connections,
- *                  and reset the local bg device list.
- *
- * Parameters       void
- *
- * Returns          void
- *
- ******************************************************************************/
-void BTM_BleClearBgConnDev(void) {
-  if (!controller_get_interface()->supports_ble()) return;
-  btm_ble_start_auto_conn(false);
-  btm_ble_clear_white_list();
-  gatt_reset_bgdev_list();
-}
-
-/*******************************************************************************
- *
- * Function         BTM_BleUpdateBgConnDev
- *
- * Description      This function is called to add or remove a device into/from
- *                  background connection procedure. The background connection
- *                  procedure is decided by the background connection type, it
- *                  can be auto connection, or selective connection.
- *
- * Parameters       add_remove: true to add; false to remove.
- *                  remote_bda: device address to add/remove.
- *
- * Returns          void
- *
- ******************************************************************************/
-bool BTM_BleUpdateBgConnDev(bool add_remove, const RawAddress& remote_bda) {
-  BTM_TRACE_EVENT("%s() add=%d", __func__, add_remove);
-  return btm_update_dev_to_white_list(add_remove, remote_bda);
-}
-
 /*******************************************************************************
  *
  * Function         BTM_BleSetConnectableMode
@@ -822,8 +774,8 @@
         if ((p_dev_rec = btm_find_or_alloc_dev(p_cb->direct_bda.bda)) != NULL &&
             p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
           btm_ble_enable_resolving_list(BTM_BLE_RL_ADV);
-          p_peer_addr_ptr = p_dev_rec->ble.static_addr;
-          *p_peer_addr_type = p_dev_rec->ble.static_addr_type;
+          p_peer_addr_ptr = p_dev_rec->ble.identity_addr;
+          *p_peer_addr_type = p_dev_rec->ble.identity_addr_type;
           *p_own_addr_type = BLE_ADDR_RANDOM_ID;
           return evt_type;
         }
@@ -853,8 +805,8 @@
        * peer */
       tBTM_SEC_DEV_REC* p_dev_rec =
           static_cast<tBTM_SEC_DEV_REC*>(list_node(n));
-      p_peer_addr_ptr = p_dev_rec->ble.static_addr;
-      *p_peer_addr_type = p_dev_rec->ble.static_addr_type;
+      p_peer_addr_ptr = p_dev_rec->ble.identity_addr;
+      *p_peer_addr_type = p_dev_rec->ble.identity_addr_type;
 
       *p_own_addr_type = BLE_ADDR_RANDOM_ID;
     } else {
@@ -875,64 +827,6 @@
   return evt_type;
 }
 
-/*******************************************************************************
- *
- * Function         BTM_BleSetAdvParams
- *
- * Description      This function is called to set advertising parameters.
- *
- * Parameters       adv_int_min: minimum advertising interval
- *                  adv_int_max: maximum advertising interval
- *                  p_dir_bda: connectable direct initiator's LE device address
- *                  chnl_map: advertising channel map.
- *
- * Returns          void
- *
- ******************************************************************************/
-tBTM_STATUS BTM_BleSetAdvParams(uint16_t adv_int_min, uint16_t adv_int_max,
-                                const RawAddress& p_dir_bda,
-                                tBTM_BLE_ADV_CHNL_MAP chnl_map) {
-  tBTM_LE_RANDOM_CB* p_addr_cb = &btm_cb.ble_ctr_cb.addr_mgnt_cb;
-  tBTM_BLE_INQ_CB* p_cb = &btm_cb.ble_ctr_cb.inq_var;
-  tBTM_STATUS status = BTM_SUCCESS;
-  RawAddress address = RawAddress::kEmpty;
-  tBLE_ADDR_TYPE init_addr_type = BLE_ADDR_PUBLIC;
-  tBLE_ADDR_TYPE own_addr_type = p_addr_cb->own_addr_type;
-  uint8_t adv_mode = p_cb->adv_mode;
-
-  BTM_TRACE_EVENT("BTM_BleSetAdvParams");
-
-  if (!controller_get_interface()->supports_ble()) return BTM_ILLEGAL_VALUE;
-
-  if (!BTM_BLE_ISVALID_PARAM(adv_int_min, BTM_BLE_ADV_INT_MIN,
-                             BTM_BLE_ADV_INT_MAX) ||
-      !BTM_BLE_ISVALID_PARAM(adv_int_max, BTM_BLE_ADV_INT_MIN,
-                             BTM_BLE_ADV_INT_MAX)) {
-    return BTM_ILLEGAL_VALUE;
-  }
-
-  p_cb->adv_interval_min = adv_int_min;
-  p_cb->adv_interval_max = adv_int_max;
-  p_cb->adv_chnl_map = chnl_map;
-  p_cb->direct_bda.bda = p_dir_bda;
-
-  BTM_TRACE_EVENT("update params for an active adv");
-
-  btm_ble_stop_adv();
-
-  p_cb->evt_type = btm_set_conn_mode_adv_init_addr(
-      p_cb, address, &init_addr_type, &own_addr_type);
-
-  /* update adv params */
-  btsnd_hcic_ble_write_adv_params(
-      p_cb->adv_interval_min, p_cb->adv_interval_max, p_cb->evt_type,
-      own_addr_type, init_addr_type, address, p_cb->adv_chnl_map, p_cb->afp);
-
-  if (adv_mode == BTM_BLE_ADV_ENABLE) btm_ble_start_adv();
-
-  return status;
-}
-
 /**
  * This function is called to set scan parameters. |cb| is called with operation
  * status
@@ -1416,7 +1310,7 @@
 
     if (duration != 0) {
       /* start inquiry timer */
-      period_ms_t duration_ms = duration * 1000;
+      uint64_t duration_ms = duration * 1000;
       alarm_set_on_mloop(p_ble_cb->inq_var.inquiry_timer, duration_ms,
                          btm_ble_inquiry_timer_timeout, NULL);
     }
@@ -1584,7 +1478,7 @@
   if (!adv_data.empty()) {
     const uint8_t* p_flag = AdvertiseDataParser::GetFieldByType(
         adv_data, BTM_BLE_AD_TYPE_FLAG, &data_len);
-    if (p_flag != NULL) {
+    if (p_flag != NULL && data_len != 0) {
       flag = *p_flag;
 
       if ((btm_cb.btm_inq_vars.inq_active & BTM_BLE_GENERAL_INQUIRY) &&
@@ -1770,7 +1664,7 @@
   if (!data.empty()) {
     const uint8_t* p_flag =
         AdvertiseDataParser::GetFieldByType(data, BTM_BLE_AD_TYPE_FLAG, &len);
-    if (p_flag != NULL) p_cur->flag = *p_flag;
+    if (p_flag != NULL && len != 0) p_cur->flag = *p_flag;
   }
 
   if (!data.empty()) {
@@ -2591,8 +2485,7 @@
      now in order */
   if (btm_ble_get_conn_st() == BLE_CONN_IDLE &&
       status != HCI_ERR_HOST_REJECT_RESOURCES &&
-      status != HCI_ERR_MAX_NUM_OF_CONNECTIONS &&
-      !btm_send_pending_direct_conn()) {
+      status != HCI_ERR_MAX_NUM_OF_CONNECTIONS) {
     btm_ble_resume_bg_conn();
   }
 }
@@ -2619,7 +2512,6 @@
 
   p_cb->observer_timer = alarm_new("btm_ble.observer_timer");
   p_cb->cur_states = 0;
-  p_cb->conn_pending_q = fixed_queue_new(SIZE_MAX);
 
   p_cb->inq_var.adv_mode = BTM_BLE_ADV_DISABLE;
   p_cb->inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE;
diff --git a/stack/btm/btm_ble_int.h b/stack/btm/btm_ble_int.h
index d4cb411..fc1bfcf 100644
--- a/stack/btm/btm_ble_int.h
+++ b/stack/btm/btm_ble_int.h
@@ -68,7 +68,6 @@
 extern void btm_read_ble_local_supported_states_complete(uint8_t* p,
                                                          uint16_t evt_len);
 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 tBTM_STATUS btm_ble_start_adv(void);
 extern tBTM_STATUS btm_ble_stop_adv(void);
 extern void btm_le_on_advertising_set_terminated(uint8_t* p, uint16_t length);
@@ -80,7 +79,7 @@
                                    tBTM_LE_AUTH_REQ auth_req,
                                    tBTM_BLE_SEC_REQ_ACT* p_sec_req_act);
 extern void btm_ble_ltk_request_reply(const RawAddress& bda, bool use_stk,
-                                      BT_OCTET16 stk);
+                                      const Octet16& stk);
 extern uint8_t btm_proc_smp_cback(tSMP_EVT event, const RawAddress& bd_addr,
                                   tSMP_EVT_DATA* p_data);
 extern tBTM_STATUS btm_ble_set_encryption(const RawAddress& bd_addr,
@@ -89,7 +88,7 @@
 extern void btm_ble_ltk_request(uint16_t handle, uint8_t rand[8],
                                 uint16_t ediv);
 extern tBTM_STATUS btm_ble_start_encrypt(const RawAddress& bda, bool use_stk,
-                                         BT_OCTET16 stk);
+                                         Octet16* p_stk);
 extern void btm_ble_link_encrypted(const RawAddress& bd_addr,
                                    uint8_t encr_enable);
 
@@ -116,31 +115,15 @@
 extern uint8_t btm_ble_read_sec_key_size(const RawAddress& bd_addr);
 
 /* white list function */
-extern bool btm_update_dev_to_white_list(bool to_add,
-                                         const RawAddress& bd_addr);
 extern void btm_update_scanner_filter_policy(tBTM_BLE_SFP scan_policy);
 extern void btm_update_adv_filter_policy(tBTM_BLE_AFP adv_policy);
-extern void btm_ble_clear_white_list(void);
-extern void btm_read_white_list_size_complete(uint8_t* p, uint16_t evt_len);
-extern void btm_ble_add_2_white_list_complete(uint8_t status);
-extern void btm_ble_remove_from_white_list_complete(uint8_t* p,
-                                                    uint16_t evt_len);
-extern void btm_ble_clear_white_list_complete(uint8_t* p, uint16_t evt_len);
 extern void btm_ble_white_list_init(uint8_t white_list_size);
 
 /* background connection function */
 extern bool btm_ble_suspend_bg_conn(void);
 extern bool btm_ble_resume_bg_conn(void);
-extern void btm_send_hci_create_connection(
-    uint16_t scan_int, uint16_t scan_win, uint8_t init_filter_policy,
-    uint8_t addr_type_peer, const RawAddress& bda_peer, uint8_t addr_type_own,
-    uint16_t conn_int_min, uint16_t conn_int_max, uint16_t conn_latency,
-    uint16_t conn_timeout, uint16_t min_ce_len, uint16_t max_ce_len,
-    uint8_t phy);
-extern bool btm_ble_start_auto_conn(bool start);
-extern bool btm_ble_start_select_conn(bool start);
-extern bool btm_ble_renew_bg_conn_params(bool add, const RawAddress& bd_addr);
-extern void btm_write_dir_conn_wl(const RawAddress& target_addr);
+extern bool btm_ble_start_auto_conn();
+extern bool btm_ble_stop_auto_conn();
 extern void btm_ble_update_mode_operation(uint8_t link_role,
                                           const RawAddress* bda,
                                           uint8_t status);
@@ -148,18 +131,14 @@
 extern void btm_ble_update_link_topology_mask(uint8_t role, bool increase);
 extern void btm_ble_bgconn_cancel_if_disconnected(const RawAddress& bd_addr);
 
-/* direct connection utility */
-extern bool 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(const RawAddress& rem_bda);
-
 /* BLE address management */
-extern void btm_gen_resolvable_private_addr(base::Callback<void(BT_OCTET8)> cb);
+extern void btm_gen_resolvable_private_addr(
+    base::Callback<void(const RawAddress& rpa)> cb);
 extern void btm_gen_non_resolvable_private_addr(tBTM_BLE_ADDR_CBACK* p_cback,
                                                 void* p);
 extern tBTM_SEC_DEV_REC* btm_ble_resolve_random_addr(
     const RawAddress& random_bda);
-extern void btm_gen_resolve_paddr_low(BT_OCTET8 rand);
+extern void btm_gen_resolve_paddr_low(const RawAddress& address);
 
 /*  privacy function */
 #if (BLE_PRIVACY_SPT == TRUE)
@@ -168,7 +147,7 @@
                                                uint8_t* p_addr_type,
                                                bool refresh);
 extern bool btm_random_pseudo_to_identity_addr(RawAddress* random_pseudo,
-                                               uint8_t* p_static_addr_type);
+                                               uint8_t* p_identity_addr_type);
 extern void btm_ble_refresh_peer_resolvable_private_addr(
     const RawAddress& pseudo_bda, const RawAddress& rra, uint8_t rra_type);
 extern void btm_ble_refresh_local_resolvable_private_addr(
diff --git a/stack/btm/btm_ble_int_types.h b/stack/btm/btm_ble_int_types.h
index 2167f2f..d2fa554 100644
--- a/stack/btm/btm_ble_int_types.h
+++ b/stack/btm/btm_ble_int_types.h
@@ -185,9 +185,8 @@
 } tBTM_LE_BG_CONN_DEV;
 
 /* white list using state as a bit mask */
-#define BTM_BLE_WL_IDLE 0
-#define BTM_BLE_WL_INIT 1
-typedef uint8_t tBTM_BLE_WL_STATE;
+constexpr uint8_t BTM_BLE_WL_IDLE = 0;
+constexpr uint8_t BTM_BLE_WL_INIT = 1;
 
 /* resolving list using state as a bit mask */
 #define BTM_BLE_RL_IDLE 0
@@ -198,8 +197,7 @@
 
 /* BLE connection state */
 #define BLE_CONN_IDLE 0
-#define BLE_DIR_CONN 1
-#define BLE_BG_CONN 2
+#define BLE_CONNECTING 2
 #define BLE_CONN_CANCEL 3
 typedef uint8_t tBTM_BLE_CONN_ST;
 
@@ -287,14 +285,12 @@
   alarm_t* observer_timer;
 
   /* background connection procedure cb value */
-  tBTM_BLE_CONN_TYPE bg_conn_type;
-  uint32_t scan_int;
-  uint32_t scan_win;
+  uint16_t scan_int;
+  uint16_t scan_win;
 
   /* white list information */
-  tBTM_BLE_WL_STATE wl_state;
+  uint8_t wl_state;
 
-  fixed_queue_t* conn_pending_q;
   tBTM_BLE_CONN_ST conn_state;
 
   /* random address management control block */
diff --git a/stack/btm/btm_ble_multi_adv.cc b/stack/btm/btm_ble_multi_adv.cc
index 60490fb..22d2e17 100644
--- a/stack/btm/btm_ble_multi_adv.cc
+++ b/stack/btm/btm_ble_multi_adv.cc
@@ -17,16 +17,6 @@
  *
  ******************************************************************************/
 
-#include <base/bind.h>
-#include <base/location.h>
-#include <base/logging.h>
-#include <base/memory/weak_ptr.h>
-#include <base/strings/string_number_conversions.h>
-#include <base/time/time.h>
-#include <string.h>
-#include <queue>
-#include <vector>
-
 #include "bt_target.h"
 #include "device/include/controller.h"
 #include "osi/include/alarm.h"
@@ -35,6 +25,18 @@
 #include "ble_advertiser_hci_interface.h"
 #include "btm_int_types.h"
 
+#include <string.h>
+#include <queue>
+#include <vector>
+
+#include <base/bind.h>
+#include <base/bind_helpers.h>
+#include <base/location.h>
+#include <base/logging.h>
+#include <base/memory/weak_ptr.h>
+#include <base/strings/string_number_conversions.h>
+#include <base/time/time.h>
+
 using base::Bind;
 using base::TimeDelta;
 using base::TimeTicks;
@@ -44,7 +46,7 @@
     uint8_t /* inst_id */, int8_t /* tx_power */, uint8_t /* status */)>;
 using SetEnableData = BleAdvertiserHciInterface::SetEnableData;
 extern void btm_gen_resolvable_private_addr(
-    base::Callback<void(uint8_t[8])> cb);
+    base::Callback<void(const RawAddress& rpa)> cb);
 
 constexpr int ADV_DATA_LEN_MAX = 251;
 
@@ -113,12 +115,9 @@
 
 void btm_ble_adv_raddr_timer_timeout(void* data);
 
-void DoNothing(uint8_t) {}
-void DoNothing2(uint8_t, uint8_t) {}
-
 struct closure_data {
   base::Closure user_task;
-  tracked_objects::Location posted_from;
+  base::Location posted_from;
 };
 
 static void alarm_closure_cb(void* p) {
@@ -129,9 +128,8 @@
 }
 
 // Periodic alarms are not supported, because we clean up data in callback
-void alarm_set_closure(const tracked_objects::Location& posted_from,
-                       alarm_t* alarm, period_ms_t interval_ms,
-                       base::Closure user_task) {
+void alarm_set_closure(const base::Location& posted_from, alarm_t* alarm,
+                       uint64_t interval_ms, base::Closure user_task) {
   closure_data* data = new closure_data;
   data->posted_from = posted_from;
   data->user_task = std::move(user_task);
@@ -187,38 +185,8 @@
     }
   }
 
-  void OnRpaGenerationComplete(base::Callback<void(RawAddress)> cb,
-                               uint8_t rand[8]) {
-    VLOG(1) << __func__;
-
-    RawAddress bda;
-
-    rand[2] &= (~BLE_RESOLVE_ADDR_MASK);
-    rand[2] |= BLE_RESOLVE_ADDR_MSB;
-
-    bda.address[2] = rand[0];
-    bda.address[1] = rand[1];
-    bda.address[0] = rand[2];
-
-    BT_OCTET16 irk;
-    BTM_GetDeviceIDRoot(irk);
-    tSMP_ENC output;
-
-    if (!SMP_Encrypt(irk, BT_OCTET16_LEN, rand, 3, &output))
-      LOG_ASSERT(false) << "SMP_Encrypt failed";
-
-    /* set hash to be LSB of rpAddress */
-    bda.address[5] = output.param_buf[0];
-    bda.address[4] = output.param_buf[1];
-    bda.address[3] = output.param_buf[2];
-
-    cb.Run(bda);
-  }
-
-  void GenerateRpa(base::Callback<void(RawAddress)> cb) {
-    btm_gen_resolvable_private_addr(
-        Bind(&BleAdvertisingManagerImpl::OnRpaGenerationComplete,
-             weak_factory_.GetWeakPtr(), std::move(cb)));
+  void GenerateRpa(base::Callback<void(const RawAddress&)> cb) {
+    btm_gen_resolvable_private_addr(std::move(cb));
   }
 
   void ConfigureRpa(AdvertisingInstance* p_inst, MultiAdvCb configuredCb) {
@@ -236,7 +204,7 @@
 
     GenerateRpa(Bind(
         [](AdvertisingInstance* p_inst, MultiAdvCb configuredCb,
-           RawAddress bda) {
+           const RawAddress& bda) {
           /* Connectable advertising set must be disabled when updating RPA */
           bool restart = p_inst->IsEnabled() && p_inst->IsConnectable();
 
@@ -246,7 +214,7 @@
           if (restart) {
             p_inst->enable_status = false;
             hci_interface->Enable(false, p_inst->inst_id, 0x00, 0x00,
-                                  Bind(DoNothing));
+                                  base::DoNothing());
           }
 
           /* set it to controller */
@@ -263,7 +231,7 @@
           if (restart) {
             p_inst->enable_status = true;
             hci_interface->Enable(true, p_inst->inst_id, 0x00, 0x00,
-                                  Bind(DoNothing));
+                                  base::DoNothing());
           }
         },
         p_inst, std::move(configuredCb)));
@@ -285,7 +253,7 @@
             [](AdvertisingInstance* p_inst,
                base::Callback<void(uint8_t /* inst_id */, uint8_t /* status */)>
                    cb,
-               RawAddress bda) {
+               const RawAddress& bda) {
               p_inst->own_address = bda;
 
               alarm_set_on_mloop(p_inst->adv_raddr_timer,
@@ -630,7 +598,7 @@
 
     base::Closure cb = Bind(
         &BleAdvertisingManagerImpl::Enable, weak_factory_.GetWeakPtr(), inst_id,
-        0 /* disable */, std::move(timeout_cb), 0, 0, base::Bind(DoNothing));
+        0 /* disable */, std::move(timeout_cb), 0, 0, base::DoNothing());
 
     // schedule disable when the timeout passes
     alarm_set_closure(FROM_HERE, p_inst->timeout_timer, duration * 10,
@@ -714,7 +682,7 @@
     // TODO: disable only if was enabled, currently no use scenario needs
     // that,
     // we always set parameters before enabling
-    // GetHciInterface()->Enable(false, inst_id, Bind(DoNothing));
+    // GetHciInterface()->Enable(false, inst_id, base::DoNothing());
     p_inst->advertising_event_properties =
         p_params->advertising_event_properties;
     p_inst->tx_power = p_params->tx_power;
@@ -889,18 +857,18 @@
 
     if (adv_inst[inst_id].IsEnabled()) {
       p_inst->enable_status = false;
-      GetHciInterface()->Enable(false, inst_id, 0x00, 0x00, Bind(DoNothing));
+      GetHciInterface()->Enable(false, inst_id, 0x00, 0x00, base::DoNothing());
     }
 
     if (p_inst->periodic_enabled) {
       p_inst->periodic_enabled = false;
       GetHciInterface()->SetPeriodicAdvertisingEnable(false, inst_id,
-                                                      Bind(DoNothing));
+                                                      base::DoNothing());
     }
 
     alarm_cancel(p_inst->adv_raddr_timer);
     p_inst->in_use = false;
-    GetHciInterface()->RemoveAdvertisingSet(inst_id, Bind(DoNothing));
+    GetHciInterface()->RemoveAdvertisingSet(inst_id, base::DoNothing());
     p_inst->address_update_required = false;
   }
 
@@ -931,7 +899,7 @@
     }
   }
 
-  void Suspend() {
+  void Suspend() override {
     std::vector<SetEnableData> sets;
 
     for (AdvertisingInstance& inst : adv_inst) {
@@ -943,7 +911,8 @@
       sets.emplace_back(SetEnableData{.handle = inst.inst_id});
     }
 
-    if (!sets.empty()) GetHciInterface()->Enable(false, sets, Bind(DoNothing));
+    if (!sets.empty())
+      GetHciInterface()->Enable(false, sets, base::DoNothing());
   }
 
   void Resume() override {
@@ -958,7 +927,7 @@
       }
     }
 
-    if (!sets.empty()) GetHciInterface()->Enable(true, sets, Bind(DoNothing));
+    if (!sets.empty()) GetHciInterface()->Enable(true, sets, base::DoNothing());
   }
 
   void OnAdvertisingSetTerminated(
@@ -999,7 +968,7 @@
         RecomputeTimeout(p_inst, TimeTicks::Now());
         if (p_inst->enable_status) {
           GetHciInterface()->Enable(true, advertising_handle, p_inst->duration,
-                                    p_inst->maxExtAdvEvents, Bind(DoNothing));
+                                    p_inst->maxExtAdvEvents, base::DoNothing());
         }
 
       } else {
@@ -1040,7 +1009,7 @@
 
 void btm_ble_adv_raddr_timer_timeout(void* data) {
   BleAdvertisingManagerImpl* ptr = instance_weakptr.get();
-  if (ptr) ptr->ConfigureRpa((AdvertisingInstance*)data, base::Bind(DoNothing));
+  if (ptr) ptr->ConfigureRpa((AdvertisingInstance*)data, base::DoNothing());
 }
 }  // namespace
 
@@ -1073,7 +1042,7 @@
 
   if (BleAdvertiserHciInterface::Get()->QuirkAdvertiserZeroHandle()) {
     // If handle 0 can't be used, register advertiser for it, but never use it.
-    BleAdvertisingManager::Get().get()->RegisterAdvertiser(Bind(DoNothing2));
+    BleAdvertisingManager::Get().get()->RegisterAdvertiser(base::DoNothing());
   }
 }
 
diff --git a/stack/btm/btm_ble_privacy.cc b/stack/btm/btm_ble_privacy.cc
index 3845ba6..4f1d386 100644
--- a/stack/btm/btm_ble_privacy.cc
+++ b/stack/btm/btm_ble_privacy.cc
@@ -415,15 +415,15 @@
     return BTM_WRONG_MODE;
 
   if (controller_get_interface()->supports_ble_privacy()) {
-    btsnd_hcic_ble_rm_device_resolving_list(p_dev_rec->ble.static_addr_type,
-                                            p_dev_rec->ble.static_addr);
+    btsnd_hcic_ble_rm_device_resolving_list(p_dev_rec->ble.identity_addr_type,
+                                            p_dev_rec->ble.identity_addr);
   } else {
     uint8_t param[20] = {0};
     uint8_t* p = param;
 
     UINT8_TO_STREAM(p, BTM_BLE_META_REMOVE_IRK_ENTRY);
-    UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
-    BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+    UINT8_TO_STREAM(p, p_dev_rec->ble.identity_addr_type);
+    BDADDR_TO_STREAM(p, p_dev_rec->ble.identity_addr);
 
     BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC,
                               BTM_BLE_META_REMOVE_IRK_LEN, param,
@@ -474,8 +474,8 @@
     return BTM_WRONG_MODE;
 
   if (controller_get_interface()->supports_ble_privacy()) {
-    btsnd_hcic_ble_read_resolvable_addr_peer(p_dev_rec->ble.static_addr_type,
-                                             p_dev_rec->ble.static_addr);
+    btsnd_hcic_ble_read_resolvable_addr_peer(p_dev_rec->ble.identity_addr_type,
+                                             p_dev_rec->ble.identity_addr);
   } else {
     uint8_t param[20] = {0};
     uint8_t* p = param;
@@ -514,12 +514,6 @@
   /* if already suspended */
   if (p_ble_cb->suspended_rl_state != BTM_BLE_RL_IDLE) return true;
 
-  /* direct connection active, wait until it completed */
-  if (btm_ble_get_conn_st() == BLE_DIR_CONN) {
-    BTM_TRACE_ERROR("resolving list can not be edited, EnQ now");
-    return false;
-  }
-
   p_ble_cb->suspended_rl_state = BTM_BLE_RL_IDLE;
 
   if (p_ble_cb->inq_var.adv_mode == BTM_BLE_ADV_ENABLE) {
@@ -728,35 +722,35 @@
 
   btm_ble_update_resolving_list(p_dev_rec->bd_addr, true);
   if (controller_get_interface()->supports_ble_privacy()) {
-    uint8_t* peer_irk = p_dev_rec->ble.keys.irk;
-    uint8_t* local_irk = btm_cb.devcb.id_keys.irk;
+    const Octet16& peer_irk = p_dev_rec->ble.keys.irk;
+    const Octet16& local_irk = btm_cb.devcb.id_keys.irk;
 
-    if (p_dev_rec->ble.static_addr.IsEmpty()) {
-      p_dev_rec->ble.static_addr = p_dev_rec->bd_addr;
-      p_dev_rec->ble.static_addr_type = p_dev_rec->ble.ble_addr_type;
+    if (p_dev_rec->ble.identity_addr.IsEmpty()) {
+      p_dev_rec->ble.identity_addr = p_dev_rec->bd_addr;
+      p_dev_rec->ble.identity_addr_type = p_dev_rec->ble.ble_addr_type;
     }
 
     BTM_TRACE_DEBUG("%s: adding device %s to controller resolving list",
-                    __func__, p_dev_rec->ble.static_addr.ToString().c_str());
+                    __func__, p_dev_rec->ble.identity_addr.ToString().c_str());
 
     // use identical IRK for now
-    btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.static_addr_type,
-                                             p_dev_rec->ble.static_addr,
+    btsnd_hcic_ble_add_device_resolving_list(p_dev_rec->ble.identity_addr_type,
+                                             p_dev_rec->ble.identity_addr,
                                              peer_irk, local_irk);
 
     if (controller_get_interface()->supports_ble_set_privacy_mode()) {
       BTM_TRACE_DEBUG("%s: adding device privacy mode", __func__);
-      btsnd_hcic_ble_set_privacy_mode(p_dev_rec->ble.static_addr_type,
-                                      p_dev_rec->ble.static_addr, 0x01);
+      btsnd_hcic_ble_set_privacy_mode(p_dev_rec->ble.identity_addr_type,
+                                      p_dev_rec->ble.identity_addr, 0x01);
     }
   } else {
     uint8_t param[40] = {0};
     uint8_t* p = param;
 
     UINT8_TO_STREAM(p, BTM_BLE_META_ADD_IRK_ENTRY);
-    ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, BT_OCTET16_LEN);
-    UINT8_TO_STREAM(p, p_dev_rec->ble.static_addr_type);
-    BDADDR_TO_STREAM(p, p_dev_rec->ble.static_addr);
+    ARRAY_TO_STREAM(p, p_dev_rec->ble.keys.irk, OCTET16_LEN);
+    UINT8_TO_STREAM(p, p_dev_rec->ble.identity_addr_type);
+    BDADDR_TO_STREAM(p, p_dev_rec->ble.identity_addr);
 
     BTM_VendorSpecificCommand(HCI_VENDOR_BLE_RPA_VSC, BTM_BLE_META_ADD_IRK_LEN,
                               param, btm_ble_resolving_list_vsc_op_cmpl);
diff --git a/stack/btm/btm_dev.cc b/stack/btm/btm_dev.cc
index 4aa0c04..d5e2850 100644
--- a/stack/btm/btm_dev.cc
+++ b/stack/btm/btm_dev.cc
@@ -60,7 +60,7 @@
  ******************************************************************************/
 bool BTM_SecAddDevice(const RawAddress& bd_addr, DEV_CLASS dev_class,
                       BD_NAME bd_name, uint8_t* features,
-                      uint32_t trusted_mask[], LINK_KEY link_key,
+                      uint32_t trusted_mask[], LinkKey* p_link_key,
                       uint8_t key_type, tBTM_IO_CAP io_cap,
                       uint8_t pin_length) {
   BTM_TRACE_API("%s: link key type:%x", __func__, key_type);
@@ -120,10 +120,10 @@
 
   BTM_SEC_COPY_TRUSTED_DEVICE(trusted_mask, p_dev_rec->trusted_mask);
 
-  if (link_key) {
+  if (p_link_key) {
     VLOG(2) << __func__ << ": BDA: " << bd_addr;
     p_dev_rec->sec_flags |= BTM_SEC_LINK_KEY_KNOWN;
-    memcpy(p_dev_rec->link_key, link_key, LINK_KEY_LEN);
+    p_dev_rec->link_key = *p_link_key;
     p_dev_rec->link_key_type = key_type;
     p_dev_rec->pin_code_length = pin_length;
 
@@ -150,7 +150,7 @@
 }
 
 void wipe_secrets_and_remove(tBTM_SEC_DEV_REC* p_dev_rec) {
-  memset(p_dev_rec->link_key, 0, LINK_KEY_LEN);
+  p_dev_rec->link_key.fill(0);
   memset(&p_dev_rec->ble.keys, 0, sizeof(tBTM_SEC_BLE_KEYS));
   list_remove(btm_cb.sec_dev_rec, p_dev_rec);
 }
@@ -281,10 +281,8 @@
   uint8_t xx;
   bool feature_empty = true;
 
-#if (BTM_SCO_INCLUDED == TRUE)
   /* Role switch is not allowed if a SCO is up */
   if (btm_is_sco_active_by_bdaddr(bd_addr)) return (false);
-#endif
   p_dev_rec = btm_find_dev(bd_addr);
   if (p_dev_rec &&
       controller_get_interface()->supports_master_slave_role_switch()) {
diff --git a/stack/btm/btm_devctl.cc b/stack/btm/btm_devctl.cc
index 2e425aa..bc3fb56 100644
--- a/stack/btm/btm_devctl.cc
+++ b/stack/btm/btm_devctl.cc
@@ -34,16 +34,17 @@
 #include "btcore/include/module.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/message_loop_thread.h"
 #include "device/include/controller.h"
 #include "hci_layer.h"
 #include "hcimsgs.h"
 #include "l2c_int.h"
 #include "osi/include/osi.h"
-#include "osi/include/thread.h"
+#include "stack/gatt/connection_manager.h"
 
 #include "gatt_int.h"
 
-extern thread_t* bt_workqueue_thread;
+extern bluetooth::common::MessageLoopThread bt_startup_thread;
 
 /******************************************************************************/
 /*               L O C A L    D A T A    D E F I N I T I O N S                */
@@ -66,6 +67,7 @@
 
 static void btm_decode_ext_features_page(uint8_t page_number,
                                          const BD_FEATURES p_features);
+static void BTM_BT_Quality_Report_VSE_CBack(uint8_t length, uint8_t* p_stream);
 
 /*******************************************************************************
  *
@@ -76,7 +78,7 @@
  * Returns          void
  *
  ******************************************************************************/
-void btm_dev_init(void) {
+void btm_dev_init() {
   /* Initialize nonzero defaults */
   memset(btm_cb.cfg.bd_name, 0, sizeof(tBTM_LOC_BD_NAME));
 
@@ -188,8 +190,7 @@
   btm_cb.btm_inq_vars.page_scan_type = HCI_DEF_SCAN_TYPE;
 
   btm_cb.ble_ctr_cb.conn_state = BLE_CONN_IDLE;
-  btm_cb.ble_ctr_cb.bg_conn_type = BTM_BLE_CONN_NONE;
-  gatt_reset_bgdev_list();
+  connection_manager::reset(true);
 
   btm_pm_reset();
 
@@ -231,7 +232,7 @@
   btm_db_reset();
 
   module_start_up_callbacked_wrapper(get_module(CONTROLLER_MODULE),
-                                     bt_workqueue_thread, reset_complete);
+                                     &bt_startup_thread, reset_complete);
 }
 
 /*******************************************************************************
@@ -320,9 +321,7 @@
 
       /* Create (e)SCO supported packet types mask */
       btm_cb.btm_sco_pkt_types_supported = 0;
-#if (BTM_SCO_INCLUDED == TRUE)
       btm_cb.sco_cb.esco_supported = false;
-#endif
       if (HCI_SCO_LINK_SUPPORTED(p_features)) {
         btm_cb.btm_sco_pkt_types_supported = ESCO_PKT_TYPES_MASK_HV1;
 
@@ -867,3 +866,74 @@
   /* Call the call back to pass the device status to application */
   if (p_cb) (*p_cb)(status);
 }
+
+/*******************************************************************************
+ *
+ * Function         BTM_BT_Quality_Report_VSE_CBack
+ *
+ * Description      Callback invoked on receiving of Vendor Specific Events.
+ *                  This function will call registered BQR report receiver if
+ *                  Bluetooth Quality Report sub-event is identified.
+ *
+ * Parameters:      length - Lengths of all of the parameters contained in the
+ *                    Vendor Specific Event.
+ *                  p_stream - A pointer to the quality report which is sent
+ *                    from the Bluetooth controller via Vendor Specific Event.
+ *
+ ******************************************************************************/
+static void BTM_BT_Quality_Report_VSE_CBack(uint8_t length, uint8_t* p_stream) {
+  if (length == 0) {
+    LOG(WARNING) << __func__ << ": Lengths of all of the parameters are zero.";
+    return;
+  }
+
+  uint8_t sub_event = 0;
+  STREAM_TO_UINT8(sub_event, p_stream);
+  length--;
+
+  if (sub_event == HCI_VSE_SUBCODE_BQR_SUB_EVT) {
+    LOG(INFO) << __func__
+              << ": BQR sub event, report length: " << std::to_string(length);
+
+    if (btm_cb.p_bqr_report_receiver == nullptr) {
+      LOG(WARNING) << __func__ << ": No registered report receiver.";
+      return;
+    }
+
+    btm_cb.p_bqr_report_receiver(length, p_stream);
+  }
+}
+
+/*******************************************************************************
+ *
+ * Function         BTM_BT_Quality_Report_VSE_Register
+ *
+ * Description      Register/Deregister for Bluetooth Quality Report VSE sub
+ *                  event Callback.
+ *
+ * Parameters:      is_register - True/False to register/unregister for VSE.
+ *                  p_bqr_report_receiver - The receiver for receiving Bluetooth
+ *                    Quality Report VSE sub event.
+ *
+ ******************************************************************************/
+tBTM_STATUS BTM_BT_Quality_Report_VSE_Register(
+    bool is_register, tBTM_BT_QUALITY_REPORT_RECEIVER* p_bqr_report_receiver) {
+  tBTM_STATUS retval =
+      BTM_RegisterForVSEvents(BTM_BT_Quality_Report_VSE_CBack, is_register);
+
+  if (retval != BTM_SUCCESS) {
+    LOG(WARNING) << __func__ << ": Fail to (un)register VSEvents: " << retval
+                 << ", is_register: " << logbool(is_register);
+    return retval;
+  }
+
+  if (is_register) {
+    btm_cb.p_bqr_report_receiver = p_bqr_report_receiver;
+  } else {
+    btm_cb.p_bqr_report_receiver = nullptr;
+  }
+
+  LOG(INFO) << __func__ << ": Success to (un)register VSEvents."
+            << " is_register: " << logbool(is_register);
+  return retval;
+}
diff --git a/stack/btm/btm_inq.cc b/stack/btm/btm_inq.cc
index bdcce38..1a5d7f5 100644
--- a/stack/btm/btm_inq.cc
+++ b/stack/btm/btm_inq.cc
@@ -30,9 +30,9 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "common/time_util.h"
 #include "device/include/controller.h"
 #include "osi/include/osi.h"
-#include "osi/include/time.h"
 
 #include "advertise_data_parser.h"
 #include "bt_common.h"
@@ -1324,7 +1324,7 @@
   uint16_t xx;
   tINQ_DB_ENT* p_ent = btm_cb.btm_inq_vars.inq_db;
   tINQ_DB_ENT* p_old = btm_cb.btm_inq_vars.inq_db;
-  uint32_t ot = 0xFFFFFFFF;
+  uint64_t ot = UINT64_MAX;
 
   for (xx = 0; xx < BTM_INQ_DB_SIZE; xx++, p_ent++) {
     if (!p_ent->in_use) {
@@ -1738,7 +1738,7 @@
       p_cur->dev_class[2] = dc[2];
       p_cur->clock_offset = clock_offset | BTM_CLOCK_OFFSET_VALID;
 
-      p_i->time_of_resp = time_get_os_boottime_ms();
+      p_i->time_of_resp = bluetooth::common::time_get_os_boottime_ms();
 
       if (p_i->inq_count != p_inq->inq_counter)
         p_inq->inq_cmpl_info.num_resp++; /* A new response was found */
@@ -1951,7 +1951,7 @@
  *
  ******************************************************************************/
 tBTM_STATUS btm_initiate_rem_name(const RawAddress& remote_bda, uint8_t origin,
-                                  period_ms_t timeout_ms, tBTM_CMPL_CB* p_cb) {
+                                  uint64_t timeout_ms, tBTM_CMPL_CB* p_cb) {
   tBTM_INQUIRY_VAR_ST* p_inq = &btm_cb.btm_inq_vars;
 
   /*** Make sure the device is ready ***/
diff --git a/stack/btm/btm_int.h b/stack/btm/btm_int.h
index 761061e..6b80717 100644
--- a/stack/btm/btm_int.h
+++ b/stack/btm/btm_int.h
@@ -39,6 +39,7 @@
 
 #include "btm_ble_int.h"
 #include "btm_int_types.h"
+#include "l2cdefs.h"
 #include "smp_api.h"
 
 extern tBTM_CB btm_cb;
@@ -53,7 +54,7 @@
  ******************************************
 */
 extern tBTM_STATUS btm_initiate_rem_name(const RawAddress& remote_bda,
-                                         uint8_t origin, period_ms_t timeout_ms,
+                                         uint8_t origin, uint64_t timeout_ms,
                                          tBTM_CMPL_CB* p_cb);
 
 extern void btm_process_remote_name(const RawAddress* bda, BD_NAME name,
@@ -142,12 +143,7 @@
 extern void btm_pm_proc_ssr_evt(uint8_t* p, uint16_t evt_len);
 extern tBTM_STATUS btm_read_power_mode_state(const RawAddress& remote_bda,
                                              tBTM_PM_STATE* pmState);
-#if (BTM_SCO_INCLUDED == TRUE)
 extern void btm_sco_chk_pend_unpark(uint8_t hci_status, uint16_t hci_handle);
-#else
-#define btm_sco_chk_pend_unpark(hci_status, hci_handle)
-#endif /* BTM_SCO_INCLUDED */
-
 extern void btm_qos_setup_timeout(void* data);
 extern void btm_qos_setup_complete(uint8_t status, uint16_t handle,
                                    FLOW_SPEC* p_flow);
@@ -181,10 +177,6 @@
 extern void btm_read_local_name_timeout(void* data);
 extern void btm_read_local_name_complete(uint8_t* p, uint16_t evt_len);
 
-extern void btm_ble_add_2_white_list_complete(uint8_t status);
-extern void btm_ble_remove_from_white_list_complete(uint8_t* p,
-                                                    uint16_t evt_len);
-extern void btm_ble_clear_white_list_complete(uint8_t* p, uint16_t evt_len);
 extern void btm_ble_create_conn_cancel_complete(uint8_t* p);
 extern bool btm_ble_addr_resolvable(const RawAddress& rpa,
                                     tBTM_SEC_DEV_REC* p_dev_rec);
@@ -200,6 +192,8 @@
 extern void btm_vendor_specific_evt(uint8_t* p, uint8_t evt_len);
 extern void btm_delete_stored_link_key_complete(uint8_t* p);
 extern void btm_report_device_status(tBTM_DEV_STATUS status);
+extern tBTM_STATUS BTM_BT_Quality_Report_VSE_Register(
+    bool is_register, tBTM_BT_QUALITY_REPORT_RECEIVER* p_bqr_report_receiver);
 
 /* Internal functions provided by btm_dev.cc
  *********************************************
@@ -256,7 +250,7 @@
 extern void btm_keypress_notif_evt(uint8_t* p);
 extern void btm_simple_pair_complete(uint8_t* p);
 extern void btm_sec_link_key_notification(const RawAddress& p_bda,
-                                          uint8_t* p_link_key,
+                                          const Octet16& link_key,
                                           uint8_t key_type);
 extern void btm_sec_link_key_request(const RawAddress& p_bda);
 extern void btm_sec_pin_code_request(const RawAddress& p_bda);
@@ -274,10 +268,9 @@
                                      const RawAddress& new_pseudo_addr);
 extern tBTM_SEC_SERV_REC* btm_sec_find_first_serv(CONNECTION_TYPE conn_type,
                                                   uint16_t psm);
-extern bool btm_ble_start_sec_check(const RawAddress& bd_addr, uint16_t psm,
-                                    bool is_originator,
-                                    tBTM_SEC_CALLBACK* p_callback,
-                                    void* p_ref_data);
+extern tL2CAP_LE_RESULT_CODE btm_ble_start_sec_check(
+    const RawAddress& bd_addr, uint16_t psm, bool is_originator,
+    tBTM_SEC_CALLBACK* p_callback, void* p_ref_data);
 
 extern tINQ_DB_ENT* btm_inq_db_new(const RawAddress& p_bda);
 
diff --git a/stack/btm/btm_int_types.h b/stack/btm/btm_int_types.h
index 8f91cef..a0460b1 100644
--- a/stack/btm/btm_int_types.h
+++ b/stack/btm/btm_int_types.h
@@ -18,6 +18,7 @@
 #ifndef BTM_INT_TYPES_H
 #define BTM_INT_TYPES_H
 
+#include "btif/include/btif_bqr.h"
 #include "btm_api_types.h"
 #include "btm_ble_api_types.h"
 #include "btm_ble_int_types.h"
@@ -170,7 +171,7 @@
   uint8_t le_supported_states[BTM_LE_SUPPORT_STATE_SIZE];
 
   tBTM_BLE_LOCAL_ID_KEYS id_keys;      /* local BLE ID keys */
-  BT_OCTET16 ble_encryption_key_value; /* BLE encryption key */
+  Octet16 ble_encryption_key_value;    /* BLE encryption key */
 
 #if (BTM_BLE_CONFORMANCE_TESTING == TRUE)
   bool no_disc_if_pair_fail;
@@ -210,7 +211,7 @@
 } tINQ_BDADDR;
 
 typedef struct {
-  uint32_t time_of_resp;
+  uint64_t time_of_resp;
   uint32_t
       inq_count; /* "timestamps" the entry with a particular inquiry count   */
                  /* Used for determining if a response has already been      */
@@ -369,7 +370,6 @@
   esco_data_path_t sco_route; /* HCI, PCM, or TEST */
 } tSCO_CB;
 
-#if (BTM_SCO_INCLUDED == TRUE)
 extern void btm_set_sco_ind_cback(tBTM_SCO_IND_CBACK* sco_ind_cb);
 extern void btm_accept_sco_link(uint16_t sco_inx, enh_esco_params_t* p_setup,
                                 tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb);
@@ -377,13 +377,6 @@
 extern void btm_sco_chk_pend_rolechange(uint16_t hci_handle);
 extern void btm_sco_disc_chk_pend_for_modechange(uint16_t hci_handle);
 
-#else
-#define btm_accept_sco_link(sco_inx, p_setup, p_conn_cb, p_disc_cb)
-#define btm_reject_sco_link(sco_inx)
-#define btm_set_sco_ind_cback(sco_ind_cb)
-#define btm_sco_chk_pend_rolechange(hci_handle)
-#endif /* BTM_SCO_INCLUDED */
-
 /*
  * Define structure for Security Service Record.
  * A record exists for each service registered with the Security Manager
@@ -415,12 +408,12 @@
 
 /* LE Security information of device in Slave Role */
 typedef struct {
-  BT_OCTET16 irk;   /* peer diverified identity root */
-  BT_OCTET16 pltk;  /* peer long term key */
-  BT_OCTET16 pcsrk; /* peer SRK peer device used to secured sign local data  */
+  Octet16 irk;   /* peer diverified identity root */
+  Octet16 pltk;  /* peer long term key */
+  Octet16 pcsrk; /* peer SRK peer device used to secured sign local data  */
 
-  BT_OCTET16 lltk;  /* local long term key */
-  BT_OCTET16 lcsrk; /* local SRK peer device used to secured sign local data  */
+  Octet16 lltk;  /* local long term key */
+  Octet16 lcsrk; /* local SRK peer device used to secured sign local data  */
 
   BT_OCTET8 rand;        /* random vector for LTK generation */
   uint16_t ediv;         /* LTK diversifier of this slave device */
@@ -440,8 +433,8 @@
   RawAddress pseudo_addr; /* LE pseudo address of the device if different from
                           device address  */
   tBLE_ADDR_TYPE ble_addr_type; /* LE device type: public or random address */
-  tBLE_ADDR_TYPE static_addr_type; /* static address type */
-  RawAddress static_addr;          /* static address */
+  tBLE_ADDR_TYPE identity_addr_type; /* identity address type */
+  RawAddress identity_addr;          /* identity address */
 
 #define BTM_WHITE_LIST_BIT 0x01
 #define BTM_RESOLVING_LIST_BIT 0x02
@@ -479,7 +472,7 @@
   uint16_t clock_offset;   /* Latest known clock offset          */
   RawAddress bd_addr;      /* BD_ADDR of the device              */
   DEV_CLASS dev_class;     /* DEV_CLASS of the device            */
-  LINK_KEY link_key;       /* Device link key                    */
+  LinkKey link_key;        /* Device link key                    */
   uint8_t pin_code_length; /* Length of the pin_code used for paring */
 
 #define BTM_SEC_AUTHORIZED BTM_SEC_FLAG_AUTHORIZED       /* 0x01 */
@@ -732,6 +725,9 @@
 #define CONN_ORIENT_ORIG true
 typedef bool CONNECTION_TYPE;
 
+// Bluetooth Quality Report - Report receiver
+typedef void(tBTM_BT_QUALITY_REPORT_RECEIVER)(uint8_t len, uint8_t* p_stream);
+
 /* Define a structure to hold all the BTM data
 */
 
@@ -784,12 +780,10 @@
   *****************************************************/
   tBTM_INQUIRY_VAR_ST btm_inq_vars;
 
-/*****************************************************
-**      SCO Management
-*****************************************************/
-#if (BTM_SCO_INCLUDED == TRUE)
+  /*****************************************************
+  **      SCO Management
+  *****************************************************/
   tSCO_CB sco_cb;
-#endif
 
   /*****************************************************
   **      Security Management
@@ -801,8 +795,7 @@
 
   tBTM_SEC_DEV_REC* p_collided_dev_rec;
   alarm_t* sec_collision_timer;
-  uint32_t collision_start_time;
-  uint32_t max_collision_delay;
+  uint64_t collision_start_time;
   uint32_t dev_rec_count; /* Counter used for device record timestamp */
   uint8_t security_mode;
   bool pairing_disabled;
@@ -839,6 +832,8 @@
                                    tBTM_SEC_QUEUE_ENTRY format */
 
   char state_temp_buffer[BTM_STATE_BUFFER_SIZE];
+  // BQR Receiver
+  tBTM_BT_QUALITY_REPORT_RECEIVER* p_bqr_report_receiver;
 } tBTM_CB;
 
 /* security action for L2CAP COC channels */
diff --git a/stack/btm/btm_main.cc b/stack/btm/btm_main.cc
index 13d977e..f58f444 100644
--- a/stack/btm/btm_main.cc
+++ b/stack/btm/btm_main.cc
@@ -66,9 +66,7 @@
     btm_sec_init(BTM_SEC_MODE_SC);
   else
     btm_sec_init(BTM_SEC_MODE_SP);
-#if (BTM_SCO_INCLUDED == TRUE)
   btm_sco_init(); /* SCO Database and Structures (If included) */
-#endif
 
   btm_cb.sec_dev_rec = list_new(osi_free);
 
diff --git a/stack/btm/btm_pm.cc b/stack/btm/btm_pm.cc
index af06c1b..793c854 100644
--- a/stack/btm/btm_pm.cc
+++ b/stack/btm/btm_pm.cc
@@ -813,10 +813,8 @@
       (*btm_cb.pm_reg_db[yy].cback)(p->remote_addr, mode, interval, hci_status);
     }
   }
-#if (BTM_SCO_INCLUDED == TRUE)
   /*check if sco disconnect  is waiting for the mode change */
   btm_sco_disc_chk_pend_for_modechange(hci_handle);
-#endif
 
   /* If mode change was because of an active role switch or change link key */
   btm_cont_rswitch(p, btm_find_dev(p->remote_addr), hci_status);
diff --git a/stack/btm/btm_sco.cc b/stack/btm/btm_sco.cc
index 6e7f97c..d8d2def 100644
--- a/stack/btm/btm_sco.cc
+++ b/stack/btm/btm_sco.cc
@@ -40,8 +40,6 @@
 #include "hcimsgs.h"
 #include "osi/include/osi.h"
 
-#if (BTM_SCO_INCLUDED == TRUE)
-
 /******************************************************************************/
 /*               L O C A L    D A T A    D E F I N I T I O N S                */
 /******************************************************************************/
@@ -485,8 +483,7 @@
     if (p->state == SCO_ST_UNUSED) {
       if (remote_bda) {
         if (is_orig) {
-/* can not create SCO link if in park mode */
-#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
+          // can not create SCO link if in park mode
           tBTM_PM_STATE state;
           if ((btm_read_power_mode_state(*remote_bda, &state) == BTM_SUCCESS)) {
             if (state == BTM_PM_ST_SNIFF || state == BTM_PM_ST_PARK ||
@@ -503,12 +500,6 @@
             LOG(ERROR) << __func__ << ": failed to read power mode for "
                        << *remote_bda;
           }
-#else   // BTM_SCO_WAKE_PARKED_LINK
-          uint8_t mode;
-          if ((BTM_ReadPowerMode(*remote_bda, &mode) == BTM_SUCCESS) &&
-              (mode == BTM_PM_MD_PARK))
-            return (BTM_WRONG_MODE);
-#endif  // BTM_SCO_WAKE_PARKED_LINK
         }
         p->esco.data.bd_addr = *remote_bda;
         p->rem_bd_known = true;
@@ -580,7 +571,6 @@
   return BTM_NO_RESOURCES;
 }
 
-#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
 /*******************************************************************************
  *
  * Function         btm_sco_chk_pend_unpark
@@ -614,7 +604,6 @@
   }
 #endif  // BTM_MAX_SCO_LINKS
 }
-#endif  // BTM_SCO_WAKE_PARKED_LINK
 
 /*******************************************************************************
  *
@@ -1691,43 +1680,3 @@
 
   return (voice_settings);
 }
-
-#else /* SCO_EXCLUDED == TRUE (Link in stubs) */
-
-tBTM_STATUS BTM_CreateSco(const RawAddress* remote_bda, bool is_orig,
-                          uint16_t pkt_types, uint16_t* p_sco_inx,
-                          tBTM_SCO_CB* p_conn_cb, tBTM_SCO_CB* p_disc_cb) {
-  return (BTM_NO_RESOURCES);
-}
-tBTM_STATUS BTM_RemoveSco(uint16_t sco_inx) { return (BTM_NO_RESOURCES); }
-tBTM_STATUS BTM_SetScoPacketTypes(uint16_t sco_inx, uint16_t pkt_types) {
-  return (BTM_NO_RESOURCES);
-}
-uint16_t BTM_ReadScoPacketTypes(uint16_t sco_inx) { return (0); }
-uint16_t BTM_ReadDeviceScoPacketTypes(void) { return (0); }
-uint16_t BTM_ReadScoHandle(uint16_t sco_inx) {
-  return (BTM_INVALID_HCI_HANDLE);
-}
-const RawAddress* BTM_ReadScoBdAddr(uint16_t sco_inx) {
-  return ((uint8_t*)NULL);
-}
-uint16_t BTM_ReadScoDiscReason(void) { return (BTM_INVALID_SCO_DISC_REASON); }
-tBTM_STATUS BTM_SetEScoMode(enh_esco_params_t* p_parms) {
-  return (BTM_MODE_UNSUPPORTED);
-}
-tBTM_STATUS BTM_RegForEScoEvts(uint16_t sco_inx,
-                               tBTM_ESCO_CBACK* p_esco_cback) {
-  return (BTM_ILLEGAL_VALUE);
-}
-tBTM_STATUS BTM_ReadEScoLinkParms(uint16_t sco_inx, tBTM_ESCO_DATA* p_parms) {
-  return (BTM_MODE_UNSUPPORTED);
-}
-tBTM_STATUS BTM_ChangeEScoLinkParms(uint16_t sco_inx,
-                                    tBTM_CHG_ESCO_PARAMS* p_parms) {
-  return (BTM_MODE_UNSUPPORTED);
-}
-void BTM_EScoConnRsp(uint16_t sco_inx, uint8_t hci_status,
-                     enh_esco_params_t* p_parms) {}
-uint8_t BTM_GetNumScoLinks(void) { return (0); }
-
-#endif /* If SCO is being used */
diff --git a/stack/btm/btm_sec.cc b/stack/btm/btm_sec.cc
index 19280ad..4df0974 100644
--- a/stack/btm/btm_sec.cc
+++ b/stack/btm/btm_sec.cc
@@ -24,18 +24,22 @@
 
 #define LOG_TAG "bt_btm_sec"
 
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
+#include <frameworks/base/core/proto/android/bluetooth/hci/enums.pb.h>
 #include <log/log.h>
 #include <stdarg.h>
 #include <stdio.h>
 #include <string.h>
 
+#include "common/metrics.h"
+#include "common/time_util.h"
 #include "device/include/controller.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "osi/include/time.h"
 
 #include "bt_types.h"
 #include "bt_utils.h"
+#include "btif_storage.h"
 #include "btm_int.h"
 #include "btu.h"
 #include "hcimsgs.h"
@@ -49,6 +53,8 @@
 bool(APPL_AUTH_WRITE_EXCEPTION)(const RawAddress& bd_addr);
 #endif
 
+extern void btm_ble_advertiser_notify_terminated_legacy(
+    uint8_t status, uint16_t connection_handle);
 extern void bta_dm_remove_device(const RawAddress& bd_addr);
 
 /*******************************************************************************
@@ -226,7 +232,6 @@
  *
  ******************************************************************************/
 bool BTM_SecRegister(const tBTM_APPL_INFO* p_cb_info) {
-  BT_OCTET16 temp_value = {0};
 
   BTM_TRACE_EVENT("%s application registered", __func__);
 
@@ -235,8 +240,9 @@
   if (p_cb_info->p_le_callback) {
     BTM_TRACE_EVENT("%s SMP_Register( btm_proc_smp_cback )", __func__);
     SMP_Register(btm_proc_smp_cback);
+    Octet16 zero{0};
     /* if no IR is loaded, need to regenerate all the keys */
-    if (memcmp(btm_cb.devcb.id_keys.ir, &temp_value, sizeof(BT_OCTET16)) == 0) {
+    if (btm_cb.devcb.id_keys.ir == zero) {
       btm_ble_reset_id();
     }
   } else {
@@ -1171,15 +1177,15 @@
  *                  the device or device record does not contain link key info
  *
  * Parameters:      bd_addr      - Address of the device
- *                  link_key     - Link Key is copied into this array
+ *                  link_key     - Link Key is copied into this pointer
  *
  ******************************************************************************/
 tBTM_STATUS BTM_SecGetDeviceLinkKey(const RawAddress& bd_addr,
-                                    LINK_KEY link_key) {
+                                    LinkKey* link_key) {
   tBTM_SEC_DEV_REC* p_dev_rec;
   p_dev_rec = btm_find_dev(bd_addr);
   if ((p_dev_rec != NULL) && (p_dev_rec->sec_flags & BTM_SEC_LINK_KEY_KNOWN)) {
-    memcpy(link_key, p_dev_rec->link_key, LINK_KEY_LEN);
+    *link_key = p_dev_rec->link_key;
     return (BTM_SUCCESS);
   }
   return (BTM_UNKNOWN_ADDR);
@@ -1435,7 +1441,6 @@
  *                  BTM_MAX_PASSKEY_VAL(999999(0xF423F)).
  *
  ******************************************************************************/
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
 void BTM_PasskeyReqReply(tBTM_STATUS res, const RawAddress& bd_addr,
                          uint32_t passkey) {
   BTM_TRACE_API("BTM_PasskeyReqReply: State: %s  res:%d",
@@ -1482,7 +1487,6 @@
     btsnd_hcic_user_passkey_reply(bd_addr, passkey);
   }
 }
-#endif
 
 /*******************************************************************************
  *
@@ -1498,13 +1502,11 @@
  *                  type - notification type
  *
  ******************************************************************************/
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
 void BTM_SendKeypressNotif(const RawAddress& bd_addr, tBTM_SP_KEY_TYPE type) {
   /* This API only make sense between PASSKEY_REQ and SP complete */
   if (btm_cb.pairing_state == BTM_PAIR_STATE_KEY_ENTRY)
     btsnd_hcic_send_keypress_notif(bd_addr, type);
 }
-#endif
 
 /*******************************************************************************
  *
@@ -1564,7 +1566,7 @@
  *
  ******************************************************************************/
 void BTM_RemoteOobDataReply(tBTM_STATUS res, const RawAddress& bd_addr,
-                            BT_OCTET16 c, BT_OCTET16 r) {
+                            const Octet16& c, const Octet16& r) {
   BTM_TRACE_EVENT("%s() - State: %s res: %d", __func__,
                   btm_pair_state_descr(btm_cb.pairing_state), res);
 
@@ -1602,8 +1604,8 @@
  * Returns          Number of bytes in p_data.
  *
  ******************************************************************************/
-uint16_t BTM_BuildOobData(uint8_t* p_data, uint16_t max_len, BT_OCTET16 c,
-                          BT_OCTET16 r, uint8_t name_len) {
+uint16_t BTM_BuildOobData(uint8_t* p_data, uint16_t max_len, const Octet16& c,
+                          const Octet16& r, uint8_t name_len) {
   uint8_t* p = p_data;
   uint16_t len = 0;
   uint16_t name_size;
@@ -1624,7 +1626,7 @@
     if (max_len >= delta) {
       *p++ = BTM_OOB_HASH_C_SIZE + 1;
       *p++ = BTM_EIR_OOB_SSP_HASH_C_TYPE;
-      ARRAY_TO_STREAM(p, c, BTM_OOB_HASH_C_SIZE);
+      ARRAY_TO_STREAM(p, c.data(), BTM_OOB_HASH_C_SIZE);
       len += delta;
       max_len -= delta;
     }
@@ -1634,7 +1636,7 @@
     if (max_len >= delta) {
       *p++ = BTM_OOB_RAND_R_SIZE + 1;
       *p++ = BTM_EIR_OOB_SSP_RAND_R_TYPE;
-      ARRAY_TO_STREAM(p, r, BTM_OOB_RAND_R_SIZE);
+      ARRAY_TO_STREAM(p, r.data(), BTM_OOB_RAND_R_SIZE);
       len += delta;
       max_len -= delta;
     }
@@ -2609,10 +2611,18 @@
  ******************************************************************************/
 void btm_create_conn_cancel_complete(uint8_t* p) {
   uint8_t status;
-
   STREAM_TO_UINT8(status, p);
+  RawAddress bd_addr;
+  STREAM_TO_BDADDR(bd_addr, p);
   BTM_TRACE_EVENT("btm_create_conn_cancel_complete(): in State: %s  status:%d",
                   btm_pair_state_descr(btm_cb.pairing_state), status);
+  bluetooth::common::LogLinkLayerConnectionEvent(
+      &bd_addr, bluetooth::common::kUnknownConnectionHandle,
+      android::bluetooth::DIRECTION_OUTGOING, android::bluetooth::LINK_TYPE_ACL,
+      android::bluetooth::hci::CMD_CREATE_CONNECTION_CANCEL,
+      android::bluetooth::hci::EVT_COMMAND_COMPLETE,
+      android::bluetooth::hci::BLE_EVT_UNKNOWN, status,
+      android::bluetooth::hci::STATUS_UNKNOWN);
 
   /* if the create conn cancel cmd was issued by the bond cancel,
   ** the application needs to be notified that bond cancel succeeded
@@ -2691,7 +2701,6 @@
 void btm_sec_init(uint8_t sec_mode) {
   btm_cb.security_mode = sec_mode;
   btm_cb.pairing_bda = RawAddress::kAny;
-  btm_cb.max_collision_delay = BTM_SEC_MAX_COLLISION_DELAY;
 }
 
 /*******************************************************************************
@@ -2722,7 +2731,7 @@
 void btm_sec_dev_reset(void) {
   if (controller_get_interface()->supports_simple_pairing()) {
     /* set the default IO capabilities */
-    btm_cb.devcb.loc_io_caps = BTM_LOCAL_IO_CAPS;
+    btm_cb.devcb.loc_io_caps = btif_storage_get_local_io_caps();
     /* add mx service to use no security */
     BTM_SetSecurityLevel(false, "RFC_MUX", BTM_SEC_SERVICE_RFC_MUX,
                          BTM_SEC_NONE, BT_PSM_RFCOMM, BTM_SEC_PROTO_RFCOMM, 0);
@@ -2793,7 +2802,7 @@
   /* set up the control block to indicated dedicated bonding */
   btm_cb.pairing_flags |= BTM_PAIR_FLAGS_DISC_WHEN_DONE;
 
-  if (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR)) {
+  if (!l2cu_create_conn_br_edr(p_lcb)) {
     LOG(WARNING) << "Security Manager: failed create allocate LCB "
                  << p_dev_rec->bd_addr;
 
@@ -3401,26 +3410,27 @@
 
         evt_data.cfm_req.just_works = true;
 
-/* process user confirm req in association with the auth_req param */
-#if (BTM_LOCAL_IO_CAPS == BTM_IO_CAP_IO)
-        if (p_dev_rec->rmt_io_caps == BTM_IO_CAP_UNKNOWN) {
-          BTM_TRACE_ERROR(
-              "%s did not receive IO cap response prior"
-              " to BTM_SP_CFM_REQ_EVT, failing pairing request",
-              __func__);
-          status = BTM_WRONG_MODE;
-          BTM_ConfirmReqReply(status, p_bda);
-          return;
+        /* process user confirm req in association with the auth_req param */
+        if (btm_cb.devcb.loc_io_caps == BTM_IO_CAP_IO) {
+          if (p_dev_rec->rmt_io_caps == BTM_IO_CAP_UNKNOWN) {
+            BTM_TRACE_ERROR(
+                "%s did not receive IO cap response prior"
+                " to BTM_SP_CFM_REQ_EVT, failing pairing request",
+                __func__);
+            status = BTM_WRONG_MODE;
+            BTM_ConfirmReqReply(status, p_bda);
+            return;
+          }
+          if ((p_dev_rec->rmt_io_caps == BTM_IO_CAP_IO) &&
+              (btm_cb.devcb.loc_io_caps == BTM_IO_CAP_IO) &&
+              ((p_dev_rec->rmt_auth_req & BTM_AUTH_SP_YES) ||
+               (btm_cb.devcb.loc_auth_req & BTM_AUTH_SP_YES))) {
+            /* Both devices are DisplayYesNo and one or both devices want to
+               authenticate -> use authenticated link key */
+            evt_data.cfm_req.just_works = false;
+          }
         }
-        if ((p_dev_rec->rmt_io_caps == BTM_IO_CAP_IO) &&
-            (btm_cb.devcb.loc_io_caps == BTM_IO_CAP_IO) &&
-            ((p_dev_rec->rmt_auth_req & BTM_AUTH_SP_YES) ||
-             (btm_cb.devcb.loc_auth_req & BTM_AUTH_SP_YES))) {
-          /* Both devices are DisplayYesNo and one or both devices want to
-             authenticate -> use authenticated link key */
-          evt_data.cfm_req.just_works = false;
-        }
-#endif
+
         BTM_TRACE_DEBUG(
             "btm_proc_sp_req_evt()  just_works:%d, io loc:%d, rmt:%d, auth "
             "loc:%d, rmt:%d",
@@ -3443,12 +3453,12 @@
         btm_sec_change_pairing_state(BTM_PAIR_STATE_WAIT_AUTH_COMPLETE);
         break;
 
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
       case BTM_SP_KEY_REQ_EVT:
-        /* HCI_USER_PASSKEY_REQUEST_EVT */
-        btm_sec_change_pairing_state(BTM_PAIR_STATE_KEY_ENTRY);
+        if (btm_cb.devcb.loc_io_caps != BTM_IO_CAP_NONE) {
+          /* HCI_USER_PASSKEY_REQUEST_EVT */
+          btm_sec_change_pairing_state(BTM_PAIR_STATE_KEY_ENTRY);
+        }
         break;
-#endif
     }
 
     if (btm_cb.api.p_sp_callback) {
@@ -3466,12 +3476,10 @@
     if (event == BTM_SP_CFM_REQ_EVT) {
       BTM_TRACE_DEBUG("calling BTM_ConfirmReqReply with status: %d", status);
       BTM_ConfirmReqReply(status, p_bda);
-    }
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
-    else if (event == BTM_SP_KEY_REQ_EVT) {
+    } else if (btm_cb.devcb.loc_io_caps != BTM_IO_CAP_NONE &&
+               event == BTM_SP_KEY_REQ_EVT) {
       BTM_PasskeyReqReply(status, p_bda, 0);
     }
-#endif
     return;
   }
 
@@ -3492,12 +3500,9 @@
     if (p_dev_rec != NULL) {
       btm_sec_disconnect(p_dev_rec->hci_handle, HCI_ERR_AUTH_FAILURE);
     }
-  }
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
-  else {
+  } else if (btm_cb.devcb.loc_io_caps != BTM_IO_CAP_NONE) {
     btsnd_hcic_user_passkey_neg_reply(p_bda);
   }
-#endif
 }
 
 /*******************************************************************************
@@ -3612,8 +3617,8 @@
 void btm_rem_oob_req(uint8_t* p) {
   tBTM_SP_RMT_OOB evt_data;
   tBTM_SEC_DEV_REC* p_dev_rec;
-  BT_OCTET16 c;
-  BT_OCTET16 r;
+  Octet16 c;
+  Octet16 r;
 
   RawAddress& p_bda = evt_data.bd_addr;
 
@@ -3658,8 +3663,8 @@
   BTM_TRACE_EVENT("btm_read_local_oob_complete:%d", status);
   if (status == HCI_SUCCESS) {
     evt_data.status = BTM_SUCCESS;
-    STREAM_TO_ARRAY16(evt_data.c, p);
-    STREAM_TO_ARRAY16(evt_data.r, p);
+    STREAM_TO_ARRAY16(evt_data.c.data(), p);
+    STREAM_TO_ARRAY16(evt_data.r.data(), p);
   } else
     evt_data.status = BTM_ERR_PROCESSING;
 
@@ -3684,10 +3689,10 @@
   tBTM_SEC_DEV_REC* p_dev_rec;
 
   if (!btm_cb.collision_start_time)
-    btm_cb.collision_start_time = time_get_os_boottime_ms();
+    btm_cb.collision_start_time = bluetooth::common::time_get_os_boottime_ms();
 
-  if ((time_get_os_boottime_ms() - btm_cb.collision_start_time) <
-      btm_cb.max_collision_delay) {
+  if ((bluetooth::common::time_get_os_boottime_ms() -
+       btm_cb.collision_start_time) < BTM_SEC_MAX_COLLISION_DELAY) {
     if (handle == BTM_SEC_INVALID_HANDLE) {
       p_dev_rec = btm_sec_find_dev_by_sec_state(BTM_SEC_STATE_AUTHENTICATING);
       if (p_dev_rec == NULL)
@@ -4112,6 +4117,7 @@
   tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev(bda);
   uint8_t res;
   bool is_pairing_device = false;
+  bool addr_matched;
   tACL_CONN* p_acl_cb;
   uint8_t bit_shift = 0;
 
@@ -4201,8 +4207,9 @@
 
   p_dev_rec->rs_disc_pending = BTM_SEC_RS_NOT_PENDING; /* reset flag */
 
-  if ((btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) &&
-      (btm_cb.pairing_bda == bda)) {
+  addr_matched = (btm_cb.pairing_bda == bda);
+
+  if ((btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) && addr_matched) {
     /* if we rejected incoming connection from bonding device */
     if ((status == HCI_ERR_HOST_REJECT_DEVICE) &&
         (btm_cb.pairing_flags & BTM_PAIR_FLAGS_REJECTED_CONNECT)) {
@@ -4298,7 +4305,7 @@
       }
     }
 
-    if (btm_cb.pairing_bda != bda) {
+    if (!addr_matched) {
       /* Don't callback unless this Connection-Complete-failure event has the
        * same mac address as the bonding device */
       VLOG(1) << __func__
@@ -4522,6 +4529,12 @@
     p_dev_rec->ble_hci_handle = BTM_SEC_INVALID_HANDLE;
     p_dev_rec->sec_flags &= ~(BTM_SEC_LE_AUTHENTICATED | BTM_SEC_LE_ENCRYPTED);
     p_dev_rec->enc_key_size = 0;
+
+    // This is for chips that don't support being in connected and advertising
+    // state at same time.
+    if (!p_dev_rec->is_originator) {
+      btm_ble_advertiser_notify_terminated_legacy(HCI_SUCCESS, handle);
+    }
   } else {
     p_dev_rec->hci_handle = BTM_SEC_INVALID_HANDLE;
     p_dev_rec->sec_flags &=
@@ -4539,8 +4552,7 @@
    */
   if (is_sample_ltk(p_dev_rec->ble.keys.pltk)) {
     android_errorWriteLog(0x534e4554, "128437297");
-    LOG(INFO) << __func__ << " removing bond to device that used sample LTK: "
-              << p_dev_rec->bd_addr;
+    LOG(INFO) << __func__ << " removing bond to device that used sample LTK: " << p_dev_rec->bd_addr;
 
     bta_dm_remove_device(p_dev_rec->bd_addr);
   }
@@ -4571,18 +4583,9 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         btm_sec_link_key_notification
- *
- * Description      This function is called when a new connection link key is
- *                  generated
- *
- * Returns          Pointer to the record or NULL
- *
- ******************************************************************************/
-void btm_sec_link_key_notification(const RawAddress& p_bda, uint8_t* p_link_key,
-                                   uint8_t key_type) {
+/** This function is called when a new connection link key is generated */
+void btm_sec_link_key_notification(const RawAddress& p_bda,
+                                   const Octet16& link_key, uint8_t key_type) {
   tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(p_bda);
   bool we_are_bonding = false;
   bool ltk_derived_lk = false;
@@ -4615,7 +4618,7 @@
 
   /* BR/EDR connection, update the encryption key size to be 16 as always */
   p_dev_rec->enc_key_size = 16;
-  memcpy(p_dev_rec->link_key, p_link_key, LINK_KEY_LEN);
+  p_dev_rec->link_key = link_key;
 
   if ((btm_cb.pairing_state != BTM_PAIR_STATE_IDLE) &&
       (btm_cb.pairing_bda == p_bda)) {
@@ -4631,7 +4634,7 @@
       BTM_TRACE_DEBUG("%s() Save LTK derived LK (key_type = %d)", __func__,
                       p_dev_rec->link_key_type);
       (*btm_cb.api.p_link_key_callback)(p_bda, p_dev_rec->dev_class,
-                                        p_dev_rec->sec_bd_name, p_link_key,
+                                        p_dev_rec->sec_bd_name, link_key,
                                         p_dev_rec->link_key_type);
     }
   } else {
@@ -4695,7 +4698,7 @@
             p_dev_rec->link_key_type);
       } else {
         (*btm_cb.api.p_link_key_callback)(p_bda, p_dev_rec->dev_class,
-                                          p_dev_rec->sec_bd_name, p_link_key,
+                                          p_dev_rec->sec_bd_name, link_key,
                                           p_dev_rec->link_key_type);
       }
     }
@@ -4751,11 +4754,9 @@
 static void btm_sec_pairing_timeout(UNUSED_ATTR void* data) {
   tBTM_CB* p_cb = &btm_cb;
   tBTM_SEC_DEV_REC* p_dev_rec;
-#if (BTM_LOCAL_IO_CAPS == BTM_IO_CAP_NONE)
-  tBTM_AUTH_REQ auth_req = BTM_AUTH_AP_NO;
-#else
-  tBTM_AUTH_REQ auth_req = BTM_AUTH_AP_YES;
-#endif
+  tBTM_AUTH_REQ auth_req = (btm_cb.devcb.loc_io_caps == BTM_IO_CAP_NONE)
+                               ? BTM_AUTH_AP_NO
+                               : BTM_AUTH_AP_YES;
   uint8_t name[2];
 
   p_dev_rec = btm_find_dev(p_cb->pairing_bda);
@@ -4791,12 +4792,13 @@
       /* btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); */
       break;
 
-#if (BTM_LOCAL_IO_CAPS != BTM_IO_CAP_NONE)
     case BTM_PAIR_STATE_KEY_ENTRY:
-      btsnd_hcic_user_passkey_neg_reply(p_cb->pairing_bda);
-      /* btm_sec_change_pairing_state (BTM_PAIR_STATE_IDLE); */
+      if (btm_cb.devcb.loc_io_caps != BTM_IO_CAP_NONE) {
+        btsnd_hcic_user_passkey_neg_reply(p_cb->pairing_bda);
+      } else {
+        btm_sec_change_pairing_state(BTM_PAIR_STATE_IDLE);
+      }
       break;
-#endif /* !BTM_IO_CAP_NONE */
 
     case BTM_PAIR_STATE_WAIT_LOCAL_IOCAPS:
       if (btm_cb.pairing_flags & BTM_PAIR_FLAGS_WE_STARTED_DD)
diff --git a/stack/btu/btu_hcif.cc b/stack/btu/btu_hcif.cc
index b5243cd..4612422 100644
--- a/stack/btu/btu_hcif.cc
+++ b/stack/btu/btu_hcif.cc
@@ -32,6 +32,8 @@
 #include <base/location.h>
 #include <base/logging.h>
 #include <base/threading/thread.h>
+#include <frameworks/base/core/proto/android/bluetooth/enums.pb.h>
+#include <frameworks/base/core/proto/android/bluetooth/hci/enums.pb.h>
 #include <log/log.h>
 #include <statslog.h>
 #include <stdio.h>
@@ -44,6 +46,7 @@
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/metrics.h"
 #include "device/include/controller.h"
 #include "hci_layer.h"
 #include "hcimsgs.h"
@@ -51,10 +54,11 @@
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
 
-using tracked_objects::Location;
+using base::Location;
 
 extern void btm_process_cancel_complete(uint8_t status, uint8_t mode);
 extern void btm_ble_test_command_complete(uint8_t* p);
+extern void smp_cancel_start_encryption_attempt();
 
 /******************************************************************************/
 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
@@ -128,16 +132,110 @@
 static void btu_ble_proc_enhanced_conn_cmpl(uint8_t* p, uint16_t evt_len);
 #endif
 
-static void do_in_hci_thread(const tracked_objects::Location& from_here,
-                             const base::Closure& task) {
-  base::MessageLoop* hci_message_loop = get_message_loop();
-  if (!hci_message_loop || !hci_message_loop->task_runner().get()) {
-    LOG_ERROR(LOG_TAG, "%s: HCI message loop not running, accessed from %s",
-              __func__, from_here.ToString().c_str());
-    return;
-  }
+/**
+ * Log HCI event metrics that are not handled in special functions
+ * @param evt_code event code
+ * @param p_event pointer to event parameter, skipping paremter length
+ */
+void btu_hcif_log_event_metrics(uint8_t evt_code, uint8_t* p_event) {
+  uint32_t cmd = android::bluetooth::hci::CMD_UNKNOWN;
+  uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
+  uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
+  uint16_t handle = bluetooth::common::kUnknownConnectionHandle;
+  int64_t value = 0;
 
-  hci_message_loop->task_runner()->PostTask(from_here, task);
+  RawAddress bda = RawAddress::kEmpty;
+  switch (evt_code) {
+    case HCI_IO_CAPABILITY_REQUEST_EVT:
+    case HCI_IO_CAPABILITY_RESPONSE_EVT:
+    case HCI_LINK_KEY_REQUEST_EVT:
+    case HCI_LINK_KEY_NOTIFICATION_EVT:
+    case HCI_USER_PASSKEY_REQUEST_EVT:
+    case HCI_USER_PASSKEY_NOTIFY_EVT:
+    case HCI_USER_CONFIRMATION_REQUEST_EVT:
+    case HCI_KEYPRESS_NOTIFY_EVT:
+    case HCI_REMOTE_OOB_DATA_REQUEST_EVT:
+      STREAM_TO_BDADDR(bda, p_event);
+      bluetooth::common::LogClassicPairingEvent(bda, handle, cmd, evt_code, status, reason, value);
+      break;
+    case HCI_SIMPLE_PAIRING_COMPLETE_EVT:
+    case HCI_RMT_NAME_REQUEST_COMP_EVT:
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_BDADDR(bda, p_event);
+      bluetooth::common::LogClassicPairingEvent(bda, handle, cmd, evt_code, status, reason, value);
+      break;
+    case HCI_AUTHENTICATION_COMP_EVT:
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_UINT16(handle, p_event);
+      handle = HCID_GET_HANDLE(handle);
+      bluetooth::common::LogClassicPairingEvent(bda, handle, cmd, evt_code, status, reason, value);
+      break;
+    case HCI_ENCRYPTION_CHANGE_EVT: {
+      uint8_t encryption_enabled;
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_UINT16(handle, p_event);
+      STREAM_TO_UINT8(encryption_enabled, p_event);
+      bluetooth::common::LogClassicPairingEvent(bda, handle, cmd, evt_code, status, reason, encryption_enabled);
+      break;
+    }
+    case HCI_CONNECTION_COMP_EVT: {
+      uint8_t link_type;
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_UINT16(handle, p_event);
+      STREAM_TO_BDADDR(bda, p_event);
+      STREAM_TO_UINT8(link_type, p_event);
+      handle = HCID_GET_HANDLE(handle);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          &bda, handle, android::bluetooth::DIRECTION_UNKNOWN, link_type, cmd,
+          evt_code, android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+      break;
+    }
+    case HCI_CONNECTION_REQUEST_EVT: {
+      DEV_CLASS dc;
+      uint8_t link_type;
+      STREAM_TO_BDADDR(bda, p_event);
+      STREAM_TO_DEVCLASS(dc, p_event);
+      STREAM_TO_UINT8(link_type, p_event);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          &bda, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_INCOMING, link_type, cmd, evt_code,
+          android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+      break;
+    }
+    case HCI_DISCONNECTION_COMP_EVT: {
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_UINT16(handle, p_event);
+      STREAM_TO_UINT8(reason, p_event);
+      handle = HCID_GET_HANDLE(handle);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
+          android::bluetooth::LINK_TYPE_UNKNOWN, cmd, evt_code,
+          android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+      break;
+    }
+    case HCI_ESCO_CONNECTION_COMP_EVT: {
+      uint8_t link_type;
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_UINT16(handle, p_event);
+      STREAM_TO_BDADDR(bda, p_event);
+      STREAM_TO_UINT8(link_type, p_event);
+      handle = HCID_GET_HANDLE(handle);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          &bda, handle, android::bluetooth::DIRECTION_UNKNOWN, link_type, cmd,
+          evt_code, android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+      break;
+    }
+    case HCI_ESCO_CONNECTION_CHANGED_EVT: {
+      STREAM_TO_UINT8(status, p_event);
+      STREAM_TO_UINT16(handle, p_event);
+      handle = HCID_GET_HANDLE(handle);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
+          android::bluetooth::LINK_TYPE_UNKNOWN, cmd, evt_code,
+          android::bluetooth::hci::BLE_EVT_UNKNOWN, status, reason);
+      break;
+    }
+  }
 }
 
 /*******************************************************************************
@@ -157,6 +255,8 @@
   STREAM_TO_UINT8(hci_evt_code, p);
   STREAM_TO_UINT8(hci_evt_len, p);
 
+  btu_hcif_log_event_metrics(hci_evt_code, p);
+
   switch (hci_evt_code) {
     case HCI_INQUIRY_COMP_EVT:
       btu_hcif_inquiry_comp_evt(p);
@@ -366,6 +466,245 @@
   }
 }
 
+static void btu_hcif_log_command_metrics(uint16_t opcode, uint8_t* p_cmd,
+                                         uint16_t cmd_status,
+                                         bool is_cmd_status) {
+  static uint16_t kUnknownBleEvt = android::bluetooth::hci::BLE_EVT_UNKNOWN;
+
+  uint16_t hci_event = android::bluetooth::hci::EVT_COMMAND_STATUS;
+  if (!is_cmd_status) {
+    hci_event = android::bluetooth::hci::EVT_UNKNOWN;
+    cmd_status = android::bluetooth::hci::STATUS_UNKNOWN;
+  }
+
+  RawAddress bd_addr;
+  uint16_t handle;
+  uint8_t reason;
+
+  switch (opcode) {
+    case HCI_CREATE_CONNECTION:
+    case HCI_CREATE_CONNECTION_CANCEL:
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          &bd_addr, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_OUTGOING,
+          android::bluetooth::LINK_TYPE_ACL, opcode, hci_event, kUnknownBleEvt,
+          cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
+      break;
+    case HCI_DISCONNECT:
+      STREAM_TO_UINT16(handle, p_cmd);
+      STREAM_TO_UINT8(reason, p_cmd);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          nullptr, handle, android::bluetooth::DIRECTION_UNKNOWN,
+          android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
+          kUnknownBleEvt, cmd_status, reason);
+      break;
+    case HCI_SETUP_ESCO_CONNECTION:
+    case HCI_ENH_SETUP_ESCO_CONNECTION:
+      STREAM_TO_UINT16(handle, p_cmd);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          nullptr, handle, android::bluetooth::DIRECTION_OUTGOING,
+          android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
+          kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
+      break;
+    case HCI_ACCEPT_CONNECTION_REQUEST:
+    case HCI_ACCEPT_ESCO_CONNECTION:
+    case HCI_ENH_ACCEPT_ESCO_CONNECTION:
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          &bd_addr, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_INCOMING,
+          android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
+          kUnknownBleEvt, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
+      break;
+    case HCI_REJECT_CONNECTION_REQUEST:
+    case HCI_REJECT_ESCO_CONNECTION:
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      STREAM_TO_UINT8(reason, p_cmd);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          &bd_addr, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_INCOMING,
+          android::bluetooth::LINK_TYPE_UNKNOWN, opcode, hci_event,
+          kUnknownBleEvt, cmd_status, reason);
+      break;
+
+      // BLE Commands
+    case HCI_BLE_CREATE_LL_CONN: {
+      p_cmd += 2;  // Skip LE_Scan_Interval
+      p_cmd += 2;  // Skip LE_Scan_Window;
+      uint8_t initiator_filter_policy;
+      STREAM_TO_UINT8(initiator_filter_policy, p_cmd);
+      uint8_t peer_address_type;
+      STREAM_TO_UINT8(peer_address_type, p_cmd);
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      // Peer address should not be used if initiator filter policy is not 0x00
+      const RawAddress* bd_addr_p = nullptr;
+      if (initiator_filter_policy == 0x00) {
+        bd_addr_p = &bd_addr;
+#if (BLE_PRIVACY_SPT == TRUE)
+        if (peer_address_type == BLE_ADDR_PUBLIC_ID ||
+            peer_address_type == BLE_ADDR_RANDOM_ID) {
+          // if identity address is not matched, this address is invalid
+          if (!btm_identity_addr_to_random_pseudo(&bd_addr, &peer_address_type,
+                                                  false)) {
+            bd_addr_p = nullptr;
+          }
+        }
+#endif
+      }
+      if (initiator_filter_policy == 0x00 ||
+          (cmd_status != HCI_SUCCESS && !is_cmd_status)) {
+        // Selectively log to avoid log spam due to whitelist connections:
+        // - When doing non-whitelist connection
+        // - When there is an error in command status
+        bluetooth::common::LogLinkLayerConnectionEvent(
+            bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
+            android::bluetooth::DIRECTION_OUTGOING,
+            android::bluetooth::LINK_TYPE_ACL, opcode, hci_event,
+            kUnknownBleEvt, cmd_status,
+            android::bluetooth::hci::STATUS_UNKNOWN);
+      }
+      break;
+    }
+    case HCI_LE_EXTENDED_CREATE_CONNECTION: {
+      uint8_t initiator_filter_policy;
+      STREAM_TO_UINT8(initiator_filter_policy, p_cmd);
+      p_cmd += 1;  // Skip Own_Address_Type
+      uint8_t peer_addr_type;
+      STREAM_TO_UINT8(peer_addr_type, p_cmd);
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      // Peer address should not be used if initiator filter policy is not 0x00
+      const RawAddress* bd_addr_p = nullptr;
+      if (initiator_filter_policy == 0x00) {
+        bd_addr_p = &bd_addr;
+#if (BLE_PRIVACY_SPT == TRUE)
+        // if identity address is not matched, this should be a static address
+        btm_identity_addr_to_random_pseudo(&bd_addr, &peer_addr_type, false);
+#endif
+      }
+      if (initiator_filter_policy == 0x00 ||
+          (cmd_status != HCI_SUCCESS && !is_cmd_status)) {
+        // Selectively log to avoid log spam due to whitelist connections:
+        // - When doing non-whitelist connection
+        // - When there is an error in command status
+        bluetooth::common::LogLinkLayerConnectionEvent(
+            bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
+            android::bluetooth::DIRECTION_OUTGOING,
+            android::bluetooth::LINK_TYPE_ACL, opcode, hci_event,
+            kUnknownBleEvt, cmd_status,
+            android::bluetooth::hci::STATUS_UNKNOWN);
+      }
+      break;
+    }
+    case HCI_BLE_CREATE_CONN_CANCEL:
+      if (cmd_status != HCI_SUCCESS && !is_cmd_status) {
+        // Only log errors to prevent log spam due to whitelist connections
+        bluetooth::common::LogLinkLayerConnectionEvent(
+            nullptr, bluetooth::common::kUnknownConnectionHandle,
+            android::bluetooth::DIRECTION_OUTGOING,
+            android::bluetooth::LINK_TYPE_ACL, opcode, hci_event,
+            kUnknownBleEvt, cmd_status,
+            android::bluetooth::hci::STATUS_UNKNOWN);
+      }
+      break;
+    case HCI_BLE_CLEAR_WHITE_LIST:
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          nullptr, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_INCOMING,
+          android::bluetooth::LINK_TYPE_ACL, opcode, hci_event, kUnknownBleEvt,
+          cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
+      break;
+    case HCI_BLE_ADD_WHITE_LIST:
+    case HCI_BLE_REMOVE_WHITE_LIST: {
+      uint8_t peer_addr_type;
+      STREAM_TO_UINT8(peer_addr_type, p_cmd);
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      const RawAddress* bd_addr_p = nullptr;
+      // When peer_addr_type is 0xFF, bd_addr should be ignored per BT spec
+      if (peer_addr_type != BLE_ADDR_ANONYMOUS) {
+        bd_addr_p = &bd_addr;
+#if (BLE_PRIVACY_SPT == TRUE)
+        bool addr_is_rpa = peer_addr_type == BLE_ADDR_RANDOM &&
+                           BTM_BLE_IS_RESOLVE_BDA(bd_addr);
+        // Only try to match identity address for pseudo if address is not RPA
+        if (!addr_is_rpa) {
+          // if identity address is not matched, this should be a static address
+          btm_identity_addr_to_random_pseudo(&bd_addr, &peer_addr_type, false);
+        }
+#endif
+      }
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          bd_addr_p, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_INCOMING,
+          android::bluetooth::LINK_TYPE_ACL, opcode, hci_event, kUnknownBleEvt,
+          cmd_status, android::bluetooth::hci::STATUS_UNKNOWN);
+      break;
+    }
+    case HCI_READ_LOCAL_OOB_DATA:
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle, opcode,
+                                                hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, 0);
+      break;
+    case HCI_WRITE_SIMPLE_PAIRING_MODE: {
+      uint8_t simple_pairing_mode;
+      STREAM_TO_UINT8(simple_pairing_mode, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle, opcode,
+                                                hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN,
+                                                simple_pairing_mode);
+      break;
+    }
+    case HCI_WRITE_SECURE_CONNS_SUPPORT: {
+      uint8_t secure_conn_host_support;
+      STREAM_TO_UINT8(secure_conn_host_support, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle, opcode,
+                                                hci_event, cmd_status, android::bluetooth::hci::STATUS_UNKNOWN,
+                                                secure_conn_host_support);
+      break;
+    }
+    case HCI_AUTHENTICATION_REQUESTED:
+      STREAM_TO_UINT16(handle, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, handle, opcode, hci_event, cmd_status,
+                                                android::bluetooth::hci::STATUS_UNKNOWN, 0);
+      break;
+    case HCI_SET_CONN_ENCRYPTION: {
+      STREAM_TO_UINT16(handle, p_cmd);
+      uint8_t encryption_enable;
+      STREAM_TO_UINT8(encryption_enable, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, handle, opcode, hci_event, cmd_status,
+                                                android::bluetooth::hci::STATUS_UNKNOWN, encryption_enable);
+      break;
+    }
+    case HCI_DELETE_STORED_LINK_KEY: {
+      uint8_t delete_all_flag;
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      STREAM_TO_UINT8(delete_all_flag, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode, hci_event,
+                                                cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, delete_all_flag);
+      break;
+    }
+    case HCI_RMT_NAME_REQUEST:
+    case HCI_RMT_NAME_REQUEST_CANCEL:
+    case HCI_LINK_KEY_REQUEST_REPLY:
+    case HCI_LINK_KEY_REQUEST_NEG_REPLY:
+    case HCI_IO_CAPABILITY_REQUEST_REPLY:
+    case HCI_USER_CONF_REQUEST_REPLY:
+    case HCI_USER_CONF_VALUE_NEG_REPLY:
+    case HCI_USER_PASSKEY_REQ_REPLY:
+    case HCI_USER_PASSKEY_REQ_NEG_REPLY:
+    case HCI_REM_OOB_DATA_REQ_REPLY:
+    case HCI_REM_OOB_DATA_REQ_NEG_REPLY:
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode, hci_event,
+                                                cmd_status, android::bluetooth::hci::STATUS_UNKNOWN, 0);
+      break;
+    case HCI_IO_CAP_REQ_NEG_REPLY:
+      STREAM_TO_BDADDR(bd_addr, p_cmd);
+      STREAM_TO_UINT8(reason, p_cmd);
+      bluetooth::common::LogClassicPairingEvent(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode, hci_event,
+                                                cmd_status, reason, 0);
+      break;
+  }
+}
+
 /*******************************************************************************
  *
  * Function         btu_hcif_send_cmd
@@ -392,13 +731,18 @@
     vsc_callback = *((void**)(p_buf + 1));
   }
 
+  // Skip parameter length before logging
+  stream++;
+  btu_hcif_log_command_metrics(opcode, stream,
+                               android::bluetooth::hci::STATUS_UNKNOWN, false);
+
   hci_layer_get_interface()->transmit_command(
       p_buf, btu_hcif_command_complete_evt, btu_hcif_command_status_evt,
       vsc_callback);
 }
 
-using hci_cmd_cb = base::Callback<void(uint8_t* /* return_parameters */,
-                                       uint16_t /* return_parameters_length*/)>;
+using hci_cmd_cb = base::OnceCallback<void(
+    uint8_t* /* return_parameters */, uint16_t /* return_parameters_length*/)>;
 
 struct cmd_with_cb_data {
   hci_cmd_cb cb;
@@ -415,18 +759,84 @@
   cb_wrapper->posted_from.~Location();
 }
 
+/**
+ * Log command complete events that is not handled individually in this file
+ * @param opcode opcode of the command
+ * @param p_return_params pointer to returned parameter after parameter length
+ *                        field
+ */
+static void btu_hcif_log_command_complete_metrics(uint16_t opcode,
+                                                  uint8_t* p_return_params) {
+  uint16_t status = android::bluetooth::hci::STATUS_UNKNOWN;
+  uint16_t reason = android::bluetooth::hci::STATUS_UNKNOWN;
+  uint16_t hci_event = android::bluetooth::hci::EVT_COMMAND_COMPLETE;
+  uint16_t hci_ble_event = android::bluetooth::hci::BLE_EVT_UNKNOWN;
+  RawAddress bd_addr = RawAddress::kEmpty;
+  switch (opcode) {
+    case HCI_BLE_CLEAR_WHITE_LIST:
+    case HCI_BLE_ADD_WHITE_LIST:
+    case HCI_BLE_REMOVE_WHITE_LIST: {
+      STREAM_TO_UINT8(status, p_return_params);
+      bluetooth::common::LogLinkLayerConnectionEvent(
+          nullptr, bluetooth::common::kUnknownConnectionHandle,
+          android::bluetooth::DIRECTION_INCOMING,
+          android::bluetooth::LINK_TYPE_ACL, opcode, hci_event, hci_ble_event,
+          status, reason);
+      break;
+    }
+    case HCI_DELETE_STORED_LINK_KEY:
+    case HCI_READ_LOCAL_OOB_DATA:
+    case HCI_WRITE_SIMPLE_PAIRING_MODE:
+    case HCI_WRITE_SECURE_CONNS_SUPPORT:
+      STREAM_TO_UINT8(status, p_return_params);
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, bluetooth::common::kUnknownConnectionHandle, opcode,
+                                                hci_event, status, reason, 0);
+      break;
+    case HCI_READ_ENCR_KEY_SIZE: {
+      uint16_t handle;
+      uint8_t key_size;
+      STREAM_TO_UINT8(status, p_return_params);
+      STREAM_TO_UINT16(handle, p_return_params);
+      STREAM_TO_UINT8(key_size, p_return_params);
+      bluetooth::common::LogClassicPairingEvent(RawAddress::kEmpty, handle, opcode, hci_event, status, reason,
+                                                key_size);
+      break;
+    }
+    case HCI_LINK_KEY_REQUEST_REPLY:
+    case HCI_LINK_KEY_REQUEST_NEG_REPLY:
+    case HCI_IO_CAPABILITY_REQUEST_REPLY:
+    case HCI_IO_CAP_REQ_NEG_REPLY:
+    case HCI_USER_CONF_REQUEST_REPLY:
+    case HCI_USER_CONF_VALUE_NEG_REPLY:
+    case HCI_USER_PASSKEY_REQ_REPLY:
+    case HCI_USER_PASSKEY_REQ_NEG_REPLY:
+    case HCI_REM_OOB_DATA_REQ_REPLY:
+    case HCI_REM_OOB_DATA_REQ_NEG_REPLY:
+      STREAM_TO_UINT8(status, p_return_params);
+      STREAM_TO_BDADDR(bd_addr, p_return_params);
+      bluetooth::common::LogClassicPairingEvent(bd_addr, bluetooth::common::kUnknownConnectionHandle, opcode, hci_event,
+                                                status, reason, 0);
+      break;
+  }
+}
+
 static void btu_hcif_command_complete_evt_with_cb_on_task(BT_HDR* event,
                                                           void* context) {
   command_opcode_t opcode;
-  uint8_t* stream =
-      event->data + event->offset +
-      3;  // 2 to skip the event headers, 1 to skip the command credits
+  // 2 for event header: event code (1) + parameter length (1)
+  // 1 for num_hci_pkt command credit
+  uint8_t* stream = event->data + event->offset + 3;
   STREAM_TO_UINT16(opcode, stream);
 
+  btu_hcif_log_command_complete_metrics(opcode, stream);
+
   cmd_with_cb_data* cb_wrapper = (cmd_with_cb_data*)context;
   HCI_TRACE_DEBUG("command complete for: %s",
                   cb_wrapper->posted_from.ToString().c_str());
-  cb_wrapper->cb.Run(stream, event->len - 5);
+  // 2 for event header: event code (1) + parameter length (1)
+  // 3 for command complete header: num_hci_pkt (1) + opcode (2)
+  uint16_t param_len = static_cast<uint16_t>(event->len - 5);
+  std::move(cb_wrapper->cb).Run(stream, param_len);
   cmd_with_cb_data_cleanup(cb_wrapper);
   osi_free(cb_wrapper);
 
@@ -435,9 +845,9 @@
 
 static void btu_hcif_command_complete_evt_with_cb(BT_HDR* response,
                                                   void* context) {
-  do_in_hci_thread(FROM_HERE,
-                   base::Bind(btu_hcif_command_complete_evt_with_cb_on_task,
-                              response, context));
+  do_in_main_thread(FROM_HERE,
+                    base::Bind(btu_hcif_command_complete_evt_with_cb_on_task,
+                               response, context));
 }
 
 static void btu_hcif_command_status_evt_with_cb_on_task(uint8_t status,
@@ -449,11 +859,15 @@
 
   CHECK(status != 0);
 
+  // stream + 1 to skip parameter length field
+  // No need to check length since stream is written by us
+  btu_hcif_log_command_metrics(opcode, stream + 1, status, true);
+
   // report command status error
   cmd_with_cb_data* cb_wrapper = (cmd_with_cb_data*)context;
   HCI_TRACE_DEBUG("command status for: %s",
                   cb_wrapper->posted_from.ToString().c_str());
-  cb_wrapper->cb.Run(&status, sizeof(uint16_t));
+  std::move(cb_wrapper->cb).Run(&status, sizeof(uint16_t));
   cmd_with_cb_data_cleanup(cb_wrapper);
   osi_free(cb_wrapper);
 
@@ -468,7 +882,7 @@
     return;
   }
 
-  do_in_hci_thread(
+  do_in_main_thread(
       FROM_HERE, base::Bind(btu_hcif_command_status_evt_with_cb_on_task, status,
                             command, context));
 }
@@ -476,9 +890,9 @@
 /* This function is called to send commands to the Host Controller. |cb| is
  * called when command status event is called with error code, or when the
  * command complete event is received. */
-void btu_hcif_send_cmd_with_cb(const tracked_objects::Location& posted_from,
-                               uint16_t opcode, uint8_t* params,
-                               uint8_t params_len, hci_cmd_cb cb) {
+void btu_hcif_send_cmd_with_cb(const Location& posted_from, uint16_t opcode,
+                               uint8_t* params, uint8_t params_len,
+                               hci_cmd_cb cb) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
 
@@ -491,11 +905,14 @@
     memcpy(pp, params, params_len);
   }
 
+  btu_hcif_log_command_metrics(opcode, pp,
+                               android::bluetooth::hci::STATUS_UNKNOWN, false);
+
   cmd_with_cb_data* cb_wrapper =
       (cmd_with_cb_data*)osi_malloc(sizeof(cmd_with_cb_data));
 
   cmd_with_cb_data_init(cb_wrapper);
-  cb_wrapper->cb = cb;
+  cb_wrapper->cb = std::move(cb);
   cb_wrapper->posted_from = posted_from;
 
   hci_layer_get_interface()->transmit_command(
@@ -578,9 +995,7 @@
   RawAddress bda;
   uint8_t link_type;
   uint8_t enc_mode;
-#if (BTM_SCO_INCLUDED == TRUE)
   tBTM_ESCO_DATA esco_data;
-#endif
 
   STREAM_TO_UINT8(status, p);
   STREAM_TO_UINT16(handle, p);
@@ -601,15 +1016,12 @@
     btm_sec_connected(bda, handle, status, enc_mode);
 
     l2c_link_hci_conn_comp(status, handle, bda);
-  }
-#if (BTM_SCO_INCLUDED == TRUE)
-  else {
+  } else {
     memset(&esco_data, 0, sizeof(tBTM_ESCO_DATA));
     /* esco_data.link_type = HCI_LINK_TYPE_SCO; already zero */
     esco_data.bd_addr = bda;
     btm_sco_connected(status, &bda, handle, &esco_data);
   }
-#endif /* BTM_SCO_INCLUDED */
 }
 
 /*******************************************************************************
@@ -634,12 +1046,9 @@
   /* passing request to l2cap */
   if (link_type == HCI_LINK_TYPE_ACL) {
     btm_sec_conn_req(bda, dc);
-  }
-#if (BTM_SCO_INCLUDED == TRUE)
-  else {
+  } else {
     btm_sco_conn_req(bda, dc, link_type);
   }
-#endif /* BTM_SCO_INCLUDED */
 }
 
 /*******************************************************************************
@@ -652,10 +1061,11 @@
  *
  ******************************************************************************/
 static void btu_hcif_disconnection_comp_evt(uint8_t* p) {
+  uint8_t status;
   uint16_t handle;
   uint8_t reason;
 
-  ++p;
+  STREAM_TO_UINT8(status, p);
   STREAM_TO_UINT16(handle, p);
   STREAM_TO_UINT8(reason, p);
 
@@ -668,12 +1078,8 @@
                     __func__, reason, handle);
   }
 
-#if (BTM_SCO_INCLUDED == TRUE)
   /* If L2CAP doesn't know about it, send it to SCO */
   if (!l2c_link_hci_disc_comp(handle, reason)) btm_sco_removed(handle, reason);
-#else
-  l2c_link_hci_disc_comp(handle, reason);
-#endif /* BTM_SCO_INCLUDED */
 
   /* Notify security manager */
   btm_sec_disconnected(handle, reason);
@@ -723,16 +1129,8 @@
 
 constexpr uint8_t MIN_KEY_SIZE = 7;
 
-static void read_encryption_key_size_complete_after_encryption_change(
-    uint8_t status, uint16_t handle, uint8_t key_size) {
-  int ret = android::util::stats_write(
-      android::util::BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED, "", handle,
-      HCI_READ_ENCR_KEY_SIZE, HCI_COMMAND_COMPLETE_EVT, status, 0, key_size);
-  if (ret < 0) {
-    LOG(WARNING) << __func__ << ": failed to log encryption key size "
-                 << std::to_string(key_size);
-  }
-
+static void read_encryption_key_size_complete_after_encryption_change(uint8_t status, uint16_t handle,
+                                                                      uint8_t key_size) {
   if (status == HCI_ERR_INSUFFCIENT_SECURITY) {
     /* If remote device stop the encryption before we call "Read Encryption Key
      * Size", we might receive Insufficient Security, which means that link is
@@ -749,9 +1147,8 @@
 
   if (key_size < MIN_KEY_SIZE) {
     android_errorWriteLog(0x534e4554, "124301137");
-    LOG(ERROR) << __func__
-               << " encryption key too short, disconnecting. handle: "
-               << loghex(handle) << " key_size: " << +key_size;
+    LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
+               << " key_size: " << +key_size;
 
     btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
     return;
@@ -779,14 +1176,16 @@
   STREAM_TO_UINT16(handle, p);
   STREAM_TO_UINT8(encr_enable, p);
 
-  if (status != HCI_SUCCESS || encr_enable == 0 ||
-      BTM_IsBleConnection(handle)) {
+  if (status != HCI_SUCCESS || encr_enable == 0 || BTM_IsBleConnection(handle)) {
+    if (status == HCI_ERR_CONNECTION_TOUT) {
+      smp_cancel_start_encryption_attempt();
+      return;
+    }
+
     btm_acl_encrypt_change(handle, status, encr_enable);
     btm_sec_encrypt_change(handle, status, encr_enable);
   } else {
-    btsnd_hcic_read_encryption_key_size(
-        handle,
-        base::Bind(&read_encryption_key_size_complete_after_encryption_change));
+    btsnd_hcic_read_encryption_key_size(handle, base::Bind(&read_encryption_key_size_complete_after_encryption_change));
   }
 }
 
@@ -876,7 +1275,6 @@
  *
  ******************************************************************************/
 static void btu_hcif_esco_connection_comp_evt(uint8_t* p) {
-#if (BTM_SCO_INCLUDED == TRUE)
   tBTM_ESCO_DATA data;
   uint16_t handle;
   RawAddress bda;
@@ -893,9 +1291,10 @@
   STREAM_TO_UINT16(data.tx_pkt_len, p);
   STREAM_TO_UINT8(data.air_mode, p);
 
+  handle = HCID_GET_HANDLE(handle);
+
   data.bd_addr = bda;
   btm_sco_connected(status, &bda, handle, &data);
-#endif
 }
 
 /*******************************************************************************
@@ -908,7 +1307,6 @@
  *
  ******************************************************************************/
 static void btu_hcif_esco_connection_chg_evt(uint8_t* p) {
-#if (BTM_SCO_INCLUDED == TRUE)
   uint16_t handle;
   uint16_t tx_pkt_len;
   uint16_t rx_pkt_len;
@@ -924,9 +1322,10 @@
   STREAM_TO_UINT16(rx_pkt_len, p);
   STREAM_TO_UINT16(tx_pkt_len, p);
 
+  handle = HCID_GET_HANDLE(handle);
+
   btm_esco_proc_conn_chg(status, handle, tx_interval, retrans_window,
                          rx_pkt_len, tx_pkt_len);
-#endif
 }
 
 /*******************************************************************************
@@ -991,18 +1390,6 @@
       break;
 
     /* BLE Commands sComplete*/
-    case HCI_BLE_ADD_WHITE_LIST:
-      btm_ble_add_2_white_list_complete(*p);
-      break;
-
-    case HCI_BLE_CLEAR_WHITE_LIST:
-      btm_ble_clear_white_list_complete(p, evt_len);
-      break;
-
-    case HCI_BLE_REMOVE_WHITE_LIST:
-      btm_ble_remove_from_white_list_complete(p, evt_len);
-      break;
-
     case HCI_BLE_RAND:
     case HCI_BLE_ENCRYPT:
       btm_ble_rand_enc_complete(p, opcode, (tBTM_RAND_ENC_CB*)p_cplt_cback);
@@ -1073,23 +1460,23 @@
 static void btu_hcif_command_complete_evt_on_task(BT_HDR* event,
                                                   void* context) {
   command_opcode_t opcode;
-  uint8_t* stream =
-      event->data + event->offset +
-      3;  // 2 to skip the event headers, 1 to skip the command credits
+  // 2 for event header: event code (1) + parameter length (1)
+  // 1 for num_hci_pkt command credit
+  uint8_t* stream = event->data + event->offset + 3;
   STREAM_TO_UINT16(opcode, stream);
 
-  btu_hcif_hdl_command_complete(
-      opcode, stream,
-      event->len -
-          5,  // 3 for the command complete headers, 2 for the event headers
-      context);
+  btu_hcif_log_command_complete_metrics(opcode, stream);
+  // 2 for event header: event code (1) + parameter length (1)
+  // 3 for command complete header: num_hci_pkt (1) + opcode (2)
+  uint16_t param_len = static_cast<uint16_t>(event->len - 5);
+  btu_hcif_hdl_command_complete(opcode, stream, param_len, context);
 
   osi_free(event);
 }
 
 static void btu_hcif_command_complete_evt(BT_HDR* response, void* context) {
-  do_in_hci_thread(FROM_HERE, base::Bind(btu_hcif_command_complete_evt_on_task,
-                                         response, context));
+  do_in_main_thread(FROM_HERE, base::Bind(btu_hcif_command_complete_evt_on_task,
+                                          response, context));
 }
 
 /*******************************************************************************
@@ -1104,27 +1491,107 @@
 static void btu_hcif_hdl_command_status(uint16_t opcode, uint8_t status,
                                         uint8_t* p_cmd,
                                         void* p_vsc_status_cback) {
+  CHECK_NE(p_cmd, nullptr) << "Null command for opcode 0x" << loghex(opcode);
+  p_cmd++;  // Skip parameter total length
+
   RawAddress bd_addr;
   uint16_t handle;
-#if (BTM_SCO_INCLUDED == TRUE)
-  tBTM_ESCO_DATA esco_data;
-#endif
 
   switch (opcode) {
-    case HCI_EXIT_SNIFF_MODE:
-    case HCI_EXIT_PARK_MODE:
-#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
+    // Link Control Commands
+    case HCI_INQUIRY:
       if (status != HCI_SUCCESS) {
-        /* Allow SCO initiation to continue if waiting for change mode event */
-        if (p_cmd != NULL) {
-          p_cmd++; /* bypass length field */
-          STREAM_TO_UINT16(handle, p_cmd);
-          btm_sco_chk_pend_unpark(status, handle);
+        // Tell inquiry processing that we are done
+        btm_process_inq_complete(status, BTM_BR_INQUIRY_MASK);
+      }
+      break;
+    case HCI_QOS_SETUP:
+      if (status != HCI_SUCCESS) {
+        // Tell qos setup that we are done
+        btm_qos_setup_complete(status, 0, nullptr);
+      }
+      break;
+    case HCI_SWITCH_ROLE:
+      if (status != HCI_SUCCESS) {
+        // Tell BTM that the command failed
+        STREAM_TO_BDADDR(bd_addr, p_cmd);
+        btm_acl_role_changed(status, &bd_addr, BTM_ROLE_UNDEFINED);
+        l2c_link_role_changed(nullptr, BTM_ROLE_UNDEFINED,
+                              HCI_ERR_COMMAND_DISALLOWED);
+      }
+      break;
+    case HCI_CREATE_CONNECTION:
+      if (status != HCI_SUCCESS) {
+        STREAM_TO_BDADDR(bd_addr, p_cmd);
+        btm_sec_connected(bd_addr, HCI_INVALID_HANDLE, status, 0);
+        l2c_link_hci_conn_comp(status, HCI_INVALID_HANDLE, bd_addr);
+      }
+      break;
+    case HCI_AUTHENTICATION_REQUESTED:
+      if (status != HCI_SUCCESS) {
+        // Device refused to start authentication
+        // This is treated as an authentication failure
+        btm_sec_auth_complete(BTM_INVALID_HCI_HANDLE, status);
+      }
+      break;
+    case HCI_SET_CONN_ENCRYPTION:
+      if (status != HCI_SUCCESS) {
+        // Device refused to start encryption
+        // This is treated as an encryption failure
+        btm_sec_encrypt_change(BTM_INVALID_HCI_HANDLE, status, false);
+      }
+      break;
+    case HCI_RMT_NAME_REQUEST:
+      if (status != HCI_SUCCESS) {
+        // Tell inquiry processing that we are done
+        btm_process_remote_name(nullptr, nullptr, 0, status);
+        btm_sec_rmt_name_request_complete(nullptr, nullptr, status);
+      }
+      break;
+    case HCI_READ_RMT_EXT_FEATURES:
+      if (status != HCI_SUCCESS) {
+        STREAM_TO_UINT16(handle, p_cmd);
+        btm_read_remote_ext_features_failed(status, handle);
+      }
+      break;
+    case HCI_SETUP_ESCO_CONNECTION:
+    case HCI_ENH_SETUP_ESCO_CONNECTION:
+      if (status != HCI_SUCCESS) {
+        STREAM_TO_UINT16(handle, p_cmd);
+        // Determine if initial connection failed or is a change of setup
+        if (btm_is_sco_active(handle)) {
+          btm_esco_proc_conn_chg(status, handle, 0, 0, 0, 0);
+        } else {
+          btm_sco_connected(status, nullptr, handle, nullptr);
         }
       }
-#endif
-    /* Case Falls Through */
+      break;
 
+    // BLE Commands
+    case HCI_BLE_CREATE_LL_CONN:
+    case HCI_LE_EXTENDED_CREATE_CONNECTION:
+      if (status != HCI_SUCCESS) {
+        btm_ble_create_ll_conn_complete(status);
+      }
+      break;
+    case HCI_BLE_START_ENC:
+      // Race condition: disconnection happened right before we send
+      // "LE Encrypt", controller responds with no connection, we should
+      // cancel the encryption attempt, rather than unpair the device.
+      if (status == HCI_ERR_NO_CONNECTION) {
+        smp_cancel_start_encryption_attempt();
+      }
+      break;
+
+    // Link Policy Commands
+    case HCI_EXIT_SNIFF_MODE:
+    case HCI_EXIT_PARK_MODE:
+      if (status != HCI_SUCCESS) {
+        // Allow SCO initiation to continue if waiting for change mode event
+        STREAM_TO_UINT16(handle, p_cmd);
+        btm_sco_chk_pend_unpark(status, handle);
+      }
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case HCI_HOLD_MODE:
     case HCI_SNIFF_MODE:
     case HCI_PARK_MODE:
@@ -1132,112 +1599,9 @@
       break;
 
     default:
-      /* If command failed to start, we may need to tell BTM */
-      if (status != HCI_SUCCESS) {
-        switch (opcode) {
-          case HCI_INQUIRY:
-            /* Tell inquiry processing that we are done */
-            btm_process_inq_complete(status, BTM_BR_INQUIRY_MASK);
-            break;
-
-          case HCI_RMT_NAME_REQUEST:
-            /* Tell inquiry processing that we are done */
-            btm_process_remote_name(NULL, NULL, 0, status);
-
-            btm_sec_rmt_name_request_complete(NULL, NULL, status);
-            break;
-
-          case HCI_QOS_SETUP_COMP_EVT:
-            /* Tell qos setup that we are done */
-            btm_qos_setup_complete(status, 0, NULL);
-            break;
-
-          case HCI_SWITCH_ROLE:
-            /* Tell BTM that the command failed */
-            /* read bd addr out of stored command */
-            if (p_cmd != NULL) {
-              p_cmd++;
-              STREAM_TO_BDADDR(bd_addr, p_cmd);
-              btm_acl_role_changed(status, &bd_addr, BTM_ROLE_UNDEFINED);
-            } else
-              btm_acl_role_changed(status, NULL, BTM_ROLE_UNDEFINED);
-            l2c_link_role_changed(nullptr, BTM_ROLE_UNDEFINED,
-                                  HCI_ERR_COMMAND_DISALLOWED);
-            break;
-
-          case HCI_CREATE_CONNECTION:
-            /* read bd addr out of stored command */
-            if (p_cmd != NULL) {
-              p_cmd++;
-              STREAM_TO_BDADDR(bd_addr, p_cmd);
-              btm_sec_connected(bd_addr, HCI_INVALID_HANDLE, status, 0);
-              l2c_link_hci_conn_comp(status, HCI_INVALID_HANDLE, bd_addr);
-            }
-            break;
-
-          case HCI_READ_RMT_EXT_FEATURES:
-            if (p_cmd != NULL) {
-              p_cmd++; /* skip command length */
-              STREAM_TO_UINT16(handle, p_cmd);
-            } else
-              handle = HCI_INVALID_HANDLE;
-
-            btm_read_remote_ext_features_failed(status, handle);
-            break;
-
-          case HCI_AUTHENTICATION_REQUESTED:
-            /* Device refused to start authentication.  That should be treated
-             * as authentication failure. */
-            btm_sec_auth_complete(BTM_INVALID_HCI_HANDLE, status);
-            break;
-
-          case HCI_SET_CONN_ENCRYPTION:
-            /* Device refused to start encryption.  That should be treated as
-             * encryption failure. */
-            btm_sec_encrypt_change(BTM_INVALID_HCI_HANDLE, status, false);
-            break;
-
-          case HCI_BLE_CREATE_LL_CONN:
-          case HCI_LE_EXTENDED_CREATE_CONNECTION:
-            btm_ble_create_ll_conn_complete(status);
-            break;
-
-#if (BTM_SCO_INCLUDED == TRUE)
-          case HCI_SETUP_ESCO_CONNECTION:
-          case HCI_ENH_SETUP_ESCO_CONNECTION:
-            /* read handle out of stored command */
-            if (p_cmd != NULL) {
-              p_cmd++;
-              STREAM_TO_UINT16(handle, p_cmd);
-
-              /* Determine if initial connection failed or is a change
-               * of setup */
-              if (btm_is_sco_active(handle))
-                btm_esco_proc_conn_chg(status, handle, 0, 0, 0, 0);
-              else
-                btm_sco_connected(status, NULL, handle, &esco_data);
-            }
-            break;
-#endif
-
-          /* This is commented out until an upper layer cares about returning
-          event
-          #if (L2CAP_NON_FLUSHABLE_PB_INCLUDED == TRUE)
-                      case HCI_ENHANCED_FLUSH:
-                          break;
-          #endif
-          */
-          default:
-            if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC)
-              btm_vsc_complete(&status, opcode, 1,
-                               (tBTM_VSC_CMPL_CB*)p_vsc_status_cback);
-            break;
-        }
-
-      } else {
-        if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC)
-          btm_vsc_complete(&status, opcode, 1,
-                           (tBTM_VSC_CMPL_CB*)p_vsc_status_cback);
+      if ((opcode & HCI_GRP_VENDOR_SPECIFIC) == HCI_GRP_VENDOR_SPECIFIC) {
+        btm_vsc_complete(&status, opcode, 1,
+                         (tBTM_VSC_CMPL_CB*)p_vsc_status_cback);
       }
   }
 }
@@ -1257,14 +1621,18 @@
   uint8_t* stream = event->data + event->offset;
   STREAM_TO_UINT16(opcode, stream);
 
+  // stream + 1 to skip parameter length field
+  // No need to check length since stream is written by us
+  btu_hcif_log_command_metrics(opcode, stream + 1, status, true);
+
   btu_hcif_hdl_command_status(opcode, status, stream, context);
   osi_free(event);
 }
 
 static void btu_hcif_command_status_evt(uint8_t status, BT_HDR* command,
                                         void* context) {
-  do_in_hci_thread(FROM_HERE, base::Bind(btu_hcif_command_status_evt_on_task,
-                                         status, command, context));
+  do_in_main_thread(FROM_HERE, base::Bind(btu_hcif_command_status_evt_on_task,
+                                          status, command, context));
 }
 
 /*******************************************************************************
@@ -1357,9 +1725,7 @@
   STREAM_TO_UINT16(handle, p);
   STREAM_TO_UINT8(current_mode, p);
   STREAM_TO_UINT16(interval, p);
-#if (BTM_SCO_WAKE_PARKED_LINK == TRUE)
   btm_sco_chk_pend_unpark(status, handle);
-#endif
   btm_pm_proc_mode_change(status, handle, current_mode, interval);
 
 #if (HID_DEV_INCLUDED == TRUE && HID_DEV_PM_INCLUDED == TRUE)
@@ -1430,11 +1796,11 @@
  ******************************************************************************/
 static void btu_hcif_link_key_notification_evt(uint8_t* p) {
   RawAddress bda;
-  LINK_KEY key;
+  Octet16 key;
   uint8_t key_type;
 
   STREAM_TO_BDADDR(bda, p);
-  STREAM_TO_ARRAY16(key, p);
+  STREAM_TO_ARRAY16(key.data(), p);
   STREAM_TO_UINT8(key_type, p);
 
   btm_sec_link_key_notification(bda, key, key_type);
@@ -1692,16 +2058,7 @@
  * End of Simple Pairing Events
  **********************************************/
 
-static void read_encryption_key_size_complete_after_key_refresh(
-    uint8_t status, uint16_t handle, uint8_t key_size) {
-  int ret = android::util::stats_write(
-      android::util::BLUETOOTH_CLASSIC_PAIRING_EVENT_REPORTED, "", handle,
-      HCI_READ_ENCR_KEY_SIZE, HCI_COMMAND_COMPLETE_EVT, status, 0, key_size);
-  if (ret < 0) {
-    LOG(WARNING) << __func__ << ": failed to log encryption key size "
-                 << std::to_string(key_size);
-  }
-
+static void read_encryption_key_size_complete_after_key_refresh(uint8_t status, uint16_t handle, uint8_t key_size) {
   if (status == HCI_ERR_INSUFFCIENT_SECURITY) {
     /* If remote device stop the encryption before we call "Read Encryption Key
      * Size", we might receive Insufficient Security, which means that link is
@@ -1718,9 +2075,8 @@
 
   if (key_size < MIN_KEY_SIZE) {
     android_errorWriteLog(0x534e4554, "124301137");
-    LOG(ERROR) << __func__
-               << " encryption key too short, disconnecting. handle: "
-               << loghex(handle) << " key_size: " << +key_size;
+    LOG(ERROR) << __func__ << " encryption key too short, disconnecting. handle: " << loghex(handle)
+               << " key_size: " << +key_size;
 
     btsnd_hcic_disconnect(handle, HCI_ERR_HOST_REJECT_SECURITY);
     return;
@@ -1739,9 +2095,7 @@
   if (status != HCI_SUCCESS || BTM_IsBleConnection(handle)) {
     btm_sec_encrypt_change(handle, status, (status == HCI_SUCCESS) ? 1 : 0);
   } else {
-    btsnd_hcic_read_encryption_key_size(
-        handle,
-        base::Bind(&read_encryption_key_size_complete_after_key_refresh));
+    btsnd_hcic_read_encryption_key_size(handle, base::Bind(&read_encryption_key_size_complete_after_key_refresh));
   }
 }
 
diff --git a/stack/btu/btu_init.cc b/stack/btu/btu_init.cc
index cad79df..e6e5a74 100644
--- a/stack/btu/btu_init.cc
+++ b/stack/btu/btu_init.cc
@@ -25,6 +25,7 @@
 #include "bt_target.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/message_loop_thread.h"
 #include "device/include/controller.h"
 #include "gatt_api.h"
 #include "gatt_int.h"
@@ -32,20 +33,12 @@
 #include "osi/include/alarm.h"
 #include "osi/include/fixed_queue.h"
 #include "osi/include/log.h"
-#include "osi/include/thread.h"
 #include "sdpint.h"
 #include "smp_int.h"
 
-// RT priority for audio-related tasks
-#define BTU_TASK_RT_PRIORITY 1
+using bluetooth::common::MessageLoopThread;
 
-// Communication queue from hci thread to bt_workqueue.
-extern fixed_queue_t* btu_hci_msg_queue;
-
-thread_t* bt_workqueue_thread;
-static const char* BT_WORKQUEUE_NAME = "bt_workqueue";
-
-extern void PLATFORM_DisableHciTransport(uint8_t bDisable);
+MessageLoopThread bt_startup_thread("bt_startup_thread");
 
 void btu_task_start_up(void* context);
 void btu_task_shut_down(void* context);
@@ -60,7 +53,7 @@
  * Returns          void
  *
  *****************************************************************************/
-void btu_init_core(void) {
+void btu_init_core() {
   /* Initialize the mandatory core stack components */
   btm_init();
 
@@ -85,7 +78,7 @@
  * Returns          void
  *
  *****************************************************************************/
-void btu_free_core(void) {
+void btu_free_core() {
   /* Free the mandatory core stack components */
   gatt_free();
 
@@ -108,29 +101,25 @@
  * Returns          void
  *
  *****************************************************************************/
-void BTU_StartUp(void) {
+void BTU_StartUp() {
   btu_trace_level = HCI_INITIAL_TRACE_LEVEL;
-
-  bt_workqueue_thread = thread_new(BT_WORKQUEUE_NAME);
-  if (bt_workqueue_thread == NULL) goto error_exit;
-
-  thread_set_rt_priority(bt_workqueue_thread, BTU_TASK_RT_PRIORITY);
-
-  // Continue startup on bt workqueue thread.
-  thread_post(bt_workqueue_thread, btu_task_start_up, NULL);
-  return;
-
-error_exit:;
-  LOG_ERROR(LOG_TAG, "%s Unable to allocate resources for bt_workqueue",
-            __func__);
-  BTU_ShutDown();
+  bt_startup_thread.StartUp();
+  if (!bt_startup_thread.EnableRealTimeScheduling()) {
+    LOG(ERROR) << __func__ << ": Unable to set real time scheduling policy for "
+               << bt_startup_thread;
+    BTU_ShutDown();
+    return;
+  }
+  if (!bt_startup_thread.DoInThread(FROM_HERE,
+                                    base::Bind(btu_task_start_up, nullptr))) {
+    LOG(ERROR) << __func__ << ": Unable to continue start-up on "
+               << bt_startup_thread;
+    BTU_ShutDown();
+    return;
+  }
 }
 
-void BTU_ShutDown(void) {
-  btu_task_shut_down(NULL);
-
-
-  thread_free(bt_workqueue_thread);
-
-  bt_workqueue_thread = NULL;
+void BTU_ShutDown() {
+  btu_task_shut_down(nullptr);
+  bt_startup_thread.ShutDown();
 }
diff --git a/stack/btu/btu_task.cc b/stack/btu/btu_task.cc
index 7d2527a..49c9697 100644
--- a/stack/btu/btu_task.cc
+++ b/stack/btu/btu_task.cc
@@ -23,31 +23,27 @@
 #include <stdlib.h>
 #include <string.h>
 
+#include "bta/sys/bta_sys.h"
+#include "btcore/include/module.h"
+#include "bte.h"
+#include "btif/include/btif_common.h"
+#include "common/message_loop_thread.h"
+#include "osi/include/osi.h"
+#include "stack/btm/btm_int.h"
+#include "stack/include/btu.h"
+#include "stack/l2cap/l2c_int.h"
+
 #include <base/bind.h>
 #include <base/logging.h>
 #include <base/run_loop.h>
 #include <base/threading/thread.h>
 
-#include "bta/sys/bta_sys.h"
-#include "btcore/include/module.h"
-#include "bte.h"
-#include "btif/include/btif_common.h"
-#include "osi/include/osi.h"
-#include "osi/include/thread.h"
-#include "stack/btm/btm_int.h"
-#include "stack/include/btu.h"
-#include "stack/l2cap/l2c_int.h"
-
-static const int THREAD_RT_PRIORITY = 1;
+using bluetooth::common::MessageLoopThread;
 
 /* Define BTU storage area */
 uint8_t btu_trace_level = HCI_INITIAL_TRACE_LEVEL;
 
-extern thread_t* bt_workqueue_thread;
-
-static base::MessageLoop* message_loop_ = NULL;
-static base::RunLoop* run_loop_ = NULL;
-static thread_t* message_loop_thread_;
+static MessageLoopThread main_thread("bt_main_thread");
 
 void btu_hci_msg_process(BT_HDR* p_msg) {
   /* Determine the input message type. */
@@ -63,10 +59,8 @@
       break;
 
     case BT_EVT_TO_BTU_HCI_SCO:
-#if (BTM_SCO_INCLUDED == TRUE)
       btm_route_sco_data(p_msg);
       break;
-#endif
 
     case BT_EVT_TO_BTU_HCI_EVT:
       btu_hcif_process_event((uint8_t)(p_msg->event & BT_SUB_EVT_MASK), p_msg);
@@ -83,24 +77,19 @@
   }
 }
 
-base::MessageLoop* get_message_loop() { return message_loop_; }
+bluetooth::common::MessageLoopThread* get_main_thread() { return &main_thread; }
 
-void btu_message_loop_run(UNUSED_ATTR void* context) {
-  message_loop_ = new base::MessageLoop();
-  run_loop_ = new base::RunLoop();
+base::MessageLoop* get_main_message_loop() {
+  return main_thread.message_loop();
+}
 
-  // Inform the bt jni thread initialization is ok.
-  message_loop_->task_runner()->PostTask(
-      FROM_HERE, base::Bind(base::IgnoreResult(&btif_transfer_context),
-                            btif_init_ok, 0, nullptr, 0, nullptr));
-
-  run_loop_->Run();
-
-  delete message_loop_;
-  message_loop_ = NULL;
-
-  delete run_loop_;
-  run_loop_ = NULL;
+bt_status_t do_in_main_thread(const base::Location& from_here,
+                              base::OnceClosure task) {
+  if (!main_thread.DoInThread(from_here, std::move(task))) {
+    LOG(ERROR) << __func__ << ": failed from " << from_here.ToString();
+    return BT_STATUS_FAIL;
+  }
+  return BT_STATUS_SUCCESS;
 }
 
 void btu_task_start_up(UNUSED_ATTR void* context) {
@@ -123,21 +112,22 @@
    */
   module_init(get_module(BTE_LOGMSG_MODULE));
 
-  message_loop_thread_ = thread_new("btu message loop");
-  if (!message_loop_thread_) {
-    LOG(FATAL) << __func__ << " unable to create btu message loop thread.";
+  main_thread.StartUp();
+  if (!main_thread.IsRunning()) {
+    LOG(FATAL) << __func__ << ": unable to start btu message loop thread.";
   }
-
-  thread_set_rt_priority(message_loop_thread_, THREAD_RT_PRIORITY);
-  thread_post(message_loop_thread_, btu_message_loop_run, nullptr);
-
+  if (!main_thread.EnableRealTimeScheduling()) {
+    LOG(FATAL) << __func__ << ": unable to enable real time scheduling";
+  }
+  if (do_in_jni_thread(FROM_HERE, base::Bind(btif_init_ok, 0, nullptr)) !=
+      BT_STATUS_SUCCESS) {
+    LOG(FATAL) << __func__ << ": unable to continue starting Bluetooth";
+  }
 }
 
 void btu_task_shut_down(UNUSED_ATTR void* context) {
   // Shutdown message loop on task completed
-  if (run_loop_ && message_loop_) {
-    message_loop_->task_runner()->PostTask(FROM_HERE, run_loop_->QuitClosure());
-  }
+  main_thread.ShutDown();
 
   module_clean_up(get_module(BTE_LOGMSG_MODULE));
 
diff --git a/stack/smp/aes.cc b/stack/crypto_toolbox/aes.cc
similarity index 99%
rename from stack/smp/aes.cc
rename to stack/crypto_toolbox/aes.cc
index 362a4ee..f53894e 100644
--- a/stack/smp/aes.cc
+++ b/stack/crypto_toolbox/aes.cc
@@ -43,12 +43,9 @@
 #endif
 #endif
 
+#include <stdint.h>
 #include <stdlib.h>
 
-/* add the target configuration to allow using internal data types and
- * compilation options */
-#include "bt_target.h"
-
 /* define if you have fast 32-bit types on your system */
 #if 1
 #define HAVE_UINT_32T
diff --git a/stack/smp/aes.h b/stack/crypto_toolbox/aes.h
similarity index 100%
rename from stack/smp/aes.h
rename to stack/crypto_toolbox/aes.h
diff --git a/stack/crypto_toolbox/aes_cmac.cc b/stack/crypto_toolbox/aes_cmac.cc
new file mode 100644
index 0000000..8b8246e
--- /dev/null
+++ b/stack/crypto_toolbox/aes_cmac.cc
@@ -0,0 +1,217 @@
+/******************************************************************************
+ *
+ *  Copyright 2008-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.
+ *
+ ******************************************************************************/
+
+/******************************************************************************
+ *
+ *  This file contains the implementation of the AES128 and AES CMAC algorithm.
+ *
+ ******************************************************************************/
+
+#include "stack/crypto_toolbox/aes.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+
+namespace crypto_toolbox {
+
+namespace {
+
+typedef struct {
+  uint8_t* text;
+  uint16_t len;
+  uint16_t round;
+} tCMAC_CB;
+
+tCMAC_CB cmac_cb;
+
+/* Rb for AES-128 as block cipher, LSB as [0] */
+Octet16 const_Rb{0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+/** utility function to do an biteise exclusive-OR of two bit strings of the
+ * length of OCTET16_LEN. Result is stored in first argument.
+ */
+static void xor_128(Octet16* a, const Octet16& b) {
+  CHECK(a);
+  uint8_t i, *aa = a->data();
+  const uint8_t* bb = b.data();
+
+  for (i = 0; i < OCTET16_LEN; i++) {
+    aa[i] = aa[i] ^ bb[i];
+  }
+}
+}  // namespace
+
+/* This function computes AES_128(key, message) */
+Octet16 aes_128(const Octet16& key, const Octet16& message) {
+  Octet16 key_reversed;
+  Octet16 message_reversed;
+  Octet16 output;
+
+  std::reverse_copy(key.begin(), key.end(), key_reversed.begin());
+  std::reverse_copy(message.begin(), message.end(), message_reversed.begin());
+
+  aes_context ctx;
+  aes_set_key(key_reversed.data(), key_reversed.size(), &ctx);
+  aes_encrypt(message_reversed.data(), output.data(), &ctx);
+
+  std::reverse(output.begin(), output.end());
+  return output;
+}
+
+/** utility function to padding the given text to be a 128 bits data. The
+ * parameter dest is input and output parameter, it must point to a
+ * OCTET16_LEN memory space; where include length bytes valid data. */
+static void padding(Octet16* dest, uint8_t length) {
+  uint8_t i, *p = dest->data();
+  /* original last block */
+  for (i = length; i < OCTET16_LEN; i++)
+    p[OCTET16_LEN - i - 1] = (i == length) ? 0x80 : 0;
+}
+
+/** utility function to left shift one bit for a 128 bits value. */
+static void leftshift_onebit(uint8_t* input, uint8_t* output) {
+  uint8_t i, overflow = 0, next_overflow = 0;
+  DVLOG(2) << __func__;
+  /* input[0] is LSB */
+  for (i = 0; i < OCTET16_LEN; i++) {
+    next_overflow = (input[i] & 0x80) ? 1 : 0;
+    output[i] = (input[i] << 1) | overflow;
+    overflow = next_overflow;
+  }
+  return;
+}
+
+/** This function is the calculation of block cipher using AES-128. */
+static Octet16 cmac_aes_k_calculate(const Octet16& key) {
+  Octet16 output;
+  Octet16 x{0};  // zero initialized
+
+  DVLOG(2) << __func__;
+
+  uint8_t i = 1;
+  while (i <= cmac_cb.round) {
+    /* Mi' := Mi (+) X  */
+    xor_128((Octet16*)&cmac_cb.text[(cmac_cb.round - i) * OCTET16_LEN], x);
+
+    output = aes_128(key, &cmac_cb.text[(cmac_cb.round - i) * OCTET16_LEN],
+                     OCTET16_LEN);
+    x = output;
+    i++;
+  }
+
+  return output;
+}
+
+/** This function proceeed to prepare the last block of message Mn depending on
+ * the size of the message.
+ */
+static void cmac_prepare_last_block(const Octet16& k1, const Octet16& k2) {
+  //    uint8_t     x[16] = {0};
+  bool flag;
+
+  DVLOG(2) << __func__;
+  /* last block is a complete block set flag to 1 */
+  flag = ((cmac_cb.len % OCTET16_LEN) == 0 && cmac_cb.len != 0) ? true : false;
+
+  DVLOG(2) << "flag=" << flag << " round=" << cmac_cb.round;
+
+  if (flag) { /* last block is complete block */
+    xor_128((Octet16*)&cmac_cb.text[0], k1);
+  } else /* padding then xor with k2 */
+  {
+    padding((Octet16*)&cmac_cb.text[0], (uint8_t)(cmac_cb.len % 16));
+
+    xor_128((Octet16*)&cmac_cb.text[0], k2);
+  }
+}
+
+/** This is the function to generate the two subkeys.
+ * |key| is CMAC key, expect SRK when used by SMP.
+ */
+static void cmac_generate_subkey(const Octet16& key) {
+  DVLOG(2) << __func__;
+
+  Octet16 zero{};
+  Octet16 p = aes_128(key, zero.data(), OCTET16_LEN);
+
+  Octet16 k1, k2;
+  uint8_t* pp = p.data();
+
+  /* If MSB(L) = 0, then K1 = L << 1 */
+  if ((pp[OCTET16_LEN - 1] & 0x80) != 0) {
+    /* Else K1 = ( L << 1 ) (+) Rb */
+    leftshift_onebit(pp, k1.data());
+    xor_128(&k1, const_Rb);
+  } else {
+    leftshift_onebit(pp, k1.data());
+  }
+
+  if ((k1[OCTET16_LEN - 1] & 0x80) != 0) {
+    /* K2 =  (K1 << 1) (+) Rb */
+    leftshift_onebit(k1.data(), k2.data());
+    xor_128(&k2, const_Rb);
+  } else {
+    /* If MSB(K1) = 0, then K2 = K1 << 1 */
+    leftshift_onebit(k1.data(), k2.data());
+  }
+
+  cmac_prepare_last_block(k1, k2);
+}
+
+/** key - CMAC key in little endian order
+ *  input - text to be signed in little endian byte order.
+ *  length - length of the input in byte.
+ */
+Octet16 aes_cmac(const Octet16& key, const uint8_t* input, uint16_t length) {
+  uint16_t len, diff;
+  /* n is number of rounds */
+  uint16_t n = (length + OCTET16_LEN - 1) / OCTET16_LEN;
+
+  DVLOG(2) << __func__;
+
+  if (n == 0) n = 1;
+  len = n * OCTET16_LEN;
+
+  DVLOG(2) << "AES128_CMAC started, allocate buffer size=" << len;
+  /* allocate a memory space of multiple of 16 bytes to hold text  */
+  cmac_cb.text = (uint8_t*)alloca(len);
+  cmac_cb.round = n;
+  diff = len - length;
+
+  if (input != NULL && length > 0) {
+    memcpy(&cmac_cb.text[diff], input, (int)length);
+    cmac_cb.len = length;
+  } else {
+    cmac_cb.len = 0;
+  }
+
+  /* prepare calculation for subkey s and last block of data */
+  cmac_generate_subkey(key);
+  /* start calculation */
+  Octet16 signature = cmac_aes_k_calculate(key);
+
+  /* clean up */
+  memset(&cmac_cb, 0, sizeof(tCMAC_CB));
+  // cmac_cb.text is auto-freed by alloca
+
+  return signature;
+}
+
+}  // namespace crypto_toolbox
diff --git a/stack/crypto_toolbox/crypto_toolbox.cc b/stack/crypto_toolbox/crypto_toolbox.cc
new file mode 100644
index 0000000..ae33bd9
--- /dev/null
+++ b/stack/crypto_toolbox/crypto_toolbox.cc
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stack/crypto_toolbox/crypto_toolbox.h"
+#include "stack/crypto_toolbox/aes.h"
+
+#include <algorithm>
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+
+using base::HexEncode;
+
+namespace crypto_toolbox {
+
+Octet16 h6(const Octet16& w, std::array<uint8_t, 4> keyid) {
+  return aes_cmac(w, keyid.data(), keyid.size());
+}
+
+Octet16 h7(const Octet16& salt, const Octet16& w) {
+  return aes_cmac(salt, w.data(), w.size());
+}
+
+Octet16 f4(uint8_t* u, uint8_t* v, const Octet16& x, uint8_t z) {
+  constexpr size_t msg_len = BT_OCTET32_LEN /* U size */ +
+                             BT_OCTET32_LEN /* V size */ + 1 /* Z size */;
+
+  DVLOG(2) << "U=" << HexEncode(u, BT_OCTET32_LEN)
+           << ", V=" << HexEncode(v, BT_OCTET32_LEN)
+           << ", X=" << HexEncode(x.data(), x.size()) << ", Z=" << std::hex
+           << +z;
+
+  std::array<uint8_t, msg_len> msg;
+  auto it = msg.begin();
+  it = std::copy(&z, &z + 1, it);
+  it = std::copy(v, v + BT_OCTET32_LEN, it);
+  it = std::copy(u, u + BT_OCTET32_LEN, it);
+  return aes_cmac(x, msg.data(), msg.size());
+}
+
+/** helper for f5 */
+static Octet16 calculate_mac_key_or_ltk(const Octet16& t, uint8_t counter,
+                                        uint8_t* key_id, const Octet16& n1,
+                                        const Octet16& n2, uint8_t* a1,
+                                        uint8_t* a2, uint8_t* length) {
+  constexpr size_t msg_len = 1 /* Counter size */ + 4 /* keyID size */ +
+                             OCTET16_LEN /* N1 size */ +
+                             OCTET16_LEN /* N2 size */ + 7 /* A1 size*/ +
+                             7 /* A2 size*/ + 2 /* Length size */;
+  std::array<uint8_t, msg_len> msg;
+  auto it = msg.begin();
+  it = std::copy(length, length + 2, it);
+  it = std::copy(a2, a2 + 7, it);
+  it = std::copy(a1, a1 + 7, it);
+  it = std::copy(n2.begin(), n2.end(), it);
+  it = std::copy(n1.begin(), n1.end(), it);
+  it = std::copy(key_id, key_id + 4, it);
+  it = std::copy(&counter, &counter + 1, it);
+
+  return aes_cmac(t, msg.data(), msg.size());
+}
+
+void f5(uint8_t* w, const Octet16& n1, const Octet16& n2, uint8_t* a1,
+        uint8_t* a2, Octet16* mac_key, Octet16* ltk) {
+  DVLOG(2) << __func__ << "W=" << HexEncode(w, BT_OCTET32_LEN)
+           << ", N1=" << HexEncode(n1.data(), n1.size())
+           << ", N2=" << HexEncode(n2.data(), n2.size())
+           << ", A1=" << HexEncode(a1, 7) << ", A2=" << HexEncode(a2, 7);
+
+  const Octet16 salt{0xBE, 0x83, 0x60, 0x5A, 0xDB, 0x0B, 0x37, 0x60,
+                     0x38, 0xA5, 0xF5, 0xAA, 0x91, 0x83, 0x88, 0x6C};
+  Octet16 t = aes_cmac(salt, w, BT_OCTET32_LEN);
+
+  DVLOG(2) << "T=" << HexEncode(t.data(), t.size());
+
+  uint8_t key_id[4] = {0x65, 0x6c, 0x74, 0x62}; /* 0x62746c65 */
+  uint8_t length[2] = {0x00, 0x01};             /* 0x0100 */
+
+  *mac_key = calculate_mac_key_or_ltk(t, 0, key_id, n1, n2, a1, a2, length);
+
+  *ltk = calculate_mac_key_or_ltk(t, 1, key_id, n1, n2, a1, a2, length);
+
+  DVLOG(2) << "mac_key=" << HexEncode(mac_key->data(), mac_key->size());
+  DVLOG(2) << "ltk=" << HexEncode(ltk->data(), ltk->size());
+}
+
+Octet16 f6(const Octet16& w, const Octet16& n1, const Octet16& n2,
+           const Octet16& r, uint8_t* iocap, uint8_t* a1, uint8_t* a2) {
+  const uint8_t msg_len = OCTET16_LEN /* N1 size */ +
+                          OCTET16_LEN /* N2 size */ + OCTET16_LEN /* R size */ +
+                          3 /* IOcap size */ + 7 /* A1 size*/
+                          + 7 /* A2 size*/;
+
+  DVLOG(2) << __func__ << "W=" << HexEncode(w.data(), w.size())
+           << ", N1=" << HexEncode(n1.data(), n1.size())
+           << ", N2=" << HexEncode(n2.data(), n2.size())
+           << ", R=" << HexEncode(r.data(), r.size())
+           << ", IOcap=" << HexEncode(iocap, 3) << ", A1=" << HexEncode(a1, 7)
+           << ", A2=" << HexEncode(a2, 7);
+
+  std::array<uint8_t, msg_len> msg;
+  auto it = msg.begin();
+  it = std::copy(a2, a2 + 7, it);
+  it = std::copy(a1, a1 + 7, it);
+  it = std::copy(iocap, iocap + 3, it);
+  it = std::copy(r.begin(), r.end(), it);
+  it = std::copy(n2.begin(), n2.end(), it);
+  it = std::copy(n1.begin(), n1.end(), it);
+
+  return aes_cmac(w, msg.data(), msg.size());
+}
+
+uint32_t g2(uint8_t* u, uint8_t* v, const Octet16& x, const Octet16& y) {
+  constexpr size_t msg_len = BT_OCTET32_LEN /* U size */ +
+                             BT_OCTET32_LEN /* V size */
+                             + OCTET16_LEN /* Y size */;
+
+  DVLOG(2) << __func__ << "U=" << HexEncode(u, BT_OCTET32_LEN)
+           << ", V=" << HexEncode(v, BT_OCTET32_LEN)
+           << ", X=" << HexEncode(x.data(), x.size())
+           << ", Y=" << HexEncode(y.data(), y.size());
+
+  std::array<uint8_t, msg_len> msg;
+  auto it = msg.begin();
+  it = std::copy(y.begin(), y.end(), it);
+  it = std::copy(v, v + BT_OCTET32_LEN, it);
+  it = std::copy(u, u + BT_OCTET32_LEN, it);
+
+  Octet16 cmac = aes_cmac(x, msg.data(), msg.size());
+
+  /* vres = cmac mod 2**32 mod 10**6 */
+  uint32_t vres;
+  uint8_t* p = cmac.data();
+  STREAM_TO_UINT32(vres, p);
+
+  vres = vres % 1000000;
+  return vres;
+}
+
+Octet16 ltk_to_link_key(const Octet16& ltk, bool use_h7) {
+  Octet16 ilk; /* intermidiate link key */
+  if (use_h7) {
+    constexpr Octet16 salt{0x31, 0x70, 0x6D, 0x74, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    ilk = h7(salt, ltk);
+  } else {
+    /* "tmp1" mapping to extended ASCII, little endian*/
+    constexpr std::array<uint8_t, 4> keyID_tmp1 = {0x31, 0x70, 0x6D, 0x74};
+    ilk = h6(ltk, keyID_tmp1);
+  }
+
+  /* "lebr" mapping to extended ASCII, little endian */
+  constexpr std::array<uint8_t, 4> keyID_lebr = {0x72, 0x62, 0x65, 0x6c};
+  return h6(ilk, keyID_lebr);
+}
+
+Octet16 link_key_to_ltk(const Octet16& link_key, bool use_h7) {
+  Octet16 iltk; /* intermidiate long term key */
+  if (use_h7) {
+    constexpr Octet16 salt{0x32, 0x70, 0x6D, 0x74, 0x00, 0x00, 0x00, 0x00,
+                           0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+    iltk = h7(salt, link_key);
+  } else {
+    /* "tmp2" mapping to extended ASCII, little endian */
+    constexpr std::array<uint8_t, 4> keyID_tmp2 = {0x32, 0x70, 0x6D, 0x74};
+    iltk = h6(link_key, keyID_tmp2);
+  }
+
+  /* "brle" mapping to extended ASCII, little endian */
+  constexpr std::array<uint8_t, 4> keyID_brle = {0x65, 0x6c, 0x72, 0x62};
+  return h6(iltk, keyID_brle);
+}
+
+}  // namespace crypto_toolbox
diff --git a/stack/crypto_toolbox/crypto_toolbox.h b/stack/crypto_toolbox/crypto_toolbox.h
new file mode 100644
index 0000000..90d7392
--- /dev/null
+++ b/stack/crypto_toolbox/crypto_toolbox.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "stack/include/bt_types.h"
+
+namespace crypto_toolbox {
+
+extern Octet16 aes_128(const Octet16& key, const Octet16& message);
+extern Octet16 aes_cmac(const Octet16& key, const uint8_t* message,
+                        uint16_t length);
+extern Octet16 f4(uint8_t* u, uint8_t* v, const Octet16& x, uint8_t z);
+extern void f5(uint8_t* w, const Octet16& n1, const Octet16& n2, uint8_t* a1,
+               uint8_t* a2, Octet16* mac_key, Octet16* ltk);
+extern Octet16 f6(const Octet16& w, const Octet16& n1, const Octet16& n2,
+                  const Octet16& r, uint8_t* iocap, uint8_t* a1, uint8_t* a2);
+extern Octet16 h6(const Octet16& w, std::array<uint8_t, 4> keyid);
+extern Octet16 h7(const Octet16& salt, const Octet16& w);
+extern uint32_t g2(uint8_t* u, uint8_t* v, const Octet16& x, const Octet16& y);
+extern Octet16 ltk_to_link_key(const Octet16& ltk, bool use_h7);
+extern Octet16 link_key_to_ltk(const Octet16& link_key, bool use_h7);
+
+/* This function computes AES_128(key, message). |key| must be 128bit.
+ * |message| can be at most 16 bytes long, it's length in bytes is given in
+ * |length| */
+inline Octet16 aes_128(const Octet16& key, const uint8_t* message,
+                       const uint8_t length) {
+  CHECK(length <= OCTET16_LEN) << "you tried aes_128 more than 16 bytes!";
+  Octet16 msg{0};
+  std::copy(message, message + length, msg.begin());
+  return aes_128(key, msg);
+}
+
+// |tlen| - lenth of mac desired
+// |p_signature| - data pointer to where signed data to be stored, tlen long.
+inline void aes_cmac(const Octet16& key, const uint8_t* message,
+                     uint16_t length, uint16_t tlen, uint8_t* p_signature) {
+  Octet16 signature = aes_cmac(key, message, length);
+
+  uint8_t* p_mac = signature.data() + (OCTET16_LEN - tlen);
+  memcpy(p_signature, p_mac, tlen);
+}
+
+inline Octet16 aes_cmac(const Octet16& key, const Octet16& message) {
+  return aes_cmac(key, message.data(), message.size());
+}
+
+}  // namespace crypto_toolbox
\ No newline at end of file
diff --git a/stack/gap/gap_conn.cc b/stack/gap/gap_conn.cc
index 72183bb..15d3ddb 100644
--- a/stack/gap/gap_conn.cc
+++ b/stack/gap/gap_conn.cc
@@ -235,8 +235,7 @@
 
   /* Register the PSM with L2CAP */
   if (transport == BT_TRANSPORT_BR_EDR) {
-    p_ccb->psm = L2CA_REGISTER(
-        psm, &conn.reg_info, AMP_AUTOSWITCH_ALLOWED | AMP_USE_AMP_IF_POSSIBLE);
+    p_ccb->psm = L2CA_REGISTER(psm, &conn.reg_info, false /* enable_snoop */);
     if (p_ccb->psm == 0) {
       LOG(ERROR) << StringPrintf("%s: Failure registering PSM 0x%04x", __func__,
                                  psm);
diff --git a/stack/gatt/att_protocol.cc b/stack/gatt/att_protocol.cc
index 142216c..5d3d4a8 100644
--- a/stack/gatt/att_protocol.cc
+++ b/stack/gatt/att_protocol.cc
@@ -352,9 +352,7 @@
           "ATT_RSP_READ_BLOB/GATT_RSP_PREPARE_WRITE: len = %d offset = %d",
           p_msg->attr_value.len, p_msg->attr_value.offset);
       offset = p_msg->attr_value.offset;
-    /* Coverity: [FALSE-POSITIVE error] intended fall through */
-    /* Missing break statement between cases in switch statement */
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case GATT_RSP_READ_BY_TYPE:
     case GATT_RSP_READ:
     case GATT_HANDLE_VALUE_NOTIF:
@@ -482,7 +480,7 @@
 
     case GATT_REQ_READ_BLOB:
       offset = p_msg->read_blob.offset;
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case GATT_REQ_READ:
       handle =
           (op_code == GATT_REQ_READ) ? p_msg->handle : p_msg->read_blob.handle;
@@ -498,7 +496,7 @@
 
     case GATT_REQ_PREPARE_WRITE:
       offset = p_msg->attr_value.offset;
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case GATT_REQ_WRITE:
     case GATT_CMD_WRITE:
     case GATT_SIGN_CMD_WRITE:
diff --git a/stack/gatt/connection_manager.cc b/stack/gatt/connection_manager.cc
new file mode 100644
index 0000000..cfbb02e
--- /dev/null
+++ b/stack/gatt/connection_manager.cc
@@ -0,0 +1,295 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "connection_manager.h"
+
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/location.h>
+#include <base/logging.h>
+#include <map>
+#include <memory>
+#include <set>
+
+#include "internal_include/bt_trace.h"
+#include "osi/include/alarm.h"
+#include "stack/btm/btm_ble_bgconn.h"
+
+#define DIRECT_CONNECT_TIMEOUT (30 * 1000) /* 30 seconds */
+
+struct closure_data {
+  base::OnceClosure user_task;
+  base::Location posted_from;
+};
+
+static void alarm_closure_cb(void* p) {
+  closure_data* data = (closure_data*)p;
+  VLOG(1) << "executing timer scheduled at %s" << data->posted_from.ToString();
+  std::move(data->user_task).Run();
+  delete data;
+}
+
+// Periodic alarms are not supported, because we clean up data in callback
+void alarm_set_closure(const base::Location& posted_from, alarm_t* alarm,
+                       uint64_t interval_ms, base::OnceClosure user_task) {
+  closure_data* data = new closure_data;
+  data->posted_from = posted_from;
+  data->user_task = std::move(user_task);
+  VLOG(1) << "scheduling timer %s" << data->posted_from.ToString();
+  alarm_set_on_mloop(alarm, interval_ms, alarm_closure_cb, data);
+}
+
+using unique_alarm_ptr = std::unique_ptr<alarm_t, decltype(&alarm_free)>;
+
+namespace connection_manager {
+
+struct tAPPS_CONNECTING {
+  // ids of clients doing background connection to given device
+  std::set<tAPP_ID> doing_bg_conn;
+
+  // Apps trying to do direct connection.
+  std::map<tAPP_ID, unique_alarm_ptr> doing_direct_conn;
+};
+
+namespace {
+// Maps address to apps trying to connect to it
+std::map<RawAddress, tAPPS_CONNECTING> bgconn_dev;
+
+bool anyone_connecting(
+    const std::map<RawAddress, tAPPS_CONNECTING>::iterator it) {
+  return (!it->second.doing_bg_conn.empty() ||
+          !it->second.doing_direct_conn.empty());
+}
+
+}  // namespace
+
+/** background connection device from the list. Returns pointer to the device
+ * record, or nullptr if not found */
+std::set<tAPP_ID> get_apps_connecting_to(const RawAddress& address) {
+  auto it = bgconn_dev.find(address);
+  return (it != bgconn_dev.end()) ? it->second.doing_bg_conn
+                                  : std::set<tAPP_ID>();
+}
+
+/** Add a device from the background connection list.  Returns true if device
+ * added to the list, or already in list, false otherwise */
+bool background_connect_add(uint8_t app_id, const RawAddress& address) {
+  auto it = bgconn_dev.find(address);
+  bool in_white_list = false;
+  if (it != bgconn_dev.end()) {
+    // device already in the whitelist, just add interested app to the list
+    if (it->second.doing_bg_conn.count(app_id)) {
+      LOG(INFO) << "App id=" << loghex(app_id)
+                << "already doing background connection to " << address;
+      return true;
+    }
+
+    // Already in white list ?
+    if (anyone_connecting(it)) {
+      in_white_list = true;
+    }
+  }
+
+  if (!in_white_list) {
+    // the device is not in the whitelist
+    if (!BTM_WhiteListAdd(address)) return false;
+  }
+
+  // create endtry for address, and insert app_id.
+  bgconn_dev[address].doing_bg_conn.insert(app_id);
+  return true;
+}
+
+/** Removes all registrations for connection for given device.
+ * Returns true if anything was removed, false otherwise */
+bool remove_unconditional(const RawAddress& address) {
+  auto it = bgconn_dev.find(address);
+  if (it == bgconn_dev.end()) return false;
+
+  BTM_WhiteListRemove(address);
+  bgconn_dev.erase(it);
+  return true;
+}
+
+/** Remove device from the background connection device list or listening to
+ * advertising list.  Returns true if device was on the list and was succesfully
+ * removed */
+bool background_connect_remove(uint8_t app_id, const RawAddress& address) {
+  VLOG(2) << __func__;
+  auto it = bgconn_dev.find(address);
+  if (it == bgconn_dev.end()) return false;
+
+  if (!it->second.doing_bg_conn.erase(app_id)) return false;
+
+  if (anyone_connecting(it)) return true;
+
+  // no more apps interested - remove from whitelist and delete record
+  BTM_WhiteListRemove(address);
+  bgconn_dev.erase(it);
+  return true;
+}
+
+/** deregister all related background connetion device. */
+void on_app_deregistered(uint8_t app_id) {
+  auto it = bgconn_dev.begin();
+  auto end = bgconn_dev.end();
+  /* update the BG conn device list */
+  while (it != end) {
+    it->second.doing_bg_conn.erase(app_id);
+
+    it->second.doing_direct_conn.erase(app_id);
+
+    if (anyone_connecting(it)) {
+      it++;
+      continue;
+    }
+
+    BTM_WhiteListRemove(it->first);
+    it = bgconn_dev.erase(it);
+  }
+}
+
+void on_connection_complete(const RawAddress& address) {
+  VLOG(2) << __func__;
+  auto it = bgconn_dev.find(address);
+
+  while (it != bgconn_dev.end() && !it->second.doing_direct_conn.empty()) {
+    uint8_t app_id = it->second.doing_direct_conn.begin()->first;
+    direct_connect_remove(app_id, address);
+    it = bgconn_dev.find(address);
+  }
+}
+
+/** Reset bg device list. If called after controller reset, set |after_reset| to
+ * true, as there is no need to wipe controller white list in this case. */
+void reset(bool after_reset) {
+  bgconn_dev.clear();
+  if (!after_reset) BTM_WhiteListClear();
+}
+
+void wl_direct_connect_timeout_cb(uint8_t app_id, const RawAddress& address) {
+  on_connection_timed_out(app_id, address);
+
+  // TODO: this would free the timer, from within the timer callback, which is
+  // bad.
+  direct_connect_remove(app_id, address);
+}
+
+/** Add a device to the direcgt connection list.  Returns true if device
+ * added to the list, false otherwise */
+bool direct_connect_add(uint8_t app_id, const RawAddress& address) {
+  auto it = bgconn_dev.find(address);
+  bool in_white_list = false;
+
+  if (it != bgconn_dev.end()) {
+    // app already trying to connect to this particular device
+    if (it->second.doing_direct_conn.count(app_id)) {
+      LOG(INFO) << "direct connect attempt from app_id=" << loghex(app_id)
+                << " already in progress";
+      return false;
+    }
+
+    // are we already in the white list ?
+    if (anyone_connecting(it)) {
+      in_white_list = true;
+    }
+  }
+
+  bool params_changed = BTM_SetLeConnectionModeToFast();
+
+  if (!in_white_list) {
+    if (!BTM_WhiteListAdd(address)) {
+      // if we can't add to white list, turn parameters back to slow.
+      if (params_changed) BTM_SetLeConnectionModeToSlow();
+      return false;
+    }
+  }
+
+  // Setup a timer
+  alarm_t* timeout = alarm_new("wl_conn_params_30s");
+  alarm_set_closure(
+      FROM_HERE, timeout, DIRECT_CONNECT_TIMEOUT,
+      base::BindOnce(&wl_direct_connect_timeout_cb, app_id, address));
+
+  bgconn_dev[address].doing_direct_conn.emplace(
+      app_id, unique_alarm_ptr(timeout, &alarm_free));
+  return true;
+}
+
+bool any_direct_connect_left() {
+  for (const auto& tmp : bgconn_dev) {
+    if (!tmp.second.doing_direct_conn.empty()) return true;
+  }
+  return false;
+}
+
+bool direct_connect_remove(uint8_t app_id, const RawAddress& address) {
+  VLOG(2) << __func__ << ": "
+          << "app_id: " << +app_id << ", address:" << address;
+  auto it = bgconn_dev.find(address);
+  if (it == bgconn_dev.end()) return false;
+
+  auto app_it = it->second.doing_direct_conn.find(app_id);
+  if (app_it == it->second.doing_direct_conn.end()) return false;
+
+  // this will free the alarm
+  it->second.doing_direct_conn.erase(app_it);
+
+  // if we removed last direct connection, lower the scan parameters used for
+  // connecting
+  if (!any_direct_connect_left()) {
+    BTM_SetLeConnectionModeToSlow();
+  }
+
+  if (anyone_connecting(it)) return true;
+
+  // no more apps interested - remove from whitelist
+  BTM_WhiteListRemove(address);
+  bgconn_dev.erase(it);
+  return true;
+}
+
+void dump(int fd) {
+  dprintf(fd, "\nconnection_manager state:\n");
+  if (bgconn_dev.empty()) {
+    dprintf(fd, "\n\tno Low Energy connection attempts\n");
+    return;
+  }
+
+  dprintf(fd, "\n\tdevices attempting connection: %d\n",
+          (int)bgconn_dev.size());
+  for (const auto& entry : bgconn_dev) {
+    dprintf(fd, "\n\t * %s: ", entry.first.ToString().c_str());
+
+    if (!entry.second.doing_direct_conn.empty()) {
+      dprintf(fd, "\n\t\tapps doing direct connect: ");
+      for (const auto& id : entry.second.doing_direct_conn) {
+        dprintf(fd, "%d, ", id.first);
+      }
+    }
+
+    if (entry.second.doing_bg_conn.empty()) {
+      dprintf(fd, "\n\t\tapps doing background connect: ");
+      for (const auto& id : entry.second.doing_bg_conn) {
+        dprintf(fd, "%d, ", id);
+      }
+    }
+  }
+}
+
+}  // namespace connection_manager
diff --git a/stack/gatt/connection_manager.h b/stack/gatt/connection_manager.h
new file mode 100644
index 0000000..4704c8f
--- /dev/null
+++ b/stack/gatt/connection_manager.h
@@ -0,0 +1,61 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <set>
+
+#include "types/raw_address.h"
+
+/* connection_manager takes care of all the low-level details of LE connection
+ * initiation. It accept requests from multiple subsystems to connect to
+ * devices, and multiplex them into whitelist add/remove, and scan parameter
+ * changes.
+ *
+ * There is no code for app_id generation. GATT clients use their GATT_IF, and
+ * L2CAP layer uses CONN_MGR_ID_L2CAP as fixed app_id. In case any further
+ * subsystems also use connection_manager, we should consider adding a proper
+ * mechanism for app_id generation.
+ */
+namespace connection_manager {
+
+using tAPP_ID = uint8_t;
+
+/* for background connection */
+extern bool background_connect_add(tAPP_ID app_id, const RawAddress& address);
+extern bool background_connect_remove(tAPP_ID app_id,
+                                      const RawAddress& address);
+extern bool remove_unconditional(const RawAddress& address);
+
+extern void reset(bool after_reset);
+
+extern void on_app_deregistered(tAPP_ID app_id);
+extern void on_connection_complete(const RawAddress& address);
+
+extern std::set<tAPP_ID> get_apps_connecting_to(const RawAddress& remote_bda);
+
+extern bool direct_connect_add(tAPP_ID app_id, const RawAddress& address);
+extern bool direct_connect_remove(tAPP_ID app_id, const RawAddress& address);
+
+extern void dump(int fd);
+
+/* This callback will be executed when direct connect attempt fails due to
+ * timeout. It must be implemented by users of connection_manager */
+extern void on_connection_timed_out(uint8_t app_id, const RawAddress& address);
+
+}  // namespace connection_manager
diff --git a/stack/gatt/gatt_api.cc b/stack/gatt/gatt_api.cc
index b983318..37bc614 100644
--- a/stack/gatt/gatt_api.cc
+++ b/stack/gatt/gatt_api.cc
@@ -24,7 +24,6 @@
 #include "bt_target.h"
 
 #include <base/strings/string_number_conversions.h>
-#include <base/strings/stringprintf.h>
 #include <stdio.h>
 #include <string.h>
 #include "bt_common.h"
@@ -33,10 +32,11 @@
 #include "gatt_api.h"
 #include "gatt_int.h"
 #include "l2c_api.h"
+#include "stack/gatt/connection_manager.h"
 
-using base::StringPrintf;
 using bluetooth::Uuid;
 
+extern bool BTM_BackgroundConnectAddressKnown(const RawAddress& address);
 /**
  * Add an service handle range to the list in decending order of the start
  * handle. Return reference to the newly added element.
@@ -184,9 +184,8 @@
 
   /* check for space */
   if (num_handles > (0xFFFF - s_hdl + 1)) {
-    LOG(ERROR) << StringPrintf(
-        "GATTS_ReserveHandles: no handles, s_hdl: %u  needed: %u", s_hdl,
-        num_handles);
+    LOG(ERROR) << __func__ << ": no handles, s_hdl=" << +s_hdl
+               << " needed=" << num_handles;
     return GATT_INTERNAL_ERROR;
   }
 
@@ -204,10 +203,11 @@
 
   gatts_init_service_db(list.svc_db, svc_uuid, is_pri, s_hdl, num_handles);
 
-  VLOG(1) << StringPrintf(
-      "%s: handles needed:%u s_hdl=%u e_hdl=%u %s is_primary=%d", __func__,
-      num_handles, list.asgn_range.s_handle, list.asgn_range.e_handle,
-      list.asgn_range.svc_uuid.ToString().c_str(), list.asgn_range.is_primary);
+  VLOG(1) << __func__ << ": handles needed=" << num_handles
+          << ", s_hdl=" << loghex(list.asgn_range.s_handle)
+          << ", e_hdl=" << loghex(list.asgn_range.e_handle)
+          << ", uuid=" << list.asgn_range.svc_uuid
+          << ", is_primary=" << +list.asgn_range.is_primary;
 
   service->attribute_handle = s_hdl;
 
@@ -221,17 +221,16 @@
            !(el->permissions & GATT_WRITE_SIGNED_PERM)) ||
           ((el->permissions & GATT_WRITE_SIGNED_PERM) &&
            !(el->properties & GATT_CHAR_PROP_BIT_AUTH))) {
-        VLOG(1) << StringPrintf(
-            "Invalid configuration property=0x%02x perm=0x%04x ",
-            el->properties, el->permissions);
+        VLOG(1) << "Invalid configuration property=" << loghex(el->properties)
+                << ", perm=" << loghex(el->permissions);
         return GATT_INTERNAL_ERROR;
       }
 
       if (is_gatt_attr_type(uuid)) {
-        LOG(ERROR) << StringPrintf(
-            "%s: attept to add characteristic with UUID equal to GATT "
-            "Attribute Type %s ",
-            __func__, uuid.ToString().c_str());
+        LOG(ERROR) << __func__
+                   << ": attept to add characteristic with UUID equal to GATT "
+                      "Attribute Type "
+                   << uuid;
         return GATT_INTERNAL_ERROR;
       }
 
@@ -239,10 +238,10 @@
           list.svc_db, el->permissions, el->properties, uuid);
     } else if (el->type == BTGATT_DB_DESCRIPTOR) {
       if (is_gatt_attr_type(uuid)) {
-        LOG(ERROR) << StringPrintf(
-            "%s: attept to add descriptor with UUID equal to GATT "
-            "Attribute Type %s",
-            __func__, uuid.ToString().c_str());
+        LOG(ERROR) << __func__
+                   << ": attept to add descriptor with UUID equal to GATT "
+                      "Attribute Type "
+                   << uuid;
         return GATT_INTERNAL_ERROR;
       }
 
@@ -294,9 +293,9 @@
 
   gatt_update_last_srv_info();
 
-  VLOG(1) << StringPrintf(
-      "%s: allocated el: s_hdl=%d e_hdl=%d type=0x%x sdp_hdl=0x%x", __func__,
-      elem.s_hdl, elem.e_hdl, elem.type, elem.sdp_handle);
+  VLOG(1) << __func__ << ": allocated el s_hdl=" << loghex(elem.s_hdl)
+          << ", e_hdl=" << loghex(elem.e_hdl) << ", type=" << loghex(elem.type)
+          << ", sdp_hdl=" << loghex(elem.sdp_handle);
 
   gatt_proc_srv_chg();
 
@@ -354,8 +353,8 @@
     GATTS_StopService(it->asgn_range.s_handle);
   }
 
-  VLOG(1) << StringPrintf("released handles s_hdl=%u e_hdl=%u",
-                          it->asgn_range.s_handle, it->asgn_range.e_handle);
+  VLOG(1) << "released handles s_hdl=" << loghex(it->asgn_range.s_handle)
+          << ", e_hdl=" << loghex(it->asgn_range.e_handle);
 
   if ((it->asgn_range.s_handle >= gatt_cb.hdl_cfg.app_start_hdl) &&
       gatt_cb.cb_info.p_nv_save_callback)
@@ -377,12 +376,13 @@
  *
  ******************************************************************************/
 void GATTS_StopService(uint16_t service_handle) {
-  LOG(INFO) << __func__ << ": 0x" << std::hex << +service_handle;
+  LOG(INFO) << __func__ << ": " << loghex(service_handle);
 
   auto it = gatt_sr_find_i_rcb_by_handle(service_handle);
   if (it == gatt_cb.srv_list_info->end()) {
-    LOG(ERROR) << StringPrintf("%s: service_handle: %u is not in use", __func__,
-                               service_handle);
+    LOG(ERROR) << __func__ << ": service_handle=" << loghex(service_handle)
+               << " is not in use";
+    return;
   }
 
   if (it->sdp_handle) {
@@ -410,11 +410,6 @@
  ******************************************************************************/
 tGATT_STATUS GATTS_HandleValueIndication(uint16_t conn_id, uint16_t attr_handle,
                                          uint16_t val_len, uint8_t* p_val) {
-  tGATT_STATUS cmd_status = GATT_NO_RESOURCES;
-
-  tGATT_VALUE indication;
-  BT_HDR* p_msg;
-  tGATT_VALUE* p_buf;
   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
@@ -422,12 +417,13 @@
 
   VLOG(1) << __func__;
   if ((p_reg == NULL) || (p_tcb == NULL)) {
-    LOG(ERROR) << __func__ << ": Unknown  conn_id: " << +conn_id;
+    LOG(ERROR) << __func__ << ": Unknown  conn_id=" << loghex(conn_id);
     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
   }
 
   if (!GATT_HANDLE_IS_VALID(attr_handle)) return GATT_ILLEGAL_PARAMETER;
 
+  tGATT_VALUE indication;
   indication.conn_id = conn_id;
   indication.handle = attr_handle;
   indication.len = val_len;
@@ -436,24 +432,20 @@
 
   if (GATT_HANDLE_IS_VALID(p_tcb->indicate_handle)) {
     VLOG(1) << "Add a pending indication";
-    p_buf = gatt_add_pending_ind(p_tcb, &indication);
-    if (p_buf != NULL) {
-      cmd_status = GATT_SUCCESS;
-    } else {
-      cmd_status = GATT_NO_RESOURCES;
-    }
-  } else {
-    tGATT_SR_MSG gatt_sr_msg;
-    gatt_sr_msg.attr_value = indication;
-    p_msg = attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
-    if (p_msg != NULL) {
-      cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
+    gatt_add_pending_ind(p_tcb, &indication);
+    return GATT_SUCCESS;
+  }
 
-      if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
-        p_tcb->indicate_handle = indication.handle;
-        gatt_start_conf_timer(p_tcb);
-      }
-    }
+  tGATT_SR_MSG gatt_sr_msg;
+  gatt_sr_msg.attr_value = indication;
+  BT_HDR* p_msg =
+      attp_build_sr_msg(*p_tcb, GATT_HANDLE_VALUE_IND, &gatt_sr_msg);
+  if (!p_msg) return GATT_NO_RESOURCES;
+
+  tGATT_STATUS cmd_status = attp_send_sr_msg(*p_tcb, p_msg);
+  if (cmd_status == GATT_SUCCESS || cmd_status == GATT_CONGESTED) {
+    p_tcb->indicate_handle = indication.handle;
+    gatt_start_conf_timer(p_tcb);
   }
   return cmd_status;
 }
@@ -532,19 +524,17 @@
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
 
-  VLOG(1) << __func__
-          << StringPrintf(": conn_id: %u  trans_id: %u  Status: 0x%04x",
-                          conn_id, trans_id, status);
+  VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
+          << ", trans_id=" << loghex(trans_id) << ", status=" << loghex(status);
 
   if ((p_reg == NULL) || (p_tcb == NULL)) {
-    LOG(ERROR) << StringPrintf("Unknown  conn_id: %u ", conn_id);
+    LOG(ERROR) << "Unknown  conn_id=" << loghex(conn_id);
     return (tGATT_STATUS)GATT_INVALID_CONN_ID;
   }
 
   if (p_tcb->sr_cmd.trans_id != trans_id) {
-    LOG(ERROR) << StringPrintf("conn_id: %u  waiting for op_code = %02x",
-                               conn_id, p_tcb->sr_cmd.op_code);
-
+    LOG(ERROR) << "conn_id=" << loghex(conn_id)
+               << " waiting for op_code=" << loghex(p_tcb->sr_cmd.op_code);
     return (GATT_WRONG_STATE);
   }
   /* Process App response */
@@ -582,7 +572,7 @@
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
 
-  VLOG(1) << __func__ << StringPrintf("conn_id=%d mtu=%d", conn_id, mtu);
+  VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id) << ", mtu=" << +mtu;
 
   if ((p_tcb == NULL) || (p_reg == NULL) || (mtu < GATT_DEF_BLE_MTU_SIZE) ||
       (mtu > GATT_MAX_MTU_SIZE)) {
@@ -618,32 +608,36 @@
  *
  * Parameters       conn_id: connection identifier.
  *                  disc_type:discovery type.
- *                  p_param: parameters of discovery requirement.
+ *                  start_handle and end_handle: range of handles for discovery
+ *                  uuid: uuid to discovery. set to Uuid::kEmpty for requests
+ *                        that don't need it
  *
  * Returns          GATT_SUCCESS if command received/sent successfully.
  *
  ******************************************************************************/
 tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
-                            tGATT_DISC_PARAM* p_param) {
+                            uint16_t start_handle, uint16_t end_handle,
+                            const Uuid& uuid) {
   tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
 
-  LOG(INFO) << __func__
-            << StringPrintf(" conn_id=%d disc_type=%d", conn_id, disc_type);
-
-  if ((p_tcb == NULL) || (p_reg == NULL) || (p_param == NULL) ||
-      (disc_type >= GATT_DISC_MAX)) {
-    LOG(ERROR) << StringPrintf("Illegal param: disc_type %d conn_id = %d",
-                               disc_type, conn_id);
+  if ((p_tcb == NULL) || (p_reg == NULL) || (disc_type >= GATT_DISC_MAX)) {
+    LOG(ERROR) << __func__ << " Illegal param: disc_type=" << +disc_type
+               << " conn_id=" << loghex(conn_id);
     return GATT_ILLEGAL_PARAMETER;
   }
 
-  if (!GATT_HANDLE_IS_VALID(p_param->s_handle) ||
-      !GATT_HANDLE_IS_VALID(p_param->e_handle) ||
+  LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id)
+            << ", disc_type=" << +disc_type
+            << ", s_handle=" << loghex(start_handle)
+            << ", e_handle=" << loghex(end_handle);
+
+  if (!GATT_HANDLE_IS_VALID(start_handle) ||
+      !GATT_HANDLE_IS_VALID(end_handle) ||
       /* search by type does not have a valid UUID param */
-      (disc_type == GATT_DISC_SRVC_BY_UUID && p_param->service.IsEmpty())) {
+      (disc_type == GATT_DISC_SRVC_BY_UUID && uuid.IsEmpty())) {
     return GATT_ILLEGAL_PARAMETER;
   }
 
@@ -657,14 +651,20 @@
 
   p_clcb->operation = GATTC_OPTYPE_DISCOVERY;
   p_clcb->op_subtype = disc_type;
-  p_clcb->s_handle = p_param->s_handle;
-  p_clcb->e_handle = p_param->e_handle;
-  p_clcb->uuid = p_param->service;
+  p_clcb->s_handle = start_handle;
+  p_clcb->e_handle = end_handle;
+  p_clcb->uuid = uuid;
 
   gatt_act_discovery(p_clcb);
   return GATT_SUCCESS;
 }
 
+tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
+                            uint16_t start_handle, uint16_t end_handle) {
+  return GATTC_Discover(conn_id, disc_type, start_handle, end_handle,
+                        Uuid::kEmpty);
+}
+
 /*******************************************************************************
  *
  * Function         GATTC_Read
@@ -686,17 +686,18 @@
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
 
-  VLOG(1) << __func__ << StringPrintf(" conn_id=%d type=%d", conn_id, type);
+  VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
+          << ", type=" << loghex(type);
 
   if ((p_tcb == NULL) || (p_reg == NULL) || (p_read == NULL) ||
       ((type >= GATT_READ_MAX) || (type == 0))) {
-    LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id,
-                               type);
+    LOG(ERROR) << ": illegal param: conn_id=" << loghex(conn_id)
+               << "type=" << loghex(type);
     return GATT_ILLEGAL_PARAMETER;
   }
 
   if (gatt_is_clcb_allocated(conn_id)) {
-    LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id);
+    LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
     return GATT_BUSY;
   }
 
@@ -739,7 +740,7 @@
   }
 
   /* start security check */
-  gatt_security_check_start(p_clcb);
+  if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
   return GATT_SUCCESS;
 }
 
@@ -767,14 +768,13 @@
   if ((p_tcb == NULL) || (p_reg == NULL) || (p_write == NULL) ||
       ((type != GATT_WRITE) && (type != GATT_WRITE_PREPARE) &&
        (type != GATT_WRITE_NO_RSP))) {
-    LOG(ERROR) << __func__
-               << StringPrintf(" Illegal param: conn_id %d, type 0%d,", conn_id,
-                               type);
+    LOG(ERROR) << __func__ << " Illegal param: conn_id=" << loghex(conn_id)
+               << ", type=" << loghex(type);
     return GATT_ILLEGAL_PARAMETER;
   }
 
   if (gatt_is_clcb_allocated(conn_id)) {
-    LOG(ERROR) << StringPrintf("GATT_BUSY conn_id = %d", conn_id);
+    LOG(ERROR) << "GATT_BUSY conn_id=" << loghex(conn_id);
     return GATT_BUSY;
   }
 
@@ -794,7 +794,7 @@
     p->offset = 0;
   }
 
-  gatt_security_check_start(p_clcb);
+  if (gatt_security_check_start(p_clcb)) p_tcb->pending_enc_clcb.push(p_clcb);
   return GATT_SUCCESS;
 }
 
@@ -818,16 +818,16 @@
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
 
-  VLOG(1) << __func__
-          << StringPrintf(": conn_id=%d is_execute=%d", conn_id, is_execute);
+  VLOG(1) << __func__ << ": conn_id=" << loghex(conn_id)
+          << ", is_execute=" << +is_execute;
 
   if ((p_tcb == NULL) || (p_reg == NULL)) {
-    LOG(ERROR) << StringPrintf(" Illegal param: conn_id %d", conn_id);
+    LOG(ERROR) << " Illegal param: conn_id=" << loghex(conn_id);
     return GATT_ILLEGAL_PARAMETER;
   }
 
   if (gatt_is_clcb_allocated(conn_id)) {
-    LOG(ERROR) << StringPrintf(" GATT_BUSY conn_id = %d", conn_id);
+    LOG(ERROR) << " GATT_BUSY conn_id=" << loghex(conn_id);
     return GATT_BUSY;
   }
 
@@ -855,17 +855,17 @@
  *
  ******************************************************************************/
 tGATT_STATUS GATTC_SendHandleValueConfirm(uint16_t conn_id, uint16_t handle) {
-  VLOG(1) << __func__
-          << StringPrintf(" conn_id=%d handle=0x%x", conn_id, handle);
+  VLOG(1) << __func__ << " conn_id=" << loghex(conn_id)
+          << ", handle=" << loghex(handle);
 
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(GATT_GET_TCB_IDX(conn_id));
   if (!p_tcb) {
-    LOG(ERROR) << StringPrintf(" Unknown conn_id: %u", conn_id);
+    LOG(ERROR) << "Unknown conn_id=" << loghex(conn_id);
     return GATT_ILLEGAL_PARAMETER;
   }
 
   if (p_tcb->ind_count == 0) {
-    VLOG(1) << " conn_id: " << +conn_id
+    VLOG(1) << " conn_id: " << loghex(conn_id)
             << " ignored not waiting for indicaiton ack";
     return GATT_SUCCESS;
   }
@@ -904,10 +904,9 @@
  ******************************************************************************/
 void GATT_SetIdleTimeout(const RawAddress& bd_addr, uint16_t idle_tout,
                          tBT_TRANSPORT transport) {
-  tGATT_TCB* p_tcb;
   bool status = false;
 
-  p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
   if (p_tcb != NULL) {
     if (p_tcb->att_lcid == L2CAP_ATT_CID) {
       status = L2CA_SetFixedChannelTout(bd_addr, L2CAP_ATT_CID, idle_tout);
@@ -921,9 +920,8 @@
     }
   }
 
-  VLOG(1) << __func__
-          << StringPrintf(" idle_tout=%d status=%d(1-OK 0-not performed)",
-                          idle_tout, status);
+  VLOG(1) << __func__ << " idle_tout=" << idle_tout << ", status=" << +status
+          << " (1-OK 0-not performed)";
 }
 
 /*******************************************************************************
@@ -992,7 +990,7 @@
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
   /* Index 0 is GAP and is never deregistered */
   if ((gatt_if == 0) || (p_reg == NULL)) {
-    LOG(ERROR) << "invalid gatt_if: " << +gatt_if;
+    LOG(ERROR) << "invalid gatt_if=" << +gatt_if;
     return;
   }
 
@@ -1001,7 +999,8 @@
     other application
     deregisteration need to bed performed in an orderly fashion
     no check for now */
-  for (auto it = gatt_cb.srv_list_info->begin(); it != gatt_cb.srv_list_info->end(); ) {
+  for (auto it = gatt_cb.srv_list_info->begin();
+       it != gatt_cb.srv_list_info->end();) {
     if (it->gatt_if == gatt_if) {
       GATTS_StopService(it++->s_hdl);
     } else {
@@ -1017,25 +1016,24 @@
   tGATT_TCB* p_tcb;
   int i, j;
   for (i = 0, p_tcb = gatt_cb.tcb; i < GATT_MAX_PHY_CHANNEL; i++, p_tcb++) {
-    if (p_tcb->in_use) {
-      if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
-        gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
-      }
+    if (!p_tcb->in_use) continue;
 
-      tGATT_CLCB* p_clcb;
-      for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB;
-           j++, p_clcb++) {
-        if (p_clcb->in_use && (p_clcb->p_reg->gatt_if == gatt_if) &&
-            (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
-          alarm_cancel(p_clcb->gatt_rsp_timer_ent);
-          gatt_clcb_dealloc(p_clcb);
-          break;
-        }
+    if (gatt_get_ch_state(p_tcb) != GATT_CH_CLOSE) {
+      gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
+    }
+
+    tGATT_CLCB* p_clcb;
+    for (j = 0, p_clcb = &gatt_cb.clcb[j]; j < GATT_CL_MAX_LCB; j++, p_clcb++) {
+      if (p_clcb->in_use && (p_clcb->p_reg->gatt_if == gatt_if) &&
+          (p_clcb->p_tcb->tcb_idx == p_tcb->tcb_idx)) {
+        alarm_cancel(p_clcb->gatt_rsp_timer_ent);
+        gatt_clcb_dealloc(p_clcb);
+        break;
       }
     }
   }
 
-  gatt_deregister_bgdev_list(gatt_if);
+  connection_manager::on_app_deregistered(gatt_if);
 
   memset(p_reg, 0, sizeof(tGATT_REG));
 }
@@ -1061,7 +1059,7 @@
   uint16_t conn_id;
   tGATT_TRANSPORT transport;
 
-  VLOG(1) << __func__ << " gatt_if=" << gatt_if;
+  VLOG(1) << __func__ << " gatt_if=" << +gatt_if;
   p_reg = gatt_get_regcb(gatt_if);
   if (p_reg != NULL) {
     start_idx = 0;
@@ -1103,30 +1101,46 @@
 bool GATT_Connect(tGATT_IF gatt_if, const RawAddress& bd_addr, bool is_direct,
                   tBT_TRANSPORT transport, bool opportunistic,
                   uint8_t initiating_phys) {
-  tGATT_REG* p_reg;
-  bool status = false;
-
-  LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << " " << bd_addr;
+  LOG(INFO) << __func__ << "gatt_if=" << +gatt_if << ", address=" << bd_addr;
 
   /* Make sure app is registered */
-  p_reg = gatt_get_regcb(gatt_if);
-  if (p_reg == NULL) {
-    LOG(ERROR) << "gatt_if = " << gatt_if << " is not registered";
-    return (false);
+  tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
+  if (!p_reg) {
+    LOG(ERROR) << "gatt_if = " << +gatt_if << " is not registered";
+    return false;
   }
 
-  if (is_direct)
-    status = gatt_act_connect(p_reg, bd_addr, transport, opportunistic,
-                              initiating_phys);
-  else {
-    if (transport == BT_TRANSPORT_LE)
-      status = gatt_update_auto_connect_dev(gatt_if, true, bd_addr);
-    else {
-      LOG(ERROR) << "Unsupported transport for background connection";
+  if (!is_direct && transport != BT_TRANSPORT_LE) {
+    LOG(ERROR) << "Unsupported transport for background connection";
+    return false;
+  }
+
+  if (opportunistic) {
+    LOG(INFO) << __func__ << " opportunistic connection";
+    return true;
+  }
+
+  bool ret;
+  if (is_direct) {
+    ret = gatt_act_connect(p_reg, bd_addr, transport, initiating_phys);
+  } else {
+    if (!BTM_BackgroundConnectAddressKnown(bd_addr)) {
+      //  RPA can rotate, causing address to "expire" in the background
+      //  connection list. RPA is allowed for direct connect, as such request
+      //  times out after 30 seconds
+      LOG(INFO) << "Can't add RPA to background connection.";
+      ret = true;
+    } else {
+      ret = connection_manager::background_connect_add(gatt_if, bd_addr);
     }
   }
 
-  return status;
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
+  // background connections don't necessarily create tcb
+  if (p_tcb && ret)
+    gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, !is_direct);
+
+  return ret;
 }
 
 /*******************************************************************************
@@ -1146,42 +1160,39 @@
  ******************************************************************************/
 bool GATT_CancelConnect(tGATT_IF gatt_if, const RawAddress& bd_addr,
                         bool is_direct) {
-  LOG(INFO) << __func__ << ": gatt_if=" << +gatt_if;
+  LOG(INFO) << __func__ << ": gatt_if:" << +gatt_if << ", address: " << bd_addr
+            << ", direct:" << is_direct;
 
-  if (gatt_if && !gatt_get_regcb(gatt_if)) {
-    LOG(ERROR) << "gatt_if =" << +gatt_if << " is not registered";
-    return false;
-  }
-
-  if (is_direct) {
-    if (gatt_if) {
-      return gatt_cancel_open(gatt_if, bd_addr);
-    }
-
-    VLOG(1) << " unconditional";
-    /* only LE connection can be cancelled */
-    tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
-    if (!p_tcb || p_tcb->app_hold_link.empty()) {
-      LOG(ERROR) << __func__ << " no app found";
+  tGATT_REG* p_reg;
+  if (gatt_if) {
+    p_reg = gatt_get_regcb(gatt_if);
+    if (!p_reg) {
+      LOG(ERROR) << "gatt_if=" << +gatt_if << " is not registered";
       return false;
     }
 
+    if (is_direct)
+      return gatt_cancel_open(gatt_if, bd_addr);
+    else
+      return gatt_auto_connect_dev_remove(p_reg->gatt_if, bd_addr);
+  }
+
+  VLOG(1) << " unconditional";
+
+  /* only LE connection can be cancelled */
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
+  if (p_tcb && !p_tcb->app_hold_link.empty()) {
     for (auto it = p_tcb->app_hold_link.begin();
          it != p_tcb->app_hold_link.end();) {
       auto next = std::next(it);
       // gatt_cancel_open modifies the app_hold_link.
-      if (!gatt_cancel_open(*it, bd_addr)) return false;
+      gatt_cancel_open(*it, bd_addr);
 
       it = next;
     }
-
-    return true;
   }
-  // is not direct
 
-  if (gatt_if) return gatt_remove_bg_dev_for_app(gatt_if, bd_addr);
-
-  if (!gatt_clear_bg_dev_for_addr(bd_addr)) {
+  if (!connection_manager::remove_unconditional(bd_addr)) {
     LOG(ERROR)
         << __func__
         << ": no app associated with the bg device for unconditional removal";
@@ -1204,20 +1215,15 @@
  *
  ******************************************************************************/
 tGATT_STATUS GATT_Disconnect(uint16_t conn_id) {
-  tGATT_STATUS ret = GATT_ILLEGAL_PARAMETER;
-  tGATT_TCB* p_tcb = NULL;
-  tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
+  LOG(INFO) << __func__ << " conn_id=" << loghex(conn_id);
+
   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
+  tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
+  if (!p_tcb) return GATT_ILLEGAL_PARAMETER;
 
-  LOG(INFO) << __func__ << " conn_id=" << +conn_id;
-
-  p_tcb = gatt_get_tcb_by_idx(tcb_idx);
-
-  if (p_tcb) {
-    gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
-    ret = GATT_SUCCESS;
-  }
-  return ret;
+  tGATT_IF gatt_if = GATT_GET_GATT_IF(conn_id);
+  gatt_update_app_use_link_flag(gatt_if, p_tcb, false, true);
+  return GATT_SUCCESS;
 }
 
 /*******************************************************************************
@@ -1240,17 +1246,15 @@
   tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
   uint8_t tcb_idx = GATT_GET_TCB_IDX(conn_id);
   tGATT_TCB* p_tcb = gatt_get_tcb_by_idx(tcb_idx);
-  bool status = false;
 
-  VLOG(1) << __func__ << " conn_id=" << +conn_id;
+  VLOG(1) << __func__ << " conn_id=" << loghex(conn_id);
 
-  if (p_tcb && p_reg) {
-    bd_addr = p_tcb->peer_bda;
-    *p_gatt_if = gatt_if;
-    *p_transport = p_tcb->transport;
-    status = true;
-  }
-  return status;
+  if (!p_tcb || !p_reg) return false;
+
+  bd_addr = p_tcb->peer_bda;
+  *p_gatt_if = gatt_if;
+  *p_transport = p_tcb->transport;
+  return true;
 }
 
 /*******************************************************************************
diff --git a/stack/gatt/gatt_attr.cc b/stack/gatt/gatt_attr.cc
index 75a8057..8861a7a 100644
--- a/stack/gatt/gatt_attr.cc
+++ b/stack/gatt/gatt_attr.cc
@@ -385,41 +385,35 @@
  *
  ******************************************************************************/
 static void gatt_cl_start_config_ccc(tGATT_PROFILE_CLCB* p_clcb) {
-  tGATT_DISC_PARAM srvc_disc_param;
-  tGATT_VALUE ccc_value;
 
   VLOG(1) << __func__ << ": stage: " << +p_clcb->ccc_stage;
 
-  memset(&srvc_disc_param, 0, sizeof(tGATT_DISC_PARAM));
-  memset(&ccc_value, 0, sizeof(tGATT_VALUE));
-
   switch (p_clcb->ccc_stage) {
     case GATT_SVC_CHANGED_SERVICE: /* discover GATT service */
-      srvc_disc_param.s_handle = 1;
-      srvc_disc_param.e_handle = 0xffff;
-      srvc_disc_param.service = Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER);
-      GATTC_Discover(p_clcb->conn_id, GATT_DISC_SRVC_BY_UUID, &srvc_disc_param);
+      GATTC_Discover(p_clcb->conn_id, GATT_DISC_SRVC_BY_UUID, 0x0001, 0xffff,
+                     Uuid::From16Bit(UUID_SERVCLASS_GATT_SERVER));
       break;
 
     case GATT_SVC_CHANGED_CHARACTERISTIC: /* discover service change char */
-      srvc_disc_param.s_handle = 1;
-      srvc_disc_param.e_handle = p_clcb->e_handle;
-      srvc_disc_param.service = Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD);
-      GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, &srvc_disc_param);
+      GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR, 0x0001, p_clcb->e_handle,
+                     Uuid::From16Bit(GATT_UUID_GATT_SRV_CHGD));
       break;
 
     case GATT_SVC_CHANGED_DESCRIPTOR: /* discover service change ccc */
-      srvc_disc_param.s_handle = p_clcb->s_handle;
-      srvc_disc_param.e_handle = p_clcb->e_handle;
-      GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR_DSCPT, &srvc_disc_param);
+      GATTC_Discover(p_clcb->conn_id, GATT_DISC_CHAR_DSCPT, p_clcb->s_handle,
+                     p_clcb->e_handle);
       break;
 
     case GATT_SVC_CHANGED_CONFIGURE_CCCD: /* write ccc */
+    {
+      tGATT_VALUE ccc_value;
+      memset(&ccc_value, 0, sizeof(tGATT_VALUE));
       ccc_value.handle = p_clcb->s_handle;
       ccc_value.len = 2;
       ccc_value.value[0] = GATT_CLT_CONFIG_INDICATION;
       GATTC_Write(p_clcb->conn_id, GATT_WRITE, &ccc_value);
       break;
+    }
   }
 }
 
diff --git a/stack/gatt/gatt_auth.cc b/stack/gatt/gatt_auth.cc
index 3794388..ba44c71 100644
--- a/stack/gatt/gatt_auth.cc
+++ b/stack/gatt/gatt_auth.cc
@@ -188,11 +188,13 @@
   gatt_sec_check_complete(status, p_clcb, p_tcb->sec_act);
 
   /* start all other pending operation in queue */
+  std::queue<tGATT_CLCB*> new_pending_clcbs;
   while (!p_tcb->pending_enc_clcb.empty()) {
     tGATT_CLCB* p_clcb = p_tcb->pending_enc_clcb.front();
     p_tcb->pending_enc_clcb.pop();
-    gatt_security_check_start(p_clcb);
+    if (gatt_security_check_start(p_clcb)) new_pending_clcbs.push(p_clcb);
   }
+  p_tcb->pending_enc_clcb = new_pending_clcbs;
 }
 
 /*******************************************************************************
@@ -223,11 +225,13 @@
   if (gatt_get_sec_act(p_tcb) == GATT_SEC_ENC_PENDING) {
     gatt_set_sec_act(p_tcb, GATT_SEC_NONE);
 
+    std::queue<tGATT_CLCB*> new_pending_clcbs;
     while (!p_tcb->pending_enc_clcb.empty()) {
       tGATT_CLCB* p_clcb = p_tcb->pending_enc_clcb.front();
       p_tcb->pending_enc_clcb.pop();
-      gatt_security_check_start(p_clcb);
+      if (gatt_security_check_start(p_clcb)) new_pending_clcbs.push(p_clcb);
     }
+    p_tcb->pending_enc_clcb = new_pending_clcbs;
   }
 }
 /*******************************************************************************
@@ -397,8 +401,8 @@
   return status;
 }
 
-/** check link security */
-void gatt_security_check_start(tGATT_CLCB* p_clcb) {
+/** check link security, return true if p_clcb should be added back to queue */
+bool gatt_security_check_start(tGATT_CLCB* p_clcb) {
   tGATT_TCB* p_tcb = p_clcb->p_tcb;
   tGATT_SEC_ACTION sec_act_old = gatt_get_sec_act(p_tcb);
 
@@ -430,17 +434,17 @@
           gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
 
           gatt_end_operation(p_clcb, GATT_INSUF_ENCRYPTION, NULL);
-          return;
+          return false;
         }
       }
-      p_tcb->pending_enc_clcb.push(p_clcb);
-      break;
+      return true;
     case GATT_SEC_ENC_PENDING:
-      p_tcb->pending_enc_clcb.push(p_clcb);
       /* wait for link encrypotion to finish */
-      break;
+      return true;
     default:
       gatt_sec_check_complete(true, p_clcb, gatt_sec_act);
       break;
   }
+
+  return false;
 }
diff --git a/stack/gatt/gatt_cl.cc b/stack/gatt/gatt_cl.cc
index dca4973..27a4f4f 100644
--- a/stack/gatt/gatt_cl.cc
+++ b/stack/gatt/gatt_cl.cc
@@ -297,7 +297,7 @@
 bool gatt_check_write_long_terminate(tGATT_TCB& tcb, tGATT_CLCB* p_clcb,
                                      tGATT_VALUE* p_rsp_value) {
   tGATT_VALUE* p_attr = (tGATT_VALUE*)p_clcb->p_attr_buf;
-  bool exec = false;
+  bool terminate = false;
   tGATT_EXEC_FLAG flag = GATT_PREP_WRITE_EXEC;
 
   VLOG(1) << __func__;
@@ -310,19 +310,18 @@
       /* data does not match    */
       p_clcb->status = GATT_ERROR;
       flag = GATT_PREP_WRITE_CANCEL;
-      exec = true;
+      terminate = true;
     } else /* response checking is good */
     {
       p_clcb->status = GATT_SUCCESS;
       /* update write offset and check if end of attribute value */
-      if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) exec = true;
+      if ((p_attr->offset += p_rsp_value->len) >= p_attr->len) terminate = true;
     }
   }
-  if (exec) {
+  if (terminate && p_clcb->op_subtype != GATT_WRITE_PREPARE) {
     gatt_send_queue_write_cancel(tcb, p_clcb, flag);
-    return true;
   }
-  return false;
+  return terminate;
 }
 
 /** Send prepare write */
@@ -586,15 +585,15 @@
 
   memcpy(value.value, p, value.len);
 
+  if (!gatt_check_write_long_terminate(tcb, p_clcb, &value)) {
+    gatt_send_prepare_write(tcb, p_clcb);
+    return;
+  }
+
   if (p_clcb->op_subtype == GATT_WRITE_PREPARE) {
-    p_clcb->status = GATT_SUCCESS;
     /* application should verify handle offset
        and value are matched or not */
-
     gatt_end_operation(p_clcb, p_clcb->status, &value);
-  } else if (p_clcb->op_subtype == GATT_WRITE) {
-    if (!gatt_check_write_long_terminate(tcb, p_clcb, &value))
-      gatt_send_prepare_write(tcb, p_clcb);
   }
 }
 /*******************************************************************************
@@ -628,6 +627,10 @@
   memset(&value, 0, sizeof(value));
   STREAM_TO_UINT16(value.handle, p);
   value.len = len - 2;
+  if (value.len > GATT_MAX_ATTR_LEN) {
+    LOG(ERROR) << "value.len larger than GATT_MAX_ATTR_LEN, discard";
+    return;
+  }
   memcpy(value.value, p, value.len);
 
   if (!GATT_HANDLE_IS_VALID(value.handle)) {
diff --git a/stack/gatt/gatt_db.cc b/stack/gatt/gatt_db.cc
index 31a262d..2d0c5b0 100644
--- a/stack/gatt/gatt_db.cc
+++ b/stack/gatt/gatt_db.cc
@@ -601,10 +601,10 @@
           break;
 
         case GATT_UUID_CHAR_CLIENT_CONFIG:
-        /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case GATT_UUID_CHAR_SRVR_CONFIG:
           max_size = 2;
-        /* fall through */
+          FALLTHROUGH_INTENDED; /* FALLTHROUGH */
         case GATT_UUID_CHAR_DESCRIPTION:
         default: /* any other must be character value declaration */
           status = GATT_SUCCESS;
diff --git a/stack/gatt/gatt_int.h b/stack/gatt/gatt_int.h
index 5052918..2c00fd7 100644
--- a/stack/gatt/gatt_int.h
+++ b/stack/gatt/gatt_int.h
@@ -331,11 +331,6 @@
   uint32_t service_change;
 } tGATT_SVC_CHG;
 
-typedef struct {
-  std::unordered_set<tGATT_IF> gatt_if;
-  RawAddress remote_bda;
-} tGATT_BG_CONN_DEV;
-
 #define GATT_SVC_CHANGED_CONNECTING 1     /* wait for connection */
 #define GATT_SVC_CHANGED_SERVICE 2        /* GATT service discovery */
 #define GATT_SVC_CHANGED_CHARACTERISTIC 3 /* service change char discovery */
@@ -386,7 +381,6 @@
   tGATT_APPL_INFO cb_info;
 
   tGATT_HDL_CFG hdl_cfg;
-  std::list<tGATT_BG_CONN_DEV> bgconn_dev;
 } tGATT_CB;
 
 #define GATT_SIZE_OF_SRV_CHG_HNDL_RANGE 4
@@ -402,10 +396,10 @@
 /* from gatt_main.cc */
 extern bool gatt_disconnect(tGATT_TCB* p_tcb);
 extern bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr,
-                             tBT_TRANSPORT transport, bool opportunistic,
-                             int8_t initiating_phys);
+                             tBT_TRANSPORT transport, int8_t initiating_phys);
 extern bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb,
-                         tBT_TRANSPORT transport, uint8_t initiating_phys);
+                         tBT_TRANSPORT transport, uint8_t initiating_phys,
+                         tGATT_IF gatt_if);
 extern void gatt_data_process(tGATT_TCB& p_tcb, BT_HDR* p_buf);
 extern void gatt_update_app_use_link_flag(tGATT_IF gatt_if, tGATT_TCB* p_tcb,
                                           bool is_add, bool check_acl_link);
@@ -461,7 +455,7 @@
                                         tBT_TRANSPORT* p_transport);
 extern void gatt_set_srv_chg(void);
 extern void gatt_delete_dev_from_srv_chg_clt_list(const RawAddress& bd_addr);
-extern tGATT_VALUE* gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind);
+extern void gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind);
 extern void gatt_free_srvc_db_buffer_app_id(const bluetooth::Uuid& app_id);
 extern bool gatt_cl_send_next_cmd_inq(tGATT_TCB& tcb);
 
@@ -473,14 +467,8 @@
 extern tGATTS_SRV_CHG* gatt_add_srv_chg_clt(tGATTS_SRV_CHG* p_srv_chg);
 
 /* for background connection */
-extern bool gatt_update_auto_connect_dev(tGATT_IF gatt_if, bool add,
+extern bool gatt_auto_connect_dev_remove(tGATT_IF gatt_if,
                                          const RawAddress& bd_addr);
-extern bool gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV* p_dev, tGATT_IF gatt_if);
-extern bool gatt_remove_bg_dev_for_app(tGATT_IF gatt_if,
-                                       const RawAddress& bd_addr);
-extern uint8_t gatt_clear_bg_dev_for_addr(const RawAddress& bd_addr);
-extern tGATT_BG_CONN_DEV* gatt_find_bg_dev(const RawAddress& remote_bda);
-extern void gatt_deregister_bgdev_list(tGATT_IF gatt_if);
 
 /* server function */
 extern std::list<tGATT_SRV_LIST_ELEM>::iterator gatt_sr_find_i_rcb_by_handle(
@@ -548,7 +536,7 @@
                                          tGATT_EXEC_FLAG flag);
 
 /* gatt_auth.cc */
-extern void gatt_security_check_start(tGATT_CLCB* p_clcb);
+extern bool gatt_security_check_start(tGATT_CLCB* p_clcb);
 extern void gatt_verify_signature(tGATT_TCB& tcb, BT_HDR* p_buf);
 extern tGATT_STATUS gatt_get_link_encrypt_status(tGATT_TCB& tcb);
 extern tGATT_SEC_ACTION gatt_get_sec_act(tGATT_TCB* p_tcb);
diff --git a/stack/gatt/gatt_main.cc b/stack/gatt/gatt_main.cc
index afae25f..87f9c87 100644
--- a/stack/gatt/gatt_main.cc
+++ b/stack/gatt/gatt_main.cc
@@ -29,6 +29,7 @@
 #include "btif_storage.h"
 #include "btm_ble_int.h"
 #include "btm_int.h"
+#include "connection_manager.h"
 #include "device/include/interop.h"
 #include "gatt_int.h"
 #include "l2c_api.h"
@@ -101,6 +102,7 @@
   VLOG(1) << __func__;
 
   gatt_cb = tGATT_CB();
+  connection_manager::reset(true);
   memset(&fixed_reg, 0, sizeof(tL2CAP_FIXED_CHNL_REG));
 
   gatt_cb.def_mtu_size = GATT_DEF_BLE_MTU_SIZE;
@@ -122,7 +124,8 @@
   L2CA_RegisterFixedChannel(L2CAP_ATT_CID, &fixed_reg);
 
   /* Now, register with L2CAP for ATT PSM over BR/EDR */
-  if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info)) {
+  if (!L2CA_Register(BT_PSM_ATT, (tL2CAP_APPL_INFO*)&dyn_info,
+                     false /* enable_snoop */)) {
     LOG(ERROR) << "ATT Dynamic Registration failed";
   }
 
@@ -192,21 +195,24 @@
  *
  ******************************************************************************/
 bool gatt_connect(const RawAddress& rem_bda, tGATT_TCB* p_tcb,
-                  tBT_TRANSPORT transport, uint8_t initiating_phys) {
-  bool gatt_ret = false;
-
+                  tBT_TRANSPORT transport, uint8_t initiating_phys,
+                  tGATT_IF gatt_if) {
   if (gatt_get_ch_state(p_tcb) != GATT_CH_OPEN)
     gatt_set_ch_state(p_tcb, GATT_CH_CONN);
 
-  if (transport == BT_TRANSPORT_LE) {
-    p_tcb->att_lcid = L2CAP_ATT_CID;
-    gatt_ret = L2CA_ConnectFixedChnl(L2CAP_ATT_CID, rem_bda, initiating_phys);
-  } else {
+  if (transport != BT_TRANSPORT_LE) {
     p_tcb->att_lcid = L2CA_ConnectReq(BT_PSM_ATT, rem_bda);
-    if (p_tcb->att_lcid != 0) gatt_ret = true;
+    return p_tcb->att_lcid != 0;
   }
 
-  return gatt_ret;
+  // Already connected, mark the link as used
+  if (gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
+    gatt_update_app_use_link_flag(gatt_if, p_tcb, true, true);
+    return true;
+  }
+
+  p_tcb->att_lcid = L2CAP_ATT_CID;
+  return connection_manager::direct_connect_add(gatt_if, rem_bda);
 }
 
 /*******************************************************************************
@@ -222,33 +228,32 @@
  *
  ******************************************************************************/
 bool gatt_disconnect(tGATT_TCB* p_tcb) {
-  bool ret = false;
-  tGATT_CH_STATE ch_state;
-
   VLOG(1) << __func__;
 
-  if (p_tcb != NULL) {
-    ret = true;
-    ch_state = gatt_get_ch_state(p_tcb);
-    if (ch_state != GATT_CH_CLOSING) {
-      if (p_tcb->att_lcid == L2CAP_ATT_CID) {
-        if (ch_state == GATT_CH_OPEN) {
-          /* only LCB exist between remote device and local */
-          ret = L2CA_RemoveFixedChnl(L2CAP_ATT_CID, p_tcb->peer_bda);
-        } else {
-          ret = L2CA_CancelBleConnectReq(p_tcb->peer_bda);
-          if (!ret) gatt_set_ch_state(p_tcb, GATT_CH_CLOSE);
-        }
-        gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
-      } else {
-        if ((ch_state == GATT_CH_OPEN) || (ch_state == GATT_CH_CFG))
-          ret = L2CA_DisconnectReq(p_tcb->att_lcid);
-        else
-          VLOG(1) << __func__ << " gatt_disconnect channel not opened";
-      }
+  if (!p_tcb) return false;
+
+  tGATT_CH_STATE ch_state = gatt_get_ch_state(p_tcb);
+  if (ch_state == GATT_CH_CLOSING) {
+    VLOG(1) << __func__ << " already in closing state";
+    return true;
+  }
+
+  bool ret = true;
+  if (p_tcb->att_lcid == L2CAP_ATT_CID) {
+    if (ch_state == GATT_CH_OPEN) {
+      /* only LCB exist between remote device and local */
+      ret = L2CA_RemoveFixedChnl(L2CAP_ATT_CID, p_tcb->peer_bda);
     } else {
-      VLOG(1) << __func__ << " already in closing state";
+      L2CA_CancelBleConnectReq(p_tcb->peer_bda);
+      gatt_cleanup_upon_disc(p_tcb->peer_bda, HCI_ERR_CONN_CAUSE_LOCAL_HOST, p_tcb->transport);
+      return true;
     }
+    gatt_set_ch_state(p_tcb, GATT_CH_CLOSING);
+  } else {
+    if ((ch_state == GATT_CH_OPEN) || (ch_state == GATT_CH_CFG))
+      ret = L2CA_DisconnectReq(p_tcb->att_lcid);
+    else
+      VLOG(1) << __func__ << " gatt_disconnect channel not opened";
   }
 
   return ret;
@@ -311,97 +316,85 @@
   // device, skip updating the device state.
   if (!gatt_update_app_hold_link_status(gatt_if, p_tcb, is_add)) return;
 
-  if (!check_acl_link ||
-      p_tcb->att_lcid !=
-          L2CAP_ATT_CID || /* only update link idle timer for fixed channel */
-      (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) ==
-       GATT_INVALID_ACL_HANDLE)) {
+  if (!check_acl_link) {
     return;
   }
 
+  bool is_valid_handle =
+      (BTM_GetHCIConnHandle(p_tcb->peer_bda, p_tcb->transport) !=
+       GATT_INVALID_ACL_HANDLE);
+
   if (is_add) {
-    VLOG(1) << "disable link idle timer";
-    /* acl link is connected disable the idle timeout */
-    GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT,
-                        p_tcb->transport);
-  } else {
-    if (p_tcb->app_hold_link.empty()) {
-      /* acl link is connected but no application needs to use the link
-         so set the timeout value to GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds
-         */
-      VLOG(1) << " start link idle timer = "
-              << GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP << " sec";
-      GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
+    if (p_tcb->att_lcid == L2CAP_ATT_CID && is_valid_handle) {
+      VLOG(1) << "disable link idle timer";
+      /* acl link is connected disable the idle timeout */
+      GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_NO_IDLE_TIMEOUT,
                           p_tcb->transport);
     }
+  } else {
+    if (p_tcb->app_hold_link.empty()) {
+      // acl link is connected but no application needs to use the link
+      if (p_tcb->att_lcid == L2CAP_ATT_CID && is_valid_handle) {
+        /* for fixed channel, set the timeout value to
+           GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP seconds */
+        VLOG(1) << " start link idle timer = "
+                << GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP << " sec";
+        GATT_SetIdleTimeout(p_tcb->peer_bda, GATT_LINK_IDLE_TIMEOUT_WHEN_NO_APP,
+                            p_tcb->transport);
+      } else
+        // disconnect the dynamic channel
+        gatt_disconnect(p_tcb);
+    }
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_act_connect
- *
- * Description      GATT connection initiation.
- *
- * Returns          void.
- *
- ******************************************************************************/
+/** GATT connection initiation */
 bool gatt_act_connect(tGATT_REG* p_reg, const RawAddress& bd_addr,
-                      tBT_TRANSPORT transport, bool opportunistic,
-                      int8_t initiating_phys) {
-  bool ret = false;
-  tGATT_TCB* p_tcb;
-  uint8_t st;
-
-  p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
+                      tBT_TRANSPORT transport, int8_t initiating_phys) {
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, transport);
   if (p_tcb != NULL) {
-    ret = true;
-    st = gatt_get_ch_state(p_tcb);
-
     /* before link down, another app try to open a GATT connection */
+    uint8_t st = gatt_get_ch_state(p_tcb);
     if (st == GATT_CH_OPEN && p_tcb->app_hold_link.empty() &&
         transport == BT_TRANSPORT_LE) {
-      if (!gatt_connect(bd_addr, p_tcb, transport, initiating_phys))
-        ret = false;
+      if (!gatt_connect(bd_addr, p_tcb, transport, initiating_phys,
+                        p_reg->gatt_if))
+        return false;
     } else if (st == GATT_CH_CLOSING) {
+      LOG(INFO) << "Must finish disconnection before new connection";
       /* need to complete the closing first */
-      ret = false;
+      return false;
     }
-  } else {
-    p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport);
-    if (p_tcb != NULL) {
-      if (!gatt_connect(bd_addr, p_tcb, transport, initiating_phys)) {
-        LOG(ERROR) << "gatt_connect failed";
-        fixed_queue_free(p_tcb->pending_ind_q, NULL);
-        *p_tcb = tGATT_TCB();
-      } else
-        ret = true;
-    } else {
-      ret = 0;
-      LOG(ERROR) << "Max TCB for gatt_if [ " << +p_reg->gatt_if << "] reached.";
-    }
+
+    return true;
   }
 
-  if (ret) {
-    if (!opportunistic)
-      gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, false);
-    else
-      VLOG(1) << __func__
-              << ": connection is opportunistic, not updating app usage";
+  p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, transport);
+  if (!p_tcb) {
+    LOG(ERROR) << "Max TCB for gatt_if [ " << +p_reg->gatt_if << "] reached.";
+    return false;
   }
 
-  return ret;
+  if (!gatt_connect(bd_addr, p_tcb, transport, initiating_phys,
+                    p_reg->gatt_if)) {
+    LOG(ERROR) << "gatt_connect failed";
+    fixed_queue_free(p_tcb->pending_ind_q, NULL);
+    *p_tcb = tGATT_TCB();
+    return false;
+  }
+
+  return true;
 }
 
-/*******************************************************************************
- *
- * Function         gatt_le_connect_cback
- *
- * Description      This callback function is called by L2CAP to indicate that
- *                  the ATT fixed channel for LE is
- *                      connected (conn = true)/disconnected (conn = false).
- *
- ******************************************************************************/
+namespace connection_manager {
+void on_connection_timed_out(uint8_t app_id, const RawAddress& address) {
+  gatt_le_connect_cback(L2CAP_ATT_CID, address, false, 0xff, BT_TRANSPORT_LE);
+}
+}  // namespace connection_manager
+
+/** This callback function is called by L2CAP to indicate that the ATT fixed
+ * channel for LE is connected (conn = true)/disconnected (conn = false).
+ */
 static void gatt_le_connect_cback(uint16_t chan, const RawAddress& bd_addr,
                                   bool connected, uint16_t reason,
                                   tBT_TRANSPORT transport) {
@@ -423,54 +416,47 @@
       gatt_add_a_bonded_dev_for_srv_chg(bd_addr);
   }
 
-  if (connected) {
-    /* do we have a channel initiating a connection? */
-    if (p_tcb) {
-      /* we are initiating connection */
-      if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) {
-        /* send callback */
-        gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
-        p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
-
-        gatt_send_conn_cback(p_tcb);
-      }
-      if (check_srv_chg) gatt_chk_srv_chg(p_srv_chg_clt);
-    }
-    /* this is incoming connection or background connection callback */
-
-    else {
-      p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_LE);
-      if (p_tcb != NULL) {
-        p_tcb->att_lcid = L2CAP_ATT_CID;
-
-        gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
-
-        p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
-
-        gatt_send_conn_cback(p_tcb);
-        if (check_srv_chg) {
-          gatt_chk_srv_chg(p_srv_chg_clt);
-        }
-      } else {
-        LOG(ERROR) << "CCB max out, no rsources";
-      }
-    }
-  } else {
+  if (!connected) {
     gatt_cleanup_upon_disc(bd_addr, reason, transport);
     VLOG(1) << "ATT disconnected";
+    return;
+  }
+
+  /* do we have a channel initiating a connection? */
+  if (p_tcb) {
+    /* we are initiating connection */
+    if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) {
+      /* send callback */
+      gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+      p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
+
+      gatt_send_conn_cback(p_tcb);
+    }
+    if (check_srv_chg) gatt_chk_srv_chg(p_srv_chg_clt);
+  }
+  /* this is incoming connection or background connection callback */
+
+  else {
+    p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_LE);
+    if (!p_tcb) {
+      LOG(ERROR) << "CCB max out, no rsources";
+      return;
+    }
+
+    p_tcb->att_lcid = L2CAP_ATT_CID;
+
+    gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+
+    p_tcb->payload_size = GATT_DEF_BLE_MTU_SIZE;
+
+    gatt_send_conn_cback(p_tcb);
+    if (check_srv_chg) {
+      gatt_chk_srv_chg(p_srv_chg_clt);
+    }
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_channel_congestion
- *
- * Description      This function is called to process the congestion callback
- *                  from lcb
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is called to process the congestion callback from lcb */
 static void gatt_channel_congestion(tGATT_TCB* p_tcb, bool congested) {
   uint8_t i = 0;
   tGATT_REG* p_reg = NULL;
@@ -501,7 +487,7 @@
 
   tGATT_TCB* p_tcb =
       gatt_find_tcb_by_addr(p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
-  if (p_tcb == NULL) return;
+  if (!p_tcb) return;
 
   for (int i = 0; i < GATT_MAX_APPS; i++) {
     tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
@@ -517,13 +503,11 @@
                              uint16_t latency, uint16_t timeout,
                              uint8_t status) {
   tBTM_SEC_DEV_REC* p_dev_rec = btm_find_dev_by_handle(handle);
-  if (!p_dev_rec) {
-    return;
-  }
+  if (!p_dev_rec) return;
 
   tGATT_TCB* p_tcb =
       gatt_find_tcb_by_addr(p_dev_rec->ble.pseudo_addr, BT_TRANSPORT_LE);
-  if (p_tcb == NULL) return;
+  if (!p_tcb) return;
 
   for (int i = 0; i < GATT_MAX_APPS; i++) {
     tGATT_REG* p_reg = &gatt_cb.cl_rcb[i];
@@ -535,23 +519,14 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_le_cong_cback
- *
- * Description      This function is called when GATT fixed channel is congested
- *                  or uncongested.
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is called when GATT fixed channel is congested or uncongested
+ */
 static void gatt_le_cong_cback(const RawAddress& remote_bda, bool congested) {
   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(remote_bda, BT_TRANSPORT_LE);
+  if (!p_tcb) return;
 
   /* if uncongested, check to see if there is any more pending data */
-  if (p_tcb != NULL) {
     gatt_channel_congestion(p_tcb, congested);
-  }
 }
 
 /*******************************************************************************
@@ -572,10 +547,10 @@
  ******************************************************************************/
 static void gatt_le_data_ind(uint16_t chan, const RawAddress& bd_addr,
                              BT_HDR* p_buf) {
-  tGATT_TCB* p_tcb;
 
   /* Find CCB based on bd addr */
-  if ((p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE)) != NULL) {
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
+  if (p_tcb) {
     if (gatt_get_ch_state(p_tcb) < GATT_CH_OPEN) {
       LOG(WARNING) << "ATT - Ignored L2CAP data while in state: "
                    << +gatt_get_ch_state(p_tcb);
@@ -600,13 +575,11 @@
 static void gatt_l2cif_connect_ind_cback(const RawAddress& bd_addr,
                                          uint16_t lcid,
                                          UNUSED_ATTR uint16_t psm, uint8_t id) {
-  /* do we already have a control channel for this peer? */
   uint8_t result = L2CAP_CONN_OK;
-  tL2CAP_CFG_INFO cfg;
-  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_BR_EDR);
+  LOG(INFO) << "Connection indication cid = " << +lcid;
 
-  LOG(ERROR) << "Connection indication cid = " << +lcid;
   /* new connection ? */
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_BR_EDR);
   if (p_tcb == NULL) {
     /* allocate tcb */
     p_tcb = gatt_allocate_tcb_by_bdaddr(bd_addr, BT_TRANSPORT_BR_EDR);
@@ -625,253 +598,192 @@
   L2CA_ConnectRsp(bd_addr, id, lcid, result, 0);
 
   /* if result ok, proceed with connection */
-  if (result == L2CAP_CONN_OK) {
-    /* transition to configuration state */
-    gatt_set_ch_state(p_tcb, GATT_CH_CFG);
+  if (result != L2CAP_CONN_OK) return;
 
-    /* Send L2CAP config req */
-    memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-    cfg.mtu_present = true;
-    cfg.mtu = GATT_MAX_MTU_SIZE;
+  /* transition to configuration state */
+  gatt_set_ch_state(p_tcb, GATT_CH_CFG);
 
-    L2CA_ConfigReq(lcid, &cfg);
-  }
+  /* Send L2CAP config req */
+  tL2CAP_CFG_INFO cfg;
+  memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+  cfg.mtu_present = true;
+  cfg.mtu = GATT_MAX_MTU_SIZE;
+
+  L2CA_ConfigReq(lcid, &cfg);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2c_connect_cfm_cback
- *
- * Description      This is the L2CAP connect confirm callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This is the L2CAP connect confirm callback function */
 static void gatt_l2cif_connect_cfm_cback(uint16_t lcid, uint16_t result) {
   tGATT_TCB* p_tcb;
   tL2CAP_CFG_INFO cfg;
 
   /* look up clcb for this channel */
   p_tcb = gatt_find_tcb_by_cid(lcid);
-  if (p_tcb != NULL) {
-    VLOG(1) << __func__
-            << StringPrintf(" result: %d ch_state: %d, lcid:0x%x", result,
-                            gatt_get_ch_state(p_tcb), p_tcb->att_lcid);
+  if (!p_tcb) return;
 
-    /* if in correct state */
-    if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) {
-      /* if result successful */
-      if (result == L2CAP_CONN_OK) {
-        /* set channel state */
-        gatt_set_ch_state(p_tcb, GATT_CH_CFG);
+  VLOG(1) << __func__
+          << StringPrintf(" result: %d ch_state: %d, lcid:0x%x", result,
+                          gatt_get_ch_state(p_tcb), p_tcb->att_lcid);
 
-        /* Send L2CAP config req */
-        memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-        cfg.mtu_present = true;
-        cfg.mtu = GATT_MAX_MTU_SIZE;
-        L2CA_ConfigReq(lcid, &cfg);
-      }
-      /* else initiating connection failure */
-      else {
-        gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR);
-      }
-    } else /* wrong state, disconnect it */
-    {
-      if (result == L2CAP_CONN_OK) {
-        /* just in case the peer also accepts our connection - Send L2CAP
-         * disconnect req */
-        L2CA_DisconnectReq(lcid);
-      }
+  /* if in correct state */
+  if (gatt_get_ch_state(p_tcb) == GATT_CH_CONN) {
+    /* if result successful */
+    if (result == L2CAP_CONN_OK) {
+      /* set channel state */
+      gatt_set_ch_state(p_tcb, GATT_CH_CFG);
+
+      /* Send L2CAP config req */
+      memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
+      cfg.mtu_present = true;
+      cfg.mtu = GATT_MAX_MTU_SIZE;
+      L2CA_ConfigReq(lcid, &cfg);
+    }
+    /* else initiating connection failure */
+    else {
+      gatt_cleanup_upon_disc(p_tcb->peer_bda, result, GATT_TRANSPORT_BR_EDR);
+    }
+  } else /* wrong state, disconnect it */
+  {
+    if (result == L2CAP_CONN_OK) {
+      /* just in case the peer also accepts our connection - Send L2CAP
+       * disconnect req */
+      L2CA_DisconnectReq(lcid);
     }
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2cif_config_cfm_cback
- *
- * Description      This is the L2CAP config confirm callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This is the L2CAP config confirm callback function */
 void gatt_l2cif_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
-  tGATT_TCB* p_tcb;
-  tGATTS_SRV_CHG* p_srv_chg_clt = NULL;
 
   /* look up clcb for this channel */
-  p_tcb = gatt_find_tcb_by_cid(lcid);
-  if (p_tcb != NULL) {
-    /* if in correct state */
-    if (gatt_get_ch_state(p_tcb) == GATT_CH_CFG) {
-      /* if result successful */
-      if (p_cfg->result == L2CAP_CFG_OK) {
-        /* update flags */
-        p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE;
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
+  if (!p_tcb) return;
 
-        /* if configuration complete */
-        if (p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) {
-          gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+  /* if in incorrect state */
+  if (gatt_get_ch_state(p_tcb) != GATT_CH_CFG) return;
 
-          p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda);
-          if (p_srv_chg_clt != NULL) {
-            gatt_chk_srv_chg(p_srv_chg_clt);
-          } else {
-            if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
-              gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
-          }
-
-          /* send callback */
-          gatt_send_conn_cback(p_tcb);
-        }
-      }
-      /* else failure */
-      else {
-        /* Send L2CAP disconnect req */
-        L2CA_DisconnectReq(lcid);
-      }
-    }
+  /* if result not successful */
+  if (p_cfg->result != L2CAP_CFG_OK) {
+    /* Send L2CAP disconnect req */
+    L2CA_DisconnectReq(lcid);
+    return;
   }
+
+  /* update flags */
+  p_tcb->ch_flags |= GATT_L2C_CFG_CFM_DONE;
+
+  /* if configuration not complete */
+  if (!(p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE)) return;
+
+  gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+
+  tGATTS_SRV_CHG* p_srv_chg_clt =
+      gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda);
+  if (p_srv_chg_clt != NULL) {
+    gatt_chk_srv_chg(p_srv_chg_clt);
+  } else {
+    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+      gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+  }
+
+  /* send callback */
+  gatt_send_conn_cback(p_tcb);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2cif_config_ind_cback
- *
- * Description      This is the L2CAP config indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This is the L2CAP config indication callback function */
 void gatt_l2cif_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
-  tGATT_TCB* p_tcb;
   tGATTS_SRV_CHG* p_srv_chg_clt = NULL;
   /* look up clcb for this channel */
-  p_tcb = gatt_find_tcb_by_cid(lcid);
-  if (p_tcb != NULL) {
-    /* GATT uses the smaller of our MTU and peer's MTU  */
-    if (p_cfg->mtu_present &&
-        (p_cfg->mtu >= GATT_MIN_BR_MTU_SIZE && p_cfg->mtu < L2CAP_DEFAULT_MTU))
-      p_tcb->payload_size = p_cfg->mtu;
-    else
-      p_tcb->payload_size = L2CAP_DEFAULT_MTU;
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
+  if (!p_tcb) return;
 
-    /* send L2CAP configure response */
-    memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
-    p_cfg->result = L2CAP_CFG_OK;
-    L2CA_ConfigRsp(lcid, p_cfg);
+  /* GATT uses the smaller of our MTU and peer's MTU  */
+  if (p_cfg->mtu_present &&
+      (p_cfg->mtu >= GATT_MIN_BR_MTU_SIZE && p_cfg->mtu < L2CAP_DEFAULT_MTU))
+    p_tcb->payload_size = p_cfg->mtu;
+  else
+    p_tcb->payload_size = L2CAP_DEFAULT_MTU;
 
-    /* if first config ind */
-    if ((p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE) == 0) {
-      /* update flags */
-      p_tcb->ch_flags |= GATT_L2C_CFG_IND_DONE;
+  /* send L2CAP configure response */
+  memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
+  p_cfg->result = L2CAP_CFG_OK;
+  L2CA_ConfigRsp(lcid, p_cfg);
 
-      /* if configuration complete */
-      if (p_tcb->ch_flags & GATT_L2C_CFG_CFM_DONE) {
-        gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
-        p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda);
-        if (p_srv_chg_clt != NULL) {
-          gatt_chk_srv_chg(p_srv_chg_clt);
-        } else {
-          if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
-            gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
-        }
+  /* if not first config ind */
+  if ((p_tcb->ch_flags & GATT_L2C_CFG_IND_DONE)) return;
 
-        /* send callback */
-        gatt_send_conn_cback(p_tcb);
-      }
-    }
+  /* update flags */
+  p_tcb->ch_flags |= GATT_L2C_CFG_IND_DONE;
+
+  /* if configuration not complete */
+  if ((p_tcb->ch_flags & GATT_L2C_CFG_CFM_DONE) == 0) return;
+
+  gatt_set_ch_state(p_tcb, GATT_CH_OPEN);
+  p_srv_chg_clt = gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda);
+  if (p_srv_chg_clt != NULL) {
+    gatt_chk_srv_chg(p_srv_chg_clt);
+  } else {
+    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+      gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
   }
+
+  /* send callback */
+  gatt_send_conn_cback(p_tcb);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2cif_disconnect_ind_cback
- *
- * Description      This is the L2CAP disconnect indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This is the L2CAP disconnect indication callback function */
 void gatt_l2cif_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
-  tGATT_TCB* p_tcb;
-  uint16_t reason;
 
   /* look up clcb for this channel */
-  p_tcb = gatt_find_tcb_by_cid(lcid);
-  if (p_tcb != NULL) {
-    if (ack_needed) {
-      /* send L2CAP disconnect response */
-      L2CA_DisconnectRsp(lcid);
-    }
-    if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) {
-      if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
-        gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
-    }
-    /* if ACL link is still up, no reason is logged, l2cap is disconnect from
-     * peer */
-    reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport);
-    if (reason == 0) reason = GATT_CONN_TERMINATE_PEER_USER;
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
+  if (!p_tcb) return;
 
-    /* send disconnect callback */
-    gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
+  if (ack_needed) {
+    /* send L2CAP disconnect response */
+    L2CA_DisconnectRsp(lcid);
   }
+
+  if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) {
+    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+      gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
+  }
+  /* if ACL link is still up, no reason is logged, l2cap is disconnect from
+   * peer */
+  uint16_t reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport);
+  if (reason == 0) reason = GATT_CONN_TERMINATE_PEER_USER;
+
+  /* send disconnect callback */
+  gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2cif_disconnect_cfm_cback
- *
- * Description      This is the L2CAP disconnect confirm callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This is the L2CAP disconnect confirm callback function */
 static void gatt_l2cif_disconnect_cfm_cback(uint16_t lcid,
                                             UNUSED_ATTR uint16_t result) {
-  tGATT_TCB* p_tcb;
-  uint16_t reason;
 
   /* look up clcb for this channel */
-  p_tcb = gatt_find_tcb_by_cid(lcid);
-  if (p_tcb != NULL) {
-    /* If the device is not in the service changed client list, add it... */
-    if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) {
-      if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
-        gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
-    }
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
+  if (!p_tcb) return;
 
-    /* send disconnect callback */
-    /* if ACL link is still up, no reason is logged, l2cap is disconnect from
-     * peer */
-    reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport);
-    if (reason == 0) reason = GATT_CONN_TERMINATE_LOCAL_HOST;
-
-    gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
+  /* If the device is not in the service changed client list, add it... */
+  if (gatt_is_bda_in_the_srv_chg_clt_list(p_tcb->peer_bda) == NULL) {
+    if (btm_sec_is_a_bonded_dev(p_tcb->peer_bda))
+      gatt_add_a_bonded_dev_for_srv_chg(p_tcb->peer_bda);
   }
+
+  /* send disconnect callback */
+  /* if ACL link is still up, no reason is logged, l2cap is disconnect from
+   * peer */
+  uint16_t reason = L2CA_GetDisconnectReason(p_tcb->peer_bda, p_tcb->transport);
+  if (reason == 0) reason = GATT_CONN_TERMINATE_LOCAL_HOST;
+
+  gatt_cleanup_upon_disc(p_tcb->peer_bda, reason, GATT_TRANSPORT_BR_EDR);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2cif_data_ind_cback
- *
- * Description      This is the L2CAP data indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This is the L2CAP data indication callback function */
 static void gatt_l2cif_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
-  tGATT_TCB* p_tcb;
-
   /* look up clcb for this channel */
-  if ((p_tcb = gatt_find_tcb_by_cid(lcid)) != NULL &&
-      gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
+  tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
+  if (p_tcb && gatt_get_ch_state(p_tcb) == GATT_CH_OPEN) {
     /* process the data */
     gatt_data_process(*p_tcb, p_buf);
   }
@@ -879,15 +791,7 @@
   osi_free(p_buf);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_l2cif_congest_cback
- *
- * Description      L2CAP congestion callback
- *
- * Returns          void
- *
- ******************************************************************************/
+/** L2CAP congestion callback */
 static void gatt_l2cif_congest_cback(uint16_t lcid, bool congested) {
   tGATT_TCB* p_tcb = gatt_find_tcb_by_cid(lcid);
 
@@ -896,34 +800,26 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_send_conn_cback
- *
- * Description      Callback used to notify layer above about a connection.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
+/** Callback used to notify layer above about a connection */
 static void gatt_send_conn_cback(tGATT_TCB* p_tcb) {
   uint8_t i;
   tGATT_REG* p_reg;
   uint16_t conn_id;
 
-  tGATT_BG_CONN_DEV* p_bg_dev = gatt_find_bg_dev(p_tcb->peer_bda);
+  std::set<tGATT_IF> apps =
+      connection_manager::get_apps_connecting_to(p_tcb->peer_bda);
 
   /* notifying all applications for the connection up event */
   for (i = 0, p_reg = gatt_cb.cl_rcb; i < GATT_MAX_APPS; i++, p_reg++) {
-    if (p_reg->in_use) {
-      if (p_bg_dev && gatt_is_bg_dev_for_app(p_bg_dev, p_reg->gatt_if))
-        gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true);
+    if (!p_reg->in_use) continue;
 
-      if (p_reg->app_cb.p_conn_cb) {
-        conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
-        (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id,
-                                   true, 0, p_tcb->transport);
-      }
+    if (apps.find(p_reg->gatt_if) != apps.end())
+      gatt_update_app_use_link_flag(p_reg->gatt_if, p_tcb, true, true);
+
+    if (p_reg->app_cb.p_conn_cb) {
+      conn_id = GATT_CREATE_CONN_ID(p_tcb->tcb_idx, p_reg->gatt_if);
+      (*p_reg->app_cb.p_conn_cb)(p_reg->gatt_if, p_tcb->peer_bda, conn_id, true,
+                                 0, p_tcb->transport);
     }
   }
 
@@ -986,71 +882,45 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_add_a_bonded_dev_for_srv_chg
- *
- * Description      Add a bonded dev to the service changed client list
- *
- * Returns          void
- *
- ******************************************************************************/
+/** Add a bonded dev to the service changed client list */
 void gatt_add_a_bonded_dev_for_srv_chg(const RawAddress& bda) {
   tGATTS_SRV_CHG_REQ req;
   tGATTS_SRV_CHG srv_chg_clt;
 
   srv_chg_clt.bda = bda;
   srv_chg_clt.srv_changed = false;
-  if (gatt_add_srv_chg_clt(&srv_chg_clt) != NULL) {
-    req.srv_chg.bda = bda;
-    req.srv_chg.srv_changed = false;
-    if (gatt_cb.cb_info.p_srv_chg_callback)
-      (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req,
-                                            NULL);
-  }
+  if (!gatt_add_srv_chg_clt(&srv_chg_clt)) return;
+
+  req.srv_chg.bda = bda;
+  req.srv_chg.srv_changed = false;
+  if (gatt_cb.cb_info.p_srv_chg_callback)
+    (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_ADD_CLIENT, &req,
+                                          NULL);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_send_srv_chg_ind
- *
- * Description      This function is called to send a service chnaged indication
- *                  to the specified bd address
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is called to send a service chnaged indication to the
+ * specified bd address */
 void gatt_send_srv_chg_ind(const RawAddress& peer_bda) {
+  VLOG(1) << __func__;
+
+  if (!gatt_cb.handle_of_h_r) return;
+
+  uint16_t conn_id = gatt_profile_find_conn_id_by_bd_addr(peer_bda);
+  if (conn_id == GATT_INVALID_CONN_ID) {
+    LOG(ERROR) << "Unable to find conn_id for " << peer_bda;
+    return;
+  }
+
   uint8_t handle_range[GATT_SIZE_OF_SRV_CHG_HNDL_RANGE];
   uint8_t* p = handle_range;
-  uint16_t conn_id;
-
-  VLOG(1) << "gatt_send_srv_chg_ind";
-
-  if (gatt_cb.handle_of_h_r) {
-    conn_id = gatt_profile_find_conn_id_by_bd_addr(peer_bda);
-    if (conn_id != GATT_INVALID_CONN_ID) {
-      UINT16_TO_STREAM(p, 1);
-      UINT16_TO_STREAM(p, 0xFFFF);
-      GATTS_HandleValueIndication(conn_id, gatt_cb.handle_of_h_r,
-                                  GATT_SIZE_OF_SRV_CHG_HNDL_RANGE,
-                                  handle_range);
-    } else {
-      LOG(ERROR) << "Unable to find conn_id for " << peer_bda;
-    }
-  }
+  UINT16_TO_STREAM(p, 1);
+  UINT16_TO_STREAM(p, 0xFFFF);
+  GATTS_HandleValueIndication(conn_id, gatt_cb.handle_of_h_r,
+                              GATT_SIZE_OF_SRV_CHG_HNDL_RANGE, handle_range);
 }
 
-/*******************************************************************************
- *
- * Function         gatt_chk_srv_chg
- *
- * Description      Check sending service chnaged Indication is required or not
- *                  if required then send the Indication
- *
- * Returns          void
- *
- ******************************************************************************/
+/** Check sending service chnaged Indication is required or not if required then
+ * send the Indication */
 void gatt_chk_srv_chg(tGATTS_SRV_CHG* p_srv_chg_clt) {
   VLOG(1) << __func__ << " srv_changed=" << +p_srv_chg_clt->srv_changed;
 
@@ -1059,130 +929,93 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_init_srv_chg
- *
- * Description      This function is used to initialize the service changed
- *                  attribute value
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is used to initialize the service changed attribute value */
 void gatt_init_srv_chg(void) {
   tGATTS_SRV_CHG_REQ req;
   tGATTS_SRV_CHG_RSP rsp;
-  bool status;
-  uint8_t num_clients, i;
   tGATTS_SRV_CHG srv_chg_clt;
 
   VLOG(1) << __func__;
-  if (gatt_cb.cb_info.p_srv_chg_callback) {
-    status = (*gatt_cb.cb_info.p_srv_chg_callback)(
-        GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp);
+  if (!gatt_cb.cb_info.p_srv_chg_callback) {
+    VLOG(1) << __func__ << " callback not registered yet";
+    return;
+  }
 
-    if (status && rsp.num_clients) {
-      VLOG(1) << "num_srv_chg_clt_clients=" << +rsp.num_clients;
-      num_clients = rsp.num_clients;
-      i = 1; /* use one based index */
-      while ((i <= num_clients) && status) {
-        req.client_read_index = i;
-        status = (*gatt_cb.cb_info.p_srv_chg_callback)(
-            GATTS_SRV_CHG_CMD_READ_CLENT, &req, &rsp);
-        if (status) {
-          memcpy(&srv_chg_clt, &rsp.srv_chg, sizeof(tGATTS_SRV_CHG));
-          if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL) {
-            LOG(ERROR) << "Unable to add a service change client";
-            status = false;
-          }
-        }
-        i++;
+  bool status = (*gatt_cb.cb_info.p_srv_chg_callback)(
+      GATTS_SRV_CHG_CMD_READ_NUM_CLENTS, NULL, &rsp);
+
+  if (!(status && rsp.num_clients)) return;
+
+  VLOG(1) << "num_srv_chg_clt_clients=" << +rsp.num_clients;
+  uint8_t num_clients = rsp.num_clients;
+  uint8_t i = 1; /* use one based index */
+  while ((i <= num_clients) && status) {
+    req.client_read_index = i;
+    status = (*gatt_cb.cb_info.p_srv_chg_callback)(GATTS_SRV_CHG_CMD_READ_CLENT,
+                                                   &req, &rsp);
+    if (status) {
+      memcpy(&srv_chg_clt, &rsp.srv_chg, sizeof(tGATTS_SRV_CHG));
+      if (gatt_add_srv_chg_clt(&srv_chg_clt) == NULL) {
+        LOG(ERROR) << "Unable to add a service change client";
+        status = false;
       }
     }
-  } else {
-    VLOG(1) << __func__ << " callback not registered yet";
+    i++;
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_proc_srv_chg
- *
- * Description      This function is process the service changed request
- *
- * Returns          void
- *
- ******************************************************************************/
+/**This function is process the service changed request */
 void gatt_proc_srv_chg(void) {
-  uint8_t start_idx, found_idx;
   RawAddress bda;
-  tGATT_TCB* p_tcb;
   tBT_TRANSPORT transport;
+  uint8_t found_idx;
 
   VLOG(1) << __func__;
 
-  if (gatt_cb.cb_info.p_srv_chg_callback && gatt_cb.handle_of_h_r) {
-    gatt_set_srv_chg();
-    start_idx = 0;
-    while (
-        gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
-      p_tcb = &gatt_cb.tcb[found_idx];
+  if (!gatt_cb.cb_info.p_srv_chg_callback || !gatt_cb.handle_of_h_r) return;
 
-      bool send_indication = true;
+  gatt_set_srv_chg();
+  uint8_t start_idx = 0;
+  while (gatt_find_the_connected_bda(start_idx, bda, &found_idx, &transport)) {
+    tGATT_TCB* p_tcb = &gatt_cb.tcb[found_idx];
 
-      if (gatt_is_srv_chg_ind_pending(p_tcb)) {
-        send_indication = false;
-        VLOG(1) << "discard srv chg - already has one in the queue";
-      }
+    bool send_indication = true;
 
-      // Some LE GATT clients don't respond to service changed indications.
-      char remote_name[BTM_MAX_REM_BD_NAME_LEN] = "";
-      if (send_indication &&
-          btif_storage_get_stored_remote_name(bda, remote_name)) {
-        if (interop_match_name(INTEROP_GATTC_NO_SERVICE_CHANGED_IND,
-                               remote_name)) {
-          VLOG(1) << "discard srv chg - interop matched " << remote_name;
-          send_indication = false;
-        }
-      }
-
-      if (send_indication) gatt_send_srv_chg_ind(bda);
-
-      start_idx = ++found_idx;
+    if (gatt_is_srv_chg_ind_pending(p_tcb)) {
+      send_indication = false;
+      VLOG(1) << "discard srv chg - already has one in the queue";
     }
+
+    // Some LE GATT clients don't respond to service changed indications.
+    char remote_name[BTM_MAX_REM_BD_NAME_LEN] = "";
+    if (send_indication &&
+        btif_storage_get_stored_remote_name(bda, remote_name)) {
+      if (interop_match_name(INTEROP_GATTC_NO_SERVICE_CHANGED_IND,
+                             remote_name)) {
+        VLOG(1) << "discard srv chg - interop matched " << remote_name;
+        send_indication = false;
+      }
+    }
+
+    if (send_indication) gatt_send_srv_chg_ind(bda);
+
+    start_idx = ++found_idx;
   }
 }
 
-/*******************************************************************************
- *
- * Function         gatt_set_ch_state
- *
- * Description      This function set the ch_state in tcb
- *
- * Returns          none
- *
- ******************************************************************************/
+/** This function set the ch_state in tcb */
 void gatt_set_ch_state(tGATT_TCB* p_tcb, tGATT_CH_STATE ch_state) {
-  if (p_tcb) {
-    VLOG(1) << __func__ << ": old=" << +p_tcb->ch_state << " new=" << ch_state;
-    p_tcb->ch_state = ch_state;
-  }
+  if (!p_tcb) return;
+
+  VLOG(1) << __func__ << ": old=" << +p_tcb->ch_state
+          << " new=" << loghex(ch_state);
+  p_tcb->ch_state = ch_state;
 }
 
-/*******************************************************************************
- *
- * Function         gatt_get_ch_state
- *
- * Description      This function get the ch_state in tcb
- *
- * Returns          none
- *
- ******************************************************************************/
+/** This function get the ch_state in tcb */
 tGATT_CH_STATE gatt_get_ch_state(tGATT_TCB* p_tcb) {
-  tGATT_CH_STATE ch_state = GATT_CH_CLOSE;
-  if (p_tcb) {
-    VLOG(1) << "gatt_get_ch_state: ch_state=" << +p_tcb->ch_state;
-    ch_state = p_tcb->ch_state;
-  }
-  return ch_state;
+  if (!p_tcb) return GATT_CH_CLOSE;
+
+  VLOG(1) << "gatt_get_ch_state: ch_state=" << +p_tcb->ch_state;
+  return p_tcb->ch_state;
 }
diff --git a/stack/gatt/gatt_sr.cc b/stack/gatt/gatt_sr.cc
index b9921fe..94d81ef 100644
--- a/stack/gatt/gatt_sr.cc
+++ b/stack/gatt/gatt_sr.cc
@@ -22,12 +22,13 @@
  *
  ******************************************************************************/
 
-#include <log/log.h>
 #include "bt_target.h"
 #include "bt_utils.h"
 #include "osi/include/osi.h"
 
+#include <log/log.h>
 #include <string.h>
+
 #include "gatt_int.h"
 #include "l2c_api.h"
 #include "l2c_int.h"
@@ -335,7 +336,7 @@
   } else /* nothing needs to be executed , send response now */
   {
     LOG(ERROR) << "gatt_process_exec_write_req: no prepare write pending";
-    gatt_send_error_rsp(tcb, GATT_INVALID_OFFSET, GATT_REQ_EXEC_WRITE, 0, false);
+    gatt_send_error_rsp(tcb, GATT_ERROR, GATT_REQ_EXEC_WRITE, 0, false);
   }
 }
 
@@ -749,7 +750,7 @@
   else
     tcb.payload_size = mtu;
 
-  LOG(ERROR) << "MTU request PDU with MTU size " << +tcb.payload_size;
+  LOG(INFO) << "MTU request PDU with MTU size " << +tcb.payload_size;
 
   l2cble_set_fixed_channel_tx_data_length(tcb.peer_bda, L2CAP_ATT_CID,
                                           tcb.payload_size);
@@ -884,13 +885,13 @@
       sr_data.write_req.is_prep = true;
       STREAM_TO_UINT16(sr_data.write_req.offset, p);
       len -= 2;
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case GATT_SIGN_CMD_WRITE:
       if (op_code == GATT_SIGN_CMD_WRITE) {
         VLOG(1) << "Write CMD with data sigining";
         len -= GATT_AUTH_SIGN_LEN;
       }
-    /* fall through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
     case GATT_CMD_WRITE:
     case GATT_REQ_WRITE:
       if (op_code == GATT_REQ_WRITE || op_code == GATT_REQ_PREPARE_WRITE)
@@ -1076,7 +1077,7 @@
  * Returns          void
  *
  ******************************************************************************/
-static void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb) {
+void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb) {
   tGATTS_SRV_CHG_REQ req;
   tGATTS_SRV_CHG* p_buf = NULL;
 
diff --git a/stack/gatt/gatt_utils.cc b/stack/gatt/gatt_utils.cc
index 9e8d3b9..2bd4240 100644
--- a/stack/gatt/gatt_utils.cc
+++ b/stack/gatt/gatt_utils.cc
@@ -30,11 +30,13 @@
 #include "stdio.h"
 
 #include "btm_int.h"
+#include "connection_manager.h"
 #include "gatt_api.h"
 #include "gatt_int.h"
 #include "gattdefs.h"
 #include "l2cdefs.h"
 #include "sdp_api.h"
+#include "stack/gatt/connection_manager.h"
 
 using base::StringPrintf;
 using bluetooth::Uuid;
@@ -155,25 +157,13 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function     gatt_add_pending_ind
- *
- * Description  Add a pending indication
- *
- * Returns    Pointer to the current pending indication buffer, NULL no buffer
- *            available
- *
- ******************************************************************************/
-tGATT_VALUE* gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind) {
-  tGATT_VALUE* p_buf = (tGATT_VALUE*)osi_malloc(sizeof(tGATT_VALUE));
-
+/** Add a pending indication */
+void gatt_add_pending_ind(tGATT_TCB* p_tcb, tGATT_VALUE* p_ind) {
   VLOG(1) << __func__ << "enqueue a pending indication";
 
+  tGATT_VALUE* p_buf = (tGATT_VALUE*)osi_malloc(sizeof(tGATT_VALUE));
   memcpy(p_buf, p_ind, sizeof(tGATT_VALUE));
   fixed_queue_enqueue(p_tcb->pending_ind_q, p_buf);
-
-  return p_buf;
 }
 
 /*******************************************************************************
@@ -318,7 +308,6 @@
  *
  ******************************************************************************/
 tGATTS_SRV_CHG* gatt_is_bda_in_the_srv_chg_clt_list(const RawAddress& bda) {
-  tGATTS_SRV_CHG* p_buf = NULL;
 
   VLOG(1) << __func__ << ": " << bda;
 
@@ -330,11 +319,11 @@
     tGATTS_SRV_CHG* p_buf = (tGATTS_SRV_CHG*)list_node(node);
     if (bda == p_buf->bda) {
       VLOG(1) << "bda is in the srv chg clt list";
-      break;
+      return p_buf;
     }
   }
 
-  return p_buf;
+  return NULL;
 }
 
 /*******************************************************************************
@@ -529,7 +518,7 @@
  *
  ******************************************************************************/
 void gatt_start_rsp_timer(tGATT_CLCB* p_clcb) {
-  period_ms_t timeout_ms = GATT_WAIT_FOR_RSP_TIMEOUT_MS;
+  uint64_t timeout_ms = GATT_WAIT_FOR_RSP_TIMEOUT_MS;
 
   if (p_clcb->operation == GATTC_OPTYPE_DISCOVERY &&
       p_clcb->op_subtype == GATT_DISC_SRVC_ALL) {
@@ -608,6 +597,8 @@
   gatt_disconnect(p_clcb->p_tcb);
 }
 
+extern void gatts_proc_srv_chg_ind_ack(tGATT_TCB tcb);
+
 /*******************************************************************************
  *
  * Function         gatt_indication_confirmation_timeout
@@ -620,6 +611,26 @@
 void gatt_indication_confirmation_timeout(void* data) {
   tGATT_TCB* p_tcb = (tGATT_TCB*)data;
 
+  if (p_tcb->indicate_handle == gatt_cb.handle_of_h_r) {
+    /* There are some GATT Server only devices, that don't implement GATT client
+     * functionalities, and ignore "Service Changed" indication. Android does
+     * not have CCC in "Service Changed" characteristic, and sends it to all
+     * bonded devices. This leads to situation where remote can ignore the
+     * indication, and trigger 30s timeout, then reconnection in a loop.
+     *
+     * Since chances of healthy Client device keeping connection for 30 seconds
+     * and not responding to "Service Changed" indication are very low, assume
+     * we are dealing with Server only device, and don't trigger disconnection.
+     *
+     * TODO: In future, we should properly expose CCC, and send indication only
+     * to devices that register for it.
+     */
+    LOG(WARNING) << " Service Changed notification timed out in 30 "
+                    "seconds, assuming server-only remote, not disconnecting";
+    gatts_proc_srv_chg_ind_ack(*p_tcb);
+    return;
+  }
+
   LOG(WARNING) << __func__ << " disconnecting...";
   gatt_disconnect(p_tcb);
 }
@@ -1095,15 +1106,8 @@
     }
   }
 }
-/*******************************************************************************
- *
- * Function         gatt_cancel_open
- *
- * Description      Cancel open request
- *
- * Returns         Boolean
- *
- ******************************************************************************/
+
+/** Cancel LE Create Connection request */
 bool gatt_cancel_open(tGATT_IF gatt_if, const RawAddress& bda) {
   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bda, BT_TRANSPORT_LE);
   if (!p_tcb) return true;
@@ -1117,6 +1121,7 @@
 
   if (p_tcb->app_hold_link.empty()) gatt_disconnect(p_tcb);
 
+  connection_manager::direct_connect_remove(gatt_if, bda);
   return true;
 }
 
@@ -1307,156 +1312,9 @@
     return (uint8_t*)"Op Code Exceed Max";
 }
 
-/** Returns true if this is one of the background devices for the application,
- * false otherwise */
-bool gatt_is_bg_dev_for_app(tGATT_BG_CONN_DEV* p_dev, tGATT_IF gatt_if) {
-  return p_dev->gatt_if.count(gatt_if);
-}
-
-/** background connection device from the list. Returns pointer to the device
- * record, or nullptr if not found */
-tGATT_BG_CONN_DEV* gatt_find_bg_dev(const RawAddress& remote_bda) {
-  for (tGATT_BG_CONN_DEV& dev : gatt_cb.bgconn_dev) {
-    if (dev.remote_bda == remote_bda) {
-      return &dev;
-    }
-  }
-  return nullptr;
-}
-
-std::list<tGATT_BG_CONN_DEV>::iterator gatt_find_bg_dev_it(
-    const RawAddress& remote_bda) {
-  auto& list = gatt_cb.bgconn_dev;
-  for (auto it = list.begin(); it != list.end(); it++) {
-    if (it->remote_bda == remote_bda) {
-      return it;
-    }
-  }
-  return list.end();
-}
-
-/** Add a device from the background connection list.  Returns true if device
- * added to the list, or already in list, false otherwise */
-bool gatt_add_bg_dev_list(tGATT_REG* p_reg, const RawAddress& bd_addr) {
-  tGATT_IF gatt_if = p_reg->gatt_if;
-
-  tGATT_BG_CONN_DEV* p_dev = gatt_find_bg_dev(bd_addr);
-  if (p_dev) {
-    // device already in the whitelist, just add interested app to the list
-    if (!p_dev->gatt_if.insert(gatt_if).second) {
-      LOG(ERROR) << "device already in iniator white list";
-    }
-
-    return true;
-  }
-  // the device is not in the whitelist
-
-  if (!BTM_BleUpdateBgConnDev(true, bd_addr)) return false;
-
-  gatt_cb.bgconn_dev.emplace_back();
-  tGATT_BG_CONN_DEV& dev = gatt_cb.bgconn_dev.back();
-  dev.remote_bda = bd_addr;
-  dev.gatt_if.insert(gatt_if);
-  return true;
-}
-
 /** Remove the application interface for the specified background device */
-bool gatt_remove_bg_dev_for_app(tGATT_IF gatt_if, const RawAddress& bd_addr) {
+bool gatt_auto_connect_dev_remove(tGATT_IF gatt_if, const RawAddress& bd_addr) {
   tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
-  bool status;
-
   if (p_tcb) gatt_update_app_use_link_flag(gatt_if, p_tcb, false, false);
-  status = gatt_update_auto_connect_dev(gatt_if, false, bd_addr);
-  return status;
-}
-
-/** Removes all registrations for background connection for given device.
- * Returns true if anything was removed, false otherwise */
-uint8_t gatt_clear_bg_dev_for_addr(const RawAddress& bd_addr) {
-  auto dev_it = gatt_find_bg_dev_it(bd_addr);
-  if (dev_it == gatt_cb.bgconn_dev.end()) return false;
-
-  CHECK(BTM_BleUpdateBgConnDev(false, dev_it->remote_bda));
-  gatt_cb.bgconn_dev.erase(dev_it);
-  return true;
-}
-
-/** Remove device from the background connection device list or listening to
- * advertising list.  Returns true if device was on the list and was succesfully
- * removed */
-bool gatt_remove_bg_dev_from_list(tGATT_REG* p_reg, const RawAddress& bd_addr) {
-  tGATT_IF gatt_if = p_reg->gatt_if;
-  auto dev_it = gatt_find_bg_dev_it(bd_addr);
-  if (dev_it == gatt_cb.bgconn_dev.end()) return false;
-
-  if (!dev_it->gatt_if.erase(gatt_if)) return false;
-
-  if (!dev_it->gatt_if.empty()) return true;
-
-  // no more apps interested - remove from whitelist and delete record
-  CHECK(BTM_BleUpdateBgConnDev(false, dev_it->remote_bda));
-  gatt_cb.bgconn_dev.erase(dev_it);
-  return true;
-}
-/** deregister all related back ground connetion device. */
-void gatt_deregister_bgdev_list(tGATT_IF gatt_if) {
-  auto it = gatt_cb.bgconn_dev.begin();
-  auto end = gatt_cb.bgconn_dev.end();
-  /* update the BG conn device list */
-  while (it != end) {
-    it->gatt_if.erase(gatt_if);
-    if (it->gatt_if.size()) {
-      it++;
-      continue;
-    }
-
-    BTM_BleUpdateBgConnDev(false, it->remote_bda);
-    it = gatt_cb.bgconn_dev.erase(it);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         gatt_reset_bgdev_list
- *
- * Description      reset bg device list
- *
- * Returns          pointer to the device record
- *
- ******************************************************************************/
-void gatt_reset_bgdev_list(void) { gatt_cb.bgconn_dev.clear(); }
-/*******************************************************************************
- *
- * Function         gatt_update_auto_connect_dev
- *
- * Description      This function add or remove a device for background
- *                  connection procedure.
- *
- * Parameters       gatt_if: Application ID.
- *                  add: add peer device
- *                  bd_addr: peer device address.
- *
- * Returns          true if connection started; false otherwise.
- *
- ******************************************************************************/
-bool gatt_update_auto_connect_dev(tGATT_IF gatt_if, bool add,
-                                  const RawAddress& bd_addr) {
-  tGATT_TCB* p_tcb = gatt_find_tcb_by_addr(bd_addr, BT_TRANSPORT_LE);
-
-  VLOG(1) << __func__;
-  /* Make sure app is registered */
-  tGATT_REG* p_reg = gatt_get_regcb(gatt_if);
-  if (!p_reg) {
-    LOG(ERROR) << __func__ << " gatt_if is not registered " << +gatt_if;
-    return false;
-  }
-
-  if (!add) return gatt_remove_bg_dev_from_list(p_reg, bd_addr);
-
-  bool ret = gatt_add_bg_dev_list(p_reg, bd_addr);
-  if (ret && p_tcb != NULL) {
-    /* if a connected device, update the link holding number */
-    gatt_update_app_use_link_flag(gatt_if, p_tcb, true, true);
-  }
-  return ret;
+  return connection_manager::background_connect_remove(gatt_if, bd_addr);
 }
diff --git a/stack/hcic/hciblecmds.cc b/stack/hcic/hciblecmds.cc
index 30d8d75..001532d 100644
--- a/stack/hcic/hciblecmds.cc
+++ b/stack/hcic/hciblecmds.cc
@@ -244,50 +244,36 @@
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
-void btsnd_hcic_ble_clear_white_list(void) {
-  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
-  uint8_t* pp = (uint8_t*)(p + 1);
-
-  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_CLEAR_WHITE_LIST;
-  p->offset = 0;
-
-  UINT16_TO_STREAM(pp, HCI_BLE_CLEAR_WHITE_LIST);
-  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_CLEAR_WHITE_LIST);
-
-  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+void btsnd_hcic_ble_clear_white_list(
+    base::OnceCallback<void(uint8_t*, uint16_t)> cb) {
+  btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_BLE_CLEAR_WHITE_LIST, nullptr, 0,
+                            std::move(cb));
 }
 
-void btsnd_hcic_ble_add_white_list(uint8_t addr_type, const RawAddress& bda) {
-  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
-  uint8_t* pp = (uint8_t*)(p + 1);
-
-  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_ADD_WHITE_LIST;
-  p->offset = 0;
-
-  UINT16_TO_STREAM(pp, HCI_BLE_ADD_WHITE_LIST);
-  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_ADD_WHITE_LIST);
+void btsnd_hcic_ble_add_white_list(
+    uint8_t addr_type, const RawAddress& bda,
+    base::OnceCallback<void(uint8_t*, uint16_t)> cb) {
+  uint8_t param[HCIC_PARAM_SIZE_ADD_WHITE_LIST];
+  uint8_t* pp = param;
 
   UINT8_TO_STREAM(pp, addr_type);
   BDADDR_TO_STREAM(pp, bda);
 
-  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+  btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_BLE_ADD_WHITE_LIST, param,
+                            HCIC_PARAM_SIZE_ADD_WHITE_LIST, std::move(cb));
 }
 
-void btsnd_hcic_ble_remove_from_white_list(uint8_t addr_type,
-                                           const RawAddress& bda) {
-  BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
-  uint8_t* pp = (uint8_t*)(p + 1);
-
-  p->len = HCIC_PREAMBLE_SIZE + HCIC_PARAM_SIZE_REMOVE_WHITE_LIST;
-  p->offset = 0;
-
-  UINT16_TO_STREAM(pp, HCI_BLE_REMOVE_WHITE_LIST);
-  UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REMOVE_WHITE_LIST);
+void btsnd_hcic_ble_remove_from_white_list(
+    uint8_t addr_type, const RawAddress& bda,
+    base::OnceCallback<void(uint8_t*, uint16_t)> cb) {
+  uint8_t param[HCIC_PARAM_SIZE_REMOVE_WHITE_LIST];
+  uint8_t* pp = param;
 
   UINT8_TO_STREAM(pp, addr_type);
   BDADDR_TO_STREAM(pp, bda);
 
-  btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
+  btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_BLE_REMOVE_WHITE_LIST, param,
+                            HCIC_PARAM_SIZE_REMOVE_WHITE_LIST, std::move(cb));
 }
 
 void btsnd_hcic_ble_upd_ll_conn_params(uint16_t handle, uint16_t conn_int_min,
@@ -405,8 +391,7 @@
 
 void btsnd_hcic_ble_start_enc(uint16_t handle,
                               uint8_t rand[HCIC_BLE_RAND_DI_SIZE],
-                              uint16_t ediv,
-                              uint8_t ltk[HCIC_BLE_ENCRYT_KEY_SIZE]) {
+                              uint16_t ediv, const Octet16& ltk) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
 
@@ -419,13 +404,12 @@
   UINT16_TO_STREAM(pp, handle);
   ARRAY_TO_STREAM(pp, rand, HCIC_BLE_RAND_DI_SIZE);
   UINT16_TO_STREAM(pp, ediv);
-  ARRAY_TO_STREAM(pp, ltk, HCIC_BLE_ENCRYT_KEY_SIZE);
+  ARRAY_TO_STREAM(pp, ltk.data(), HCIC_BLE_ENCRYT_KEY_SIZE);
 
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
-void btsnd_hcic_ble_ltk_req_reply(uint16_t handle,
-                                  uint8_t ltk[HCIC_BLE_ENCRYT_KEY_SIZE]) {
+void btsnd_hcic_ble_ltk_req_reply(uint16_t handle, const Octet16& ltk) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
 
@@ -436,7 +420,7 @@
   UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_LTK_REQ_REPLY);
 
   UINT16_TO_STREAM(pp, handle);
-  ARRAY_TO_STREAM(pp, ltk, HCIC_BLE_ENCRYT_KEY_SIZE);
+  ARRAY_TO_STREAM(pp, ltk.data(), HCIC_BLE_ENCRYT_KEY_SIZE);
 
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
@@ -560,9 +544,10 @@
 }
 #endif
 
-void btsnd_hcic_ble_add_device_resolving_list(
-    uint8_t addr_type_peer, const RawAddress& bda_peer,
-    uint8_t irk_peer[HCIC_BLE_IRK_SIZE], uint8_t irk_local[HCIC_BLE_IRK_SIZE]) {
+void btsnd_hcic_ble_add_device_resolving_list(uint8_t addr_type_peer,
+                                              const RawAddress& bda_peer,
+                                              const Octet16& irk_peer,
+                                              const Octet16& irk_local) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
 
@@ -573,8 +558,8 @@
   UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_BLE_ADD_DEV_RESOLVING_LIST);
   UINT8_TO_STREAM(pp, addr_type_peer);
   BDADDR_TO_STREAM(pp, bda_peer);
-  ARRAY_TO_STREAM(pp, irk_peer, HCIC_BLE_ENCRYT_KEY_SIZE);
-  ARRAY_TO_STREAM(pp, irk_local, HCIC_BLE_ENCRYT_KEY_SIZE);
+  ARRAY_TO_STREAM(pp, irk_peer.data(), HCIC_BLE_ENCRYT_KEY_SIZE);
+  ARRAY_TO_STREAM(pp, irk_local.data(), HCIC_BLE_ENCRYT_KEY_SIZE);
 
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
diff --git a/stack/hcic/hcicmds.cc b/stack/hcic/hcicmds.cc
index 0778afc..23a8648 100644
--- a/stack/hcic/hcicmds.cc
+++ b/stack/hcic/hcicmds.cc
@@ -142,7 +142,6 @@
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
-#if (BTM_SCO_INCLUDED == TRUE)
 void btsnd_hcic_add_SCO_conn(uint16_t handle, uint16_t packet_types) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
@@ -158,7 +157,6 @@
 
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
-#endif /* BTM_SCO_INCLUDED */
 
 void btsnd_hcic_create_conn_cancel(const RawAddress& dest) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
@@ -207,7 +205,7 @@
 }
 
 void btsnd_hcic_link_key_req_reply(const RawAddress& bd_addr,
-                                   LINK_KEY link_key) {
+                                   const LinkKey& link_key) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
 
@@ -218,7 +216,7 @@
   UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_LINK_KEY_REQ_REPLY);
 
   BDADDR_TO_STREAM(pp, bd_addr);
-  ARRAY16_TO_STREAM(pp, link_key);
+  ARRAY16_TO_STREAM(pp, link_key.data());
 
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
@@ -1196,8 +1194,8 @@
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
-void btsnd_hcic_rem_oob_reply(const RawAddress& bd_addr, uint8_t* p_c,
-                              uint8_t* p_r) {
+void btsnd_hcic_rem_oob_reply(const RawAddress& bd_addr, const Octet16& c,
+                              const Octet16& r) {
   BT_HDR* p = (BT_HDR*)osi_malloc(HCI_CMD_BUF_SIZE);
   uint8_t* pp = (uint8_t*)(p + 1);
 
@@ -1208,8 +1206,8 @@
   UINT8_TO_STREAM(pp, HCIC_PARAM_SIZE_REM_OOB_REPLY);
 
   BDADDR_TO_STREAM(pp, bd_addr);
-  ARRAY16_TO_STREAM(pp, p_c);
-  ARRAY16_TO_STREAM(pp, p_r);
+  ARRAY16_TO_STREAM(pp, c.data());
+  ARRAY16_TO_STREAM(pp, r.data());
 
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
@@ -1311,9 +1309,8 @@
   btu_hcif_send_cmd(LOCAL_BR_EDR_CONTROLLER_ID, p);
 }
 
-static void read_encryption_key_size_complete(
-    ReadEncKeySizeCb cb, uint8_t* return_parameters,
-    uint16_t return_parameters_length) {
+static void read_encryption_key_size_complete(ReadEncKeySizeCb cb, uint8_t* return_parameters,
+                                              uint16_t return_parameters_length) {
   uint8_t status;
   uint16_t handle;
   uint8_t key_size;
@@ -1332,9 +1329,8 @@
   uint8_t* p = param;
   UINT16_TO_STREAM(p, handle);
 
-  btu_hcif_send_cmd_with_cb(
-      FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len,
-      base::Bind(&read_encryption_key_size_complete, base::Passed(&cb)));
+  btu_hcif_send_cmd_with_cb(FROM_HERE, HCI_READ_ENCR_KEY_SIZE, param, len,
+                            base::Bind(&read_encryption_key_size_complete, base::Passed(&cb)));
 }
 
 void btsnd_hcic_read_failed_contact_counter(uint16_t handle) {
diff --git a/stack/hid/hidd_api.cc b/stack/hid/hidd_api.cc
index f93511e..cd40c2c 100644
--- a/stack/hid/hidd_api.cc
+++ b/stack/hid/hidd_api.cc
@@ -33,7 +33,6 @@
 #include "hidd_api.h"
 #include "hidd_int.h"
 #include "hiddefs.h"
-#include "log/log.h"
 
 tHID_DEV_CTB hd_cb;
 
@@ -321,10 +320,6 @@
       UINT8_TO_BE_STREAM(p, desc_len);
       ARRAY_TO_BE_STREAM(p, p_desc_data, (int)desc_len);
 
-      if (desc_len > HIDD_APP_DESCRIPTOR_LEN - 6) {
-        android_errorWriteLog(0x534e4554, "113572366");
-      }
-
       result &= SDP_AddAttribute(handle, ATTR_ID_HID_DESCRIPTOR_LIST,
                                  DATA_ELE_SEQ_DESC_TYPE, p - p_buf, p_buf);
 
diff --git a/stack/hid/hidd_conn.cc b/stack/hid/hidd_conn.cc
index e4525f9..55ec3b2 100644
--- a/stack/hid/hidd_conn.cc
+++ b/stack/hid/hidd_conn.cc
@@ -614,6 +614,12 @@
 
   HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
 
+  if (p_msg->len < 1) {
+    HIDD_TRACE_ERROR("Invalid data length, ignore");
+    osi_free(p_msg);
+    return;
+  }
+
   p_hcon = &hd_cb.device.conn;
 
   if (p_hcon->conn_state == HID_CONN_STATE_UNUSED ||
@@ -756,12 +762,14 @@
   hd_cb.l2cap_intr_cfg.flush_to_present = TRUE;
   hd_cb.l2cap_intr_cfg.flush_to = HID_DEV_FLUSH_TO;
 
-  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
+  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&dev_reg_info,
+                     false /* enable_snoop */)) {
     HIDD_TRACE_ERROR("HID Control (device) registration failed");
     return (HID_ERR_L2CAP_FAILED);
   }
 
-  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info)) {
+  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&dev_reg_info,
+                     false /* enable_snoop */)) {
     L2CA_Deregister(HID_PSM_CONTROL);
     HIDD_TRACE_ERROR("HID Interrupt (device) registration failed");
     return (HID_ERR_L2CAP_FAILED);
diff --git a/stack/hid/hidh_api.cc b/stack/hid/hidh_api.cc
index ad84daf..de62385 100644
--- a/stack/hid/hidh_api.cc
+++ b/stack/hid/hidh_api.cc
@@ -295,8 +295,8 @@
   if (!hh_cb.reg_flag) return (HID_ERR_NOT_REGISTERED);
 
   for (i = 0; i < HID_HOST_MAX_DEVICES; i++) {
-    alarm_free(hh_cb.devices[i].conn.process_repage_timer);
     HID_HostRemoveDev(i);
+    alarm_free(hh_cb.devices[i].conn.process_repage_timer);
   }
 
   hidh_conn_dereg();
diff --git a/stack/hid/hidh_conn.cc b/stack/hid/hidh_conn.cc
index 6f99c88..3c694f0 100644
--- a/stack/hid/hidh_conn.cc
+++ b/stack/hid/hidh_conn.cc
@@ -97,11 +97,13 @@
   hh_cb.l2cap_cfg.flush_to = HID_HOST_FLUSH_TO;
 
   /* Now, register with L2CAP */
-  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info)) {
+  if (!L2CA_Register(HID_PSM_CONTROL, (tL2CAP_APPL_INFO*)&hst_reg_info,
+                     false /* enable_snoop */)) {
     HIDH_TRACE_ERROR("HID-Host Control Registration failed");
     return (HID_ERR_L2CAP_FAILED);
   }
-  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info)) {
+  if (!L2CA_Register(HID_PSM_INTERRUPT, (tL2CAP_APPL_INFO*)&hst_reg_info,
+                     false /* enable_snoop */)) {
     L2CA_Deregister(HID_PSM_CONTROL);
     HIDH_TRACE_ERROR("HID-Host Interrupt Registration failed");
     return (HID_ERR_L2CAP_FAILED);
@@ -656,7 +658,7 @@
         (!(hh_cb.devices[dhandle].attr_mask & HID_RECONN_INIT)) &&
         (hh_cb.devices[dhandle].attr_mask & HID_NORMALLY_CONNECTABLE)) {
       hh_cb.devices[dhandle].conn_tries = 0;
-      period_ms_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
+      uint64_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
       alarm_set_on_mloop(hh_cb.devices[dhandle].conn.process_repage_timer,
                          interval_ms, hidh_process_repage_timer_timeout,
                          UINT_TO_PTR(dhandle));
@@ -1073,7 +1075,7 @@
 
   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;
+  uint64_t interval_ms = HID_HOST_REPAGE_WIN * 1000;
   alarm_set_on_mloop(p_dev->conn.process_repage_timer, interval_ms,
                      hidh_process_repage_timer_timeout, UINT_TO_PTR(dhandle));
 #else
diff --git a/stack/include/a2dp_aac.h b/stack/include/a2dp_aac.h
index 29b2753..94ba730 100644
--- a/stack/include/a2dp_aac.h
+++ b/stack/include/a2dp_aac.h
@@ -48,7 +48,7 @@
   virtual ~A2dpCodecConfigAacSource();
 
   bool init() override;
-  period_ms_t encoderIntervalMs() const override;
+  uint64_t encoderIntervalMs() const override;
   int getEffectiveMtu() const override;
 
  private:
@@ -66,7 +66,7 @@
   virtual ~A2dpCodecConfigAacSink();
 
   bool init() override;
-  period_ms_t encoderIntervalMs() const override;
+  uint64_t encoderIntervalMs() const override;
   int getEffectiveMtu() const override;
 
  private:
@@ -147,6 +147,12 @@
 // contains invalid codec information.
 int A2DP_GetTrackSampleRateAac(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP AAC codec.
+// |p_codec_info| is a pointer to the AAC codec_info to decode.
+// Returns the track bits per sample on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_GetTrackBitsPerSampleAac(const uint8_t* p_codec_info);
+
 // Gets the channel count for the A2DP AAC codec.
 // |p_codec_info| is a pointer to the AAC codec_info to decode.
 // Returns the channel count on success, or -1 if |p_codec_info|
diff --git a/stack/include/a2dp_aac_encoder.h b/stack/include/a2dp_aac_encoder.h
index e6b7323..143a577 100644
--- a/stack/include/a2dp_aac_encoder.h
+++ b/stack/include/a2dp_aac_encoder.h
@@ -22,7 +22,6 @@
 #define A2DP_AAC_ENCODER_H
 
 #include "a2dp_codec_api.h"
-#include "osi/include/time.h"
 
 // Loads the A2DP AAC encoder.
 // Return true on success, otherwise false.
@@ -51,7 +50,7 @@
 void a2dp_aac_feeding_flush(void);
 
 // Get the A2DP AAC encoder interval (in milliseconds).
-period_ms_t a2dp_aac_get_encoder_interval_ms(void);
+uint64_t a2dp_aac_get_encoder_interval_ms(void);
 
 // Prepare and send A2DP AAC encoded frames.
 // |timestamp_us| is the current timestamp (in microseconds).
diff --git a/stack/include/a2dp_codec_api.h b/stack/include/a2dp_codec_api.h
index 9fdc13b..45cbf9c 100644
--- a/stack/include/a2dp_codec_api.h
+++ b/stack/include/a2dp_codec_api.h
@@ -34,7 +34,6 @@
 #include "a2dp_api.h"
 #include "audio_a2dp_hw/include/audio_a2dp_hw.h"
 #include "avdt_api.h"
-#include "osi/include/time.h"
 
 class tBT_A2DP_OFFLOAD;
 
@@ -217,7 +216,7 @@
   virtual bool isValid() const;
 
   // Returns the encoder's periodic interval (in milliseconds).
-  virtual period_ms_t encoderIntervalMs() const = 0;
+  virtual uint64_t encoderIntervalMs() const = 0;
 
   // Checks whether the A2DP Codec Configuration is valid.
   // Returns true if A2DP Codec Configuration stored in |codec_config|
@@ -302,6 +301,10 @@
   // Returns the Sink codec if found, otherwise nullptr.
   A2dpCodecConfig* findSinkCodecConfig(const uint8_t* p_codec_info);
 
+  // Checks whether the codec for |codec_index| is supported.
+  // Returns true if the codec is supported, otherwise false.
+  bool isSupportedCodec(btav_a2dp_codec_index_t codec_index);
+
   // Gets the codec config that is currently selected.
   // Returns the codec config that is currently selected, or nullptr if
   // no codec is selected.
@@ -527,7 +530,7 @@
   void (*feeding_flush)(void);
 
   // Get the A2DP encoder interval (in milliseconds).
-  period_ms_t (*get_encoder_interval_ms)(void);
+  uint64_t (*get_encoder_interval_ms)(void);
 
   // Prepare and send A2DP encoded frames.
   // |timestamp_us| is the current timestamp (in microseconds).
@@ -639,6 +642,12 @@
 // contains invalid codec information.
 int A2DP_GetTrackSampleRate(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP codec.
+// |p_codec_info| is a pointer to the codec_info to decode.
+// Returns the track bits per sample on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_GetTrackBitsPerSample(const uint8_t* p_codec_info);
+
 // Gets the channel count for the A2DP codec.
 // |p_codec_info| is a pointer to the codec_info to decode.
 // Returns the channel count on success, or -1 if |p_codec_info|
diff --git a/stack/include/a2dp_sbc.h b/stack/include/a2dp_sbc.h
index 0381d311..5f7b0aa 100644
--- a/stack/include/a2dp_sbc.h
+++ b/stack/include/a2dp_sbc.h
@@ -48,7 +48,7 @@
   virtual ~A2dpCodecConfigSbcSource();
 
   bool init() override;
-  period_ms_t encoderIntervalMs() const override;
+  uint64_t encoderIntervalMs() const override;
   int getEffectiveMtu() const override;
 
  private:
@@ -66,7 +66,7 @@
   virtual ~A2dpCodecConfigSbcSink();
 
   bool init() override;
-  period_ms_t encoderIntervalMs() const override;
+  uint64_t encoderIntervalMs() const override;
   int getEffectiveMtu() const override;
 
  private:
@@ -143,6 +143,12 @@
 // contains invalid codec information.
 int A2DP_GetTrackSampleRateSbc(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP SBC codec.
+// |p_codec_info| is a pointer to the SBC codec_info to decode.
+// Returns the track bits per sample on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_GetTrackBitsPerSampleSbc(const uint8_t* p_codec_info);
+
 // Gets the channel count for the A2DP SBC codec.
 // |p_codec_info| is a pointer to the SBC codec_info to decode.
 // Returns the channel count on success, or -1 if |p_codec_info|
diff --git a/stack/include/a2dp_sbc_encoder.h b/stack/include/a2dp_sbc_encoder.h
index a853012..0acf16f 100644
--- a/stack/include/a2dp_sbc_encoder.h
+++ b/stack/include/a2dp_sbc_encoder.h
@@ -25,7 +25,6 @@
 #define A2DP_SBC_ENCODER_H
 
 #include "a2dp_codec_api.h"
-#include "osi/include/time.h"
 
 // Loads the A2DP SBC encoder.
 // Return true on success, otherwise false.
@@ -54,7 +53,7 @@
 void a2dp_sbc_feeding_flush(void);
 
 // Get the A2DP SBC encoder interval (in milliseconds).
-period_ms_t a2dp_sbc_get_encoder_interval_ms(void);
+uint64_t a2dp_sbc_get_encoder_interval_ms(void);
 
 // Prepare and send A2DP SBC encoded frames.
 // |timestamp_us| is the current timestamp (in microseconds).
diff --git a/stack/include/a2dp_vendor.h b/stack/include/a2dp_vendor.h
index 0b5ba7c..117e25c 100644
--- a/stack/include/a2dp_vendor.h
+++ b/stack/include/a2dp_vendor.h
@@ -117,6 +117,12 @@
 // contains invalid codec information.
 int A2DP_VendorGetTrackSampleRate(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP vendor-specific codec.
+// |p_codec_info| is a pointer to the vendor-specific codec_info to decode.
+// Returns the track sample rate on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetTrackBitsPerSample(const uint8_t* p_codec_info);
+
 // Gets the channel count for the A2DP vendor-specific codec.
 // |p_codec_info| is a pointer to the vendor-specific codec_info to decode.
 // Returns the channel count on success, or -1 if |p_codec_info|
diff --git a/stack/include/a2dp_vendor_aptx.h b/stack/include/a2dp_vendor_aptx.h
index 38a1245..bf4ebf0 100644
--- a/stack/include/a2dp_vendor_aptx.h
+++ b/stack/include/a2dp_vendor_aptx.h
@@ -31,7 +31,7 @@
   virtual ~A2dpCodecConfigAptx();
 
   bool init() override;
-  period_ms_t encoderIntervalMs() const override;
+  uint64_t encoderIntervalMs() const override;
   int getEffectiveMtu() const override;
   bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
                       uint8_t* p_result_codec_config) override;
@@ -91,6 +91,12 @@
 // contains invalid codec information.
 int A2DP_VendorGetTrackSampleRateAptx(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP aptX codec.
+// |p_codec_info| is a pointer to the aptX codec_info to decode.
+// Returns the track bits per sample on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetTrackBitsPerSampleAptx(const uint8_t* p_codec_info);
+
 // Gets the track bitrate value for the A2DP aptX codec.
 // |p_codec_info| is a pointer to the aptX codec_info to decode.
 // Returns the track sample rate on success, or -1 if |p_codec_info|
diff --git a/stack/include/a2dp_vendor_aptx_encoder.h b/stack/include/a2dp_vendor_aptx_encoder.h
index 7deaca3..c0954fa 100644
--- a/stack/include/a2dp_vendor_aptx_encoder.h
+++ b/stack/include/a2dp_vendor_aptx_encoder.h
@@ -22,7 +22,6 @@
 #define A2DP_VENDOR_APTX_ENCODER_H
 
 #include "a2dp_codec_api.h"
-#include "osi/include/time.h"
 
 // Loads the A2DP aptX encoder.
 // Return true on success, otherwise false.
@@ -52,7 +51,7 @@
 void a2dp_vendor_aptx_feeding_flush(void);
 
 // Get the A2DP aptX encoder interval (in milliseconds).
-period_ms_t a2dp_vendor_aptx_get_encoder_interval_ms(void);
+uint64_t a2dp_vendor_aptx_get_encoder_interval_ms(void);
 
 // Prepare and send A2DP aptX encoded frames.
 // |timestamp_us| is the current timestamp (in microseconds).
diff --git a/stack/include/a2dp_vendor_aptx_hd.h b/stack/include/a2dp_vendor_aptx_hd.h
index 05ca16f..8efe8c6 100644
--- a/stack/include/a2dp_vendor_aptx_hd.h
+++ b/stack/include/a2dp_vendor_aptx_hd.h
@@ -31,7 +31,7 @@
   virtual ~A2dpCodecConfigAptxHd();
 
   bool init() override;
-  period_ms_t encoderIntervalMs() const override;
+  uint64_t encoderIntervalMs() const override;
   int getEffectiveMtu() const override;
   bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
                       uint8_t* p_result_codec_config) override;
@@ -91,6 +91,12 @@
 // contains invalid codec information.
 int A2DP_VendorGetTrackSampleRateAptxHd(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP aptX-HD codec.
+// |p_codec_info| is a pointer to the aptX-HD codec_info to decode.
+// Returns the track bits per sample on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetTrackBitsPerSampleAptxHd(const uint8_t* p_codec_info);
+
 // Gets the track bitrate value for the A2DP aptX-HD codec.
 // |p_codec_info| is a pointer to the aptX-HD codec_info to decode.
 // Returns the track sample rate on success, or -1 if |p_codec_info|
diff --git a/stack/include/a2dp_vendor_aptx_hd_encoder.h b/stack/include/a2dp_vendor_aptx_hd_encoder.h
index 53e7d02..84ef8a0 100644
--- a/stack/include/a2dp_vendor_aptx_hd_encoder.h
+++ b/stack/include/a2dp_vendor_aptx_hd_encoder.h
@@ -22,7 +22,6 @@
 #define A2DP_VENDOR_APTX_HD_ENCODER_H
 
 #include "a2dp_codec_api.h"
-#include "osi/include/time.h"
 
 // Loads the A2DP aptX-HD encoder.
 // Return true on success, otherwise false.
@@ -52,7 +51,7 @@
 void a2dp_vendor_aptx_hd_feeding_flush(void);
 
 // Get the A2DP aptX-HD encoder interval (in milliseconds).
-period_ms_t a2dp_vendor_aptx_hd_get_encoder_interval_ms(void);
+uint64_t a2dp_vendor_aptx_hd_get_encoder_interval_ms(void);
 
 // Prepare and send A2DP aptX-HD encoded frames.
 // |timestamp_us| is the current timestamp (in microseconds).
diff --git a/stack/include/a2dp_vendor_ldac.h b/stack/include/a2dp_vendor_ldac.h
index ccb5d1e..9b1958f 100644
--- a/stack/include/a2dp_vendor_ldac.h
+++ b/stack/include/a2dp_vendor_ldac.h
@@ -25,20 +25,33 @@
 #include "a2dp_vendor_ldac_constants.h"
 #include "avdt_api.h"
 
-class A2dpCodecConfigLdac : public A2dpCodecConfig {
- public:
-  A2dpCodecConfigLdac(btav_a2dp_codec_priority_t codec_priority);
-  virtual ~A2dpCodecConfigLdac();
-
-  bool init() override;
-  period_ms_t encoderIntervalMs() const override;
-  int getEffectiveMtu() const override;
+class A2dpCodecConfigLdacBase : public A2dpCodecConfig {
+ protected:
+  A2dpCodecConfigLdacBase(btav_a2dp_codec_index_t codec_index,
+                          const std::string& name,
+                          btav_a2dp_codec_priority_t codec_priority,
+                          bool is_source)
+      : A2dpCodecConfig(codec_index, name, codec_priority),
+        is_source_(is_source) {}
   bool setCodecConfig(const uint8_t* p_peer_codec_info, bool is_capability,
                       uint8_t* p_result_codec_config) override;
   bool setPeerCodecCapabilities(
       const uint8_t* p_peer_codec_capabilities) override;
 
  private:
+  bool is_source_;  // True if local is Source
+};
+
+class A2dpCodecConfigLdacSource : public A2dpCodecConfigLdacBase {
+ public:
+  A2dpCodecConfigLdacSource(btav_a2dp_codec_priority_t codec_priority);
+  virtual ~A2dpCodecConfigLdacSource();
+
+  bool init() override;
+  uint64_t encoderIntervalMs() const override;
+  int getEffectiveMtu() const override;
+
+ private:
   bool useRtpHeaderMarkerBit() const override;
   bool updateEncoderUserConfig(
       const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
@@ -47,6 +60,23 @@
   void debug_codec_dump(int fd) override;
 };
 
+class A2dpCodecConfigLdacSink : public A2dpCodecConfigLdacBase {
+ public:
+  A2dpCodecConfigLdacSink(btav_a2dp_codec_priority_t codec_priority);
+  virtual ~A2dpCodecConfigLdacSink();
+
+  bool init() override;
+  uint64_t encoderIntervalMs() const override;
+  int getEffectiveMtu() const override;
+
+ private:
+  bool useRtpHeaderMarkerBit() const override;
+  bool updateEncoderUserConfig(
+      const tA2DP_ENCODER_INIT_PEER_PARAMS* p_peer_params,
+      bool* p_restart_input, bool* p_restart_output,
+      bool* p_config_updated) override;
+};
+
 // Checks whether the codec capabilities contain a valid A2DP LDAC Source
 // codec.
 // NOTE: only codecs that are implemented are considered valid.
@@ -54,6 +84,13 @@
 // codec, otherwise false.
 bool A2DP_IsVendorSourceCodecValidLdac(const uint8_t* p_codec_info);
 
+// Checks whether the codec capabilities contain a valid A2DP LDAC Sink
+// codec.
+// NOTE: only codecs that are implemented are considered valid.
+// Returns true if |p_codec_info| contains information about a valid LDAC
+// codec, otherwise false.
+bool A2DP_IsVendorSinkCodecValidLdac(const uint8_t* p_codec_info);
+
 // Checks whether the codec capabilities contain a valid peer A2DP LDAC Sink
 // codec.
 // NOTE: only codecs that are implemented are considered valid.
@@ -61,6 +98,26 @@
 // codec, otherwise false.
 bool A2DP_IsVendorPeerSinkCodecValidLdac(const uint8_t* p_codec_info);
 
+// Checks whether the codec capabilities contain a valid peer A2DP LDAC Source
+// codec.
+// NOTE: only codecs that are implemented are considered valid.
+// Returns true if |p_codec_info| contains information about a valid LDAC
+// codec, otherwise false.
+bool A2DP_IsVendorPeerSourceCodecValidLdac(const uint8_t* p_codec_info);
+
+// Checks whether A2DP LDAC Sink codec is supported.
+// |p_codec_info| contains information about the codec capabilities.
+// Returns true if the A2DP LDAC Sink codec is supported, otherwise false.
+bool A2DP_IsVendorSinkCodecSupportedLdac(const uint8_t* p_codec_info);
+
+// Checks whether an A2DP LDAC Source codec for a peer Source device is
+// supported.
+// |p_codec_info| contains information about the codec capabilities of the
+// peer device.
+// Returns true if the A2DP LDAC Source codec for a peer Source device is
+// supported, otherwise false.
+bool A2DP_IsPeerSourceCodecSupportedLdac(const uint8_t* p_codec_info);
+
 // Checks whether the A2DP data packets should contain RTP header.
 // |content_protection_enabled| is true if Content Protection is
 // enabled. |p_codec_info| contains information about the codec capabilities.
@@ -91,6 +148,12 @@
 // contains invalid codec information.
 int A2DP_VendorGetTrackSampleRateLdac(const uint8_t* p_codec_info);
 
+// Gets the track bits per sample value for the A2DP LDAC codec.
+// |p_codec_info| is a pointer to the LDAC codec_info to decode.
+// Returns the track bits per sample on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetTrackBitsPerSampleLdac(const uint8_t* p_codec_info);
+
 // Gets the track bitrate value for the A2DP LDAC codec.
 // |p_codec_info| is a pointer to the LDAC codec_info to decode.
 // Returns the track sample rate on success, or -1 if |p_codec_info|
@@ -103,6 +166,13 @@
 // contains invalid codec information.
 int A2DP_VendorGetTrackChannelCountLdac(const uint8_t* p_codec_info);
 
+// Gets the channel type for the A2DP LDAC codec.
+// 1 for mono, or 3 for dual channel/stereo.
+// |p_codec_info| is a pointer to the LDAC codec_info to decode.
+// Returns the channel count on success, or -1 if |p_codec_info|
+// contains invalid codec information.
+int A2DP_VendorGetSinkTrackChannelTypeLdac(const uint8_t* p_codec_info);
+
 // Gets the channel mode code for the A2DP LDAC codec.
 // The actual value is codec-specific - see |A2DP_LDAC_CHANNEL_MODE_*|.
 // |p_codec_info| is a pointer to the LDAC codec_info to decode.
@@ -140,6 +210,14 @@
 const tA2DP_ENCODER_INTERFACE* A2DP_VendorGetEncoderInterfaceLdac(
     const uint8_t* p_codec_info);
 
+// Gets the current A2DP LDAC decoder interface that can be used to decode
+// received A2DP packets - see |tA2DP_DECODER_INTERFACE|.
+// |p_codec_info| contains the codec information.
+// Returns the A2DP LDAC decoder interface if the |p_codec_info| is valid and
+// supported, otherwise NULL.
+const tA2DP_DECODER_INTERFACE* A2DP_VendorGetDecoderInterfaceLdac(
+    const uint8_t* p_codec_info);
+
 // Adjusts the A2DP LDAC codec, based on local support and Bluetooth
 // specification.
 // |p_codec_info| contains the codec information to adjust.
@@ -152,11 +230,24 @@
 btav_a2dp_codec_index_t A2DP_VendorSourceCodecIndexLdac(
     const uint8_t* p_codec_info);
 
+// Gets the A2DP LDAC Sink codec index for a given |p_codec_info|.
+// Returns the corresponding |btav_a2dp_codec_index_t| on success,
+// otherwise |BTAV_A2DP_CODEC_INDEX_MAX|.
+btav_a2dp_codec_index_t A2DP_VendorSinkCodecIndexLdac(
+    const uint8_t* p_codec_info);
+
 // Gets the A2DP LDAC Source codec name.
 const char* A2DP_VendorCodecIndexStrLdac(void);
 
+// Gets the A2DP LDAC Sink codec name.
+const char* A2DP_VendorCodecIndexStrLdacSink(void);
+
 // Initializes A2DP LDAC Source codec information into |AvdtpSepConfig|
 // configuration entry pointed by |p_cfg|.
 bool A2DP_VendorInitCodecConfigLdac(AvdtpSepConfig* p_cfg);
 
+// Initializes A2DP LDAC Sink codec information into |AvdtpSepConfig|
+// configuration entry pointed by |p_cfg|.
+bool A2DP_VendorInitCodecConfigLdacSink(AvdtpSepConfig* p_cfg);
+
 #endif  // A2DP_VENDOR_LDAC_H
diff --git a/stack/include/a2dp_vendor_ldac_decoder.h b/stack/include/a2dp_vendor_ldac_decoder.h
new file mode 100644
index 0000000..2a05baa
--- /dev/null
+++ b/stack/include/a2dp_vendor_ldac_decoder.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+//
+// Interface to the A2DP LDAC Decoder
+//
+
+#ifndef A2DP_VENDOR_LDAC_DECODER_H
+#define A2DP_VENDOR_LDAC_DECODER_H
+
+#include "a2dp_codec_api.h"
+
+// Loads the A2DP LDAC decoder.
+// Return true on success, otherwise false.
+bool A2DP_VendorLoadDecoderLdac(void);
+
+// Unloads the A2DP LDAC decoder.
+void A2DP_VendorUnloadDecoderLdac(void);
+
+// Initialize the A2DP LDAC decoder.
+bool a2dp_vendor_ldac_decoder_init(decoded_data_callback_t decode_callback);
+
+// Cleanup the A2DP LDAC decoder.
+void a2dp_vendor_ldac_decoder_cleanup(void);
+
+// Decodes |p_buf|. Calls |decode_callback| passed into
+// |a2dp_vendor_ldac_decoder_init| if decoded frames are available.
+bool a2dp_vendor_ldac_decoder_decode_packet(BT_HDR* p_buf);
+
+#endif  // A2DP_VENDOR_LDAC_DECODER_H
diff --git a/stack/include/a2dp_vendor_ldac_encoder.h b/stack/include/a2dp_vendor_ldac_encoder.h
index 810f03b..f5e320a 100644
--- a/stack/include/a2dp_vendor_ldac_encoder.h
+++ b/stack/include/a2dp_vendor_ldac_encoder.h
@@ -22,7 +22,6 @@
 #define A2DP_VENDOR_LDAC_ENCODER_H
 
 #include "a2dp_codec_api.h"
-#include "osi/include/time.h"
 
 // Loads the A2DP LDAC encoder.
 // Return true on success, otherwise false.
@@ -52,7 +51,7 @@
 void a2dp_vendor_ldac_feeding_flush(void);
 
 // Get the A2DP LDAC encoder interval (in milliseconds).
-period_ms_t a2dp_vendor_ldac_get_encoder_interval_ms(void);
+uint64_t a2dp_vendor_ldac_get_encoder_interval_ms(void);
 
 // Prepare and send A2DP LDAC encoded frames.
 // |timestamp_us| is the current timestamp (in microseconds).
diff --git a/stack/include/advertise_data_parser.h b/stack/include/advertise_data_parser.h
index b62dbb3..a1ac17b 100644
--- a/stack/include/advertise_data_parser.h
+++ b/stack/include/advertise_data_parser.h
@@ -34,7 +34,8 @@
     auto data_start = ad.begin() + position;
 
     // Traxxas - bad name length
-    if (std::equal(data_start, data_start + 3, trx_quirk.begin()) &&
+    if ((ad.size() - position) >= 18 &&
+        std::equal(data_start, data_start + 3, trx_quirk.begin()) &&
         std::equal(data_start + 5, data_start + 11, trx_quirk.begin() + 5) &&
         std::equal(data_start + 12, data_start + 18, trx_quirk.begin() + 12)) {
       return true;
diff --git a/stack/include/avdt_api.h b/stack/include/avdt_api.h
index fd0721c..09e7f7c 100644
--- a/stack/include/avdt_api.h
+++ b/stack/include/avdt_api.h
@@ -71,6 +71,9 @@
 */
 #define AVDT_MARKER_SET 0x80
 
+#define MAX_2MBPS_AVDTP_MTU 663   // 2DH5 MTU=679, -12 for AVDTP, -4 for L2CAP
+#define MAX_3MBPS_AVDTP_MTU 1005  // 3DH5 MTU=1021, -12 for AVDTP, -4 for L2CAP
+
 /* SEP Type.  This indicates the stream endpoint type. */
 #define AVDT_TSEP_SRC 0     /* Source SEP */
 #define AVDT_TSEP_SNK 1     /* Sink SEP */
diff --git a/stack/include/avrc_api.h b/stack/include/avrc_api.h
index 1aa8ea4..77c37de 100644
--- a/stack/include/avrc_api.h
+++ b/stack/include/avrc_api.h
@@ -24,13 +24,13 @@
 #ifndef AVRC_API_H
 #define AVRC_API_H
 
-#include <base/bind.h>
-
 #include "avct_api.h"
 #include "avrc_defs.h"
 #include "bt_target.h"
 #include "sdp_api.h"
 
+#include <base/callback.h>
+
 /*****************************************************************************
  *  constants
  ****************************************************************************/
diff --git a/stack/include/bt_types.h b/stack/include/bt_types.h
index 3c479af..7804328 100644
--- a/stack/include/bt_types.h
+++ b/stack/include/bt_types.h
@@ -21,7 +21,6 @@
 
 #include <stdbool.h>
 #include <stdint.h>
-#include <string.h>
 
 #ifndef FALSE
 #define FALSE false
@@ -562,15 +561,30 @@
 #define BT_OCTET8_LEN 8
 typedef uint8_t BT_OCTET8[BT_OCTET8_LEN]; /* octet array: size 16 */
 
-#define LINK_KEY_LEN 16
-typedef uint8_t LINK_KEY[LINK_KEY_LEN]; /* Link Key */
-
 #define AMP_LINK_KEY_LEN 32
 typedef uint8_t
     AMP_LINK_KEY[AMP_LINK_KEY_LEN]; /* Dedicated AMP and GAMP Link Keys */
 
-#define BT_OCTET16_LEN 16
-typedef uint8_t BT_OCTET16[BT_OCTET16_LEN]; /* octet array: size 16 */
+/* Some C files include this header file */
+#ifdef __cplusplus
+
+#include <array>
+
+constexpr int OCTET16_LEN = 16;
+typedef std::array<uint8_t, OCTET16_LEN> Octet16;
+
+constexpr int LINK_KEY_LEN = OCTET16_LEN;
+typedef Octet16 LinkKey; /* Link Key */
+
+/* Sample LTK from BT Spec 5.1 | Vol 6, Part C 1
+ * 0x4C68384139F574D836BCF34E9DFB01BF */
+constexpr Octet16 SAMPLE_LTK = {0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
+                                0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c};
+inline bool is_sample_ltk(const Octet16& ltk) {
+  return ltk == SAMPLE_LTK;
+}
+
+#endif
 
 #define PIN_CODE_LEN 16
 typedef uint8_t PIN_CODE[PIN_CODE_LEN]; /* Pin Code (upto 128 bits) MSB is 0 */
@@ -814,7 +828,7 @@
 #define TRACE_LAYER_A2DP 0x00210000
 #define TRACE_LAYER_SAP 0x00220000
 #define TRACE_LAYER_AMP 0x00230000
-#define TRACE_LAYER_MCA 0x00240000
+#define TRACE_LAYER_MCA 0x00240000 /* OBSOLETED */
 #define TRACE_LAYER_ATT 0x00250000
 #define TRACE_LAYER_SMP 0x00260000
 #define TRACE_LAYER_NFC 0x00270000
@@ -926,12 +940,4 @@
 /* Define a function for logging */
 typedef void(BT_LOG_FUNC)(int trace_type, const char* fmt_str, ...);
 
-static inline bool is_sample_ltk(const BT_OCTET16 ltk) {
-  /* Sample LTK from BT Spec 5.1 | Vol 6, Part C 1
-   * 0x4C68384139F574D836BCF34E9DFB01BF */
-  const uint8_t SAMPLE_LTK[] = {0xbf, 0x01, 0xfb, 0x9d, 0x4e, 0xf3, 0xbc, 0x36,
-                                0xd8, 0x74, 0xf5, 0x39, 0x41, 0x38, 0x68, 0x4c};
-  return memcmp(ltk, SAMPLE_LTK, BT_OCTET16_LEN) == 0;
-}
-
 #endif
diff --git a/stack/include/btm_api.h b/stack/include/btm_api.h
index 6ffc0f9..df4cbe0 100644
--- a/stack/include/btm_api.h
+++ b/stack/include/btm_api.h
@@ -1407,7 +1407,7 @@
  ******************************************************************************/
 extern bool BTM_SecAddDevice(const RawAddress& bd_addr, DEV_CLASS dev_class,
                              BD_NAME bd_name, uint8_t* features,
-                             uint32_t trusted_mask[], LINK_KEY link_key,
+                             uint32_t trusted_mask[], LinkKey* link_key,
                              uint8_t key_type, tBTM_IO_CAP io_cap,
                              uint8_t pin_length);
 
@@ -1446,7 +1446,7 @@
  *
  ******************************************************************************/
 extern tBTM_STATUS BTM_SecGetDeviceLinkKey(const RawAddress& bd_addr,
-                                           LINK_KEY link_key);
+                                           LinkKey* link_key);
 
 /*******************************************************************************
  *
@@ -1662,7 +1662,7 @@
  *
  ******************************************************************************/
 extern void BTM_RemoteOobDataReply(tBTM_STATUS res, const RawAddress& bd_addr,
-                                   BT_OCTET16 c, BT_OCTET16 r);
+                                   const Octet16& c, const Octet16& r);
 
 /*******************************************************************************
  *
@@ -1683,7 +1683,8 @@
  *
  ******************************************************************************/
 extern uint16_t BTM_BuildOobData(uint8_t* p_data, uint16_t max_len,
-                                 BT_OCTET16 c, BT_OCTET16 r, uint8_t name_len);
+                                 const Octet16& c, const Octet16& r,
+                                 uint8_t name_len);
 
 /*******************************************************************************
  *
diff --git a/stack/include/btm_api_types.h b/stack/include/btm_api_types.h
index 8cc9485..965087c 100644
--- a/stack/include/btm_api_types.h
+++ b/stack/include/btm_api_types.h
@@ -1332,8 +1332,8 @@
 */
 typedef uint8_t(tBTM_LINK_KEY_CALLBACK)(const RawAddress& bd_addr,
                                         DEV_CLASS dev_class,
-                                        tBTM_BD_NAME bd_name, uint8_t* key,
-                                        uint8_t key_type);
+                                        tBTM_BD_NAME bd_name,
+                                        const LinkKey& key, uint8_t key_type);
 
 /* Remote Name Resolved.  Parameters are
  *              BD Address of remote
@@ -1480,8 +1480,8 @@
 /* data type for BTM_SP_LOC_OOB_EVT */
 typedef struct {
   tBTM_STATUS status; /* */
-  BT_OCTET16 c;       /* Simple Pairing Hash C */
-  BT_OCTET16 r;       /* Simple Pairing Randomnizer R */
+  Octet16 c;          /* Simple Pairing Hash C */
+  Octet16 r;          /* Simple Pairing Randomnizer R */
 } tBTM_SP_LOC_OOB;
 
 /* data type for BTM_SP_RMT_OOB_EVT */
@@ -1631,7 +1631,7 @@
 
 /* BLE encryption keys */
 typedef struct {
-  BT_OCTET16 ltk;
+  Octet16 ltk;
   BT_OCTET8 rand;
   uint16_t ediv;
   uint8_t sec_level;
@@ -1641,13 +1641,13 @@
 /* BLE CSRK keys */
 typedef struct {
   uint32_t counter;
-  BT_OCTET16 csrk;
+  Octet16 csrk;
   uint8_t sec_level;
 } tBTM_LE_PCSRK_KEYS;
 
 /* BLE Encryption reproduction keys */
 typedef struct {
-  BT_OCTET16 ltk;
+  Octet16 ltk;
   uint16_t div;
   uint8_t key_size;
   uint8_t sec_level;
@@ -1658,13 +1658,13 @@
   uint32_t counter;
   uint16_t div;
   uint8_t sec_level;
-  BT_OCTET16 csrk;
+  Octet16 csrk;
 } tBTM_LE_LCSRK_KEYS;
 
 typedef struct {
-  BT_OCTET16 irk;
-  tBLE_ADDR_TYPE addr_type;
-  RawAddress static_addr;
+  Octet16 irk;
+  tBLE_ADDR_TYPE identity_addr_type;
+  RawAddress identity_addr;
 } tBTM_LE_PID_KEYS;
 
 typedef union {
@@ -1704,15 +1704,15 @@
 #define BTM_BLE_KEY_TYPE_COUNTER 3  // tobe obsolete
 
 typedef struct {
-  BT_OCTET16 ir;
-  BT_OCTET16 irk;
-  BT_OCTET16 dhk;
+  Octet16 ir;
+  Octet16 irk;
+  Octet16 dhk;
 
 } tBTM_BLE_LOCAL_ID_KEYS;
 
 typedef union {
   tBTM_BLE_LOCAL_ID_KEYS id_keys;
-  BT_OCTET16 er;
+  Octet16 er;
 } tBTM_BLE_LOCAL_KEYS;
 
 /* New LE identity key for local device.
@@ -1808,63 +1808,6 @@
 
 } tBTM_DELETE_STORED_LINK_KEY_COMPLETE;
 
-/* MIP evnets, callbacks    */
-enum {
-  BTM_MIP_MODE_CHG_EVT,
-  BTM_MIP_DISCONNECT_EVT,
-  BTM_MIP_PKTS_COMPL_EVT,
-  BTM_MIP_RXDATA_EVT
-};
-typedef uint8_t tBTM_MIP_EVT;
-
-typedef struct {
-  tBTM_MIP_EVT event;
-  RawAddress bd_addr;
-  uint16_t mip_id;
-} tBTM_MIP_MODE_CHANGE;
-
-typedef struct {
-  tBTM_MIP_EVT event;
-  uint16_t mip_id;
-  uint8_t disc_reason;
-} tBTM_MIP_CONN_TIMEOUT;
-
-#define BTM_MIP_MAX_RX_LEN 17
-
-typedef struct {
-  tBTM_MIP_EVT event;
-  uint16_t mip_id;
-  uint8_t rx_len;
-  uint8_t rx_data[BTM_MIP_MAX_RX_LEN];
-} tBTM_MIP_RXDATA;
-
-typedef struct {
-  tBTM_MIP_EVT event;
-  RawAddress bd_addr;
-  uint8_t data[11]; /* data[0] shows Vender-specific device type */
-} tBTM_MIP_EIR_HANDSHAKE;
-
-typedef struct {
-  tBTM_MIP_EVT event;
-  uint16_t num_sent; /* Completed packet count at the controller */
-} tBTM_MIP_PKTS_COMPL;
-
-typedef union {
-  tBTM_MIP_EVT event;
-  tBTM_MIP_MODE_CHANGE mod_chg;
-  tBTM_MIP_CONN_TIMEOUT conn_tmo;
-  tBTM_MIP_EIR_HANDSHAKE eir;
-  tBTM_MIP_PKTS_COMPL completed;
-  tBTM_MIP_RXDATA rxdata;
-} tBTM_MIP_EVENT_DATA;
-
-/* MIP event callback function  */
-typedef void(tBTM_MIP_EVENTS_CB)(tBTM_MIP_EVT event, tBTM_MIP_EVENT_DATA data);
-
-/* MIP Device query callback function  */
-typedef bool(tBTM_MIP_QUERY_CB)(const RawAddress& dev_addr, uint8_t* p_mode,
-                                LINK_KEY link_key);
-
 /* ACL link on, SCO link ongoing, sniff mode */
 #define BTM_CONTRL_ACTIVE 1
 /* Scan state - paging/inquiry/trying to connect*/
diff --git a/stack/include/btm_ble_api.h b/stack/include/btm_ble_api.h
index c8ffa5e..5bf325a 100644
--- a/stack/include/btm_ble_api.h
+++ b/stack/include/btm_ble_api.h
@@ -77,22 +77,6 @@
 
 /*******************************************************************************
  *
- * Function         BTM_BleSetAdvParams
- *
- * Description      This function is called to set advertising parameters.
- *
- * Parameters:       None.
- *
- * Returns          void
- *
- ******************************************************************************/
-extern tBTM_STATUS BTM_BleSetAdvParams(uint16_t adv_int_min,
-                                       uint16_t adv_int_max,
-                                       tBLE_BD_ADDR* p_dir_bda,
-                                       tBTM_BLE_ADV_CHNL_MAP chnl_map);
-
-/*******************************************************************************
- *
  * Function         BTM_BleObtainVendorCapabilities
  *
  * Description      This function is called to obatin vendor capabilties
@@ -196,43 +180,14 @@
                                   tBTM_INQ_RESULTS_CB* p_results_cb,
                                   tBTM_CMPL_CB* p_cmpl_cb);
 
-/*******************************************************************************
- *
- * Function         BTM_GetDeviceIDRoot
- *
- * Description      This function is called to read the local device identity
- *                  root.
- *
- * Returns          void
- *                  the local device ER is copied into er
- *
- ******************************************************************************/
-extern void BTM_GetDeviceIDRoot(BT_OCTET16 ir);
+/** Returns local device encryption root (ER) */
+const Octet16& BTM_GetDeviceEncRoot();
 
-/*******************************************************************************
- *
- * Function         BTM_GetDeviceEncRoot
- *
- * Description      This function is called to read the local device encryption
- *                  root.
- *
- * Returns          void
- *                  the local device ER is copied into er
- *
- ******************************************************************************/
-extern void BTM_GetDeviceEncRoot(BT_OCTET16 er);
+/** Returns local device identity root (IR) */
+extern const Octet16& BTM_GetDeviceIDRoot();
 
-/*******************************************************************************
- *
- * Function         BTM_GetDeviceDHK
- *
- * Description      This function is called to read the local device DHK.
- *
- * Returns          void
- *                  the local device DHK is copied into dhk
- *
- ******************************************************************************/
-extern void BTM_GetDeviceDHK(BT_OCTET16 dhk);
+/** Return local device DHK. */
+extern const Octet16& BTM_GetDeviceDHK();
 
 /*******************************************************************************
  *
@@ -405,44 +360,7 @@
  ******************************************************************************/
 extern void BTM_BleLoadLocalKeys(uint8_t key_type, tBTM_BLE_LOCAL_KEYS* p_key);
 
-/**
- * Set BLE connectable mode to auto connect
- */
-extern void BTM_BleStartAutoConn();
-
-/*******************************************************************************
- *
- * Function         BTM_BleUpdateBgConnDev
- *
- * Description      This function is called to add or remove a device into/from
- *                  background connection procedure. The background connection
-*                   procedure is decided by the background connection type, it
-*can be
-*                   auto connection, or selective connection.
- *
- * Parameters       add_remove: true to add; false to remove.
- *                  remote_bda: device address to add/remove.
- *
- * Returns          void
- *
- ******************************************************************************/
-extern bool BTM_BleUpdateBgConnDev(bool add_remove,
-                                   const RawAddress& remote_bda);
-
-/*******************************************************************************
- *
- * Function         BTM_BleClearBgConnDev
- *
- * Description      This function is called to clear the whitelist,
- *                  end any pending whitelist connections,
- *                  and reset the local bg device list.
- *
- * Parameters       void
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void BTM_BleClearBgConnDev(void);
+#include "stack/btm/btm_ble_bgconn.h"
 
 /********************************************************
  *
diff --git a/stack/include/btm_ble_api_types.h b/stack/include/btm_ble_api_types.h
index 327a2e6..9f0201c 100644
--- a/stack/include/btm_ble_api_types.h
+++ b/stack/include/btm_ble_api_types.h
@@ -135,7 +135,7 @@
 #define BTM_BLE_CONN_SUP_TOUT_MAX 0x0C80
 /* use this value when a specific value not to be overwritten */
 #define BTM_BLE_CONN_PARAM_UNDEF 0xffff
-#define BTM_BLE_SCAN_PARAM_UNDEF 0xffffffff
+#define BTM_BLE_SCAN_PARAM_UNDEF 0xffff
 
 /* default connection parameters if not configured, use GAP recommended value
  * for auto/selective connection */
@@ -203,13 +203,6 @@
 #define BTM_BLE_CONN_INT_MIN_HEARINGAID 0x0010
 #endif
 
-#define BTM_BLE_DIR_CONN_FALLBACK_UNDIR 1
-#define BTM_BLE_DIR_CONN_FALLBACK_NO_ADV 2
-
-#ifndef BTM_BLE_DIR_CONN_FALLBACK
-#define BTM_BLE_DIR_CONN_FALLBACK BTM_BLE_DIR_CONN_FALLBACK_UNDIR
-#endif
-
 #define BTM_CMAC_TLEN_SIZE 8 /* 64 bits */
 #define BTM_BLE_AUTH_SIGN_LEN \
   12 /* BLE data signature length 8 Bytes + 4 bytes counter*/
@@ -279,7 +272,7 @@
   uint8_t status;
   uint8_t param_len;
   uint16_t opcode;
-  uint8_t param_buf[BT_OCTET16_LEN];
+  uint8_t param_buf[OCTET16_LEN];
 } tBTM_RAND_ENC;
 
 /* General callback function for notifying an application that a synchronous
@@ -335,7 +328,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 in dBm */
 typedef struct {
@@ -494,9 +488,6 @@
 typedef uint8_t BTM_BLE_RSSI_VALUE;
 typedef uint16_t BTM_BLE_ADV_INFO_TIMESTAMP;
 
-enum { BTM_BLE_CONN_NONE, BTM_BLE_CONN_AUTO };
-typedef uint8_t tBTM_BLE_CONN_TYPE;
-
 #define ADV_INFO_PRESENT 0x00
 #define NO_ADV_INFO_PRESENT 0x01
 
diff --git a/stack/include/btu.h b/stack/include/btu.h
index 5841efa..77d5051 100644
--- a/stack/include/btu.h
+++ b/stack/include/btu.h
@@ -27,12 +27,14 @@
 #ifndef BTU_H
 #define BTU_H
 
+#include "bt_common.h"
+#include "bt_target.h"
+#include "common/message_loop_thread.h"
+#include "osi/include/alarm.h"
+
 #include <base/callback.h>
 #include <base/location.h>
 #include <base/threading/thread.h>
-#include "bt_common.h"
-#include "bt_target.h"
-#include "osi/include/alarm.h"
 
 /* Global BTU data */
 extern uint8_t btu_trace_level;
@@ -42,10 +44,10 @@
 */
 void btu_hcif_process_event(uint8_t controller_id, BT_HDR* p_buf);
 void btu_hcif_send_cmd(uint8_t controller_id, BT_HDR* p_msg);
-void btu_hcif_send_cmd_with_cb(const tracked_objects::Location& posted_from,
+void btu_hcif_send_cmd_with_cb(const base::Location& posted_from,
                                uint16_t opcode, uint8_t* params,
                                uint8_t params_len,
-                               base::Callback<void(uint8_t*, uint16_t)> cb);
+                               base::OnceCallback<void(uint8_t*, uint16_t)> cb);
 
 /* Functions provided by btu_init.cc
  ***********************************
@@ -56,7 +58,10 @@
 /* Functions provided by btu_task.cc
  ***********************************
 */
-base::MessageLoop* get_message_loop();
+bluetooth::common::MessageLoopThread* get_main_thread();
+base::MessageLoop* get_main_message_loop();
+bt_status_t do_in_main_thread(const base::Location& from_here,
+                              base::OnceClosure task);
 
 void BTU_StartUp(void);
 void BTU_ShutDown(void);
diff --git a/stack/include/gatt_api.h b/stack/include/gatt_api.h
index f9c0642..069a179 100644
--- a/stack/include/gatt_api.h
+++ b/stack/include/gatt_api.h
@@ -410,14 +410,6 @@
 };
 typedef uint8_t tGATT_DISC_TYPE;
 
-/* Discover parameters of different discovery types
-*/
-typedef struct {
-  bluetooth::Uuid service;
-  uint16_t s_handle;
-  uint16_t e_handle;
-} tGATT_DISC_PARAM;
-
 /* GATT read type enumeration
 */
 enum {
@@ -825,13 +817,19 @@
  *
  * Parameters       conn_id: connection identifier.
  *                  disc_type:discovery type.
- *                  p_param: parameters of discovery requirement.
+ *                  start_handle and end_handle: range of handles for discovery
+ *                  uuid: uuid to discovery. set to Uuid::kEmpty for requests
+ *                        that don't need it
  *
  * Returns          GATT_SUCCESS if command received/sent successfully.
  *
  ******************************************************************************/
 extern tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
-                                   tGATT_DISC_PARAM* p_param);
+                                   uint16_t start_handle, uint16_t end_handle,
+                                   const bluetooth::Uuid& uuid);
+extern tGATT_STATUS GATTC_Discover(uint16_t conn_id, tGATT_DISC_TYPE disc_type,
+                                   uint16_t start_handle, uint16_t end_handle);
+
 /*******************************************************************************
  *
  * Function         GATTC_Read
@@ -1084,7 +1082,8 @@
 // initiated outside GATT.
 extern void gatt_notify_enc_cmpl(const RawAddress& bd_addr);
 
-// Reset bg device list.
-extern void gatt_reset_bgdev_list(void);
+/** Reset bg device list. If called after controller reset, set |after_reset| to
+ * true, as there is no need to wipe controller white list in this case. */
+extern void gatt_reset_bgdev_list(bool after_reset);
 
 #endif /* GATT_API_H */
diff --git a/stack/include/gattdefs.h b/stack/include/gattdefs.h
index 5f5093d..186542c 100644
--- a/stack/include/gattdefs.h
+++ b/stack/include/gattdefs.h
@@ -28,7 +28,7 @@
 #define GATT_ILLEGAL_UUID 0
 
 /* GATT attribute types
-*/
+ */
 #define GATT_UUID_PRI_SERVICE 0x2800
 #define GATT_UUID_SEC_SERVICE 0x2801
 #define GATT_UUID_INCLUDE_SERVICE 0x2802
@@ -52,8 +52,12 @@
 #define GATT_UUID_EXT_RPT_REF_DESCR 0x2907
 #define GATT_UUID_RPT_REF_DESCR 0x2908
 
+/*  Client Characteristic Configuration bits */
+#define GATT_CHAR_CLIENT_CONFIG_NOTIFICATION 0x0001
+#define GATT_CHAR_CLIENT_CONFIG_INDICTION 0x0002
+
 /* GAP Profile Attributes
-*/
+ */
 #define GATT_UUID_GAP_DEVICE_NAME 0x2A00
 #define GATT_UUID_GAP_ICON 0x2A01
 #define GATT_UUID_GAP_PREF_CONN_PARAM 0x2A04
diff --git a/stack/include/hcidefs.h b/stack/include/hcidefs.h
index 8f91743..ef87b5b 100644
--- a/stack/include/hcidefs.h
+++ b/stack/include/hcidefs.h
@@ -423,6 +423,9 @@
 /* A2DP offload OCF */
 #define HCI_CONTROLLER_A2DP_OPCODE_OCF (0x015D | HCI_GRP_VENDOR_SPECIFIC)
 
+/* Bluetooth Quality Report OCF */
+#define HCI_CONTROLLER_BQR_OPCODE_OCF (0x015E | HCI_GRP_VENDOR_SPECIFIC)
+
 /* subcode for multi adv feature */
 #define BTM_BLE_MULTI_ADV_SET_PARAM 0x01
 #define BTM_BLE_MULTI_ADV_WRITE_ADV_DATA 0x02
@@ -449,6 +452,9 @@
 /* debug info sub event */
 #define HCI_VSE_SUBCODE_DEBUG_INFO_SUB_EVT 0x57
 
+/* Bluetooth Quality Report sub event */
+#define HCI_VSE_SUBCODE_BQR_SUB_EVT 0x58
+
 /* LE supported states definition */
 #define HCI_LE_ADV_STATE 0x00000001
 #define HCI_LE_SCAN_STATE 0x00000002
@@ -788,12 +794,7 @@
     0x0000000000200000 Connectionless Broadcast Channel Map Change Event
     0x0000000000400000 Inquiry Response Notification Event
 */
-#if (BLE_PRIVACY_SPT == TRUE)
-/* BLE event mask */
-#define HCI_BLE_EVENT_MASK_DEF "\x00\x00\x00\x00\x00\x00\x07\xff"
-#else
-#define HCI_BLE_EVENT_MASK_DEF "\x00\x00\x00\x00\x00\x00\x00\x7f"
-#endif
+
 /*
  * Definitions for packet type masks (BT1.2 and BT2.0 definitions)
 */
diff --git a/stack/include/hcimsgs.h b/stack/include/hcimsgs.h
index 63ea8f4..285ae41 100644
--- a/stack/include/hcimsgs.h
+++ b/stack/include/hcimsgs.h
@@ -89,10 +89,8 @@
 #define HCI_DISC_REASON_OFF 2
 /* Disconnect */
 
-#if (BTM_SCO_INCLUDED == TRUE)
 /* Add SCO Connection */
 extern void btsnd_hcic_add_SCO_conn(uint16_t handle, uint16_t packet_types);
-#endif /* BTM_SCO_INCLUDED */
 
 #define HCIC_PARAM_SIZE_ADD_SCO_CONN 4
 
@@ -128,7 +126,7 @@
 
 /* Link Key Request Reply */
 extern void btsnd_hcic_link_key_req_reply(const RawAddress& bd_addr,
-                                          LINK_KEY link_key);
+                                          const LinkKey& link_key);
 
 #define HCIC_PARAM_SIZE_LINK_KEY_REQ_REPLY 22
 
@@ -428,8 +426,8 @@
 #define HCI_USER_PASSKEY_NEG_BD_ADDR_OFF 0
 
 /* Remote OOB Data Request Reply */
-extern void btsnd_hcic_rem_oob_reply(const RawAddress& bd_addr, uint8_t* p_c,
-                                     uint8_t* p_r);
+extern void btsnd_hcic_rem_oob_reply(const RawAddress& bd_addr,
+                                     const Octet16& c, const Octet16& r);
 
 #define HCIC_PARAM_SIZE_REM_OOB_REPLY 38
 
@@ -613,8 +611,7 @@
 extern void btsnd_hcic_get_link_quality(uint16_t handle); /* Get Link Quality */
 extern void btsnd_hcic_read_rssi(uint16_t handle);        /* Read RSSI */
 using ReadEncKeySizeCb = base::OnceCallback<void(uint8_t, uint16_t, uint8_t)>;
-extern void btsnd_hcic_read_encryption_key_size(uint16_t handle,
-                                                ReadEncKeySizeCb cb);
+extern void btsnd_hcic_read_encryption_key_size(uint16_t handle, ReadEncKeySizeCb cb);
 extern void btsnd_hcic_read_failed_contact_counter(uint16_t handle);
 extern void btsnd_hcic_read_automatic_flush_timeout(uint16_t handle);
 extern void btsnd_hcic_enable_test_mode(
@@ -670,7 +667,6 @@
  *             message size
  ******************************************************************************/
 #define HCIC_BLE_RAND_DI_SIZE 8
-#define HCIC_BLE_ENCRYT_KEY_SIZE 16
 #define HCIC_BLE_IRK_SIZE 16
 
 #define HCIC_PARAM_SIZE_SET_USED_FEAT_CMD 8
@@ -762,13 +758,16 @@
 
 extern void btsnd_hcic_ble_read_white_list_size(void);
 
-extern void btsnd_hcic_ble_clear_white_list(void);
+extern void btsnd_hcic_ble_clear_white_list(
+    base::OnceCallback<void(uint8_t*, uint16_t)> cb);
 
-extern void btsnd_hcic_ble_add_white_list(uint8_t addr_type,
-                                          const RawAddress& bda);
+extern void btsnd_hcic_ble_add_white_list(
+    uint8_t addr_type, const RawAddress& bda,
+    base::OnceCallback<void(uint8_t*, uint16_t)> cb);
 
-extern void btsnd_hcic_ble_remove_from_white_list(uint8_t addr_type,
-                                                  const RawAddress& bda);
+extern void btsnd_hcic_ble_remove_from_white_list(
+    uint8_t addr_type, const RawAddress& bda,
+    base::OnceCallback<void(uint8_t*, uint16_t)> cb);
 
 extern void btsnd_hcic_ble_upd_ll_conn_params(
     uint16_t handle, uint16_t conn_int_min, uint16_t conn_int_max,
@@ -790,11 +789,9 @@
 
 extern void btsnd_hcic_ble_start_enc(uint16_t handle,
                                      uint8_t rand[HCIC_BLE_RAND_DI_SIZE],
-                                     uint16_t ediv,
-                                     uint8_t ltk[HCIC_BLE_ENCRYT_KEY_SIZE]);
+                                     uint16_t ediv, const Octet16& ltk);
 
-extern void btsnd_hcic_ble_ltk_req_reply(uint16_t handle,
-                                         uint8_t ltk[HCIC_BLE_ENCRYT_KEY_SIZE]);
+extern void btsnd_hcic_ble_ltk_req_reply(uint16_t handle, const Octet16& ltk);
 
 extern void btsnd_hcic_ble_ltk_req_neg_reply(uint16_t handle);
 
@@ -830,9 +827,10 @@
                                            uint16_t tx_octets,
                                            uint16_t tx_time);
 
-extern void btsnd_hcic_ble_add_device_resolving_list(
-    uint8_t addr_type_peer, const RawAddress& bda_peer,
-    uint8_t irk_peer[HCIC_BLE_IRK_SIZE], uint8_t irk_local[HCIC_BLE_IRK_SIZE]);
+extern void btsnd_hcic_ble_add_device_resolving_list(uint8_t addr_type_peer,
+                                                     const RawAddress& bda_peer,
+                                                     const Octet16& irk_peer,
+                                                     const Octet16& irk_local);
 
 struct scanning_phy_cfg {
   uint8_t scan_type;
@@ -867,10 +865,6 @@
                                            uint8_t initiating_phys,
                                            EXT_CONN_PHY_CFG* phy_cfg);
 
-extern void btsnd_hcic_ble_add_device_resolving_list(
-    uint8_t addr_type_peer, const RawAddress& bda_peer,
-    uint8_t irk_peer[HCIC_BLE_IRK_SIZE], uint8_t irk_local[HCIC_BLE_IRK_SIZE]);
-
 extern void btsnd_hcic_ble_rm_device_resolving_list(uint8_t addr_type_peer,
                                                     const RawAddress& bda_peer);
 
diff --git a/stack/include/l2c_api.h b/stack/include/l2c_api.h
index 88121af5..8f364e7 100644
--- a/stack/include/l2c_api.h
+++ b/stack/include/l2c_api.h
@@ -328,7 +328,7 @@
 
 } tL2CAP_ERTM_INFO;
 
-#define L2CA_REGISTER(a, b, c) L2CA_Register(a, (tL2CAP_APPL_INFO*)(b))
+#define L2CA_REGISTER(a, b, c) L2CA_Register(a, (tL2CAP_APPL_INFO*)(b), c)
 #define L2CA_DEREGISTER(a) L2CA_Deregister(a)
 #define L2CA_CONNECT_REQ(a, b, c) L2CA_ErtmConnectReq(a, b, c)
 #define L2CA_CONNECT_RSP(a, b, c, d, e, f) L2CA_ErtmConnectRsp(a, b, c, d, e, f)
@@ -362,7 +362,8 @@
  *                  BTM_SetSecurityLevel().
  *
  ******************************************************************************/
-extern uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info);
+extern uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                              bool enable_snoop);
 
 /*******************************************************************************
  *
diff --git a/stack/include/l2cdefs.h b/stack/include/l2cdefs.h
index 4f4c894..2d4d6db 100644
--- a/stack/include/l2cdefs.h
+++ b/stack/include/l2cdefs.h
@@ -125,18 +125,20 @@
 #define L2CAP_CONN_NO_LINK 255
 #define L2CAP_CONN_CANCEL 256 /* L2CAP connection cancelled */
 
-/* Define the LE L2CAP connection result codes
-*/
-#define L2CAP_LE_CONN_OK 0
-#define L2CAP_LE_NO_PSM 2
-#define L2CAP_LE_NO_RESOURCES 4
-#define L2CAP_LE_INSUFFICIENT_AUTHENTICATION 5
-#define L2CAP_LE_INSUFFICIENT_AUTHORIZATION 6
-#define L2CAP_LE_INSUFFICIENT_ENCRYP_KEY_SIZE 7
-#define L2CAP_LE_INSUFFICIENT_ENCRYP 8
+/* Define the LE L2CAP Connection Response Result codes
+ */
+#define L2CAP_LE_RESULT_CONN_OK 0
+#define L2CAP_LE_RESULT_NO_PSM 2
+#define L2CAP_LE_RESULT_NO_RESOURCES 4
+#define L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION 5
+#define L2CAP_LE_RESULT_INSUFFICIENT_AUTHORIZATION 6
+#define L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE 7
+#define L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP 8
 /* We don't like peer device response */
-#define L2CAP_LE_INVALID_SOURCE_CID 9
-#define L2CAP_LE_SOURCE_CID_ALREADY_ALLOCATED 0x0A
+#define L2CAP_LE_RESULT_INVALID_SOURCE_CID 9
+#define L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED 0x0A
+
+typedef uint8_t tL2CAP_LE_RESULT_CODE;
 
 /* Define L2CAP Move Channel Response result codes
 */
diff --git a/stack/include/mca_api.h b/stack/include/mca_api.h
deleted file mode 100644
index 539d6c2..0000000
--- a/stack/include/mca_api.h
+++ /dev/null
@@ -1,553 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This interface file contains the interface to the Multi-Channel
- *  Adaptation Protocol (MCAP).
- *
- ******************************************************************************/
-#ifndef MCA_API_H
-#define MCA_API_H
-
-#include "bt_target.h"
-#include "l2c_api.h"
-
-/* move the following to bt_target.h or other place later */
-#define MCA_NUM_TC_TBL ((MCA_NUM_REGS) * (MCA_NUM_LINKS) * (MCA_NUM_MDLS + 1))
-/* Number of control channel control blocks	*/
-#define MCA_NUM_CCBS ((MCA_NUM_REGS) * (MCA_NUM_LINKS))
-/* Number of data channel control blocks */
-#define MCA_NUM_DCBS ((MCA_NUM_REGS) * (MCA_NUM_LINKS) * (MCA_NUM_MDLS))
-
-/*****************************************************************************
- * constants
- ****************************************************************************/
-/* API function return value result codes. */
-#define MCA_SUCCESS 0      /* Function successful */
-#define MCA_BAD_PARAMS 1   /* Invalid parameters */
-#define MCA_NO_RESOURCES 2 /* Not enough resources */
-#define MCA_BAD_HANDLE 3   /* Bad handle */
-#define MCA_BUSY 4         /* A procedure is already in progress */
-#define MCA_WRITE_FAIL 5   /* Write failed */
-#define MCA_BAD_MDL_ID 6   /* MDL ID is not valid for the current API */
-typedef uint8_t tMCA_RESULT;
-
-/* MDEP data type.  */
-#define MCA_TDEP_ECHO 0 /* MDEP for echo test  */
-#define MCA_TDEP_DATA 1 /* MDEP for normal data */
-
-/* Control callback events. */
-#define MCA_ERROR_RSP_EVT 0     /* error response */
-#define MCA_CREATE_IND_EVT 1    /* create mdl indication */
-#define MCA_CREATE_CFM_EVT 2    /* create mdl confirm */
-#define MCA_RECONNECT_IND_EVT 3 /* reconnect mdl indication */
-#define MCA_RECONNECT_CFM_EVT 4 /* reconnect mdl confirm */
-#define MCA_ABORT_IND_EVT 5     /* abort mdl indication */
-#define MCA_ABORT_CFM_EVT 6     /* abort mdl confirm */
-#define MCA_DELETE_IND_EVT 7    /* delete mdl indication */
-#define MCA_DELETE_CFM_EVT 8    /* delete mdl confirm */
-
-/* request sync capabilities & requirements */
-#define MCA_SYNC_CAP_IND_EVT 0x11
-#define MCA_SYNC_CAP_CFM_EVT 0x12 /* indicate completion */
-/* request to set the time-stamp clock */
-#define MCA_SYNC_SET_IND_EVT 0x13
-#define MCA_SYNC_SET_CFM_EVT 0x14 /* indicate completion */
-/* update of the actual time-stamp clock instant from the sync slave */
-#define MCA_SYNC_INFO_IND_EVT 0x15
-
-#define MCA_CONNECT_IND_EVT 0x20    /* Control channel connected */
-#define MCA_DISCONNECT_IND_EVT 0x21 /* Control channel disconnected */
-#define MCA_OPEN_IND_EVT 0x22       /* Data channel open indication */
-#define MCA_OPEN_CFM_EVT 0x23       /* Data channel open confirm */
-#define MCA_CLOSE_IND_EVT 0x24      /* Data channel close indication */
-#define MCA_CLOSE_CFM_EVT 0x25      /* Data channel close confirm */
-#define MCA_CONG_CHG_EVT 0x26       /* congestion change event */
-#define MCA_RSP_TOUT_IND_EVT                       \
-  0x27 /* Control channel message response timeout \
-          */
-/*****************************************************************************
- *  Type Definitions
- ****************************************************************************/
-typedef uint8_t
-    tMCA_HANDLE;         /* the handle for registration. 1 based index to rcb */
-typedef uint8_t tMCA_CL; /* the handle for a control channel; reported at
-                            MCA_CONNECT_IND_EVT */
-typedef uint8_t
-    tMCA_DEP; /* the handle for MCA_CreateDep. This is also the local mdep_id */
-typedef uint16_t tMCA_DL; /* the handle for the data channel. This is reported
-                             at MCA_OPEN_CFM_EVT or MCA_OPEN_IND_EVT */
-
-/* This is the data callback function.  It is executed when MCAP has a data
- * packet ready for the application.
-*/
-typedef void(tMCA_DATA_CBACK)(tMCA_DL mdl, BT_HDR* p_pkt);
-
-/* This structure contains parameters which are set at registration. */
-typedef struct {
-  uint32_t rsp_tout; /* MCAP signaling response timeout */
-  uint16_t ctrl_psm; /* L2CAP PSM for the MCAP control channel */
-  uint16_t data_psm; /* L2CAP PSM for the MCAP data channel */
-  uint16_t sec_mask; /* Security mask for BTM_SetSecurityLevel() */
-} tMCA_REG;
-
-/* This structure contains parameters to create a MDEP. */
-typedef struct {
-  uint8_t type; /* MCA_TDEP_DATA, or MCA_TDEP_ECHO. a regiatration may have only
-                   one MCA_TDEP_ECHO MDEP */
-  uint8_t max_mdl; /* The maximum number of MDLs for this MDEP (max is
-                      MCA_NUM_MDLS) */
-  tMCA_DATA_CBACK* p_data_cback; /* Data callback function */
-} tMCA_CS;
-
-#define MCA_FCS_NONE 0      /* fcs_present=false */
-#define MCA_FCS_BYPASS 0x10 /* fcs_present=true, fcs=L2CAP_CFG_FCS_BYPASS */
-#define MCA_FCS_USE 0x11    /* fcs_present=true, fcs=L2CAP_CFG_FCS_USE */
-#define MCA_FCS_PRESNT_MASK 0x10 /* fcs_present=true */
-#define MCA_FCS_USE_MASK 0x01    /* mask for fcs */
-typedef uint8_t tMCA_FCS_OPT;
-
-/* This structure contains L2CAP configuration parameters for the channel. */
-typedef struct {
-  tL2CAP_FCR_OPTS fcr_opt;
-  uint16_t user_rx_buf_size;
-  uint16_t user_tx_buf_size;
-  uint16_t fcr_rx_buf_size;
-  uint16_t fcr_tx_buf_size;
-  tMCA_FCS_OPT fcs;
-  uint16_t data_mtu; /* L2CAP MTU of the MCAP data channel */
-} tMCA_CHNL_CFG;
-
-/* Header structure for callback event parameters. */
-typedef struct {
-  uint16_t mdl_id; /* The associated MDL ID */
-  uint8_t op_code; /* The op (request/response) code */
-} tMCA_EVT_HDR;
-
-/* Response Header structure for callback event parameters. */
-typedef struct {
-  uint16_t mdl_id;  /* The associated MDL ID */
-  uint8_t op_code;  /* The op (request/response) code */
-  uint8_t rsp_code; /* The response code */
-} tMCA_RSP_EVT;
-
-/* This data structure is associated with the MCA_CREATE_IND_EVT. */
-typedef struct {
-  uint16_t mdl_id; /* The associated MDL ID */
-  uint8_t op_code; /* The op (request/response) code */
-  uint8_t dep_id;  /* MDEP ID */
-  uint8_t cfg;     /* The configuration to negotiate */
-} tMCA_CREATE_IND;
-
-/* This data structure is associated with the MCA_CREATE_CFM_EVT. */
-typedef struct {
-  uint16_t mdl_id;  /* The associated MDL ID */
-  uint8_t op_code;  /* The op (request/response) code */
-  uint8_t rsp_code; /* The response code. */
-  uint8_t cfg;      /* The configuration to negotiate */
-} tMCA_CREATE_CFM;
-
-/* This data structure is associated with MCA_CONNECT_IND_EVT. */
-typedef struct {
-  RawAddress bd_addr; /* The peer address */
-  uint16_t mtu;    /* peer mtu */
-} tMCA_CONNECT_IND;
-
-/* This data structure is associated with MCA_DISCONNECT_IND_EVT. */
-typedef struct {
-  RawAddress bd_addr; /* The peer address */
-  uint16_t reason; /* disconnect reason given by L2CAP */
-} tMCA_DISCONNECT_IND;
-
-/* This data structure is for MCA_OPEN_IND_EVT, and MCA_OPEN_CFM_EVT. */
-typedef struct {
-  uint16_t mdl_id; /* The associated MDL ID */
-  tMCA_DL mdl;     /* The handle for the data channel */
-  uint16_t mtu;    /* peer mtu */
-} tMCA_DL_OPEN;
-
-/* This data structure is for MCA_CLOSE_IND_EVT and MCA_CLOSE_CFM_EVT. */
-typedef struct {
-  uint16_t mdl_id; /* The associated MDL ID */
-  tMCA_DL mdl;     /* The handle for the data channel */
-  uint16_t reason; /* disconnect reason given by L2CAP */
-} tMCA_DL_CLOSE;
-
-/* This data structure is associated with MCA_CONG_CHG_EVT. */
-typedef struct {
-  uint16_t mdl_id; /* N/A - This is a place holder */
-  tMCA_DL mdl;     /* The handle for the data channel */
-  bool cong;       /* true, if the channel is congested */
-} tMCA_CONG_CHG;
-
-/* Union of all control callback event data structures */
-typedef union {
-  tMCA_EVT_HDR hdr;
-  tMCA_RSP_EVT rsp;
-  tMCA_CREATE_IND create_ind;
-  tMCA_CREATE_CFM create_cfm;
-  tMCA_EVT_HDR reconnect_ind;
-  tMCA_RSP_EVT reconnect_cfm;
-  tMCA_EVT_HDR abort_ind;
-  tMCA_RSP_EVT abort_cfm;
-  tMCA_EVT_HDR delete_ind;
-  tMCA_RSP_EVT delete_cfm;
-  tMCA_CONNECT_IND connect_ind;
-  tMCA_DISCONNECT_IND disconnect_ind;
-  tMCA_DL_OPEN open_ind;
-  tMCA_DL_OPEN open_cfm;
-  tMCA_DL_CLOSE close_ind;
-  tMCA_DL_CLOSE close_cfm;
-  tMCA_CONG_CHG cong_chg;
-} tMCA_CTRL;
-
-/* This is the control callback function.  This function passes control events
- * to the application.
-*/
-typedef void(tMCA_CTRL_CBACK)(tMCA_HANDLE handle, tMCA_CL mcl, uint8_t event,
-                              tMCA_CTRL* p_data);
-
-/*******************************************************************************
- *
- * Function         MCA_Init
- *
- * Description      Initialize MCAP internal control blocks.
- *                  This function is called at stack start up.
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void MCA_Init(void);
-
-/*******************************************************************************
- *
- * Function         MCA_SetTraceLevel
- *
- * Description      This function sets the debug trace level for MCA.
- *                  If 0xff is passed, the current trace level is returned.
- *
- *                  Input Parameters:
- *                      level:  The level to set the MCA 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.
- *
- ******************************************************************************/
-extern uint8_t MCA_SetTraceLevel(uint8_t level);
-
-/*******************************************************************************
- *
- * Function         MCA_Register
- *
- * Description      This function registers an MCAP implementation.
- *                  It is assumed that the control channel PSM and data channel
- *                  PSM are not used by any other instances of the stack.
- *                  If the given p_reg->ctrl_psm is 0, this handle is INT only.
- *
- * Returns          0, if failed. Otherwise, the MCA handle.
- *
- ******************************************************************************/
-extern tMCA_HANDLE MCA_Register(tMCA_REG* p_reg, tMCA_CTRL_CBACK* p_cback);
-
-/*******************************************************************************
- *
- * Function         MCA_Deregister
- *
- * Description      Deregister an MCAP implementation. Before this function can
- *                  be called, all control and data channels must be removed
- *                  with MCA_DisconnectReq and MCA_CloseReq.
- *
- * Returns          void
- *
- ******************************************************************************/
-extern void MCA_Deregister(tMCA_HANDLE handle);
-
-/*******************************************************************************
- *
- * Function         MCA_CreateDep
- *
- * Description      Create a data endpoint.  If the MDEP is created
- *                  successfully, the MDEP ID is returned in *p_dep. After a
- *                  data endpoint is created, an application can initiate a
- *                  connection between this endpoint and an endpoint on a peer
- *                  device.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_CreateDep(tMCA_HANDLE handle, tMCA_DEP* p_dep,
-                                 tMCA_CS* p_cs);
-
-/*******************************************************************************
- *
- * Function         MCA_DeleteDep
- *
- * Description      Delete a data endpoint.  This function is called when
- *                  the implementation is no longer using a data endpoint.
- *                  If this function is called when the endpoint is connected
- *                  the connection is closed and the data endpoint
- *                  is removed.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_DeleteDep(tMCA_HANDLE handle, tMCA_DEP dep);
-
-/*******************************************************************************
- *
- * Function         MCA_ConnectReq
- *
- * Description      This function initiates an MCAP control channel connection
- *                  to the peer device.  When the connection is completed, an
- *                  MCA_CONNECT_IND_EVT is reported to the application via its
- *                  control callback function.
- *                  This control channel is identified by tMCA_CL.
- *                  If the connection attempt fails, an MCA_DISCONNECT_IND_EVT
- *                  is reported. The security mask parameter overrides the
- *                  outgoing security mask set in MCA_Register().
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_ConnectReq(tMCA_HANDLE handle, const RawAddress& bd_addr,
-                                  uint16_t ctrl_psm, uint16_t sec_mask);
-
-/*******************************************************************************
- *
- * Function         MCA_DisconnectReq
- *
- * Description      This function disconnect an MCAP control channel
- *                  to the peer device.
- *                  If associated data channel exists, they are disconnected.
- *                  When the MCL is disconnected an MCA_DISCONNECT_IND_EVT is
- *                  reported to the application via its control callback
- *                  function.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_DisconnectReq(tMCA_CL mcl);
-
-/*******************************************************************************
- *
- * Function         MCA_CreateMdl
- *
- * Description      This function sends a CREATE_MDL request to the peer device.
- *                  When the response is received, a MCA_CREATE_CFM_EVT is
- *                  reported with the given MDL ID.
- *                  If the response is successful, a data channel is open
- *                  with the given p_chnl_cfg
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_CFM_EVT is reported. This data channel is
- *                  identified as tMCA_DL.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_CreateMdl(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm,
-                                 uint16_t mdl_id, uint8_t peer_dep_id,
-                                 uint8_t cfg, const tMCA_CHNL_CFG* p_chnl_cfg);
-
-/*******************************************************************************
- *
- * Function         MCA_CreateMdlRsp
- *
- * Description      This function sends a CREATE_MDL response to the peer device
- *                  in response to a received MCA_CREATE_IND_EVT.
- *                  If the rsp_code is successful, a data channel is open
- *                  with the given p_chnl_cfg
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_IND_EVT is reported. This data channel is
- *                  identified as tMCA_DL.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_CreateMdlRsp(tMCA_CL mcl, tMCA_DEP dep, uint16_t mdl_id,
-                                    uint8_t cfg, uint8_t rsp_code,
-                                    const tMCA_CHNL_CFG* p_chnl_cfg);
-
-/*******************************************************************************
- *
- * Function         MCA_CloseReq
- *
- * Description      Close a data channel.  When the channel is closed, an
- *                  MCA_CLOSE_CFM_EVT is sent to the application via the
- *                  control callback function for this handle.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_CloseReq(tMCA_DL mdl);
-
-/*******************************************************************************
- *
- * Function         MCA_ReconnectMdl
- *
- * Description      This function sends a RECONNECT_MDL request to the peer
- *                  device. When the response is received, a
- *                  MCA_RECONNECT_CFM_EVT is reported. If the response is
- *                  successful, a data channel is open. When the data channel is
- *                  open successfully, a MCA_OPEN_CFM_EVT is reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_ReconnectMdl(tMCA_CL mcl, tMCA_DEP dep,
-                                    uint16_t data_psm, uint16_t mdl_id,
-                                    const tMCA_CHNL_CFG* p_chnl_cfg);
-
-/*******************************************************************************
- *
- * Function         MCA_ReconnectMdlRsp
- *
- * Description      Send a RECONNECT_MDL response to the peer device in response
- *                  to a MCA_RECONNECT_IND_EVT event.
- *                  If the response is successful, a data channel is open.
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_IND_EVT is reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_ReconnectMdlRsp(tMCA_CL mcl, tMCA_DEP dep,
-                                       uint16_t mdl_id, uint8_t rsp_code,
-                                       const tMCA_CHNL_CFG* p_chnl_cfg);
-
-/*******************************************************************************
- *
- * Function         MCA_DataChnlCfg
- *
- * Description      This function initiates a data channel connection toward the
- *                  connected peer device.
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_CFM_EVT is reported. This data channel is
- *                  identified as tMCA_DL.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_DataChnlCfg(tMCA_CL mcl,
-                                   const tMCA_CHNL_CFG* p_chnl_cfg);
-
-/*******************************************************************************
- *
- * Function         MCA_Abort
- *
- * Description      This function sends a ABORT_MDL request to the peer device.
- *                  When the response is received, a MCA_ABORT_CFM_EVT is
- *                  reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_Abort(tMCA_CL mcl);
-
-/*******************************************************************************
- *
- * Function         MCA_Delete
- *
- * Description      This function sends a DELETE_MDL request to the peer device.
- *                  When the response is received, a MCA_DELETE_CFM_EVT is
- *                  reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_Delete(tMCA_CL mcl, uint16_t mdl_id);
-
-/*******************************************************************************
- *
- * Function         MCA_WriteReq
- *
- * Description      Send a data packet to the peer device.
- *
- *                  The application passes the packet using the BT_HDR
- *                  structure. The offset field must be equal to or greater than
- *                  L2CAP_MIN_OFFSET. This allows enough space in the buffer for
- *                  the L2CAP header.
- *
- *                  The memory pointed to by p_pkt must be a GKI buffer
- *                  allocated by the application.  This buffer will be freed
- *                  by the protocol stack; the application must not free
- *                  this buffer.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-extern tMCA_RESULT MCA_WriteReq(tMCA_DL mdl, BT_HDR* p_pkt);
-
-/*******************************************************************************
- *
- * Function         MCA_GetL2CapChannel
- *
- * Description      Get the L2CAP CID used by the given data channel handle.
- *
- * Returns          L2CAP channel ID if successful, otherwise 0.
- *
- ******************************************************************************/
-extern uint16_t MCA_GetL2CapChannel(tMCA_DL mdl);
-
-/**
- * The following definitions are for test interface only, they mirror function
- * definitions above. This struct allows an external application to load and
- * call these methods without linking against the core library.
- */
-typedef struct {
-  size_t size;
-  void (*init)(void);
-  tMCA_HANDLE (*register_application)(tMCA_REG* p_reg,
-                                      tMCA_CTRL_CBACK* p_cback);
-  void (*deregister_application)(tMCA_HANDLE handle);
-  tMCA_RESULT (*create_mdep)(tMCA_HANDLE handle, tMCA_DEP* p_dep,
-                             tMCA_CS* p_cs);
-  tMCA_RESULT (*delete_mdep)(tMCA_HANDLE handle, tMCA_DEP dep);
-  tMCA_RESULT (*connect_mcl)(tMCA_HANDLE handle, const RawAddress& bd_addr,
-                             uint16_t ctrl_psm, uint16_t sec_mask);
-  tMCA_RESULT (*disconnect_mcl)(tMCA_CL mcl);
-  tMCA_RESULT (*create_mdl_request)(tMCA_CL mcl, tMCA_DEP dep,
-                                    uint16_t data_psm, uint16_t mdl_id,
-                                    uint8_t peer_dep_id, uint8_t cfg,
-                                    const tMCA_CHNL_CFG* p_chnl_cfg);
-  tMCA_RESULT (*create_mdl_response)(tMCA_CL mcl, tMCA_DEP dep, uint16_t mdl_id,
-                                     uint8_t cfg, uint8_t rsp_code,
-                                     const tMCA_CHNL_CFG* p_chnl_cfg);
-  tMCA_RESULT (*close_mdl_request)(tMCA_DL mdl);
-  tMCA_RESULT (*reconnect_mdl_request)(tMCA_CL mcl, tMCA_DEP dep,
-                                       uint16_t data_psm, uint16_t mdl_id,
-                                       const tMCA_CHNL_CFG* p_chnl_cfg);
-  tMCA_RESULT (*reconnect_mdl_response)(tMCA_CL mcl, tMCA_DEP dep,
-                                        uint16_t mdl_id, uint8_t rsp_code,
-                                        const tMCA_CHNL_CFG* p_chnl_cfg);
-  tMCA_RESULT (*data_channel_config)(tMCA_CL mcl,
-                                     const tMCA_CHNL_CFG* p_chnl_cfg);
-  tMCA_RESULT (*abort_mdl)(tMCA_CL mcl);
-  tMCA_RESULT (*delete_mdl)(tMCA_CL mcl, uint16_t mdl_id);
-  tMCA_RESULT (*write_mdl)(tMCA_DL mdl, BT_HDR* p_pkt);
-  uint16_t (*get_l2cap_channel)(tMCA_DL mdl);
-} btmcap_test_interface_t;
-
-#endif /* MCA_API_H */
diff --git a/stack/include/mca_defs.h b/stack/include/mca_defs.h
deleted file mode 100644
index 7b6d3c2..0000000
--- a/stack/include/mca_defs.h
+++ /dev/null
@@ -1,126 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This contains constants definitions and other information from the MCAP
- *  specification.
- *
- ******************************************************************************/
-#ifndef MCA_DEFS_H
-#define MCA_DEFS_H
-
-/*****************************************************************************
- * constants
- ****************************************************************************/
-#define MCA_MIN_MTU 48
-
-/* standard op codes */
-/* invalid opcode response */
-#define MCA_OP_ERROR_RSP 0x00
-/* create an MDL, wait for an associated data channel connection */
-#define MCA_OP_MDL_CREATE_REQ 0x01
-/* response to above request */
-#define MCA_OP_MDL_CREATE_RSP 0x02
-/* req to prepare to rvc a data channel conn associated with a prev MDL */
-#define MCA_OP_MDL_RECONNECT_REQ 0x03
-/* response to above request */
-#define MCA_OP_MDL_RECONNECT_RSP 0x04
-/* stop waiting for a data channel connection */
-#define MCA_OP_MDL_ABORT_REQ 0x05
-/* response to above request */
-#define MCA_OP_MDL_ABORT_RSP 0x06
-/* delete an MDL */
-#define MCA_OP_MDL_DELETE_REQ 0x07
-/* response to above request */
-#define MCA_OP_MDL_DELETE_RSP 0x08
-#define MCA_NUM_STANDARD_OPCODE (1 + MCA_OP_MDL_DELETE_RSP)
-
-/* clock synchronization op codes */
-/* request sync capabilities & requirements */
-#define MCA_OP_SYNC_CAP_REQ 0x11
-/* indicate completion */
-#define MCA_OP_SYNC_CAP_RSP 0x12
-/* request to set the time-stamp clock */
-#define MCA_OP_SYNC_SET_REQ 0x13
-/* indicate completion */
-#define MCA_OP_SYNC_SET_RSP 0x14
-/* update of the actual time-stamp clock instant from the sync slave */
-#define MCA_OP_SYNC_INFO_IND 0x15
-
-#define MCA_FIRST_SYNC_OP MCA_OP_SYNC_CAP_REQ
-#define MCA_LAST_SYNC_OP MCA_OP_SYNC_INFO_IND
-
-/* response code */
-/* The corresponding request was received and processed successfully. */
-#define MCA_RSP_SUCCESS 0x00
-/* The Op Code received is not valid (i.e. neither a Standard Op Code nor a
- * Clock Synchronization Protocol Op Code). */
-#define MCA_RSP_BAD_OPCODE 0x01
-/* One or more of the values in the received request is invalid. */
-#define MCA_RSP_BAD_PARAM 0x02
-/* MCA_RSP_BAD_PARAM shall be used when:
-- The request length is invalid
-- Some of the parameters have invalid values and none of the other defined
-Response Codes are more appropriate.
-*/
-/* The MDEP ID referenced does not exist on this device. */
-#define MCA_RSP_BAD_MDEP 0x03
-/* The requested MDEP currently has as many active MDLs as it can manage
- * simultaneously. */
-#define MCA_RSP_MDEP_BUSY 0x04
-/* The MDL ID referenced is invalid. */
-#define MCA_RSP_BAD_MDL 0x05
-/* MCA_RSP_BAD_MDL shall be used when:
-- A reserved or invalid value for MDL ID was used.
-- The MDL ID referenced is not available (was never created, has been deleted,
-or was otherwise lost),
-- The MDL ID referenced in the Abort request is not the same value that was used
-to initiate the PENDING state
-*/
-/* The device is temporarily unable to complete the request. This is intended
- * for reasons not related to the physical sensor (e.g. communication resources
- * unavailable). */
-#define MCA_RSP_MDL_BUSY 0x06
-/* The received request is invalid in the current state. */
-#define MCA_RSP_BAD_OP 0x07
-/* MCA_RSP_BAD_OP is used when
-- Abort request was received while not in the PENDING state.
-- Create, Reconnect, or Delete request was received while in the PENDING state.
-- A response is received when a request is expected
-*/
-/* The device is temporarily unable to complete the request. This is intended
- * for reasons relating to the physical sensor (e.g. hardware fault, low
- * battery), or when processing resources are temporarily committed to other
- * processes. */
-#define MCA_RSP_NO_RESOURCE 0x08
-/* An internal error other than those listed in this table was encountered while
- * processing the request. */
-#define MCA_RSP_ERROR 0x09
-/* The Op Code that was used in this request is not supported. */
-#define MCA_RSP_NO_SUPPORT 0x0A
-/* A configuration required by a MD_CREATE_MDL or MD_RECONNECT_MDL operation has
- * been rejected. */
-#define MCA_RSP_CFG_REJ 0x0B
-
-/* the valid range for MDEP ID is 1-0x7F */
-#define MCA_MAX_MDEP_ID 0x7F
-#define MCA_IS_VALID_MDL_ID(xxx) (((xxx) > 0) && ((xxx) <= 0xFEFF))
-#define MCA_ALL_MDL_ID 0xFFFF
-
-#endif /* MCA_DEFS_H */
diff --git a/stack/include/port_api.h b/stack/include/port_api.h
index aedbe74..b0a7e63 100644
--- a/stack/include/port_api.h
+++ b/stack/include/port_api.h
@@ -309,7 +309,7 @@
  *                  p_lcid     - OUT L2CAP's LCID
  *
  ******************************************************************************/
-extern int PORT_CheckConnection(uint16_t handle, RawAddress& bd_addr,
+extern int PORT_CheckConnection(uint16_t handle, RawAddress* bd_addr,
                                 uint16_t* p_lcid);
 
 /*******************************************************************************
@@ -323,7 +323,7 @@
  *                  bd_addr    - bd_addr of the peer
  *
  ******************************************************************************/
-extern bool PORT_IsOpening(RawAddress& bd_addr);
+extern bool PORT_IsOpening(RawAddress* bd_addr);
 
 /*******************************************************************************
  *
diff --git a/stack/include/sdpdefs.h b/stack/include/sdpdefs.h
index 05b3cc1..4e4b7b9 100644
--- a/stack/include/sdpdefs.h
+++ b/stack/include/sdpdefs.h
@@ -143,11 +143,6 @@
 #define ATTR_ID_HID_SSR_HOST_MAX_LAT 0x020F
 #define ATTR_ID_HID_SSR_HOST_MIN_TOUT 0x0210
 
-/* These values are for the HDP profile */
-#define ATTR_ID_HDP_SUP_FEAT_LIST 0x0200  /* Supported features list */
-#define ATTR_ID_HDP_DATA_EXCH_SPEC 0x0301 /* Data exchange specification */
-#define ATTR_ID_HDP_MCAP_SUP_PROC 0x0302  /* MCAP supported procedures */
-
 /* Define common 16-bit protocol UUIDs
 */
 #define UUID_PROTOCOL_SDP 0x0001
diff --git a/stack/include/smp_api.h b/stack/include/smp_api.h
index 816407d..8a66aae 100644
--- a/stack/include/smp_api.h
+++ b/stack/include/smp_api.h
@@ -176,24 +176,6 @@
 
 /*******************************************************************************
  *
- * Function         SMP_Encrypt
- *
- * Description      Encrypt the data with the specified key.
- *
- * Parameters:      key                 - Pointer to key key[0] conatins the MSB
- *                  key_len             - key length
- *                  plain_text          - Pointer to data to be encrypted
- *                                        plain_text[0] conatins the MSB
- *                  pt_len              - plain text length
- *                  p_out               - pointer to the encrypted outputs
- *
- *  Returns         Boolean - true: encryption is successful
- ******************************************************************************/
-extern bool SMP_Encrypt(uint8_t* key, uint8_t key_len, uint8_t* plain_text,
-                        uint8_t pt_len, tSMP_ENC* p_out);
-
-/*******************************************************************************
- *
  * Function         SMP_KeypressNotification
  *
  * Description      Notify SM about Keypress Notification.
@@ -227,16 +209,4 @@
 // Proceed to send LTK, DIV and ER to master if bonding the devices.
 extern void smp_link_encrypted(const RawAddress& bda, uint8_t encr_enable);
 
-//
-// The AES-CMAC Generation Function with tlen implemented.
-// |key| - CMAC key in little endian order, expect SRK when used by SMP.
-// |input| - text to be signed in little endian byte order.
-// |length| - length of the input in byte.
-// |tlen| - lenth of mac desired
-// |p_signature| - data pointer to where signed data to be stored, tlen long.
-// Returns false if out of resources, true in other cases.
-//
-bool aes_cipher_msg_auth_code(BT_OCTET16 key, uint8_t* input, uint16_t length,
-                              uint16_t tlen, uint8_t* p_signature);
-
 #endif /* SMP_API_H */
diff --git a/stack/include/smp_api_types.h b/stack/include/smp_api_types.h
index fad8b75..cee1204 100644
--- a/stack/include/smp_api_types.h
+++ b/stack/include/smp_api_types.h
@@ -109,10 +109,6 @@
 #define SMP_IO_CAP_MAX BTM_IO_CAP_MAX
 typedef uint8_t tSMP_IO_CAP;
 
-#ifndef SMP_DEFAULT_IO_CAPS
-#define SMP_DEFAULT_IO_CAPS SMP_IO_CAP_KBDISP
-#endif
-
 /* OOB data present or not */
 enum { SMP_OOB_NONE, SMP_OOB_PRESENT, SMP_OOB_UNKNOWN };
 typedef uint8_t tSMP_OOB_FLAG;
@@ -224,8 +220,8 @@
 /* the data associated with the info sent to the peer via OOB interface */
 typedef struct {
   bool present;
-  BT_OCTET16 randomizer;
-  BT_OCTET16 commitment;
+  Octet16 randomizer;
+  Octet16 commitment;
 
   tBLE_BD_ADDR addr_sent_to;
   BT_OCTET32 private_key_used; /* is used to calculate: */
@@ -238,8 +234,8 @@
 /* the data associated with the info received from the peer via OOB interface */
 typedef struct {
   bool present;
-  BT_OCTET16 randomizer;
-  BT_OCTET16 commitment;
+  Octet16 randomizer;
+  Octet16 commitment;
   tBLE_BD_ADDR addr_rcvd_from;
 } tSMP_PEER_OOB_DATA;
 
@@ -261,7 +257,7 @@
   uint8_t status;
   uint8_t param_len;
   uint16_t opcode;
-  uint8_t param_buf[BT_OCTET16_LEN];
+  uint8_t param_buf[OCTET16_LEN];
 } tSMP_ENC;
 
 /* Security Manager events - Called by the stack when Security Manager related
diff --git a/stack/include/srvc_api.h b/stack/include/srvc_api.h
index e968998..ad01237 100644
--- a/stack/include/srvc_api.h
+++ b/stack/include/srvc_api.h
@@ -165,35 +165,4 @@
 extern bool DIS_ReadDISInfo(const RawAddress& peer_bda,
                             tDIS_READ_CBACK* p_cback, tDIS_ATTR_MASK mask);
 
-/*******************************************************************************
- *      BATTERY SERVICE API
- ******************************************************************************/
-/*******************************************************************************
- *
- * Function         Battery_Instantiate
- *
- * Description      Instantiate a Battery service
- *
- ******************************************************************************/
-extern uint16_t Battery_Instantiate(uint8_t app_id, tBA_REG_INFO* p_reg_info);
-
-/*******************************************************************************
- *
- * Function         Battery_Rsp
- *
- * Description      Respond to a battery service request
- *
- ******************************************************************************/
-extern void Battery_Rsp(uint8_t app_id, tGATT_STATUS st, uint8_t event,
-                        tBA_RSP_DATA* p_rsp);
-/*******************************************************************************
- *
- * Function         Battery_Notify
- *
- * Description      Send battery level notification
- *
- ******************************************************************************/
-extern void Battery_Notify(uint8_t app_id, const RawAddress& remote_bda,
-                           uint8_t battery_level);
-
 #endif
diff --git a/stack/l2cap/l2c_api.cc b/stack/l2cap/l2c_api.cc
index 951a45b..b5a9564 100644
--- a/stack/l2cap/l2c_api.cc
+++ b/stack/l2cap/l2c_api.cc
@@ -58,7 +58,8 @@
  *                  L2CA_ErtmConnectReq() and L2CA_Deregister()
  *
  ******************************************************************************/
-uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
+uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                       bool enable_snoop) {
   tL2C_RCB* p_rcb;
   uint16_t vpsm = psm;
 
@@ -104,6 +105,7 @@
     }
   }
 
+  p_rcb->log_packets = enable_snoop;
   p_rcb->api = *p_cb_info;
   p_rcb->real_psm = psm;
 
@@ -275,7 +277,7 @@
  *
  ******************************************************************************/
 uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& p_bd_addr) {
-  return L2CA_ErtmConnectReq(psm, p_bd_addr, NULL);
+  return L2CA_ErtmConnectReq(psm, p_bd_addr, nullptr);
 }
 
 /*******************************************************************************
@@ -297,10 +299,6 @@
  ******************************************************************************/
 uint16_t L2CA_ErtmConnectReq(uint16_t psm, const RawAddress& p_bd_addr,
                              tL2CAP_ERTM_INFO* p_ertm_info) {
-  tL2C_LCB* p_lcb;
-  tL2C_CCB* p_ccb;
-  tL2C_RCB* p_rcb;
-
   VLOG(1) << __func__ << "BDA " << p_bd_addr
           << StringPrintf(" PSM: 0x%04x allowed:0x%x preferred:%d", psm,
                           (p_ertm_info) ? p_ertm_info->allowed_modes : 0,
@@ -308,36 +306,36 @@
 
   /* Fail if we have not established communications with the controller */
   if (!BTM_IsDeviceUp()) {
-    L2CAP_TRACE_WARNING("L2CAP connect req - BTU not ready");
-    return (0);
+    LOG(WARNING) << __func__ << ": BTU not ready";
+    return 0;
   }
   /* Fail if the PSM is not registered */
-  p_rcb = l2cu_find_rcb_by_psm(psm);
-  if (p_rcb == NULL) {
-    L2CAP_TRACE_WARNING("L2CAP - no RCB for L2CA_conn_req, PSM: 0x%04x", psm);
-    return (0);
+  tL2C_RCB* p_rcb = l2cu_find_rcb_by_psm(psm);
+  if (p_rcb == nullptr) {
+    LOG(WARNING) << __func__ << ": no RCB, PSM=" << loghex(psm);
+    return 0;
   }
 
   /* First, see if we already have a link to the remote */
   /* assume all ERTM l2cap connection is going over BR/EDR for now */
-  p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
-  if (p_lcb == NULL) {
+  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(p_bd_addr, BT_TRANSPORT_BR_EDR);
+  if (p_lcb == nullptr) {
     /* No link. Get an LCB and start link establishment */
     p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_BR_EDR);
     /* currently use BR/EDR for ERTM mode l2cap connection */
-    if ((p_lcb == NULL) || (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR))) {
-      L2CAP_TRACE_WARNING(
-          "L2CAP - conn not started for PSM: 0x%04x  p_lcb: 0x%08x", psm,
-          p_lcb);
-      return (0);
+    if ((p_lcb == nullptr) || (!l2cu_create_conn_br_edr(p_lcb))) {
+      LOG(WARNING) << __func__
+                   << ": connection not started for PSM=" << loghex(psm)
+                   << ", p_lcb=" << p_lcb;
+      return 0;
     }
   }
 
   /* Allocate a channel control block */
-  p_ccb = l2cu_allocate_ccb(p_lcb, 0);
-  if (p_ccb == NULL) {
-    L2CAP_TRACE_WARNING("L2CAP - no CCB for L2CA_conn_req, PSM: 0x%04x", psm);
-    return (0);
+  tL2C_CCB* p_ccb = l2cu_allocate_ccb(p_lcb, 0);
+  if (p_ccb == nullptr) {
+    LOG(WARNING) << __func__ << ": no CCB, PSM=" << loghex(psm);
+    return 0;
   }
 
   /* Save registration info */
@@ -366,16 +364,14 @@
 
   /* If link is up, start the L2CAP connection */
   if (p_lcb->link_state == LST_CONNECTED) {
-    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_REQ, NULL);
-  }
-
-  /* If link is disconnecting, save link info to retry after disconnect
-   * Possible Race condition when a reconnect occurs
-   * on the channel during a disconnect of link. This
-   * ccb will be automatically retried after link disconnect
-   * arrives
-   */
-  else if (p_lcb->link_state == LST_DISCONNECTING) {
+    l2c_csm_execute(p_ccb, L2CEVT_L2CA_CONNECT_REQ, nullptr);
+  } else if (p_lcb->link_state == LST_DISCONNECTING) {
+    /* If link is disconnecting, save link info to retry after disconnect
+     * Possible Race condition when a reconnect occurs
+     * on the channel during a disconnect of link. This
+     * ccb will be automatically retried after link disconnect
+     * arrives
+     */
     L2CAP_TRACE_DEBUG("L2CAP API - link disconnecting: RETRY LATER");
 
     /* Save ccb so it can be started after disconnect is finished */
@@ -386,7 +382,7 @@
                   psm, p_ccb->local_cid);
 
   /* Return the local CID as our handle */
-  return (p_ccb->local_cid);
+  return p_ccb->local_cid;
 }
 
 /*******************************************************************************
@@ -537,7 +533,7 @@
     p_lcb = l2cu_allocate_lcb(p_bd_addr, false, BT_TRANSPORT_LE);
     if ((p_lcb == NULL)
         /* currently use BR/EDR for ERTM mode l2cap connection */
-        || (!l2cu_create_conn(p_lcb, BT_TRANSPORT_LE))) {
+        || (!l2cu_create_conn_le(p_lcb))) {
       L2CAP_TRACE_WARNING("%s conn not started for PSM: 0x%04x  p_lcb: 0x%08x",
                           __func__, psm, p_lcb);
       return 0;
@@ -982,7 +978,7 @@
       L2CAP_TRACE_WARNING("L2CAP - no LCB for L2CA_ping");
       return (false);
     }
-    if (!l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR)) {
+    if (!l2cu_create_conn_br_edr(p_lcb)) {
       return (false);
     }
 
@@ -1748,12 +1744,16 @@
     return false;
   }
 
-  if (!l2cu_create_conn(p_lcb, transport, initiating_phys)) {
-    L2CAP_TRACE_WARNING("%s() - create_conn failed", __func__);
+  bool ret = ((transport == BT_TRANSPORT_LE)
+                  ? l2cu_create_conn_le(p_lcb, initiating_phys)
+                  : l2cu_create_conn_br_edr(p_lcb));
+
+  if (!ret) {
+    L2CAP_TRACE_WARNING("%s() - create connection failed", __func__);
     l2cu_release_lcb(p_lcb);
-    return false;
   }
-  return true;
+
+  return ret;
 }
 
 /*******************************************************************************
diff --git a/stack/l2cap/l2c_ble.cc b/stack/l2cap/l2c_ble.cc
index 5fc01f9..bd1a503 100644
--- a/stack/l2cap/l2c_ble.cc
+++ b/stack/l2cap/l2c_ble.cc
@@ -32,10 +32,12 @@
 #include "btu.h"
 #include "device/include/controller.h"
 #include "hcimsgs.h"
+#include "l2c_api.h"
 #include "l2c_int.h"
 #include "l2cdefs.h"
 #include "log/log.h"
 #include "osi/include/osi.h"
+#include "stack/gatt/connection_manager.h"
 #include "stack_config.h"
 
 using base::StringPrintf;
@@ -54,26 +56,19 @@
  *
  ******************************************************************************/
 bool L2CA_CancelBleConnectReq(const RawAddress& rem_bda) {
-  tL2C_LCB* p_lcb;
+  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
 
-  /* There can be only one BLE connection request outstanding at a time */
-  if (btm_ble_get_conn_st() == BLE_CONN_IDLE) {
-    L2CAP_TRACE_WARNING("%s - no connection pending", __func__);
-    return (false);
+  tACL_CONN* p_acl = btm_bda_to_acl(rem_bda, BT_TRANSPORT_LE);
+  if (p_acl) {
+    if (p_lcb != NULL && p_lcb->link_state == LST_CONNECTING) {
+      L2CAP_TRACE_WARNING("%s - disconnecting the LE link", __func__);
+      L2CA_RemoveFixedChnl(L2CAP_ATT_CID, rem_bda);
+      return (true);
+    }
   }
 
-  if (rem_bda != l2cb.ble_connecting_bda) {
-    LOG(WARNING) << __func__
-                 << " different BDA Connecting: " << l2cb.ble_connecting_bda
-                 << " Cancel: " << rem_bda;
+  connection_manager::direct_connect_remove(CONN_MGR_ID_L2CAP, rem_bda);
 
-    btm_ble_dequeue_direct_conn_req(rem_bda);
-    return (false);
-  }
-
-  btsnd_hcic_ble_create_conn_cancel();
-
-  p_lcb = l2cu_find_lcb_by_bd_addr(rem_bda, BT_TRANSPORT_LE);
   /* Do not remove lcb if an LE link is already up as a peripheral */
   if (p_lcb != NULL &&
       !(p_lcb->link_role == HCI_ROLE_SLAVE &&
@@ -81,9 +76,6 @@
     p_lcb->disc_reason = L2CAP_CONN_CANCEL;
     l2cu_release_lcb(p_lcb);
   }
-  /* update state to be cancel, wait for connection cancel complete */
-  btm_ble_set_conn_st(BLE_CONN_CANCEL);
-
   return (true);
 }
 
@@ -261,39 +253,30 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         l2cble_scanner_conn_comp
- *
- * Description      This function is called when an HCI Connection Complete
- *                  event is received while we are a scanner (so we are master).
- *
- * Returns          void
- *
- ******************************************************************************/
-void l2cble_scanner_conn_comp(uint16_t handle, const RawAddress& bda,
-                              tBLE_ADDR_TYPE type, uint16_t conn_interval,
-                              uint16_t conn_latency, uint16_t conn_timeout) {
-  tL2C_LCB* p_lcb;
-  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda);
+/** This function is called when an HCI Connection Complete event is received.
+ */
+void l2cble_conn_comp(uint16_t handle, uint8_t role, const RawAddress& bda,
+                      tBLE_ADDR_TYPE type, uint16_t conn_interval,
+                      uint16_t conn_latency, uint16_t conn_timeout) {
+  btm_ble_update_link_topology_mask(role, true);
+
+  // role == HCI_ROLE_MASTER => scanner completed connection
+  // role == HCI_ROLE_SLAVE => advertiser completed connection
 
   L2CAP_TRACE_DEBUG(
-      "l2cble_scanner_conn_comp: HANDLE=%d addr_type=%d conn_interval=%d "
+      "%s: HANDLE=%d addr_type=%d conn_interval=%d "
       "slave_latency=%d supervision_tout=%d",
-      handle, type, conn_interval, conn_latency, conn_timeout);
-
-  l2cb.is_ble_connecting = false;
+      __func__, handle, type, conn_interval, conn_latency, conn_timeout);
 
   /* See if we have a link control block for the remote device */
-  p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
+  tL2C_LCB* p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
 
   /* If we don't have one, create one. this is auto connection complete. */
   if (!p_lcb) {
     p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE);
     if (!p_lcb) {
       btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
-      L2CAP_TRACE_ERROR("l2cble_scanner_conn_comp - failed to allocate LCB");
-      btm_ble_set_conn_st(BLE_CONN_IDLE);
+      LOG(ERROR) << __func__ << "failed to allocate LCB";
       return;
     } else {
       if (!l2cu_initialize_fixed_ccb(
@@ -301,25 +284,24 @@
               &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL]
                    .fixed_chnl_opts)) {
         btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
-        L2CAP_TRACE_WARNING("l2cble_scanner_conn_comp - LCB but no CCB");
-        btm_ble_set_conn_st(BLE_CONN_IDLE);
+        LOG(WARNING) << __func__ << "LCB but no CCB";
         return;
       }
     }
-  } else if (p_lcb->link_state != LST_CONNECTING) {
-    L2CAP_TRACE_ERROR("L2CAP got BLE scanner conn_comp in bad state: %d",
-                      p_lcb->link_state);
-    btm_ble_set_conn_st(BLE_CONN_IDLE);
+  } else if (role == HCI_ROLE_MASTER && p_lcb->link_state != LST_CONNECTING) {
+    LOG(ERROR) << "L2CAP got BLE scanner conn_comp in bad state: "
+               << +p_lcb->link_state;
     return;
   }
-  alarm_cancel(p_lcb->l2c_lcb_timer);
+
+  if (role == HCI_ROLE_MASTER) alarm_cancel(p_lcb->l2c_lcb_timer);
 
   /* Save the handle */
   p_lcb->handle = handle;
 
   /* Connected OK. Change state to connected, we were scanning so we are master
    */
-  p_lcb->link_role = HCI_ROLE_MASTER;
+  p_lcb->link_role = role;
   p_lcb->transport = BT_TRANSPORT_LE;
 
   /* update link parameter, set slave link as non-spec default upon link up */
@@ -329,6 +311,7 @@
   p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
 
   /* Tell BTM Acl management about the link */
+  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(bda);
   btm_acl_created(bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role,
                   BT_TRANSPORT_LE);
 
@@ -336,116 +319,17 @@
                              L2CAP_FIXED_CHNL_BLE_SIG_BIT |
                              L2CAP_FIXED_CHNL_SMP_BIT;
 
-  btm_ble_set_conn_st(BLE_CONN_IDLE);
-
 #if (BLE_PRIVACY_SPT == TRUE)
   btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
 #endif
-}
 
-/*******************************************************************************
- *
- * Function         l2cble_advertiser_conn_comp
- *
- * Description      This function is called when an HCI Connection Complete
- *                  event is received while we are an advertiser (so we are
- *                  slave).
- *
- * Returns          void
- *
- ******************************************************************************/
-void l2cble_advertiser_conn_comp(uint16_t handle, const RawAddress& bda,
-                                 UNUSED_ATTR tBLE_ADDR_TYPE type,
-                                 UNUSED_ATTR uint16_t conn_interval,
-                                 UNUSED_ATTR uint16_t conn_latency,
-                                 UNUSED_ATTR uint16_t conn_timeout) {
-  tL2C_LCB* p_lcb;
-  tBTM_SEC_DEV_REC* p_dev_rec;
-
-  /* See if we have a link control block for the remote device */
-  p_lcb = l2cu_find_lcb_by_bd_addr(bda, BT_TRANSPORT_LE);
-
-  /* If we don't have one, create one and accept the connection. */
-  if (!p_lcb) {
-    p_lcb = l2cu_allocate_lcb(bda, false, BT_TRANSPORT_LE);
-    if (!p_lcb) {
-      btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
-      L2CAP_TRACE_ERROR("l2cble_advertiser_conn_comp - failed to allocate LCB");
-      return;
-    } else {
-      if (!l2cu_initialize_fixed_ccb(
-              p_lcb, L2CAP_ATT_CID,
-              &l2cb.fixed_reg[L2CAP_ATT_CID - L2CAP_FIRST_FIXED_CHNL]
-                   .fixed_chnl_opts)) {
-        btm_sec_disconnect(handle, HCI_ERR_NO_CONNECTION);
-        L2CAP_TRACE_WARNING("l2cble_scanner_conn_comp - LCB but no CCB");
-        return;
-      }
+  if (role == HCI_ROLE_SLAVE) {
+    if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(
+            controller_get_interface()->get_features_ble()->as_array)) {
+      p_lcb->link_state = LST_CONNECTED;
+      l2cu_process_fixed_chnl_resp(p_lcb);
     }
   }
-
-  /* Save the handle */
-  p_lcb->handle = handle;
-
-  /* Connected OK. Change state to connected, we were advertising, so we are
-   * slave */
-  p_lcb->link_role = HCI_ROLE_SLAVE;
-  p_lcb->transport = BT_TRANSPORT_LE;
-
-  /* update link parameter, set slave link as non-spec default upon link up */
-  p_lcb->min_interval = p_lcb->max_interval = conn_interval;
-  p_lcb->timeout = conn_timeout;
-  p_lcb->latency = conn_latency;
-  p_lcb->conn_update_mask = L2C_BLE_NOT_DEFAULT_PARAM;
-
-  /* Tell BTM Acl management about the link */
-  p_dev_rec = btm_find_or_alloc_dev(bda);
-
-  btm_acl_created(bda, NULL, p_dev_rec->sec_bd_name, handle, p_lcb->link_role,
-                  BT_TRANSPORT_LE);
-
-#if (BLE_PRIVACY_SPT == TRUE)
-  btm_ble_disable_resolving_list(BTM_BLE_RL_ADV, true);
-#endif
-
-  p_lcb->peer_chnl_mask[0] = L2CAP_FIXED_CHNL_ATT_BIT |
-                             L2CAP_FIXED_CHNL_BLE_SIG_BIT |
-                             L2CAP_FIXED_CHNL_SMP_BIT;
-
-  if (!HCI_LE_SLAVE_INIT_FEAT_EXC_SUPPORTED(
-          controller_get_interface()->get_features_ble()->as_array)) {
-    p_lcb->link_state = LST_CONNECTED;
-    l2cu_process_fixed_chnl_resp(p_lcb);
-  }
-
-  /* when adv and initiating are both active, cancel the direct connection */
-  if (l2cb.is_ble_connecting && bda == l2cb.ble_connecting_bda) {
-    L2CA_CancelBleConnectReq(bda);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         l2cble_conn_comp
- *
- * Description      This function is called when an HCI Connection Complete
- *                  event is received.
- *
- * Returns          void
- *
- ******************************************************************************/
-void l2cble_conn_comp(uint16_t handle, uint8_t role, const RawAddress& bda,
-                      tBLE_ADDR_TYPE type, uint16_t conn_interval,
-                      uint16_t conn_latency, uint16_t conn_timeout) {
-  btm_ble_update_link_topology_mask(role, true);
-
-  if (role == HCI_ROLE_MASTER) {
-    l2cble_scanner_conn_comp(handle, bda, type, conn_interval, conn_latency,
-                             conn_timeout);
-  } else {
-    l2cble_advertiser_conn_comp(handle, bda, type, conn_interval, conn_latency,
-                                conn_timeout);
-  }
 }
 
 /*******************************************************************************
@@ -695,8 +579,8 @@
       if (p_ccb) {
         L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for duplicated cid: 0x%04x",
                             rcid);
-        l2cu_reject_ble_connection(p_lcb, id,
-                                   L2CAP_LE_SOURCE_CID_ALREADY_ALLOCATED);
+        l2cu_reject_ble_connection(
+            p_lcb, id, L2CAP_LE_RESULT_SOURCE_CID_ALREADY_ALLOCATED);
         break;
       }
 
@@ -704,7 +588,7 @@
       if (p_rcb == NULL) {
         L2CAP_TRACE_WARNING("L2CAP - rcvd conn req for unknown PSM: 0x%04x",
                             con_info.psm);
-        l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_NO_PSM);
+        l2cu_reject_ble_connection(p_lcb, id, L2CAP_LE_RESULT_NO_PSM);
         break;
       } else {
         if (!p_rcb->api.pL2CA_ConnectInd_Cb) {
@@ -789,7 +673,7 @@
             p_ccb->peer_conn_cfg.mps < L2CAP_LE_MIN_MPS ||
             p_ccb->peer_conn_cfg.mps > L2CAP_LE_MAX_MPS) {
           L2CAP_TRACE_ERROR("L2CAP don't like the params");
-          con_info.l2cap_result = L2CAP_LE_NO_RESOURCES;
+          con_info.l2cap_result = L2CAP_LE_RESULT_NO_RESOURCES;
           l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
           break;
         }
@@ -800,13 +684,13 @@
         p_ccb->is_first_seg = true;
         p_ccb->peer_cfg.fcr.mode = L2CAP_FCR_LE_COC_MODE;
 
-        if (con_info.l2cap_result == L2CAP_LE_CONN_OK)
+        if (con_info.l2cap_result == L2CAP_LE_RESULT_CONN_OK)
           l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP, &con_info);
         else
           l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
       } else {
         L2CAP_TRACE_DEBUG("I DO NOT remember the connection req");
-        con_info.l2cap_result = L2CAP_LE_INVALID_SOURCE_CID;
+        con_info.l2cap_result = L2CAP_LE_RESULT_INVALID_SOURCE_CID;
         l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
       }
       break;
@@ -873,129 +757,20 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         l2cble_init_direct_conn
- *
- * Description      This function is to initate a direct connection
- *
- * Returns          true connection initiated, false otherwise.
- *
- ******************************************************************************/
-bool l2cble_init_direct_conn(tL2C_LCB* p_lcb) {
-  tBTM_SEC_DEV_REC* p_dev_rec = btm_find_or_alloc_dev(p_lcb->remote_bd_addr);
-  tBTM_BLE_CB* p_cb = &btm_cb.ble_ctr_cb;
-  uint16_t scan_int;
-  uint16_t scan_win;
-  RawAddress peer_addr;
-  uint8_t peer_addr_type = BLE_ADDR_PUBLIC;
-  uint8_t own_addr_type = BLE_ADDR_PUBLIC;
-
-  /* There can be only one BLE connection request outstanding at a time */
-  if (p_dev_rec == NULL) {
-    L2CAP_TRACE_WARNING("unknown device, can not initate connection");
-    return (false);
-  }
-
-  scan_int = (p_cb->scan_int == BTM_BLE_SCAN_PARAM_UNDEF)
-                 ? BTM_BLE_SCAN_FAST_INT
-                 : p_cb->scan_int;
-  scan_win = (p_cb->scan_win == BTM_BLE_SCAN_PARAM_UNDEF)
-                 ? BTM_BLE_SCAN_FAST_WIN
-                 : p_cb->scan_win;
-
-  peer_addr_type = p_lcb->ble_addr_type;
-  peer_addr = p_lcb->remote_bd_addr;
-
-#if (BLE_PRIVACY_SPT == TRUE)
-  own_addr_type =
-      btm_cb.ble_ctr_cb.privacy_mode ? BLE_ADDR_RANDOM : BLE_ADDR_PUBLIC;
-  if (p_dev_rec->ble.in_controller_list & BTM_RESOLVING_LIST_BIT) {
-    if (btm_cb.ble_ctr_cb.privacy_mode >= BTM_PRIVACY_1_2)
-      own_addr_type |= BLE_ADDR_TYPE_ID_BIT;
-
-    btm_ble_enable_resolving_list(BTM_BLE_RL_INIT);
-    btm_random_pseudo_to_identity_addr(&peer_addr, &peer_addr_type);
-  } else {
-    btm_ble_disable_resolving_list(BTM_BLE_RL_INIT, true);
-
-    // If we have a current RPA, use that instead.
-    if (!p_dev_rec->ble.cur_rand_addr.IsEmpty()) {
-      peer_addr = p_dev_rec->ble.cur_rand_addr;
-    }
-  }
-#endif
-
-  if (!btm_ble_topology_check(BTM_BLE_STATE_INIT)) {
-    l2cu_release_lcb(p_lcb);
-    L2CAP_TRACE_ERROR("initate direct connection fail, topology limitation");
-    return false;
-  }
-
-  btm_send_hci_create_connection(
-      scan_int,       /* uint16_t scan_int      */
-      scan_win,       /* uint16_t scan_win      */
-      false,          /* uint8_t white_list     */
-      peer_addr_type, /* uint8_t addr_type_peer */
-      peer_addr,      /* BD_ADDR bda_peer     */
-      own_addr_type,  /* uint8_t addr_type_own  */
-      (uint16_t)(
-          (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_t conn_int_min  */
-      (uint16_t)(
-          (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_t conn_int_max  */
-      (uint16_t)(
-          (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_t conn_latency  */
-      (uint16_t)(
-          (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_t min_len       */
-      0,                                   /* uint16_t max_len       */
-      p_lcb->initiating_phys);
+/** This function is to initate a direct connection. Returns true if connection
+ * initiated, false otherwise. */
+bool l2cble_create_conn(tL2C_LCB* p_lcb) {
+  bool ret = connection_manager::direct_connect_add(CONN_MGR_ID_L2CAP,
+                                                    p_lcb->remote_bd_addr);
+  if (!ret) return ret;
 
   p_lcb->link_state = LST_CONNECTING;
-  l2cb.is_ble_connecting = true;
-  l2cb.ble_connecting_bda = p_lcb->remote_bd_addr;
+
+  // TODO: we should not need this timer at all, the connection failure should
+  // be reported from lower layer
   alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_BLE_LINK_CONNECT_TIMEOUT_MS,
                      l2c_lcb_timer_timeout, p_lcb);
-  btm_ble_set_conn_st(BLE_DIR_CONN);
-
-  return (true);
-}
-
-/*******************************************************************************
- *
- * Function         l2cble_create_conn
- *
- * Description      This function initiates an acl connection via HCI
- *
- * Returns          true if successful, false if connection not started.
- *
- ******************************************************************************/
-bool l2cble_create_conn(tL2C_LCB* p_lcb) {
-  tBTM_BLE_CONN_ST conn_st = btm_ble_get_conn_st();
-  bool rt = false;
-
-  /* There can be only one BLE connection request outstanding at a time */
-  if (conn_st == BLE_CONN_IDLE) {
-    rt = l2cble_init_direct_conn(p_lcb);
-  } else {
-    L2CAP_TRACE_WARNING(
-        "L2CAP - LE - cannot start new connection at conn st: %d", conn_st);
-
-    btm_ble_enqueue_direct_conn_req(p_lcb);
-
-    if (conn_st == BLE_BG_CONN) btm_ble_suspend_bg_conn();
-
-    rt = true;
-  }
-  return rt;
+  return true;
 }
 
 /*******************************************************************************
@@ -1439,20 +1214,20 @@
  * Description      This function is called by LE COC link to meet the
  *                  security requirement for the link
  *
- * Returns          true - security procedures are started
- *                  false - failure
+ * Returns          Returns  - L2CAP LE Connection Response Result Code.
  *
  ******************************************************************************/
-bool l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm,
-                          bool is_originator, tL2CAP_SEC_CBACK* p_callback,
-                          void* p_ref_data) {
+tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr,
+                                           uint16_t psm, bool is_originator,
+                                           tL2CAP_SEC_CBACK* p_callback,
+                                           void* p_ref_data) {
   L2CAP_TRACE_DEBUG("%s", __func__);
-  bool status;
+  tL2CAP_LE_RESULT_CODE result;
   tL2C_LCB* p_lcb = NULL;
 
   if (!p_callback) {
     L2CAP_TRACE_ERROR("%s No callback function", __func__);
-    return false;
+    return L2CAP_LE_RESULT_NO_RESOURCES;
   }
 
   p_lcb = l2cu_find_lcb_by_bd_addr(bd_addr, BT_TRANSPORT_LE);
@@ -1460,14 +1235,14 @@
   if (!p_lcb) {
     L2CAP_TRACE_ERROR("%s Security check for unknown device", __func__);
     p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_UNKNOWN_ADDR);
-    return false;
+    return L2CAP_LE_RESULT_NO_RESOURCES;
   }
 
   tL2CAP_SEC_DATA* p_buf =
       (tL2CAP_SEC_DATA*)osi_malloc((uint16_t)sizeof(tL2CAP_SEC_DATA));
   if (!p_buf) {
     p_callback(bd_addr, BT_TRANSPORT_LE, p_ref_data, BTM_NO_RESOURCES);
-    return false;
+    return L2CAP_LE_RESULT_NO_RESOURCES;
   }
 
   p_buf->psm = psm;
@@ -1475,10 +1250,10 @@
   p_buf->p_callback = p_callback;
   p_buf->p_ref_data = p_ref_data;
   fixed_queue_enqueue(p_lcb->le_sec_pending_q, p_buf);
-  status = btm_ble_start_sec_check(bd_addr, psm, is_originator,
+  result = btm_ble_start_sec_check(bd_addr, psm, is_originator,
                                    &l2cble_sec_comp, p_ref_data);
 
-  return status;
+  return result;
 }
 
 /* This function is called to adjust the connection intervals based on various
diff --git a/stack/l2cap/l2c_csm.cc b/stack/l2cap/l2c_csm.cc
index bb89eac..06ef7e8 100644
--- a/stack/l2cap/l2c_csm.cc
+++ b/stack/l2cap/l2c_csm.cc
@@ -30,6 +30,7 @@
 #include "bt_target.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/time_util.h"
 #include "hcidefs.h"
 #include "hcimsgs.h"
 #include "l2c_int.h"
@@ -238,8 +239,19 @@
 
       if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE) {
         p_ccb->chnl_state = CST_TERM_W4_SEC_COMP;
-        l2ble_sec_access_req(p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm,
-                             false, &l2c_link_sec_comp2, p_ccb);
+        tL2CAP_LE_RESULT_CODE result = l2ble_sec_access_req(
+            p_ccb->p_lcb->remote_bd_addr, p_ccb->p_rcb->psm, false,
+            &l2c_link_sec_comp2, p_ccb);
+
+        switch (result) {
+          case L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION:
+          case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP_KEY_SIZE:
+          case L2CAP_LE_RESULT_INSUFFICIENT_ENCRYP:
+            l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id, result);
+            l2cu_release_ccb(p_ccb);
+            break;
+            // TODO: Handle the other return codes
+        }
       } else {
         /* Cancel sniff mode if needed */
         {
@@ -442,8 +454,9 @@
                            l2c_ccb_timer_timeout, p_ccb);
       } else {
         if (p_ccb->p_lcb->transport == BT_TRANSPORT_LE)
-          l2cu_reject_ble_connection(p_ccb->p_lcb, p_ccb->remote_id,
-                                     L2CAP_LE_INSUFFICIENT_AUTHENTICATION);
+          l2cu_reject_ble_connection(
+              p_ccb->p_lcb, p_ccb->remote_id,
+              L2CAP_LE_RESULT_INSUFFICIENT_AUTHENTICATION);
         else
           l2cu_send_peer_connect_rsp(p_ccb, L2CAP_CONN_SECURITY_BLOCK, 0);
         l2cu_release_ccb(p_ccb);
@@ -804,7 +817,8 @@
           }
 
 #if (L2CAP_ERTM_STATS == TRUE)
-          p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms();
+          p_ccb->fcrb.connect_tick_count =
+              bluetooth::common::time_get_os_boottime_ms();
 #endif
           /* See if we can forward anything on the hold queue */
           if (!fixed_queue_is_empty(p_ccb->xmit_hold_q)) {
@@ -892,7 +906,8 @@
       if (p_ccb->fcrb.wait_ack) l2c_fcr_start_timer(p_ccb);
 
 #if (L2CAP_ERTM_STATS == TRUE)
-      p_ccb->fcrb.connect_tick_count = time_get_os_boottime_ms();
+      p_ccb->fcrb.connect_tick_count =
+          bluetooth::common::time_get_os_boottime_ms();
 #endif
 
       /* See if we can forward anything on the hold queue */
diff --git a/stack/l2cap/l2c_fcr.cc b/stack/l2cap/l2c_fcr.cc
index 88503fb..857a0bf 100644
--- a/stack/l2cap/l2c_fcr.cc
+++ b/stack/l2cap/l2c_fcr.cc
@@ -34,6 +34,7 @@
 #include "btm_api.h"
 #include "btm_int.h"
 #include "btu.h"
+#include "common/time_util.h"
 #include "hcimsgs.h"
 #include "l2c_api.h"
 #include "l2c_int.h"
@@ -231,7 +232,8 @@
 #if (L2CAP_ERTM_STATS == TRUE)
   if ((p_ccb->local_cid >= L2CAP_BASE_APPL_CID) &&
       (p_ccb->peer_cfg.fcr.mode == L2CAP_FCR_ERTM_MODE)) {
-    uint32_t dur = time_get_os_boottime_ms() - p_ccb->fcrb.connect_tick_count;
+    uint64_t dur = bluetooth::common::time_get_os_boottime_ms() -
+                   p_ccb->fcrb.connect_tick_count;
     size_t p_str_size = 120;
     char* p_str = (char*)osi_malloc(p_str_size);
     uint16_t i;
@@ -1804,7 +1806,9 @@
        * to include extra 4 octets at the end.
        */
       p = ((uint8_t*)(p_wack + 1)) + p_wack->offset + p_wack->len;
-      UINT32_TO_STREAM(p, time_get_os_boottime_ms());
+      // Have to cast to uint32_t which wraps in 49.7 days
+      UINT32_TO_STREAM(p, static_cast<uint32_t>(
+                              bluetooth::common::time_get_os_boottime_ms()));
 #endif
       /* We will not save the FCS in case we reconfigure and change options */
       if (p_ccb->bypass_fcs != L2CAP_BYPASS_FCS) p_wack->len -= L2CAP_FCS_LEN;
@@ -2395,7 +2399,9 @@
         }
 
         STREAM_TO_UINT32(timestamp, p);
-        delay = time_get_os_boottime_ms() - timestamp;
+        delay = static_cast<uint32_t>(
+                    bluetooth::common::time_get_os_boottime_ms()) -
+                timestamp;
 
         p_ccb->fcrb.ack_delay_avg[index] += delay;
         if (delay > p_ccb->fcrb.ack_delay_max[index])
@@ -2416,7 +2422,7 @@
     p_ccb->fcrb.ack_delay_avg[index] /= L2CAP_ERTM_STATS_AVG_NUM_SAMPLES;
 
     /* calculate throughput */
-    timestamp = time_get_os_boottime_ms();
+    timestamp = bluetooth::common::time_get_os_boottime_ms();
     if (timestamp - p_ccb->fcrb.throughput_start > 0)
       p_ccb->fcrb.throughput[index] /=
           (timestamp - p_ccb->fcrb.throughput_start);
diff --git a/stack/l2cap/l2c_int.h b/stack/l2cap/l2c_int.h
index 421e34d..53b6f32 100644
--- a/stack/l2cap/l2c_int.h
+++ b/stack/l2cap/l2c_int.h
@@ -28,6 +28,7 @@
 
 #include "bt_common.h"
 #include "btm_api.h"
+#include "btm_ble_api.h"
 #include "l2c_api.h"
 #include "l2cdefs.h"
 #include "osi/include/alarm.h"
@@ -53,6 +54,8 @@
 static_assert(L2CAP_LE_CREDIT_THRESHOLD < L2CAP_LE_CREDIT_DEFAULT,
               "Threshold must be smaller then default credits");
 
+#define L2CAP_NO_IDLE_TIMEOUT 0xFFFF
+
 /*
  * Timeout values (in milliseconds).
  */
@@ -209,7 +212,7 @@
   alarm_t* mon_retrans_timer; /* Timer Monitor or Retransmission */
 
 #if (L2CAP_ERTM_STATS == TRUE)
-  uint32_t connect_tick_count;  /* Time channel was established */
+  uint64_t connect_tick_count;  /* Time channel was established */
   uint32_t ertm_pkt_counts[2];  /* Packets sent and received */
   uint32_t ertm_byte_counts[2]; /* Bytes   sent and received */
   uint32_t s_frames_sent[4];    /* S-frames sent (RR, REJ, RNR, SREJ) */
@@ -238,6 +241,7 @@
 
 typedef struct {
   bool in_use;
+  bool log_packets;
   uint16_t psm;
   uint16_t real_psm; /* This may be a dummy RCB for an o/b connection but */
                      /* this is the real PSM that we need to connect to */
@@ -503,8 +507,6 @@
 #endif
 
   uint16_t num_ble_links_active; /* Number of LE links active */
-  bool is_ble_connecting;
-  RawAddress ble_connecting_bda;
   uint16_t controller_le_xmit_window; /* Total ACL window for all links */
   tL2C_BLE_FIXED_CHNLS_MASK l2c_ble_fixed_chnls_mask;  // LE fixed channels mask
   uint16_t num_lm_ble_bufs;         /* # of ACL buffers on controller */
@@ -688,9 +690,9 @@
 extern tL2C_LCB* l2cu_find_lcb_by_state(tL2C_LINK_STATE state);
 extern bool l2cu_lcb_disconnecting(void);
 
-extern bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport);
-extern bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
-                             uint8_t initiating_phys);
+extern bool l2cu_create_conn_br_edr(tL2C_LCB* p_lcb);
+extern bool l2cu_create_conn_le(tL2C_LCB* p_lcb);
+extern bool l2cu_create_conn_le(tL2C_LCB* p_lcb, uint8_t initiating_phys);
 extern bool l2cu_create_conn_after_switch(tL2C_LCB* p_lcb);
 extern BT_HDR* l2cu_get_next_buffer_to_send(tL2C_LCB* p_lcb,
                                             tL2C_TX_COMPLETE_CB_INFO* p_cbi);
@@ -788,7 +790,6 @@
                              const RawAddress& bda, tBLE_ADDR_TYPE type,
                              uint16_t conn_interval, uint16_t conn_latency,
                              uint16_t conn_timeout);
-extern bool l2cble_init_direct_conn(tL2C_LCB* p_lcb);
 extern void l2cble_notify_le_connection(const RawAddress& bda);
 extern void l2c_ble_link_adjust_allocation(void);
 extern void l2cble_process_conn_update_evt(uint16_t handle, uint8_t status,
@@ -800,10 +801,11 @@
 extern void l2cble_send_peer_disc_req(tL2C_CCB* p_ccb);
 extern void l2cble_send_flow_control_credit(tL2C_CCB* p_ccb,
                                             uint16_t credit_value);
-extern bool l2ble_sec_access_req(const RawAddress& bd_addr, uint16_t psm,
-                                 bool is_originator,
-                                 tL2CAP_SEC_CBACK* p_callback,
-                                 void* p_ref_data);
+extern tL2CAP_LE_RESULT_CODE l2ble_sec_access_req(const RawAddress& bd_addr,
+                                                  uint16_t psm,
+                                                  bool is_originator,
+                                                  tL2CAP_SEC_CBACK* p_callback,
+                                                  void* p_ref_data);
 
 #if (BLE_LLT_INCLUDED == TRUE)
 extern void l2cble_process_rc_param_request_evt(uint16_t handle,
diff --git a/stack/l2cap/l2c_link.cc b/stack/l2cap/l2c_link.cc
index db7e613..8e04c6e 100644
--- a/stack/l2cap/l2c_link.cc
+++ b/stack/l2cap/l2c_link.cc
@@ -159,10 +159,15 @@
   /* See if we have a link control block for the remote device */
   p_lcb = l2cu_find_lcb_by_bd_addr(ci.bd_addr, BT_TRANSPORT_BR_EDR);
 
-  /* If we don't have one, this is an error */
-  if (!p_lcb) {
-    L2CAP_TRACE_WARNING("L2CAP got conn_comp for unknown BD_ADDR");
-    return (false);
+  /* If we don't have one, allocate one */
+  if (p_lcb == nullptr) {
+    L2CAP_TRACE_WARNING("No available link control block, try allocate one");
+    p_lcb = l2cu_allocate_lcb(ci.bd_addr, false, BT_TRANSPORT_BR_EDR);
+    if (p_lcb == nullptr) {
+      L2CAP_TRACE_WARNING("%s: Failed to allocate an LCB", __func__);
+      return (false);
+    }
+    p_lcb->link_state = LST_CONNECTING;
   }
 
   if (p_lcb->link_state != LST_CONNECTING) {
@@ -217,7 +222,7 @@
       alarm_set_on_mloop(p_lcb->l2c_lcb_timer, L2CAP_ECHO_RSP_TIMEOUT_MS,
                          l2c_lcb_timer_timeout, p_lcb);
     } else if (!p_lcb->ccb_queue.p_first_ccb) {
-      period_ms_t timeout_ms = L2CAP_LINK_STARTUP_TOUT * 1000;
+      uint64_t timeout_ms = L2CAP_LINK_STARTUP_TOUT * 1000;
       alarm_set_on_mloop(p_lcb->l2c_lcb_timer, timeout_ms,
                          l2c_lcb_timer_timeout, p_lcb);
     }
@@ -253,7 +258,7 @@
          * controller */
         p_lcb->link_state = LST_CONNECTING;
       } else {
-        l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR);
+        l2cu_create_conn_br_edr(p_lcb);
       }
     }
   }
@@ -383,11 +388,9 @@
       p_ccb = pn;
     }
 
-#if (BTM_SCO_INCLUDED == TRUE)
     if (p_lcb->transport == BT_TRANSPORT_BR_EDR)
       /* Tell SCO management to drop any SCOs on this ACL */
       btm_sco_acl_removed(&p_lcb->remote_bd_addr);
-#endif
 
     /* If waiting for disconnect and reconnect is pending start the reconnect
        now
@@ -408,7 +411,6 @@
       /* for LE link, always drop and re-open to ensure to get LE remote feature
        */
       if (p_lcb->transport == BT_TRANSPORT_LE) {
-        l2cb.is_ble_connecting = false;
         btm_acl_removed(p_lcb->remote_bd_addr, p_lcb->transport);
       } else {
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
@@ -441,8 +443,13 @@
         }
 #endif
       }
-      if (l2cu_create_conn(p_lcb, transport))
-        lcb_is_free = false; /* still using this lcb */
+      if (p_lcb->transport == BT_TRANSPORT_LE) {
+        if (l2cu_create_conn_le(p_lcb))
+          lcb_is_free = false; /* still using this lcb */
+      } else {
+        if (l2cu_create_conn_br_edr(p_lcb))
+          lcb_is_free = false; /* still using this lcb */
+      }
     }
 
     p_lcb->p_pending_ccb = NULL;
@@ -455,7 +462,7 @@
   if (lcb_is_free &&
       ((p_lcb = l2cu_find_lcb_by_state(LST_CONNECT_HOLDING)) != NULL)) {
     /* we found one-- create a connection */
-    l2cu_create_conn(p_lcb, BT_TRANSPORT_BR_EDR);
+    l2cu_create_conn_br_edr(p_lcb);
   }
 
   return status;
@@ -524,9 +531,7 @@
 
       p_ccb = pn;
     }
-    if (p_lcb->link_state == LST_CONNECTING && l2cb.is_ble_connecting) {
-      L2CA_CancelBleConnectReq(l2cb.ble_connecting_bda);
-    }
+
     /* Release the LCB */
     l2cu_release_lcb(p_lcb);
   }
@@ -557,7 +562,7 @@
 
     /* If no channels in use, drop the link. */
     if (!p_lcb->ccb_queue.p_first_ccb) {
-      period_ms_t timeout_ms;
+      uint64_t timeout_ms;
       bool start_timeout = true;
 
       rc = btm_sec_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
diff --git a/stack/l2cap/l2c_main.cc b/stack/l2cap/l2c_main.cc
index 74e7135..128f60e 100644
--- a/stack/l2cap/l2c_main.cc
+++ b/stack/l2cap/l2c_main.cc
@@ -33,6 +33,7 @@
 #include "btm_int.h"
 #include "btu.h"
 #include "device/include/controller.h"
+#include "hci/include/btsnoop.h"
 #include "hcimsgs.h"
 #include "l2c_api.h"
 #include "l2c_int.h"
@@ -79,8 +80,8 @@
 
   uint16_t hci_len;
   STREAM_TO_UINT16(hci_len, p);
-  if (hci_len < L2CAP_PKT_OVERHEAD) {
-    /* Must receive at least the L2CAP length and CID */
+  if (hci_len < L2CAP_PKT_OVERHEAD || hci_len != p_msg->len - 4) {
+    /* Remote-declared packet size must match HCI_ACL size - ACL header (4) */
     L2CAP_TRACE_WARNING("L2CAP - got incorrect hci header");
     osi_free(p_msg);
     return;
@@ -396,6 +397,14 @@
         p_ccb->p_rcb = p_rcb;
         p_ccb->remote_cid = rcid;
 
+        if (p_rcb->psm == BT_PSM_RFCOMM) {
+          btsnoop_get_interface()->add_rfc_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        } else if (p_rcb->log_packets) {
+          btsnoop_get_interface()->whitelist_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        }
+
         l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_REQ, &con_info);
         break;
       }
@@ -427,6 +436,15 @@
         else
           l2c_csm_execute(p_ccb, L2CEVT_L2CAP_CONNECT_RSP_NEG, &con_info);
 
+        tL2C_RCB* p_rcb = p_ccb->p_rcb;
+        if (p_rcb->psm == BT_PSM_RFCOMM) {
+          btsnoop_get_interface()->add_rfc_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        } else if (p_rcb->log_packets) {
+          btsnoop_get_interface()->whitelist_l2c_channel(
+              p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+        }
+
         break;
       }
 
@@ -763,6 +781,10 @@
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
         if (info_type == L2CAP_FIXED_CHANNELS_INFO_TYPE) {
           if (result == L2CAP_INFO_RESP_RESULT_SUCCESS) {
+            if (p + L2CAP_FIXED_CHNL_ARRAY_SIZE > p_next_cmd) {
+              android_errorWriteLog(0x534e4554, "111215173");
+              return;
+            }
             memcpy(p_lcb->peer_chnl_mask, p, L2CAP_FIXED_CHNL_ARRAY_SIZE);
           }
 
diff --git a/stack/l2cap/l2c_utils.cc b/stack/l2cap/l2c_utils.cc
index ced48a2..593f12f 100644
--- a/stack/l2cap/l2c_utils.cc
+++ b/stack/l2cap/l2c_utils.cc
@@ -33,6 +33,7 @@
 #include "btm_int.h"
 #include "btu.h"
 #include "device/include/controller.h"
+#include "hci/include/btsnoop.h"
 #include "hcidefs.h"
 #include "hcimsgs.h"
 #include "l2c_int.h"
@@ -152,10 +153,8 @@
   /* Release any unfinished L2CAP packet on this link */
   osi_free_and_reset((void**)&p_lcb->p_hcit_rcv_acl);
 
-#if (BTM_SCO_INCLUDED == TRUE)
   if (p_lcb->transport == BT_TRANSPORT_BR_EDR) /* Release all SCO links */
     btm_remove_sco_links(p_lcb->remote_bd_addr);
-#endif
 
   if (p_lcb->sent_not_acked > 0) {
     if (p_lcb->transport == BT_TRANSPORT_LE) {
@@ -171,11 +170,6 @@
     }
   }
 
-  // Reset BLE connecting flag only if the address matches
-  if (p_lcb->transport == BT_TRANSPORT_LE &&
-      l2cb.ble_connecting_bda == p_lcb->remote_bd_addr)
-    l2cb.is_ble_connecting = false;
-
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
   l2cu_process_fixed_disc_cback(p_lcb);
 #endif
@@ -1540,7 +1534,7 @@
   if ((p_lcb->link_state == LST_CONNECTED) ||
       (p_lcb->link_state == LST_CONNECTING) ||
       (p_lcb->link_state == LST_DISCONNECTING)) {
-    period_ms_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000;
+    uint64_t timeout_ms = L2CAP_BONDING_TIMEOUT * 1000;
 
     if (p_lcb->idle_timeout == 0) {
       btsnd_hcic_disconnect(p_lcb->handle, HCI_ERR_PEER_USER);
@@ -1576,6 +1570,9 @@
   /* If already released, could be race condition */
   if (!p_ccb->in_use) return;
 
+  btsnoop_get_interface()->clear_l2cap_whitelist(
+      p_lcb->handle, p_ccb->local_cid, p_ccb->remote_cid);
+
   if (p_rcb && (p_rcb->psm != p_rcb->real_psm)) {
     btm_sec_clr_service_by_psm(p_rcb->psm);
   }
@@ -1622,18 +1619,28 @@
   p_ccb->in_use = false;
 
   /* 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) {
-      // Closing a security channel on LE device should not start connection
-      // timeout
-      if (p_lcb->transport == BT_TRANSPORT_LE &&
-          p_ccb->local_cid == L2CAP_SMP_CID)
-        return;
+  if ((p_lcb) && p_lcb->in_use) {
+    if (p_lcb->link_state == LST_CONNECTED) {
+      if (!p_lcb->ccb_queue.p_first_ccb) {
+        // Closing a security channel on LE device should not start connection
+        // timeout
+        if (p_lcb->transport == BT_TRANSPORT_LE &&
+            p_ccb->local_cid == L2CAP_SMP_CID)
+          return;
 
-      l2cu_no_dynamic_ccbs(p_lcb);
-    } else {
-      /* Link is still active, adjust channel quotas. */
-      l2c_link_adjust_chnl_allocation();
+        l2cu_no_dynamic_ccbs(p_lcb);
+      } else {
+        /* Link is still active, adjust channel quotas. */
+        l2c_link_adjust_chnl_allocation();
+      }
+    } else if (p_lcb->link_state == LST_CONNECTING) {
+      if (!p_lcb->ccb_queue.p_first_ccb) {
+        if (p_lcb->transport == BT_TRANSPORT_LE &&
+            p_ccb->local_cid == L2CAP_ATT_CID) {
+          L2CAP_TRACE_WARNING("%s - disconnecting the LE link", __func__);
+          l2cu_no_dynamic_ccbs(p_lcb);
+        }
+      }
     }
   }
 }
@@ -2100,45 +2107,36 @@
       l2c_link_hci_disc_comp(p_lcb->handle, (uint8_t)-1);
     }
   }
-  l2cb.is_ble_connecting = false;
 }
 
-/*******************************************************************************
- *
- * Function         l2cu_create_conn
- *
- * Description      This function initiates an acl connection via HCI
- *
- * Returns          true if successful, false if get buffer fails.
- *
- ******************************************************************************/
-bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport) {
+bool l2cu_create_conn_le(tL2C_LCB* p_lcb) {
   uint8_t phy = controller_get_interface()->get_le_all_initiating_phys();
-  return l2cu_create_conn(p_lcb, transport, phy);
+  return l2cu_create_conn_le(p_lcb, phy);
 }
 
-bool l2cu_create_conn(tL2C_LCB* p_lcb, tBT_TRANSPORT transport,
-                      uint8_t initiating_phys) {
-  int xx;
-  tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
-#if (BTM_SCO_INCLUDED == TRUE)
-  bool is_sco_active;
-#endif
-
+/* This function initiates an acl connection to a LE device.
+ * Returns true if request started successfully, false otherwise. */
+bool l2cu_create_conn_le(tL2C_LCB* p_lcb, uint8_t initiating_phys) {
   tBT_DEVICE_TYPE dev_type;
   tBLE_ADDR_TYPE addr_type;
 
   BTM_ReadDevInfo(p_lcb->remote_bd_addr, &dev_type, &addr_type);
 
-  if (transport == BT_TRANSPORT_LE) {
-    if (!controller_get_interface()->supports_ble()) return false;
+  if (!controller_get_interface()->supports_ble()) return false;
 
-    p_lcb->ble_addr_type = addr_type;
-    p_lcb->transport = BT_TRANSPORT_LE;
-    p_lcb->initiating_phys = initiating_phys;
+  p_lcb->ble_addr_type = addr_type;
+  p_lcb->transport = BT_TRANSPORT_LE;
+  p_lcb->initiating_phys = initiating_phys;
 
-    return (l2cble_create_conn(p_lcb));
-  }
+  return (l2cble_create_conn(p_lcb));
+}
+
+/* This function initiates an acl connection to a Classic device via HCI.
+ * Returns true on success, false otherwise. */
+bool l2cu_create_conn_br_edr(tL2C_LCB* p_lcb) {
+  int xx;
+  tL2C_LCB* p_lcb_cur = &l2cb.lcb_pool[0];
+  bool is_sco_active;
 
   /* If there is a connection where we perform as a slave, try to switch roles
      for this connection */
@@ -2147,7 +2145,6 @@
     if (p_lcb_cur == p_lcb) continue;
 
     if ((p_lcb_cur->in_use) && (p_lcb_cur->link_role == HCI_ROLE_SLAVE)) {
-#if (BTM_SCO_INCLUDED == TRUE)
       /* The LMP_switch_req shall be sent only if the ACL logical transport
       is in active mode, when encryption is disabled, and all synchronous
       logical transports on the same physical link are disabled." */
@@ -2161,7 +2158,6 @@
 
       if (is_sco_active)
         continue; /* No Master Slave switch not allowed when SCO Active */
-#endif
       /*4_1_TODO check  if btm_cb.devcb.local_features to be used instead */
       if (HCI_SWITCH_SUPPORTED(BTM_ReadLocalFeatures())) {
         /* mark this lcb waiting for switch to be completed and
@@ -2601,7 +2597,7 @@
  ******************************************************************************/
 void l2cu_no_dynamic_ccbs(tL2C_LCB* p_lcb) {
   tBTM_STATUS rc;
-  period_ms_t timeout_ms = p_lcb->idle_timeout * 1000;
+  uint64_t timeout_ms = p_lcb->idle_timeout * 1000;
   bool start_timeout = true;
 
 #if (L2CAP_NUM_FIXED_CHNLS > 0)
@@ -2610,6 +2606,12 @@
   for (xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
     if ((p_lcb->p_fixed_ccbs[xx] != NULL) &&
         (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000 > timeout_ms)) {
+
+      if (p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout == L2CAP_NO_IDLE_TIMEOUT) {
+         L2CAP_TRACE_DEBUG("%s NO IDLE timeout set for fixed cid 0x%04x", __func__,
+            p_lcb->p_fixed_ccbs[xx]->local_cid);
+         start_timeout = false;
+      }
       timeout_ms = p_lcb->p_fixed_ccbs[xx]->fixed_chnl_idle_tout * 1000;
     }
   }
@@ -2674,28 +2676,34 @@
 
   /* Tell all registered fixed channels about the connection */
   for (int xx = 0; xx < L2CAP_NUM_FIXED_CHNLS; xx++) {
+    uint16_t channel_id = xx + L2CAP_FIRST_FIXED_CHNL;
+
+    /* See BT Spec Ver 5.0 | Vol 3, Part A 2.1 table 2.1 and 2.2 */
+
     /* skip sending LE fix channel callbacks on BR/EDR links */
     if (p_lcb->transport == BT_TRANSPORT_BR_EDR &&
-        xx + L2CAP_FIRST_FIXED_CHNL >= L2CAP_ATT_CID &&
-        xx + L2CAP_FIRST_FIXED_CHNL <= L2CAP_SMP_CID)
+        channel_id >= L2CAP_ATT_CID && channel_id <= L2CAP_SMP_CID)
       continue;
-    if (l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb != NULL) {
-      if (p_lcb->peer_chnl_mask[(xx + L2CAP_FIRST_FIXED_CHNL) / 8] &
-          (1 << ((xx + L2CAP_FIRST_FIXED_CHNL) % 8))) {
-        if (p_lcb->p_fixed_ccbs[xx])
-          p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
-        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(xx + L2CAP_FIRST_FIXED_CHNL,
-                                                 p_lcb->remote_bd_addr, true, 0,
-                                                 p_lcb->transport);
-      } else {
-        (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
-            xx + L2CAP_FIRST_FIXED_CHNL, p_lcb->remote_bd_addr, false,
-            p_lcb->disc_reason, p_lcb->transport);
 
-        if (p_lcb->p_fixed_ccbs[xx]) {
-          l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
-          p_lcb->p_fixed_ccbs[xx] = NULL;
-        }
+    /* skip sending BR fix channel callbacks on LE links */
+    if (p_lcb->transport == BT_TRANSPORT_LE && channel_id == L2CAP_SMP_BR_CID)
+      continue;
+
+    if (!l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb) continue;
+
+    if (p_lcb->peer_chnl_mask[(channel_id) / 8] & (1 << ((channel_id) % 8))) {
+      if (p_lcb->p_fixed_ccbs[xx])
+        p_lcb->p_fixed_ccbs[xx]->chnl_state = CST_OPEN;
+      (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
+          channel_id, p_lcb->remote_bd_addr, true, 0, p_lcb->transport);
+    } else {
+      (*l2cb.fixed_reg[xx].pL2CA_FixedConn_Cb)(
+          channel_id, p_lcb->remote_bd_addr, false, p_lcb->disc_reason,
+          p_lcb->transport);
+
+      if (p_lcb->p_fixed_ccbs[xx]) {
+        l2cu_release_ccb(p_lcb->p_fixed_ccbs[xx]);
+        p_lcb->p_fixed_ccbs[xx] = NULL;
       }
     }
   }
diff --git a/stack/mcap/mca_api.cc b/stack/mcap/mca_api.cc
deleted file mode 100644
index 578d53e..0000000
--- a/stack/mcap/mca_api.cc
+++ /dev/null
@@ -1,860 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the API implementation file for the Multi-Channel Adaptation
- *  Protocol (MCAP).
- *
- ******************************************************************************/
-#include <base/logging.h>
-#include <string.h>
-
-#include "bt_target.h"
-#include "btm_api.h"
-#include "btm_int.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "mca_int.h"
-
-#include "btu.h"
-
-/*******************************************************************************
- *
- * Function         mca_process_timeout
- *
- * Description      This function is called by BTU when an MCA timer
- *                  expires.
- *
- *                  This function is for use internal to the stack only.
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_ccb_timer_timeout(void* data) {
-  tMCA_CCB* p_ccb = (tMCA_CCB*)data;
-
-  mca_ccb_event(p_ccb, MCA_CCB_RSP_TOUT_EVT, NULL);
-}
-
-/*******************************************************************************
- *
- * Function         MCA_Init
- *
- * Description      Initialize MCAP main control block.
- *                  This function is called at stack start up.
- *
- * Returns          void
- *
- ******************************************************************************/
-void MCA_Init(void) {
-  memset(&mca_cb, 0, sizeof(tMCA_CB));
-
-#if defined(MCA_INITIAL_TRACE_LEVEL)
-  mca_cb.trace_level = MCA_INITIAL_TRACE_LEVEL;
-#else
-  mca_cb.trace_level = BT_TRACE_LEVEL_NONE;
-#endif
-}
-
-/*******************************************************************************
- *
- * Function         MCA_SetTraceLevel
- *
- * Description      This function sets the debug trace level for MCA.
- *                  If 0xff is passed, the current trace level is returned.
- *
- *                  Input Parameters:
- *                      level:  The level to set the MCA 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_t MCA_SetTraceLevel(uint8_t level) {
-  if (level != 0xFF) mca_cb.trace_level = level;
-
-  return (mca_cb.trace_level);
-}
-
-/*******************************************************************************
- *
- * Function         MCA_Register
- *
- * Description      This function registers an MCAP implementation.
- *                  It is assumed that the control channel PSM and data channel
- *                  PSM are not used by any other instances of the stack.
- *                  If the given p_reg->ctrl_psm is 0, this handle is INT only.
- *
- * Returns          0, if failed. Otherwise, the MCA handle.
- *
- ******************************************************************************/
-tMCA_HANDLE MCA_Register(tMCA_REG* p_reg, tMCA_CTRL_CBACK* p_cback) {
-  tMCA_RCB* p_rcb;
-  tMCA_HANDLE handle = 0;
-  tL2CAP_APPL_INFO l2c_cacp_appl;
-  tL2CAP_APPL_INFO l2c_dacp_appl;
-
-  CHECK(p_reg != NULL);
-  CHECK(p_cback != NULL);
-
-  MCA_TRACE_API("MCA_Register: ctrl_psm:0x%x, data_psm:0x%x", p_reg->ctrl_psm,
-                p_reg->data_psm);
-
-  p_rcb = mca_rcb_alloc(p_reg);
-  if (p_rcb != NULL) {
-    if (p_reg->ctrl_psm) {
-      if (L2C_INVALID_PSM(p_reg->ctrl_psm) ||
-          L2C_INVALID_PSM(p_reg->data_psm)) {
-        MCA_TRACE_ERROR("INVALID_PSM");
-        return 0;
-      }
-
-      l2c_cacp_appl = *(tL2CAP_APPL_INFO*)&mca_l2c_int_appl;
-      l2c_cacp_appl.pL2CA_ConnectCfm_Cb = NULL;
-      l2c_dacp_appl = *(tL2CAP_APPL_INFO*)&l2c_cacp_appl;
-      l2c_cacp_appl.pL2CA_ConnectInd_Cb = mca_l2c_cconn_ind_cback;
-      l2c_dacp_appl.pL2CA_ConnectInd_Cb = mca_l2c_dconn_ind_cback;
-      if (L2CA_Register(p_reg->ctrl_psm, (tL2CAP_APPL_INFO*)&l2c_cacp_appl) &&
-          L2CA_Register(p_reg->data_psm, (tL2CAP_APPL_INFO*)&l2c_dacp_appl)) {
-        /* set security level */
-        BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_MCAP_CTRL,
-                             p_reg->sec_mask, p_reg->ctrl_psm,
-                             BTM_SEC_PROTO_MCA, MCA_CTRL_TCID);
-
-        /* in theory, we do not need this one for data_psm
-         * If we don't, L2CAP rejects with security block (3),
-         * which is different reject code from what MCAP spec suggests.
-         * we set this one, so mca_l2c_dconn_ind_cback can reject /w no
-         * resources (4) */
-        BTM_SetSecurityLevel(false, "", BTM_SEC_SERVICE_MCAP_DATA,
-                             p_reg->sec_mask, p_reg->data_psm,
-                             BTM_SEC_PROTO_MCA, MCA_CTRL_TCID);
-      } else {
-        MCA_TRACE_ERROR("Failed to register to L2CAP");
-        return 0;
-      }
-    } else
-      p_rcb->reg.data_psm = 0;
-    handle = mca_rcb_to_handle(p_rcb);
-    p_rcb->p_cback = p_cback;
-    p_rcb->reg.rsp_tout = p_reg->rsp_tout;
-  }
-  return handle;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_Deregister
- *
- * Description      Deregister an MCAP implementation.  Before this function can
- *                  be called, all control and data channels must be removed
- *                  with MCA_DisconnectReq and MCA_CloseReq.
- *
- * Returns          void
- *
- ******************************************************************************/
-void MCA_Deregister(tMCA_HANDLE handle) {
-  tMCA_RCB* p_rcb = mca_rcb_by_handle(handle);
-
-  MCA_TRACE_API("MCA_Deregister: %d", handle);
-  if (p_rcb && p_rcb->reg.ctrl_psm) {
-    L2CA_Deregister(p_rcb->reg.ctrl_psm);
-    L2CA_Deregister(p_rcb->reg.data_psm);
-    btm_sec_clr_service_by_psm(p_rcb->reg.ctrl_psm);
-    btm_sec_clr_service_by_psm(p_rcb->reg.data_psm);
-  }
-  mca_rcb_dealloc(handle);
-}
-
-/*******************************************************************************
- *
- * Function         MCA_CreateDep
- *
- * Description      Create a data endpoint. If the MDEP is created successfully,
- *                  the MDEP ID is returned in *p_dep. After a data endpoint is
- *                  created, an application can initiate a connection between
- *                  this endpoint and an endpoint on a peer device.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_CreateDep(tMCA_HANDLE handle, tMCA_DEP* p_dep, tMCA_CS* p_cs) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  int i;
-  tMCA_RCB* p_rcb = mca_rcb_by_handle(handle);
-  tMCA_CS* p_depcs;
-
-  CHECK(p_dep != NULL);
-  CHECK(p_cs != NULL);
-  CHECK(p_cs->p_data_cback != NULL);
-
-  MCA_TRACE_API("MCA_CreateDep: %d", handle);
-  if (p_rcb) {
-    if (p_cs->max_mdl > MCA_NUM_MDLS) {
-      MCA_TRACE_ERROR("max_mdl: %d is too big", p_cs->max_mdl);
-      result = MCA_BAD_PARAMS;
-    } else {
-      p_depcs = p_rcb->dep;
-      if (p_cs->type == MCA_TDEP_ECHO) {
-        if (p_depcs->p_data_cback) {
-          MCA_TRACE_ERROR("Already has ECHO MDEP");
-          return MCA_NO_RESOURCES;
-        }
-        memcpy(p_depcs, p_cs, sizeof(tMCA_CS));
-        *p_dep = 0;
-        result = MCA_SUCCESS;
-      } else {
-        result = MCA_NO_RESOURCES;
-        /* non-echo MDEP starts from 1 */
-        p_depcs++;
-        for (i = 1; i < MCA_NUM_DEPS; i++, p_depcs++) {
-          if (p_depcs->p_data_cback == NULL) {
-            memcpy(p_depcs, p_cs, sizeof(tMCA_CS));
-            /* internally use type as the mdep id */
-            p_depcs->type = i;
-            *p_dep = i;
-            result = MCA_SUCCESS;
-            break;
-          }
-        }
-      }
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_DeleteDep
- *
- * Description      Delete a data endpoint.  This function is called when
- *                  the implementation is no longer using a data endpoint.
- *                  If this function is called when the endpoint is connected
- *                  the connection is closed and the data endpoint
- *                  is removed.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_DeleteDep(tMCA_HANDLE handle, tMCA_DEP dep) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_RCB* p_rcb = mca_rcb_by_handle(handle);
-  tMCA_DCB* p_dcb;
-  int i, max;
-  tMCA_CS* p_depcs;
-
-  MCA_TRACE_API("MCA_DeleteDep: %d dep:%d", handle, dep);
-  if (p_rcb) {
-    if (dep < MCA_NUM_DEPS && p_rcb->dep[dep].p_data_cback) {
-      result = MCA_SUCCESS;
-      p_rcb->dep[dep].p_data_cback = NULL;
-      p_depcs = &(p_rcb->dep[dep]);
-      i = handle - 1;
-      max = MCA_NUM_MDLS * MCA_NUM_LINKS;
-      p_dcb = &mca_cb.dcb[i * max];
-      /* make sure no MDL exists for this MDEP */
-      for (i = 0; i < max; i++, p_dcb++) {
-        if (p_dcb->state && p_dcb->p_cs == p_depcs) {
-          mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
-        }
-      }
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_ConnectReq
- *
- * Description      This function initiates an MCAP control channel connection
- *                  to the peer device.  When the connection is completed, an
- *                  MCA_CONNECT_IND_EVT is reported to the application via its
- *                  control callback function.
- *                  This control channel is identified by the tMCA_CL.
- *                  If the connection attempt fails, an MCA_DISCONNECT_IND_EVT
- *                  is reported. The security mask parameter overrides the
- *                  outgoing security mask set in MCA_Register().
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_ConnectReq(tMCA_HANDLE handle, const RawAddress& bd_addr,
-                           uint16_t ctrl_psm, uint16_t sec_mask) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb;
-  tMCA_TC_TBL* p_tbl;
-
-  MCA_TRACE_API("MCA_ConnectReq: %d psm:0x%x", handle, ctrl_psm);
-  p_ccb = mca_ccb_by_bd(handle, bd_addr);
-  if (p_ccb == NULL)
-    p_ccb = mca_ccb_alloc(handle, bd_addr);
-  else {
-    MCA_TRACE_ERROR("control channel already exists");
-    return MCA_BUSY;
-  }
-
-  if (p_ccb) {
-    p_ccb->ctrl_vpsm =
-        L2CA_Register(ctrl_psm, (tL2CAP_APPL_INFO*)&mca_l2c_int_appl);
-    result = MCA_NO_RESOURCES;
-    if (p_ccb->ctrl_vpsm) {
-      BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_MCAP_CTRL, sec_mask,
-                           p_ccb->ctrl_vpsm, BTM_SEC_PROTO_MCA, MCA_CTRL_TCID);
-      p_ccb->lcid = mca_l2c_open_req(bd_addr, p_ccb->ctrl_vpsm, NULL);
-      if (p_ccb->lcid) {
-        p_tbl = mca_tc_tbl_calloc(p_ccb);
-        if (p_tbl) {
-          p_tbl->state = MCA_TC_ST_CONN;
-          p_ccb->sec_mask = sec_mask;
-          result = MCA_SUCCESS;
-        }
-      }
-    }
-    if (result != MCA_SUCCESS) mca_ccb_dealloc(p_ccb, NULL);
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_DisconnectReq
- *
- * Description      This function disconnect an MCAP control channel
- *                  to the peer device.
- *                  If associated data channel exists, they are disconnected.
- *                  When the MCL is disconnected an MCA_DISCONNECT_IND_EVT is
- *                  reported to the application via its control callback
- *                  function.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_DisconnectReq(tMCA_CL mcl) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-
-  MCA_TRACE_API("MCA_DisconnectReq: %d ", mcl);
-  if (p_ccb) {
-    result = MCA_SUCCESS;
-    mca_ccb_event(p_ccb, MCA_CCB_API_DISCONNECT_EVT, NULL);
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_CreateMdl
- *
- * Description      This function sends a CREATE_MDL request to the peer device.
- *                  When the response is received, a MCA_CREATE_CFM_EVT is
- *                  reported with the given MDL ID.
- *                  If the response is successful, a data channel is open
- *                  with the given p_chnl_cfg
- *                  If p_chnl_cfg is NULL, the data channel is not initiated
- *                  until MCA_DataChnlCfg is called to provide the p_chnl_cfg.
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_CFM_EVT is reported. This data channel is
- *                  identified as tMCA_DL.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_CreateMdl(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm,
-                          uint16_t mdl_id, uint8_t peer_dep_id, uint8_t cfg,
-                          const tMCA_CHNL_CFG* p_chnl_cfg) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-  tMCA_DCB* p_dcb;
-
-  MCA_TRACE_API("MCA_CreateMdl: %d dep=%d mdl_id=%d peer_dep_id=%d", mcl, dep,
-                mdl_id, peer_dep_id);
-  if (p_ccb) {
-    if (p_ccb->p_tx_req || p_ccb->p_rx_msg || p_ccb->cong) {
-      MCA_TRACE_ERROR("pending req");
-      return MCA_BUSY;
-    }
-
-    if ((peer_dep_id > MCA_MAX_MDEP_ID) || (!MCA_IS_VALID_MDL_ID(mdl_id))) {
-      MCA_TRACE_ERROR("bad peer dep id:%d or bad mdl id: %d ", peer_dep_id,
-                      mdl_id);
-      return MCA_BAD_PARAMS;
-    }
-
-    if (mca_ccb_uses_mdl_id(p_ccb, mdl_id)) {
-      MCA_TRACE_ERROR("mdl id: %d is used in the control link", mdl_id);
-      return MCA_BAD_MDL_ID;
-    }
-
-    p_dcb = mca_dcb_alloc(p_ccb, dep);
-    result = MCA_NO_RESOURCES;
-    if (p_dcb) {
-      /* save the info required by dcb connection */
-      p_dcb->p_chnl_cfg = p_chnl_cfg;
-      p_dcb->mdl_id = mdl_id;
-      if (!p_ccb->data_vpsm)
-        p_ccb->data_vpsm =
-            L2CA_Register(data_psm, (tL2CAP_APPL_INFO*)&mca_l2c_int_appl);
-      if (p_ccb->data_vpsm) {
-        tMCA_CCB_EVT* mca_ccb_evt =
-            (tMCA_CCB_EVT*)osi_malloc(sizeof(tMCA_CCB_EVT));
-        tMCA_CCB_MSG* p_evt_data = &mca_ccb_evt->api;
-        p_evt_data->dcb_idx = mca_dcb_to_hdl(p_dcb);
-        p_evt_data->mdep_id = peer_dep_id;
-        p_evt_data->mdl_id = mdl_id;
-        p_evt_data->param = cfg;
-        p_evt_data->op_code = MCA_OP_MDL_CREATE_REQ;
-        p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT;
-        p_evt_data->hdr.layer_specific = false;
-        mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, mca_ccb_evt);
-        return MCA_SUCCESS;
-      }
-
-      mca_dcb_dealloc(p_dcb, NULL);
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_CreateMdlRsp
- *
- * Description      This function sends a CREATE_MDL response to the peer device
- *                  in response to a received MCA_CREATE_IND_EVT.
- *                  If the rsp_code is successful, a data channel is open
- *                  with the given p_chnl_cfg
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_IND_EVT
- *                  is reported. This data channel is identified as tMCA_DL.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_CreateMdlRsp(tMCA_CL mcl, tMCA_DEP dep, uint16_t mdl_id,
-                             uint8_t cfg, uint8_t rsp_code,
-                             const tMCA_CHNL_CFG* p_chnl_cfg) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-
-  MCA_TRACE_API("MCA_CreateMdlRsp: %d dep=%d mdl_id=%d cfg=%d rsp_code=%d", mcl,
-                dep, mdl_id, cfg, rsp_code);
-  CHECK(p_chnl_cfg != NULL);
-  if (p_ccb) {
-    if (p_ccb->cong) {
-      MCA_TRACE_ERROR("congested");
-      return MCA_BUSY;
-    }
-    if (p_ccb->p_rx_msg && (p_ccb->p_rx_msg->mdep_id == dep) &&
-        (p_ccb->p_rx_msg->mdl_id == mdl_id) &&
-        (p_ccb->p_rx_msg->op_code == MCA_OP_MDL_CREATE_REQ)) {
-      tMCA_CCB_MSG evt_data;
-      result = MCA_SUCCESS;
-      evt_data.dcb_idx = 0;
-      if (rsp_code == MCA_RSP_SUCCESS) {
-        tMCA_DCB* p_dcb = mca_dcb_alloc(p_ccb, dep);
-        if (p_dcb) {
-          evt_data.dcb_idx = mca_dcb_to_hdl(p_dcb);
-          p_dcb->p_chnl_cfg = p_chnl_cfg;
-          p_dcb->mdl_id = mdl_id;
-        } else {
-          rsp_code = MCA_RSP_MDEP_BUSY;
-          result = MCA_NO_RESOURCES;
-        }
-      }
-
-      if (result == MCA_SUCCESS) {
-        evt_data.mdl_id = mdl_id;
-        evt_data.param = cfg;
-        evt_data.rsp_code = rsp_code;
-        evt_data.op_code = MCA_OP_MDL_CREATE_RSP;
-        tMCA_CCB_EVT mca_ccb_evt;
-        mca_ccb_evt.api = evt_data;
-        mca_ccb_event(p_ccb, MCA_CCB_API_RSP_EVT, &mca_ccb_evt);
-      }
-    } else {
-      MCA_TRACE_ERROR(
-          "The given MCL is not expecting a MCA_CreateMdlRsp with the given "
-          "parameters");
-      result = MCA_BAD_PARAMS;
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_CloseReq
- *
- * Description      Close a data channel.  When the channel is closed, an
- *                  MCA_CLOSE_CFM_EVT is sent to the application via the
- *                  control callback function for this handle.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_CloseReq(tMCA_DL mdl) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_DCB* p_dcb = mca_dcb_by_hdl(mdl);
-
-  MCA_TRACE_API("MCA_CloseReq: %d ", mdl);
-  if (p_dcb) {
-    result = MCA_SUCCESS;
-    mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_ReconnectMdl
- *
- * Description      This function sends a RECONNECT_MDL request to the peer
- *                  device. When the response is received, a
- *                  MCA_RECONNECT_CFM_EVT is reported. If p_chnl_cfg is NULL,
- *                  the data channel is not initiated until MCA_DataChnlCfg is
- *                  called to provide the p_chnl_cfg. If the response is
- *                  successful, a data channel is open. When the data channel is
- *                  open successfully, a MCA_OPEN_CFM_EVT is reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_ReconnectMdl(tMCA_CL mcl, tMCA_DEP dep, uint16_t data_psm,
-                             uint16_t mdl_id, const tMCA_CHNL_CFG* p_chnl_cfg) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-  tMCA_DCB* p_dcb;
-
-  MCA_TRACE_API("MCA_ReconnectMdl: %d ", mcl);
-  CHECK(p_chnl_cfg != NULL);
-  if (p_ccb) {
-    if (p_ccb->p_tx_req || p_ccb->p_rx_msg || p_ccb->cong) {
-      MCA_TRACE_ERROR("pending req");
-      return MCA_BUSY;
-    }
-
-    if (!MCA_IS_VALID_MDL_ID(mdl_id)) {
-      MCA_TRACE_ERROR("bad mdl id: %d ", mdl_id);
-      return MCA_BAD_PARAMS;
-    }
-
-    if (mca_ccb_uses_mdl_id(p_ccb, mdl_id)) {
-      MCA_TRACE_ERROR("mdl id: %d is used in the control link", mdl_id);
-      return MCA_BAD_MDL_ID;
-    }
-
-    p_dcb = mca_dcb_alloc(p_ccb, dep);
-    result = MCA_NO_RESOURCES;
-    if (p_dcb) {
-      tMCA_CCB_EVT* mca_ccb_evt =
-          (tMCA_CCB_EVT*)osi_malloc(sizeof(tMCA_CCB_EVT));
-      tMCA_CCB_MSG* p_evt_data = &mca_ccb_evt->api;
-
-      p_dcb->p_chnl_cfg = p_chnl_cfg;
-      p_dcb->mdl_id = mdl_id;
-      if (!p_ccb->data_vpsm)
-        p_ccb->data_vpsm =
-            L2CA_Register(data_psm, (tL2CAP_APPL_INFO*)&mca_l2c_int_appl);
-      p_evt_data->dcb_idx = mca_dcb_to_hdl(p_dcb);
-      p_evt_data->mdl_id = mdl_id;
-      p_evt_data->op_code = MCA_OP_MDL_RECONNECT_REQ;
-      p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT;
-      mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, mca_ccb_evt);
-      return MCA_SUCCESS;
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_ReconnectMdlRsp
- *
- * Description      This function sends a RECONNECT_MDL response to the peer
- *                  device in response to a MCA_RECONNECT_IND_EVT event.
- *                  If the response is successful, a data channel is open.
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_IND_EVT is reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_ReconnectMdlRsp(tMCA_CL mcl, tMCA_DEP dep, uint16_t mdl_id,
-                                uint8_t rsp_code,
-                                const tMCA_CHNL_CFG* p_chnl_cfg) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-  tMCA_DCB* p_dcb;
-
-  MCA_TRACE_API("MCA_ReconnectMdlRsp: %d ", mcl);
-  CHECK(p_chnl_cfg != NULL);
-  if (p_ccb) {
-    if (p_ccb->cong) {
-      MCA_TRACE_ERROR("congested");
-      return MCA_BUSY;
-    }
-    if (p_ccb->p_rx_msg && (p_ccb->p_rx_msg->mdl_id == mdl_id) &&
-        (p_ccb->p_rx_msg->op_code == MCA_OP_MDL_RECONNECT_REQ)) {
-      result = MCA_SUCCESS;
-      tMCA_CCB_MSG evt_data;
-      evt_data.dcb_idx = 0;
-      if (rsp_code == MCA_RSP_SUCCESS) {
-        p_dcb = mca_dcb_alloc(p_ccb, dep);
-        if (p_dcb) {
-          evt_data.dcb_idx = mca_dcb_to_hdl(p_dcb);
-          p_dcb->p_chnl_cfg = p_chnl_cfg;
-          p_dcb->mdl_id = mdl_id;
-        } else {
-          MCA_TRACE_ERROR("Out of MDL for this MDEP");
-          rsp_code = MCA_RSP_MDEP_BUSY;
-          result = MCA_NO_RESOURCES;
-        }
-      }
-
-      evt_data.mdl_id = mdl_id;
-      evt_data.rsp_code = rsp_code;
-      evt_data.op_code = MCA_OP_MDL_RECONNECT_RSP;
-      tMCA_CCB_EVT mca_ccb_evt;
-      mca_ccb_evt.api = evt_data;
-      mca_ccb_event(p_ccb, MCA_CCB_API_RSP_EVT, &mca_ccb_evt);
-    } else {
-      MCA_TRACE_ERROR(
-          "The given MCL is not expecting a MCA_ReconnectMdlRsp with the given "
-          "parameters");
-      result = MCA_BAD_PARAMS;
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_DataChnlCfg
- *
- * Description      This function initiates a data channel connection toward the
- *                  connected peer device.
- *                  When the data channel is open successfully, a
- *                  MCA_OPEN_CFM_EVT is reported. This data channel is
- *                  identified as tMCA_DL.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_DataChnlCfg(tMCA_CL mcl, const tMCA_CHNL_CFG* p_chnl_cfg) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-  tMCA_DCB* p_dcb;
-  tMCA_TC_TBL* p_tbl;
-
-  MCA_TRACE_API("MCA_DataChnlCfg: %d ", mcl);
-  CHECK(p_chnl_cfg != NULL);
-  if (p_ccb) {
-    result = MCA_NO_RESOURCES;
-    if ((p_ccb->p_tx_req == NULL) || (p_ccb->status != MCA_CCB_STAT_PENDING) ||
-        ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) == NULL)) {
-      MCA_TRACE_ERROR("The given MCL is not expecting this API:%d",
-                      p_ccb->status);
-      return result;
-    }
-
-    p_dcb->p_chnl_cfg = p_chnl_cfg;
-    BTM_SetSecurityLevel(true, "", BTM_SEC_SERVICE_MCAP_DATA, p_ccb->sec_mask,
-                         p_ccb->data_vpsm, BTM_SEC_PROTO_MCA,
-                         p_ccb->p_tx_req->dcb_idx);
-    p_dcb->lcid =
-        mca_l2c_open_req(p_ccb->peer_addr, p_ccb->data_vpsm, p_dcb->p_chnl_cfg);
-    if (p_dcb->lcid) {
-      p_tbl = mca_tc_tbl_dalloc(p_dcb);
-      if (p_tbl) {
-        p_tbl->state = MCA_TC_ST_CONN;
-        result = MCA_SUCCESS;
-      }
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_Abort
- *
- * Description      This function sends a ABORT_MDL request to the peer device.
- *                  When the response is received, a MCA_ABORT_CFM_EVT is
- *                  reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_Abort(tMCA_CL mcl) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-  tMCA_DCB* p_dcb;
-
-  MCA_TRACE_API("MCA_Abort: %d", mcl);
-  if (p_ccb) {
-    result = MCA_NO_RESOURCES;
-    /* verify that we are waiting for data channel to come up with the given mdl
-     */
-    if ((p_ccb->p_tx_req == NULL) || (p_ccb->status != MCA_CCB_STAT_PENDING) ||
-        ((p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) == NULL)) {
-      MCA_TRACE_ERROR("The given MCL is not expecting this API:%d",
-                      p_ccb->status);
-      return result;
-    }
-
-    if (p_ccb->cong) {
-      MCA_TRACE_ERROR("congested");
-      return MCA_BUSY;
-    }
-
-    tMCA_CCB_EVT* mca_ccb_evt = (tMCA_CCB_EVT*)osi_malloc(sizeof(tMCA_CCB_EVT));
-    tMCA_CCB_MSG* p_evt_data = &mca_ccb_evt->api;
-    result = MCA_SUCCESS;
-    p_evt_data->op_code = MCA_OP_MDL_ABORT_REQ;
-    p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT;
-    mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, mca_ccb_evt);
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_Delete
- *
- * Description      This function sends a DELETE_MDL request to the peer device.
- *                  When the response is received, a MCA_DELETE_CFM_EVT is
- *                  reported.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_Delete(tMCA_CL mcl, uint16_t mdl_id) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_CCB* p_ccb = mca_ccb_by_hdl(mcl);
-
-  MCA_TRACE_API("MCA_Delete: %d ", mcl);
-  if (p_ccb) {
-    if (p_ccb->cong) {
-      MCA_TRACE_ERROR("congested");
-      return MCA_BUSY;
-    }
-    if (!MCA_IS_VALID_MDL_ID(mdl_id) && (mdl_id != MCA_ALL_MDL_ID)) {
-      MCA_TRACE_ERROR("bad mdl id: %d ", mdl_id);
-      return MCA_BAD_PARAMS;
-    }
-
-    tMCA_CCB_EVT* mca_ccb_evt = (tMCA_CCB_EVT*)osi_malloc(sizeof(tMCA_CCB_EVT));
-    tMCA_CCB_MSG* p_evt_data = &mca_ccb_evt->api;
-    result = MCA_SUCCESS;
-    p_evt_data->mdl_id = mdl_id;
-    p_evt_data->op_code = MCA_OP_MDL_DELETE_REQ;
-    p_evt_data->hdr.event = MCA_CCB_API_REQ_EVT;
-    mca_ccb_event(p_ccb, MCA_CCB_API_REQ_EVT, mca_ccb_evt);
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_WriteReq
- *
- * Description      Send a data packet to the peer device.
- *
- *                  The application passes the packet using the BT_HDR
- *                  structure. The offset field must be equal to or greater than
- *                  L2CAP_MIN_OFFSET. This allows enough space in the buffer for
- *                  the L2CAP header.
- *
- *                  The memory pointed to by p_pkt must be a GKI buffer
- *                  allocated by the application.  This buffer will be freed
- *                  by the protocol stack; the application must not free
- *                  this buffer.
- *
- * Returns          MCA_SUCCESS if successful, otherwise error.
- *
- ******************************************************************************/
-tMCA_RESULT MCA_WriteReq(tMCA_DL mdl, BT_HDR* p_pkt) {
-  tMCA_RESULT result = MCA_BAD_HANDLE;
-  tMCA_DCB* p_dcb = mca_dcb_by_hdl(mdl);
-  tMCA_DCB_EVT evt_data;
-
-  MCA_TRACE_API("MCA_WriteReq: %d ", mdl);
-  if (p_dcb) {
-    if (p_dcb->cong) {
-      result = MCA_BUSY;
-    } else {
-      evt_data.p_pkt = p_pkt;
-      result = MCA_SUCCESS;
-      mca_dcb_event(p_dcb, MCA_DCB_API_WRITE_EVT, &evt_data);
-    }
-  }
-  return result;
-}
-
-/*******************************************************************************
- *
- * Function         MCA_GetL2CapChannel
- *
- * Description      Get the L2CAP CID used by the given data channel handle.
- *
- * Returns          L2CAP channel ID if successful, otherwise 0.
- *
- ******************************************************************************/
-uint16_t MCA_GetL2CapChannel(tMCA_DL mdl) {
-  uint16_t lcid = 0;
-  tMCA_DCB* p_dcb = mca_dcb_by_hdl(mdl);
-
-  MCA_TRACE_API("MCA_GetL2CapChannel: %d ", mdl);
-  if (p_dcb) lcid = p_dcb->lcid;
-  return lcid;
-}
-
-static const btmcap_test_interface_t mcap_test_interface = {
-    sizeof(btmcap_test_interface_t),
-    MCA_Init,
-    MCA_Register,
-    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_test_interface_t* stack_mcap_get_interface(void) {
-  BTIF_TRACE_EVENT("%s", __func__);
-  return &mcap_test_interface;
-}
diff --git a/stack/mcap/mca_cact.cc b/stack/mcap/mca_cact.cc
index 45159ca..e6d73d6 100644
--- a/stack/mcap/mca_cact.cc
+++ b/stack/mcap/mca_cact.cc
@@ -129,7 +129,7 @@
       p_msg->hdr.layer_specific = true; /* mark this message as sent */
       p_pkt->len = p - p_start;
       L2CA_DataWrite(p_ccb->lcid, p_pkt);
-      period_ms_t interval_ms = p_ccb->p_rcb->reg.rsp_tout * 1000;
+      uint64_t interval_ms = p_ccb->p_rcb->reg.rsp_tout * 1000;
       alarm_set_on_mloop(p_ccb->mca_ccb_timer, interval_ms,
                          mca_ccb_timer_timeout, p_ccb);
     }
diff --git a/stack/mcap/mca_csm.cc b/stack/mcap/mca_csm.cc
deleted file mode 100644
index 4b3a4a0..0000000
--- a/stack/mcap/mca_csm.cc
+++ /dev/null
@@ -1,328 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the MCAP Control channel state
- *  machine.
- *
- ******************************************************************************/
-#include <string.h>
-
-#include "bt_target.h"
-#include "btu.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "mca_int.h"
-
-/*****************************************************************************
- * data channel state machine constants and types
- ****************************************************************************/
-enum {
-  MCA_CCB_FREE_MSG,
-  MCA_CCB_SND_REQ,
-  MCA_CCB_SND_RSP,
-  MCA_CCB_DO_DISCONN,
-  MCA_CCB_CONG,
-  MCA_CCB_HDL_REQ,
-  MCA_CCB_HDL_RSP,
-  MCA_CCB_LL_OPEN,
-  MCA_CCB_DL_OPEN,
-  MCA_CCB_DEALLOC,
-  MCA_CCB_RSP_TOUT,
-  MCA_CCB_NUM_ACTIONS
-};
-#define MCA_CCB_IGNORE MCA_CCB_NUM_ACTIONS
-
-/* action function list */
-const tMCA_CCB_ACTION mca_ccb_action[] = {
-    mca_ccb_free_msg, mca_ccb_snd_req, mca_ccb_snd_rsp,  mca_ccb_do_disconn,
-    mca_ccb_cong,     mca_ccb_hdl_req, mca_ccb_hdl_rsp,  mca_ccb_ll_open,
-    mca_ccb_dl_open,  mca_ccb_dealloc, mca_ccb_rsp_tout,
-};
-
-/* state table information */
-#define MCA_CCB_ACTIONS 1    /* number of actions */
-#define MCA_CCB_ACT_COL 0    /* position of action function */
-#define MCA_CCB_NEXT_STATE 1 /* position of next state */
-#define MCA_CCB_NUM_COLS 2   /* number of columns in state tables */
-
-/* state table for opening state */
-const uint8_t mca_ccb_st_opening[][MCA_CCB_NUM_COLS] = {
-    /* Event                            Action              Next State */
-    /* MCA_CCB_API_CONNECT_EVT    */ {MCA_CCB_IGNORE, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_API_DISCONNECT_EVT */ {MCA_CCB_DO_DISCONN, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_API_REQ_EVT        */ {MCA_CCB_FREE_MSG, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_API_RSP_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_MSG_REQ_EVT        */ {MCA_CCB_FREE_MSG, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_MSG_RSP_EVT        */ {MCA_CCB_FREE_MSG, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_DL_OPEN_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_LL_OPEN_EVT        */ {MCA_CCB_LL_OPEN, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_LL_CLOSE_EVT       */ {MCA_CCB_DEALLOC, MCA_CCB_NULL_ST},
-    /* MCA_CCB_LL_CONG_EVT        */ {MCA_CCB_CONG, MCA_CCB_OPENING_ST},
-    /* MCA_CCB_RSP_TOUT_EVT       */ {MCA_CCB_IGNORE, MCA_CCB_OPENING_ST}};
-
-/* state table for open state */
-const uint8_t mca_ccb_st_open[][MCA_CCB_NUM_COLS] = {
-    /* Event                            Action              Next State */
-    /* MCA_CCB_API_CONNECT_EVT    */ {MCA_CCB_IGNORE, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_API_DISCONNECT_EVT */ {MCA_CCB_DO_DISCONN, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_API_REQ_EVT        */ {MCA_CCB_SND_REQ, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_API_RSP_EVT        */ {MCA_CCB_SND_RSP, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_MSG_REQ_EVT        */ {MCA_CCB_HDL_REQ, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_MSG_RSP_EVT        */ {MCA_CCB_HDL_RSP, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_DL_OPEN_EVT        */ {MCA_CCB_DL_OPEN, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_LL_OPEN_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_LL_CLOSE_EVT       */ {MCA_CCB_DEALLOC, MCA_CCB_NULL_ST},
-    /* MCA_CCB_LL_CONG_EVT        */ {MCA_CCB_CONG, MCA_CCB_OPEN_ST},
-    /* MCA_CCB_RSP_TOUT_EVT       */ {MCA_CCB_RSP_TOUT, MCA_CCB_OPEN_ST}};
-
-/* state table for closing state */
-const uint8_t mca_ccb_st_closing[][MCA_CCB_NUM_COLS] = {
-    /* Event                            Action              Next State */
-    /* MCA_CCB_API_CONNECT_EVT    */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_API_DISCONNECT_EVT */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_API_REQ_EVT        */ {MCA_CCB_FREE_MSG, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_API_RSP_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_MSG_REQ_EVT        */ {MCA_CCB_FREE_MSG, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_MSG_RSP_EVT        */ {MCA_CCB_FREE_MSG, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_DL_OPEN_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_LL_OPEN_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_LL_CLOSE_EVT       */ {MCA_CCB_DEALLOC, MCA_CCB_NULL_ST},
-    /* MCA_CCB_LL_CONG_EVT        */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST},
-    /* MCA_CCB_RSP_TOUT_EVT       */ {MCA_CCB_IGNORE, MCA_CCB_CLOSING_ST}};
-
-/* type for state table */
-typedef const uint8_t (*tMCA_CCB_ST_TBL)[MCA_CCB_NUM_COLS];
-
-/* state table */
-const tMCA_CCB_ST_TBL mca_ccb_st_tbl[] = {mca_ccb_st_opening, mca_ccb_st_open,
-                                          mca_ccb_st_closing};
-
-/* verbose event strings for trace */
-static const char* const mca_ccb_evt_str[] = {
-    "API_CONNECT_EVT", "API_DISCONNECT_EVT", "API_REQ_EVT", "API_RSP_EVT",
-    "MSG_REQ_EVT",     "MSG_RSP_EVT",        "DL_OPEN_EVT", "LL_OPEN_EVT",
-    "LL_CLOSE_EVT",    "LL_CONG_EVT",        "RSP_TOUT_EVT"};
-/* verbose state strings for trace */
-static const char* const mca_ccb_st_str[] = {"NULL_ST", "OPENING_ST", "OPEN_ST",
-                                             "CLOSING_ST"};
-
-/*******************************************************************************
- *
- * Function         mca_stop_timer
- *
- * Description      This function is stop a MCAP timer
- *
- *                  This function is for use internal to MCAP only.
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_stop_timer(tMCA_CCB* p_ccb) { alarm_cancel(p_ccb->mca_ccb_timer); }
-
-/*******************************************************************************
- *
- * Function         mca_ccb_event
- *
- * Description      This function is the CCB state machine main function.
- *                  It uses the state and action function tables to execute
- *                  action functions.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_ccb_event(tMCA_CCB* p_ccb, uint8_t event, tMCA_CCB_EVT* p_data) {
-  tMCA_CCB_ST_TBL state_table;
-  uint8_t action;
-
-  MCA_TRACE_EVENT("CCB ccb=%d event=%s state=%s", mca_ccb_to_hdl(p_ccb),
-                  mca_ccb_evt_str[event], mca_ccb_st_str[p_ccb->state]);
-
-  /* look up the state table for the current state */
-  state_table = mca_ccb_st_tbl[p_ccb->state - 1];
-
-  /* set next state */
-  p_ccb->state = state_table[event][MCA_CCB_NEXT_STATE];
-
-  /* execute action functions */
-  action = state_table[event][MCA_CCB_ACT_COL];
-  if (action != MCA_CCB_IGNORE) {
-    (*mca_ccb_action[action])(p_ccb, p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_ccb_by_bd
- *
- * Description      This function looks up the CCB based on the BD address.
- *                  It returns a pointer to the CCB.
- *                  If no CCB is found it returns NULL.
- *
- * Returns          void.
- *
- ******************************************************************************/
-tMCA_CCB* mca_ccb_by_bd(tMCA_HANDLE handle, const RawAddress& bd_addr) {
-  tMCA_CCB* p_ccb = NULL;
-  tMCA_RCB* p_rcb = mca_rcb_by_handle(handle);
-  tMCA_CCB* p_ccb_tmp;
-  int i;
-
-  if (p_rcb) {
-    i = handle - 1;
-    p_ccb_tmp = &mca_cb.ccb[i * MCA_NUM_LINKS];
-    for (i = 0; i < MCA_NUM_LINKS; i++, p_ccb_tmp++) {
-      if (p_ccb_tmp->state != MCA_CCB_NULL_ST &&
-          p_ccb_tmp->peer_addr == bd_addr) {
-        p_ccb = p_ccb_tmp;
-        break;
-      }
-    }
-  }
-  return p_ccb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_ccb_alloc
- *
- * Description      This function allocates a CCB and copies the BD address to
- *                  the CCB.  It returns a pointer to the CCB.  If no CCB can
- *                  be allocated it returns NULL.
- *
- * Returns          void.
- *
- ******************************************************************************/
-tMCA_CCB* mca_ccb_alloc(tMCA_HANDLE handle, const RawAddress& bd_addr) {
-  tMCA_CCB* p_ccb = NULL;
-  tMCA_RCB* p_rcb = mca_rcb_by_handle(handle);
-  tMCA_CCB* p_ccb_tmp;
-  int i;
-
-  MCA_TRACE_DEBUG("mca_ccb_alloc handle:0x%x", handle);
-  if (p_rcb) {
-    i = handle - 1;
-    p_ccb_tmp = &mca_cb.ccb[i * MCA_NUM_LINKS];
-    for (i = 0; i < MCA_NUM_LINKS; i++, p_ccb_tmp++) {
-      if (p_ccb_tmp->state == MCA_CCB_NULL_ST) {
-        p_ccb_tmp->p_rcb = p_rcb;
-        p_ccb_tmp->mca_ccb_timer = alarm_new("mca.mca_ccb_timer");
-        p_ccb_tmp->state = MCA_CCB_OPENING_ST;
-        p_ccb_tmp->cong = true;
-        p_ccb_tmp->peer_addr = bd_addr;
-        p_ccb = p_ccb_tmp;
-        break;
-      }
-    }
-  }
-  return p_ccb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_ccb_dealloc
- *
- * Description      This function deallocates a CCB.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_ccb_dealloc(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data) {
-  tMCA_CTRL evt_data;
-
-  MCA_TRACE_DEBUG("mca_ccb_dealloc ctrl_vpsm:0x%x", p_ccb->ctrl_vpsm);
-  mca_dcb_close_by_mdl_id(p_ccb, MCA_ALL_MDL_ID);
-  if (p_ccb->ctrl_vpsm) {
-    L2CA_Deregister(p_ccb->ctrl_vpsm);
-  }
-  if (p_ccb->data_vpsm) {
-    L2CA_Deregister(p_ccb->data_vpsm);
-  }
-  osi_free_and_reset((void**)&p_ccb->p_rx_msg);
-  osi_free_and_reset((void**)&p_ccb->p_tx_req);
-  mca_stop_timer(p_ccb);
-
-  if (p_data) {
-    /* non-NULL -> an action function -> report disconnect event */
-    evt_data.disconnect_ind.bd_addr = p_ccb->peer_addr;
-    evt_data.disconnect_ind.reason = p_data->close.reason;
-    mca_ccb_report_event(p_ccb, MCA_DISCONNECT_IND_EVT, &evt_data);
-  }
-  mca_free_tc_tbl_by_lcid(p_ccb->lcid);
-  alarm_free(p_ccb->mca_ccb_timer);
-  memset(p_ccb, 0, sizeof(tMCA_CCB));
-}
-
-/*******************************************************************************
- *
- * Function         mca_ccb_to_hdl
- *
- * Description      This function converts a pointer to a CCB to a tMCA_CL
- *                  and returns the value.
- *
- * Returns          void.
- *
- ******************************************************************************/
-tMCA_CL mca_ccb_to_hdl(tMCA_CCB* p_ccb) {
-  return (uint8_t)(p_ccb - mca_cb.ccb + 1);
-}
-
-/*******************************************************************************
- *
- * Function         mca_ccb_by_hdl
- *
- * Description      This function converts an index value to a CCB.  It returns
- *                  a pointer to the CCB.  If no valid CCB matches the index it
- *                  returns NULL.
- *
- * Returns          void.
- *
- ******************************************************************************/
-tMCA_CCB* mca_ccb_by_hdl(tMCA_CL mcl) {
-  tMCA_CCB* p_ccb = NULL;
-  if (mcl && mcl <= MCA_NUM_CCBS && mca_cb.ccb[mcl - 1].state)
-    p_ccb = &mca_cb.ccb[mcl - 1];
-  return p_ccb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_ccb_uses_mdl_id
- *
- * Description      This function checkes if a given mdl_id is in use.
- *
- * Returns          true, if the given mdl_id is currently used in the MCL.
- *
- ******************************************************************************/
-bool mca_ccb_uses_mdl_id(tMCA_CCB* p_ccb, uint16_t mdl_id) {
-  bool uses = false;
-  tMCA_DCB* p_dcb;
-  int i;
-
-  i = mca_ccb_to_hdl(p_ccb) - 1;
-  p_dcb = &mca_cb.dcb[i * MCA_NUM_MDLS];
-  for (i = 0; i < MCA_NUM_MDLS; i++, p_dcb++) {
-    if (p_dcb->state != MCA_DCB_NULL_ST && p_dcb->mdl_id == mdl_id) {
-      uses = true;
-      break;
-    }
-  }
-
-  return uses;
-}
diff --git a/stack/mcap/mca_dact.cc b/stack/mcap/mca_dact.cc
deleted file mode 100644
index 8ee3ac1..0000000
--- a/stack/mcap/mca_dact.cc
+++ /dev/null
@@ -1,157 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the MCAP Data Channel Action
- *  Functions.
- *
- ******************************************************************************/
-
-#include <stddef.h>
-#include "bt_common.h"
-#include "bt_target.h"
-#include "bt_utils.h"
-#include "mca_api.h"
-#include "mca_int.h"
-#include "osi/include/osi.h"
-
-/*******************************************************************************
- *
- * Function         mca_dcb_report_cong
- *
- * Description      This function is called to report the congestion flag.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_report_cong(tMCA_DCB* p_dcb) {
-  tMCA_CTRL evt_data;
-
-  evt_data.cong_chg.cong = p_dcb->cong;
-  evt_data.cong_chg.mdl = mca_dcb_to_hdl(p_dcb);
-  evt_data.cong_chg.mdl_id = p_dcb->mdl_id;
-  mca_ccb_report_event(p_dcb->p_ccb, MCA_CONG_CHG_EVT, &evt_data);
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_tc_open
- *
- * Description      This function is called to report MCA_OPEN_IND_EVT or
- *                  MCA_OPEN_CFM_EVT event.
- *                  It also clears the congestion flag (dcb.cong).
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_tc_open(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data) {
-  tMCA_CTRL evt_data;
-  tMCA_CCB* p_ccb = p_dcb->p_ccb;
-  uint8_t event = MCA_OPEN_IND_EVT;
-
-  if (p_data->open.param == MCA_INT) event = MCA_OPEN_CFM_EVT;
-  p_dcb->cong = false;
-  evt_data.open_cfm.mtu = p_data->open.peer_mtu;
-  evt_data.open_cfm.mdl_id = p_dcb->mdl_id;
-  evt_data.open_cfm.mdl = mca_dcb_to_hdl(p_dcb);
-  mca_ccb_event(p_ccb, MCA_CCB_DL_OPEN_EVT, NULL);
-  mca_ccb_report_event(p_ccb, event, &evt_data);
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_cong
- *
- * Description      This function sets the congestion state for the DCB.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_cong(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data) {
-  p_dcb->cong = p_data->llcong;
-  mca_dcb_report_cong(p_dcb);
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_free_data
- *
- * Description      This function frees the received message.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_free_data(UNUSED_ATTR tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data) {
-  osi_free(p_data);
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_do_disconn
- *
- * Description      This function closes a data channel.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_do_disconn(tMCA_DCB* p_dcb, UNUSED_ATTR tMCA_DCB_EVT* p_data) {
-  if ((p_dcb->lcid == 0) || (!L2CA_DisconnectReq(p_dcb->lcid))) {
-    tMCA_CLOSE close;
-    close.param = MCA_INT;
-    close.reason = L2CAP_DISC_OK;
-    close.lcid = 0;
-    tMCA_DCB_EVT mca_dcb_evt;
-    mca_dcb_evt.close = close;
-    mca_dcb_event(p_dcb, MCA_DCB_TC_CLOSE_EVT, &mca_dcb_evt);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_snd_data
- *
- * Description      Send the data from application to the peer device.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_snd_data(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data) {
-  uint8_t status;
-
-  /* do not need to check cong, because API already checked the status */
-  status = L2CA_DataWrite(p_dcb->lcid, p_data->p_pkt);
-  if (status == L2CAP_DW_CONGESTED) {
-    p_dcb->cong = true;
-    mca_dcb_report_cong(p_dcb);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_hdl_data
- *
- * Description      This function reports the received data through the data
- *                  callback function.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_hdl_data(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data) {
-  (*p_dcb->p_cs->p_data_cback)(mca_dcb_to_hdl(p_dcb), (BT_HDR*)p_data);
-}
diff --git a/stack/mcap/mca_dsm.cc b/stack/mcap/mca_dsm.cc
deleted file mode 100644
index 0d26931..0000000
--- a/stack/mcap/mca_dsm.cc
+++ /dev/null
@@ -1,295 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the MCAP Data chahnel state machine.
- *
- ******************************************************************************/
-#include <string.h>
-
-#include "bt_target.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "mca_int.h"
-
-/*****************************************************************************
- * data channel state machine constants and types
- ****************************************************************************/
-enum {
-  MCA_DCB_TC_OPEN,
-  MCA_DCB_CONG,
-  MCA_DCB_FREE_DATA,
-  MCA_DCB_DEALLOC,
-  MCA_DCB_DO_DISCONN,
-  MCA_DCB_SND_DATA,
-  MCA_DCB_HDL_DATA,
-  MCA_DCB_NUM_ACTIONS
-};
-#define MCA_DCB_IGNORE MCA_DCB_NUM_ACTIONS
-
-/* action function list */
-const tMCA_DCB_ACTION mca_dcb_action[] = {
-    mca_dcb_tc_open,    mca_dcb_cong,     mca_dcb_free_data, mca_dcb_dealloc,
-    mca_dcb_do_disconn, mca_dcb_snd_data, mca_dcb_hdl_data};
-
-/* state table information */
-#define MCA_DCB_ACTIONS 1    /* number of actions */
-#define MCA_DCB_ACT_COL 0    /* position of action function */
-#define MCA_DCB_NEXT_STATE 1 /* position of next state */
-#define MCA_DCB_NUM_COLS 2   /* number of columns in state tables */
-
-/* state table for opening state */
-const uint8_t mca_dcb_st_opening[][MCA_DCB_NUM_COLS] = {
-    /* Event                            Action              Next State */
-    /* MCA_DCB_API_CLOSE_EVT    */ {MCA_DCB_DO_DISCONN, MCA_DCB_CLOSING_ST},
-    /* MCA_DCB_API_WRITE_EVT    */ {MCA_DCB_IGNORE, MCA_DCB_OPENING_ST},
-    /* MCA_DCB_TC_OPEN_EVT      */ {MCA_DCB_TC_OPEN, MCA_DCB_OPEN_ST},
-    /* MCA_DCB_TC_CLOSE_EVT     */ {MCA_DCB_DEALLOC, MCA_DCB_NULL_ST},
-    /* MCA_DCB_TC_CONG_EVT      */ {MCA_DCB_CONG, MCA_DCB_OPENING_ST},
-    /* MCA_DCB_TC_DATA_EVT      */ {MCA_DCB_FREE_DATA, MCA_DCB_OPENING_ST}};
-
-/* state table for open state */
-const uint8_t mca_dcb_st_open[][MCA_DCB_NUM_COLS] = {
-    /* Event                            Action              Next State */
-    /* MCA_DCB_API_CLOSE_EVT    */ {MCA_DCB_DO_DISCONN, MCA_DCB_CLOSING_ST},
-    /* MCA_DCB_API_WRITE_EVT    */ {MCA_DCB_SND_DATA, MCA_DCB_OPEN_ST},
-    /* MCA_DCB_TC_OPEN_EVT      */ {MCA_DCB_IGNORE, MCA_DCB_OPEN_ST},
-    /* MCA_DCB_TC_CLOSE_EVT     */ {MCA_DCB_DEALLOC, MCA_DCB_NULL_ST},
-    /* MCA_DCB_TC_CONG_EVT      */ {MCA_DCB_CONG, MCA_DCB_OPEN_ST},
-    /* MCA_DCB_TC_DATA_EVT      */ {MCA_DCB_HDL_DATA, MCA_DCB_OPEN_ST}};
-
-/* state table for closing state */
-const uint8_t mca_dcb_st_closing[][MCA_DCB_NUM_COLS] = {
-    /* Event                            Action              Next State */
-    /* MCA_DCB_API_CLOSE_EVT    */ {MCA_DCB_IGNORE, MCA_DCB_CLOSING_ST},
-    /* MCA_DCB_API_WRITE_EVT    */ {MCA_DCB_IGNORE, MCA_DCB_CLOSING_ST},
-    /* MCA_DCB_TC_OPEN_EVT      */ {MCA_DCB_TC_OPEN, MCA_DCB_OPEN_ST},
-    /* MCA_DCB_TC_CLOSE_EVT     */ {MCA_DCB_DEALLOC, MCA_DCB_NULL_ST},
-    /* MCA_DCB_TC_CONG_EVT      */ {MCA_DCB_IGNORE, MCA_DCB_CLOSING_ST},
-    /* MCA_DCB_TC_DATA_EVT      */ {MCA_DCB_FREE_DATA, MCA_DCB_CLOSING_ST}};
-
-/* type for state table */
-typedef const uint8_t (*tMCA_DCB_ST_TBL)[MCA_DCB_NUM_COLS];
-
-/* state table */
-const tMCA_DCB_ST_TBL mca_dcb_st_tbl[] = {mca_dcb_st_opening, mca_dcb_st_open,
-                                          mca_dcb_st_closing};
-
-/* verbose event strings for trace */
-const char* const mca_dcb_evt_str[] = {"API_CLOSE_EVT", "API_WRITE_EVT",
-                                       "TC_OPEN_EVT",   "TC_CLOSE_EVT",
-                                       "TC_CONG_EVT",   "TC_DATA_EVT"};
-/* verbose state strings for trace */
-const char* const mca_dcb_st_str[] = {"NULL_ST", "OPENING_ST", "OPEN_ST",
-                                      "CLOSING_ST"};
-
-/*******************************************************************************
- *
- * Function         mca_dcb_event
- *
- * Description      This function is the DCB state machine main function.
- *                  It uses the state and action function tables to execute
- *                  action functions.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_event(tMCA_DCB* p_dcb, uint8_t event, tMCA_DCB_EVT* p_data) {
-  tMCA_DCB_ST_TBL state_table;
-  uint8_t action;
-
-  if (p_dcb == NULL) return;
-  MCA_TRACE_EVENT("DCB dcb=%d event=%s state=%s", mca_dcb_to_hdl(p_dcb),
-                  mca_dcb_evt_str[event], mca_dcb_st_str[p_dcb->state]);
-
-  /* look up the state table for the current state */
-  state_table = mca_dcb_st_tbl[p_dcb->state - 1];
-
-  /* set next state */
-  p_dcb->state = state_table[event][MCA_DCB_NEXT_STATE];
-
-  /* execute action functions */
-  action = state_table[event][MCA_DCB_ACT_COL];
-  if (action != MCA_DCB_IGNORE) {
-    (*mca_dcb_action[action])(p_dcb, p_data);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_alloc
- *
- * Description      This function is called to allocate an DCB.
- *                  It initializes the DCB with the data passed to the function.
- *
- * Returns          tMCA_DCB *
- *
- ******************************************************************************/
-tMCA_DCB* mca_dcb_alloc(tMCA_CCB* p_ccb, tMCA_DEP dep) {
-  tMCA_DCB *p_dcb = NULL, *p_dcb_tmp;
-  tMCA_RCB* p_rcb = p_ccb->p_rcb;
-  tMCA_CS* p_cs;
-  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];
-    /* 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++) {
-      if (p_dcb_tmp->state == MCA_DCB_NULL_ST) {
-        p_dcb_tmp->p_ccb = p_ccb;
-        p_dcb_tmp->state = MCA_DCB_OPENING_ST;
-        p_dcb_tmp->cong = true;
-        p_dcb_tmp->p_cs = p_cs;
-        p_dcb = p_dcb_tmp;
-        break;
-      }
-    }
-  }
-  return p_dcb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_dep_free_mdl
- *
- * Description      This function is called to check the number of free mdl for
- *                  the given dep.
- *
- * Returns          the number of free mdl for the given dep
- *
- ******************************************************************************/
-uint8_t mca_dep_free_mdl(tMCA_CCB* p_ccb, tMCA_DEP dep) {
-  tMCA_DCB* p_dcb;
-  tMCA_RCB* p_rcb = p_ccb->p_rcb;
-  tMCA_CS* p_cs;
-  int i, max;
-  uint8_t count = 0;
-  uint8_t left;
-
-  if (dep < MCA_NUM_DEPS) {
-    p_cs = &p_rcb->dep[dep];
-    i = mca_ccb_to_hdl(p_ccb) - 1;
-    p_dcb = &mca_cb.dcb[i * MCA_NUM_MDLS];
-    /* 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++) {
-      if ((p_dcb->state != MCA_DCB_NULL_ST) && (p_dcb->p_cs == p_cs)) {
-        count++;
-        break;
-      }
-    }
-  } else {
-    max = 0;
-    MCA_TRACE_WARNING("Invalid Dep ID");
-  }
-  left = max - count;
-  return left;
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_dealloc
- *
- * Description      This function deallocates an DCB.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_dcb_dealloc(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data) {
-  tMCA_CCB* p_ccb = p_dcb->p_ccb;
-  uint8_t event = MCA_CLOSE_IND_EVT;
-  tMCA_CTRL evt_data;
-
-  MCA_TRACE_DEBUG("mca_dcb_dealloc");
-  osi_free_and_reset((void**)&p_dcb->p_data);
-  if (p_data) {
-    /* non-NULL -> an action function -> report disconnect event */
-    evt_data.close_cfm.mdl = mca_dcb_to_hdl(p_dcb);
-    evt_data.close_cfm.reason = p_data->close.reason;
-    evt_data.close_cfm.mdl_id = p_dcb->mdl_id;
-    if (p_data->close.param == MCA_INT) event = MCA_CLOSE_CFM_EVT;
-    if (p_data->close.lcid) mca_ccb_report_event(p_ccb, event, &evt_data);
-  }
-  mca_free_tc_tbl_by_lcid(p_dcb->lcid);
-  memset(p_dcb, 0, sizeof(tMCA_DCB));
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_to_hdl
- *
- * Description      Convert a pointer to a DCB to a handle (tMCA_DL).
- *                  It returns the handle.
- *
- * Returns          tMCA_DL.
- *
- ******************************************************************************/
-tMCA_DL mca_dcb_to_hdl(tMCA_DCB* p_dcb) {
-  return (uint8_t)(p_dcb - mca_cb.dcb + 1);
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_by_hdl
- *
- * Description      This function finds the DCB for a handle (tMCA_DL).
- *                  It returns a pointer to the DCB.
- *                  If no DCB matches the handle it returns NULL.
- *
- * Returns          tMCA_DCB *
- *
- ******************************************************************************/
-tMCA_DCB* mca_dcb_by_hdl(tMCA_DL hdl) {
-  tMCA_DCB* p_dcb = NULL;
-  if (hdl && hdl <= MCA_NUM_DCBS && mca_cb.dcb[hdl - 1].state)
-    p_dcb = &mca_cb.dcb[hdl - 1];
-  return p_dcb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_dcb_close_by_mdl_id
- *
- * Description      This function finds the DCB for a mdl_id and
- *                  disconnect the mdl
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_dcb_close_by_mdl_id(tMCA_CCB* p_ccb, uint16_t mdl_id) {
-  tMCA_DCB* p_dcb;
-  int i;
-
-  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];
-  for (i = 0; i < MCA_NUM_MDLS; i++, p_dcb++) {
-    if (p_dcb->state) {
-      if (p_dcb->mdl_id == mdl_id) {
-        mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
-        break;
-      } else if (mdl_id == MCA_ALL_MDL_ID) {
-        mca_dcb_event(p_dcb, MCA_DCB_API_CLOSE_EVT, NULL);
-      }
-    }
-  }
-}
diff --git a/stack/mcap/mca_int.h b/stack/mcap/mca_int.h
deleted file mode 100644
index 9ae5d57..0000000
--- a/stack/mcap/mca_int.h
+++ /dev/null
@@ -1,370 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This file contains interfaces which are internal to MCAP.
- *
- ******************************************************************************/
-#ifndef MCA_INT_H
-#define MCA_INT_H
-#include "bt_common.h"
-#include "mca_api.h"
-#include "osi/include/alarm.h"
-
-/*****************************************************************************
- * constants
- ****************************************************************************/
-
-/* INT initiates the L2CAP channel */
-#define MCA_ACP 0
-#define MCA_INT 1
-
-/*****************************************************************************
- *  Type Definitions
- ****************************************************************************/
-
-/* Header structure for api/received request/response. */
-typedef struct {
-  BT_HDR hdr;       /* layer specific information */
-  uint8_t op_code;  /* the request/response opcode */
-  uint8_t rsp_code; /* valid only if op_code is a response */
-  uint16_t mdl_id;  /* the MDL ID associated with this request/response */
-  uint8_t param;    /* other parameter */
-  uint8_t mdep_id;  /* the MDEP ID associated with this request/response */
-  /* tMCA_HANDLE     rcb_idx;    For internal use only */
-  /* tMCA_CL         ccb_idx;    For internal use only */
-  tMCA_DL dcb_idx; /* For internal use only */
-} tMCA_CCB_MSG;
-
-/* This data structure is for AVDT_OPEN_IND_EVT and AVDT_OPEN_CFM_EVT. */
-typedef struct {
-  BT_HDR hdr;        /* Event header */
-  uint16_t peer_mtu; /* Transport channel L2CAP MTU of the peer */
-  uint16_t lcid;     /* L2CAP LCID  */
-  uint8_t param;
-} tMCA_OPEN;
-
-typedef struct {
-  uint16_t reason; /* disconnect reason from L2CAP */
-  uint8_t param;   /* MCA_INT or MCA_ACP */
-  uint16_t lcid;   /* L2CAP LCID  */
-} tMCA_CLOSE;
-
-/* Header structure for state machine event parameters. */
-typedef union {
-  BT_HDR hdr; /* layer specific information */
-  tMCA_CCB_MSG api;
-  bool llcong;
-  uint8_t param;
-  tMCA_OPEN open;
-  tMCA_CLOSE close;
-} tMCA_CCB_EVT;
-
-/* control channel states */
-enum {
-  MCA_CCB_NULL_ST, /* not allocated */
-  MCA_CCB_OPENING_ST,
-  MCA_CCB_OPEN_ST,    /* open */
-  MCA_CCB_CLOSING_ST, /* disconnecting */
-  MCA_CCB_MAX_ST
-};
-typedef uint8_t tMCA_CCB_STATE;
-
-/* control channel events */
-enum {
-  MCA_CCB_API_CONNECT_EVT,    /* application initiates a connect request. */
-  MCA_CCB_API_DISCONNECT_EVT, /* application initiates a disconnect request. */
-  MCA_CCB_API_REQ_EVT,  /* application initiates a request. The request may be
-                           create_mdl, delete_mdl, reconnect_mdl or abort_mdl. */
-  MCA_CCB_API_RSP_EVT,  /* application initiates a create_mdl or reconnect_mdl
-                           response. */
-  MCA_CCB_MSG_REQ_EVT,  /* a create_mdl, delete_mdl, reconnect_mdl or abort_mdl
-                           request message is received from the peer. */
-  MCA_CCB_MSG_RSP_EVT,  /* Response received event.  This event is sent whenever
-                           a response message is received for an outstanding
-                           request message. */
-  MCA_CCB_DL_OPEN_EVT,  /* data channel open. */
-  MCA_CCB_LL_OPEN_EVT,  /* Lower layer open.  This event is sent when the lower
-                           layer channel is open.  */
-  MCA_CCB_LL_CLOSE_EVT, /* Lower layer close.  This event is sent when the lower
-                           layer channel is closed. */
-  MCA_CCB_LL_CONG_EVT,  /* Lower layer congestion.  This event is sent when the
-                           lower layer is congested. */
-  MCA_CCB_RSP_TOUT_EVT  /* time out for waiting the message response on the
-                           control channel */
-};
-
-/* Header structure for callback event parameters. */
-typedef union {
-  tMCA_OPEN open;
-  tMCA_CLOSE close;
-  BT_HDR hdr; /* layer specific information */
-  BT_HDR* p_pkt;
-  bool llcong;
-  uint16_t mdl_id; /* the MDL ID associated with this request/response */
-
-  /* tMCA_HANDLE     rcb_idx;    For internal use only */
-  /* tMCA_CL         ccb_idx;    For internal use only */
-  /* tMCA_DL         dcb_idx;    For internal use only */
-} tMCA_DCB_EVT;
-
-/* data channel states */
-enum {
-  MCA_DCB_NULL_ST,    /* not allocated */
-  MCA_DCB_OPENING_ST, /* create/reconnect sequence is successful, waiting for
-                         data channel connection */
-  MCA_DCB_OPEN_ST,    /* open */
-  MCA_DCB_CLOSING_ST, /* disconnecting */
-  MCA_DCB_MAX_ST
-};
-typedef uint8_t tMCA_DCB_STATE;
-
-/* data channel events */
-enum {
-  MCA_DCB_API_CLOSE_EVT, /* This event is sent when the application wants to
-                            disconnect the data channel.*/
-  MCA_DCB_API_WRITE_EVT, /* This event is sent when the application wants to
-                            send a data packet to the peer.*/
-  MCA_DCB_TC_OPEN_EVT,   /* Transport Channel open.  This event is sent when the
-                            channel is open.*/
-  MCA_DCB_TC_CLOSE_EVT,  /* Transport Channel close.*/
-  MCA_DCB_TC_CONG_EVT,   /* Transport Channel congestion status.*/
-  MCA_DCB_TC_DATA_EVT /* This event is sent when a data packet is received from
-                         the peer.*/
-};
-
-/* "states" used in transport channel table */
-#define MCA_TC_ST_UNUSED 0  /* Unused - unallocated */
-#define MCA_TC_ST_IDLE 1    /* No connection */
-#define MCA_TC_ST_ACP 2     /* Waiting to accept a connection */
-#define MCA_TC_ST_INT 3     /* Initiating a connection */
-#define MCA_TC_ST_CONN 4    /* Waiting for connection confirm */
-#define MCA_TC_ST_CFG 5     /* Waiting for configuration complete */
-#define MCA_TC_ST_OPEN 6    /* Channel opened */
-#define MCA_TC_ST_SEC_INT 7 /* Security process as INT */
-#define MCA_TC_ST_SEC_ACP 8 /* Security process as ACP */
-
-/* Configuration flags. tMCA_TC_TBL.cfg_flags */
-#define MCA_L2C_CFG_IND_DONE (1 << 0)
-#define MCA_L2C_CFG_CFM_DONE (1 << 1)
-#define MCA_L2C_CFG_CONN_INT (1 << 2)
-#define MCA_L2C_CFG_CONN_ACP (1 << 3)
-#define MCA_L2C_CFG_DISCN_INT (1 << 4)
-#define MCA_L2C_CFG_DISCN_ACP (1 << 5)
-
-#define MCA_CTRL_TCID 0 /* to identify control channel by tMCA_TC_TBL.tcid */
-
-/* transport channel table */
-typedef struct {
-  uint16_t peer_mtu; /* L2CAP mtu of the peer device */
-  uint16_t my_mtu;   /* Our MTU for this channel */
-  uint16_t lcid;     /* L2CAP LCID */
-  uint8_t tcid;   /* transport channel id (0, for control channel. (MDEP ID + 1)
-                     for data channel) */
-  tMCA_DL cb_idx; /* 1-based index to ccb or dcb */
-  uint8_t state;  /* transport channel state */
-  uint8_t cfg_flags; /* L2CAP configuration flags */
-  uint8_t id; /* L2CAP id sent by peer device (need this to handle security
-                 pending) */
-} tMCA_TC_TBL;
-
-/* transport control block */
-typedef struct {
-  tMCA_TC_TBL tc_tbl[MCA_NUM_TC_TBL];
-  uint8_t lcid_tbl[MAX_L2CAP_CHANNELS]; /* map LCID to tc_tbl index */
-} tMCA_TC;
-
-/* registration control block */
-typedef struct {
-  tMCA_REG reg;              /* the parameter at register */
-  tMCA_CS dep[MCA_NUM_DEPS]; /* the registration info for each MDEP */
-  tMCA_CTRL_CBACK* p_cback;  /* control callback function */
-} tMCA_RCB;
-
-enum {
-  MCA_CCB_STAT_NORM,    /* normal operation (based on ccb state) */
-  MCA_CCB_STAT_PENDING, /* waiting for data channel  */
-  MCA_CCB_STAT_RECONN, /* reinitiate connection after transitioning from CLOSING
-                          to IDLE state  */
-  MCA_CCB_STAT_DISC    /* MCA_DisconnectReq or MCA_Deregister is called. waiting
-                          for all associated CL and DL to detach */
-};
-typedef uint8_t tMCA_CCB_STAT;
-
-/* control channel control block */
-/* the ccbs association with the rcbs
- * ccb[0]              ...ccb[MCA_NUM_LINKS*1-1] -> rcb[0]
- * ccb[MCA_NUM_LINKS*1]...ccb[MCA_NUM_LINKS*2-1] -> rcb[1]
- * ccb[MCA_NUM_LINKS*2]...ccb[MCA_NUM_LINKS*3-1] -> rcb[2]
- */
-typedef struct {
-  tMCA_RCB* p_rcb;        /* the associated registration control block */
-  alarm_t* mca_ccb_timer; /* MCA CCB timer entry */
-  tMCA_CCB_MSG* p_tx_req; /* Current request being sent/awaiting response */
-  tMCA_CCB_MSG* p_rx_msg; /* Current message received/being processed */
-  RawAddress peer_addr;   /* BD address of peer */
-  uint16_t sec_mask;      /* Security mask for connections as initiator */
-  uint16_t ctrl_vpsm;     /* The virtual PSM that peer is listening for control
-                             channel */
-  uint16_t
-      data_vpsm; /* The virtual PSM that peer is listening for data channel. */
-  uint16_t lcid; /* L2CAP lcid for this control channel */
-  uint8_t state; /* The CCB state machine state */
-  bool cong;     /* Whether control channel is congested */
-  tMCA_CCB_STAT status; /* see tMCA_CCB_STAT */
-} tMCA_CCB;
-typedef void (*tMCA_CCB_ACTION)(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-
-enum {
-  MCA_DCB_STAT_NORM, /* normal operation (based on dcb state) */
-  MCA_DCB_STAT_DEL,  /* MCA_Delete is called. waiting for the DL to detach */
-  MCA_DCB_STAT_DISC  /* MCA_CloseReq is called. waiting for the DL to detach */
-};
-typedef uint8_t tMCA_DCB_STAT;
-
-/* data channel control block */
-/* the dcbs association with the ccbs
- * dcb[0]             ...dcb[MCA_NUM_MDLS*1-1] -> ccb[0]
- * dcb[MCA_NUM_MDLS*1]...dcb[MCA_NUM_MDLS*2-1] -> ccb[1]
- * dcb[MCA_NUM_MDLS*2]...dcb[MCA_NUM_MDLS*3-1] -> ccb[2]
- *
- * the dcbs association with the rcbs
- * dcb[0]
- *                    ...dcb[MCA_NUM_MDLS*1*MCA_NUM_LINKS*1-1] -> rcb[0]
- * dcb[MCA_NUM_MDLS*1*MCA_NUM_LINKS*1]
- *                    ...dcb[MCA_NUM_MDLS*2*MCA_NUM_LINKS*2-1] -> rcb[1]
- * dcb[MCA_NUM_MDLS*2*MCA_NUM_LINKS*2]
- *                    ...dcb[MCA_NUM_MDLS*3*MCA_NUM_LINKS*3-1] -> rcb[2]
- */
-typedef struct {
-  tMCA_CCB* p_ccb; /* the associated control control block */
-  BT_HDR* p_data;  /* data packet held due to L2CAP channel congestion */
-  tMCA_CS* p_cs; /* the associated MDEP info. p_cs->type is the mdep id(internal
-                    use) */
-  const tMCA_CHNL_CFG* p_chnl_cfg; /* cfg params for L2CAP channel */
-  uint16_t mdl_id;                 /* the MDL ID for this data channel */
-  uint16_t lcid;                   /* L2CAP lcid */
-  uint8_t state;                   /* The DCB state machine state */
-  bool cong;                       /* Whether data channel is congested */
-  tMCA_DCB_STAT status;            /* see tMCA_DCB_STAT */
-} tMCA_DCB;
-
-typedef void (*tMCA_DCB_ACTION)(tMCA_DCB* p_ccb, tMCA_DCB_EVT* p_data);
-
-/* Control block for MCA */
-typedef struct {
-  tMCA_RCB rcb[MCA_NUM_REGS]; /* registration control block */
-  tMCA_CCB ccb[MCA_NUM_CCBS]; /* control channel control blocks */
-  tMCA_DCB dcb[MCA_NUM_DCBS]; /* data channel control blocks */
-  tMCA_TC tc;                 /* transport control block */
-  uint8_t trace_level;        /* trace level */
-} tMCA_CB;
-
-/* csm functions */
-extern void mca_ccb_event(tMCA_CCB* p_ccb, uint8_t event, tMCA_CCB_EVT* p_data);
-extern tMCA_CCB* mca_ccb_by_bd(tMCA_HANDLE handle, const RawAddress& bd_addr);
-extern tMCA_CCB* mca_ccb_alloc(tMCA_HANDLE handle, const RawAddress& bd_addr);
-extern void mca_ccb_rsp_tout(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_dealloc(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern tMCA_CL mca_ccb_to_hdl(tMCA_CCB* p_ccb);
-extern tMCA_CCB* mca_ccb_by_hdl(tMCA_CL mcl);
-extern bool mca_ccb_uses_mdl_id(tMCA_CCB* p_ccb, uint16_t mdl_id);
-
-/* cact functions */
-extern void mca_ccb_report_event(tMCA_CCB* p_ccb, uint8_t event,
-                                 tMCA_CTRL* p_data);
-extern void mca_ccb_free_msg(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_snd_req(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_snd_rsp(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_do_disconn(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_cong(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_hdl_req(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_hdl_rsp(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_ll_open(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-extern void mca_ccb_dl_open(tMCA_CCB* p_ccb, tMCA_CCB_EVT* p_data);
-
-/* dsm functions */
-extern void mca_dcb_event(tMCA_DCB* p_dcb, uint8_t event, tMCA_DCB_EVT* p_data);
-extern tMCA_DCB* mca_dcb_alloc(tMCA_CCB* p_ccb, tMCA_DEP dep);
-extern uint8_t mca_dep_free_mdl(tMCA_CCB* p_ccb, tMCA_DEP dep);
-extern void mca_dcb_dealloc(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-extern tMCA_DL mca_dcb_to_hdl(tMCA_DCB* p_dcb);
-extern tMCA_DCB* mca_dcb_by_hdl(tMCA_DL hdl);
-extern void mca_dcb_close_by_mdl_id(tMCA_CCB* p_ccb, uint16_t mdl_id);
-
-/* dact functions */
-extern void mca_dcb_tc_open(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-extern void mca_dcb_cong(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-extern void mca_dcb_free_data(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-extern void mca_dcb_do_disconn(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-extern void mca_dcb_snd_data(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-extern void mca_dcb_hdl_data(tMCA_DCB* p_dcb, tMCA_DCB_EVT* p_data);
-
-/* main/utils functions */
-extern tMCA_HANDLE mca_handle_by_cpsm(uint16_t psm);
-extern tMCA_HANDLE mca_handle_by_dpsm(uint16_t psm);
-extern tMCA_TC_TBL* mca_tc_tbl_calloc(tMCA_CCB* p_ccb);
-extern tMCA_TC_TBL* mca_tc_tbl_dalloc(tMCA_DCB* p_dcb);
-extern tMCA_TC_TBL* mca_tc_tbl_by_lcid(uint16_t lcid);
-extern void mca_free_tc_tbl_by_lcid(uint16_t lcid);
-extern void mca_set_cfg_by_tbl(tL2CAP_CFG_INFO* p_cfg, tMCA_TC_TBL* p_tbl);
-extern void mca_tc_close_ind(tMCA_TC_TBL* p_tbl, uint16_t reason);
-extern void mca_tc_open_ind(tMCA_TC_TBL* p_tbl);
-extern void mca_tc_cong_ind(tMCA_TC_TBL* p_tbl, bool is_congested);
-extern void mca_tc_data_ind(tMCA_TC_TBL* p_tbl, BT_HDR* p_buf);
-extern tMCA_RCB* mca_rcb_alloc(tMCA_REG* p_reg);
-extern void mca_rcb_dealloc(tMCA_HANDLE handle);
-extern tMCA_HANDLE mca_rcb_to_handle(tMCA_RCB* p_rcb);
-extern tMCA_RCB* mca_rcb_by_handle(tMCA_HANDLE handle);
-extern bool mca_is_valid_dep_id(tMCA_RCB* p_rcb, tMCA_DEP dep);
-extern void mca_ccb_timer_timeout(void* data);
-extern void mca_stop_timer(tMCA_CCB* p_ccb);
-
-/* l2c functions */
-extern uint16_t mca_l2c_open_req(const RawAddress& bd_addr, uint16_t PSM,
-                                 const tMCA_CHNL_CFG* p_chnl_cfg);
-
-/* callback function declarations */
-extern void mca_l2c_cconn_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
-                                    uint16_t psm, uint8_t id);
-extern void mca_l2c_dconn_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
-                                    uint16_t psm, uint8_t id);
-extern void mca_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result);
-extern void mca_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
-extern void mca_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg);
-extern void mca_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed);
-extern void mca_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result);
-extern void mca_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested);
-extern void mca_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf);
-
-/*****************************************************************************
- * global data
- ****************************************************************************/
-
-/******************************************************************************
- * Main Control Block
- ******************************************************************************/
-extern tMCA_CB mca_cb;
-
-/* L2CAP callback registration structure */
-extern const tL2CAP_APPL_INFO mca_l2c_int_appl;
-extern const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def;
-extern const uint8_t mca_std_msg_len[];
-
-#endif /* MCA_INT_H */
diff --git a/stack/mcap/mca_l2c.cc b/stack/mcap/mca_l2c.cc
deleted file mode 100644
index e0540fa..0000000
--- a/stack/mcap/mca_l2c.cc
+++ /dev/null
@@ -1,540 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the MCAP at L2CAP Interface.
- *
- ******************************************************************************/
-#include <string.h>
-
-#include "bt_target.h"
-#include "bt_utils.h"
-#include "btm_api.h"
-#include "btm_int.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "mca_int.h"
-#include "osi/include/osi.h"
-
-/* L2CAP callback function structure */
-const tL2CAP_APPL_INFO mca_l2c_int_appl = {
-    NULL,
-    mca_l2c_connect_cfm_cback,
-    NULL,
-    mca_l2c_config_ind_cback,
-    mca_l2c_config_cfm_cback,
-    mca_l2c_disconnect_ind_cback,
-    mca_l2c_disconnect_cfm_cback,
-    NULL,
-    mca_l2c_data_ind_cback,
-    mca_l2c_congestion_ind_cback,
-    NULL,
-    NULL /* tL2CA_CREDITS_RECEIVED_CB */};
-
-/* Control channel eL2CAP default options */
-const tL2CAP_FCR_OPTS mca_l2c_fcr_opts_def = {
-    L2CAP_FCR_ERTM_MODE,          /* Mandatory for MCAP */
-    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 */
-};
-
-/*******************************************************************************
- *
- * Function         mca_sec_check_complete_term
- *
- * Description      The function called when Security Manager finishes
- *                  verification of the service side connection
- *
- * Returns          void
- *
- ******************************************************************************/
-static void mca_sec_check_complete_term(const RawAddress* bd_addr,
-                                        UNUSED_ATTR tBT_TRANSPORT transport,
-                                        void* p_ref_data, uint8_t res) {
-  tMCA_TC_TBL* p_tbl = (tMCA_TC_TBL*)p_ref_data;
-  tL2CAP_CFG_INFO cfg;
-  tL2CAP_ERTM_INFO ertm_info;
-
-  MCA_TRACE_DEBUG("mca_sec_check_complete_term res: %d", res);
-
-  if (res == BTM_SUCCESS) {
-    MCA_TRACE_DEBUG("lcid:x%x id:x%x", p_tbl->lcid, p_tbl->id);
-    /* Set the FCR options: control channel mandates ERTM */
-    ertm_info.preferred_mode = mca_l2c_fcr_opts_def.mode;
-    ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
-    ertm_info.user_rx_buf_size = MCA_USER_RX_BUF_SIZE;
-    ertm_info.user_tx_buf_size = MCA_USER_TX_BUF_SIZE;
-    ertm_info.fcr_rx_buf_size = MCA_FCR_RX_BUF_SIZE;
-    ertm_info.fcr_tx_buf_size = MCA_FCR_TX_BUF_SIZE;
-    /* Send response to the L2CAP layer. */
-    L2CA_ErtmConnectRsp(*bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_OK,
-                        L2CAP_CONN_OK, &ertm_info);
-
-    /* transition to configuration state */
-    p_tbl->state = MCA_TC_ST_CFG;
-
-    /* Send L2CAP config req */
-    mca_set_cfg_by_tbl(&cfg, p_tbl);
-    L2CA_ConfigReq(p_tbl->lcid, &cfg);
-  } else {
-    L2CA_ConnectRsp(*bd_addr, p_tbl->id, p_tbl->lcid, L2CAP_CONN_SECURITY_BLOCK,
-                    L2CAP_CONN_OK);
-    mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_sec_check_complete_orig
- *
- * Description      The function called when Security Manager finishes
- *                  verification of the service side connection
- *
- * Returns          void
- *
- ******************************************************************************/
-static void mca_sec_check_complete_orig(UNUSED_ATTR const RawAddress* bd_addr,
-                                        UNUSED_ATTR tBT_TRANSPORT transport,
-                                        void* p_ref_data, uint8_t res) {
-  tMCA_TC_TBL* p_tbl = (tMCA_TC_TBL*)p_ref_data;
-  tL2CAP_CFG_INFO cfg;
-
-  MCA_TRACE_DEBUG("mca_sec_check_complete_orig res: %d", res);
-
-  if (res == BTM_SUCCESS) {
-    /* set channel state */
-    p_tbl->state = MCA_TC_ST_CFG;
-
-    /* Send L2CAP config req */
-    mca_set_cfg_by_tbl(&cfg, p_tbl);
-    L2CA_ConfigReq(p_tbl->lcid, &cfg);
-  } else {
-    L2CA_DisconnectReq(p_tbl->lcid);
-    mca_tc_close_ind(p_tbl, L2CAP_CONN_SECURITY_BLOCK);
-  }
-}
-/*******************************************************************************
- *
- * Function         mca_l2c_cconn_ind_cback
- *
- * Description      This is the L2CAP connect indication callback function.
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_cconn_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
-                             uint16_t psm, uint8_t id) {
-  tMCA_HANDLE handle = mca_handle_by_cpsm(psm);
-  tMCA_CCB* p_ccb;
-  tMCA_TC_TBL* p_tbl = NULL;
-  uint16_t result = L2CAP_CONN_NO_RESOURCES;
-  tBTM_STATUS rc;
-  tL2CAP_ERTM_INFO ertm_info, *p_ertm_info = NULL;
-  tL2CAP_CFG_INFO cfg;
-
-  MCA_TRACE_EVENT("mca_l2c_cconn_ind_cback: lcid:x%x psm:x%x id:x%x", lcid, psm,
-                  id);
-
-  /* do we already have a control channel for this peer? */
-  p_ccb = mca_ccb_by_bd(handle, bd_addr);
-  if (p_ccb == NULL) {
-    /* no, allocate ccb */
-    p_ccb = mca_ccb_alloc(handle, bd_addr);
-    if (p_ccb != NULL) {
-      /* allocate and set up entry */
-      p_ccb->lcid = lcid;
-      p_tbl = mca_tc_tbl_calloc(p_ccb);
-      p_tbl->id = id;
-      p_tbl->cfg_flags = MCA_L2C_CFG_CONN_ACP;
-      /* proceed with connection */
-      /* Check the security */
-      rc = btm_sec_mx_access_request(bd_addr, psm, false, BTM_SEC_PROTO_MCA, 0,
-                                     &mca_sec_check_complete_term, p_tbl);
-      if (rc == BTM_CMD_STARTED) {
-        /* Set the FCR options: control channel mandates ERTM */
-        ertm_info.preferred_mode = mca_l2c_fcr_opts_def.mode;
-        ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
-        ertm_info.user_rx_buf_size = MCA_USER_RX_BUF_SIZE;
-        ertm_info.user_tx_buf_size = MCA_USER_TX_BUF_SIZE;
-        ertm_info.fcr_rx_buf_size = MCA_FCR_RX_BUF_SIZE;
-        ertm_info.fcr_tx_buf_size = MCA_FCR_TX_BUF_SIZE;
-        p_ertm_info = &ertm_info;
-        result = L2CAP_CONN_PENDING;
-      } else
-        result = L2CAP_CONN_OK;
-    }
-
-    /*  deal with simultaneous control channel connect case */
-  }
-  /* else reject their connection */
-
-  if (!p_tbl || (p_tbl->state != MCA_TC_ST_CFG)) {
-    /* Send L2CAP connect rsp */
-    L2CA_ErtmConnectRsp(bd_addr, id, lcid, result, L2CAP_CONN_OK, p_ertm_info);
-
-    /* if result ok, proceed with connection and send L2CAP
-       config req */
-    if (result == L2CAP_CONN_OK) {
-      /* set channel state */
-      p_tbl->state = MCA_TC_ST_CFG;
-
-      /* Send L2CAP config req */
-      mca_set_cfg_by_tbl(&cfg, p_tbl);
-      L2CA_ConfigReq(p_tbl->lcid, &cfg);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_dconn_ind_cback
- *
- * Description      This is the L2CAP connect indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_dconn_ind_cback(const RawAddress& bd_addr, uint16_t lcid,
-                             uint16_t psm, uint8_t id) {
-  tMCA_HANDLE handle = mca_handle_by_dpsm(psm);
-  tMCA_CCB* p_ccb;
-  tMCA_DCB* p_dcb;
-  tMCA_TC_TBL* p_tbl = NULL;
-  uint16_t result;
-  tL2CAP_CFG_INFO cfg;
-  tL2CAP_ERTM_INFO *p_ertm_info = NULL, ertm_info;
-  const tMCA_CHNL_CFG* p_chnl_cfg;
-
-  MCA_TRACE_EVENT("mca_l2c_dconn_ind_cback: lcid:x%x psm:x%x ", lcid, psm);
-
-  if (((p_ccb = mca_ccb_by_bd(handle, bd_addr)) != NULL) && /* find the CCB */
-      (p_ccb->status ==
-       MCA_CCB_STAT_PENDING) && /* this CCB is expecting a MDL */
-      (p_ccb->p_tx_req &&
-       (p_dcb = mca_dcb_by_hdl(p_ccb->p_tx_req->dcb_idx)) != NULL)) {
-    /* found the associated dcb in listening mode */
-    /* proceed with connection */
-    p_dcb->lcid = lcid;
-    p_tbl = mca_tc_tbl_dalloc(p_dcb);
-    p_tbl->id = id;
-    p_tbl->cfg_flags = MCA_L2C_CFG_CONN_ACP;
-    p_chnl_cfg = p_dcb->p_chnl_cfg;
-    /* assume that control channel has verified the security requirement */
-    /* Set the FCR options: control channel mandates ERTM */
-    ertm_info.preferred_mode = p_chnl_cfg->fcr_opt.mode;
-    ertm_info.allowed_modes = (1 << p_chnl_cfg->fcr_opt.mode);
-    ertm_info.user_rx_buf_size = p_chnl_cfg->user_rx_buf_size;
-    ertm_info.user_tx_buf_size = p_chnl_cfg->user_tx_buf_size;
-    ertm_info.fcr_rx_buf_size = p_chnl_cfg->fcr_rx_buf_size;
-    ertm_info.fcr_tx_buf_size = p_chnl_cfg->fcr_tx_buf_size;
-    p_ertm_info = &ertm_info;
-    result = L2CAP_CONN_OK;
-  } else {
-    /* else we're not listening for traffic channel; reject
-     * (this error code is specified by MCAP spec) */
-    result = L2CAP_CONN_NO_RESOURCES;
-  }
-
-  /* Send L2CAP connect rsp */
-  L2CA_ErtmConnectRsp(bd_addr, id, lcid, result, result, p_ertm_info);
-
-  /* if result ok, proceed with connection */
-  if (result == L2CAP_CONN_OK) {
-    /* transition to configuration state */
-    p_tbl->state = MCA_TC_ST_CFG;
-
-    /* Send L2CAP config req */
-    mca_set_cfg_by_tbl(&cfg, p_tbl);
-    L2CA_ConfigReq(lcid, &cfg);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_connect_cfm_cback
- *
- * Description      This is the L2CAP connect confirm callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_connect_cfm_cback(uint16_t lcid, uint16_t result) {
-  tMCA_TC_TBL* p_tbl;
-  tL2CAP_CFG_INFO cfg;
-  tMCA_CCB* p_ccb;
-
-  MCA_TRACE_DEBUG("mca_l2c_connect_cfm_cback lcid: x%x, result: %d", lcid,
-                  result);
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    MCA_TRACE_DEBUG("p_tbl state: %d, tcid: %d", p_tbl->state, p_tbl->tcid);
-    /* if in correct state */
-    if (p_tbl->state == MCA_TC_ST_CONN) {
-      /* if result successful */
-      if (result == L2CAP_CONN_OK) {
-        if (p_tbl->tcid != 0) {
-          /* set channel state */
-          p_tbl->state = MCA_TC_ST_CFG;
-
-          /* Send L2CAP config req */
-          mca_set_cfg_by_tbl(&cfg, p_tbl);
-          L2CA_ConfigReq(lcid, &cfg);
-        } else {
-          p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-          if (p_ccb == NULL) {
-            result = L2CAP_CONN_NO_RESOURCES;
-          } else {
-            /* set channel state */
-            p_tbl->state = MCA_TC_ST_SEC_INT;
-            p_tbl->lcid = lcid;
-            p_tbl->cfg_flags = MCA_L2C_CFG_CONN_INT;
-
-            /* Check the security */
-            btm_sec_mx_access_request(p_ccb->peer_addr, p_ccb->ctrl_vpsm, true,
-                                      BTM_SEC_PROTO_MCA, p_tbl->tcid,
-                                      &mca_sec_check_complete_orig, p_tbl);
-          }
-        }
-      }
-
-      /* failure; notify adaption that channel closed */
-      if (result != L2CAP_CONN_OK) {
-        p_tbl->cfg_flags |= MCA_L2C_CFG_DISCN_INT;
-        mca_tc_close_ind(p_tbl, result);
-      }
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_config_cfm_cback
- *
- * Description      This is the L2CAP config confirm callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_config_cfm_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
-  tMCA_TC_TBL* p_tbl;
-
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    /* if in correct state */
-    if (p_tbl->state == MCA_TC_ST_CFG) {
-      /* if result successful */
-      if (p_cfg->result == L2CAP_CONN_OK) {
-        /* update cfg_flags */
-        p_tbl->cfg_flags |= MCA_L2C_CFG_CFM_DONE;
-
-        /* if configuration complete */
-        if (p_tbl->cfg_flags & MCA_L2C_CFG_IND_DONE) {
-          mca_tc_open_ind(p_tbl);
-        }
-      }
-      /* else failure */
-      else {
-        /* Send L2CAP disconnect req */
-        L2CA_DisconnectReq(lcid);
-      }
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_config_ind_cback
- *
- * Description      This is the L2CAP config indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_config_ind_cback(uint16_t lcid, tL2CAP_CFG_INFO* p_cfg) {
-  tMCA_TC_TBL* p_tbl;
-  uint16_t result = L2CAP_CFG_OK;
-
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    /* store the mtu in tbl */
-    if (p_cfg->mtu_present) {
-      p_tbl->peer_mtu = p_cfg->mtu;
-      if (p_tbl->peer_mtu < MCA_MIN_MTU) {
-        result = L2CAP_CFG_UNACCEPTABLE_PARAMS;
-      }
-    } else {
-      p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
-    }
-    MCA_TRACE_DEBUG("peer_mtu: %d, lcid: x%x mtu_present:%d", p_tbl->peer_mtu,
-                    lcid, p_cfg->mtu_present);
-
-    /* send L2CAP configure response */
-    memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
-    p_cfg->result = result;
-    L2CA_ConfigRsp(lcid, p_cfg);
-
-    /* if first config ind */
-    if ((p_tbl->cfg_flags & MCA_L2C_CFG_IND_DONE) == 0) {
-      /* update cfg_flags */
-      p_tbl->cfg_flags |= MCA_L2C_CFG_IND_DONE;
-
-      /* if configuration complete */
-      if (p_tbl->cfg_flags & MCA_L2C_CFG_CFM_DONE) {
-        mca_tc_open_ind(p_tbl);
-      }
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_disconnect_ind_cback
- *
- * Description      This is the L2CAP disconnect indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_disconnect_ind_cback(uint16_t lcid, bool ack_needed) {
-  tMCA_TC_TBL* p_tbl;
-  uint16_t reason = L2CAP_DISC_TIMEOUT;
-
-  MCA_TRACE_DEBUG("mca_l2c_disconnect_ind_cback lcid: %d, ack_needed: %d", lcid,
-                  ack_needed);
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    if (ack_needed) {
-      /* send L2CAP disconnect response */
-      L2CA_DisconnectRsp(lcid);
-    }
-
-    p_tbl->cfg_flags = MCA_L2C_CFG_DISCN_ACP;
-    if (ack_needed) reason = L2CAP_DISC_OK;
-    mca_tc_close_ind(p_tbl, reason);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_disconnect_cfm_cback
- *
- * Description      This is the L2CAP disconnect confirm callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_disconnect_cfm_cback(uint16_t lcid, uint16_t result) {
-  tMCA_TC_TBL* p_tbl;
-
-  MCA_TRACE_DEBUG("mca_l2c_disconnect_cfm_cback lcid: x%x, result: %d", lcid,
-                  result);
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    p_tbl->cfg_flags = MCA_L2C_CFG_DISCN_INT;
-    mca_tc_close_ind(p_tbl, result);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_congestion_ind_cback
- *
- * Description      This is the L2CAP congestion indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_congestion_ind_cback(uint16_t lcid, bool is_congested) {
-  tMCA_TC_TBL* p_tbl;
-
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    mca_tc_cong_ind(p_tbl, is_congested);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_data_ind_cback
- *
- * Description      This is the L2CAP data indication callback function.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void mca_l2c_data_ind_cback(uint16_t lcid, BT_HDR* p_buf) {
-  tMCA_TC_TBL* p_tbl;
-
-  /* look up info for this channel */
-  p_tbl = mca_tc_tbl_by_lcid(lcid);
-  if (p_tbl != NULL) {
-    mca_tc_data_ind(p_tbl, p_buf);
-  } else /* prevent buffer leak */
-    osi_free(p_buf);
-}
-
-/*******************************************************************************
- *
- * Function         mca_l2c_open_req
- *
- * Description      This function calls L2CA_ConnectReq() to initiate a L2CAP
- *                  channel.
- *
- * Returns          void.
- *
- ******************************************************************************/
-uint16_t mca_l2c_open_req(const RawAddress& bd_addr, uint16_t psm,
-                          const tMCA_CHNL_CFG* p_chnl_cfg) {
-  tL2CAP_ERTM_INFO ertm_info;
-
-  if (p_chnl_cfg) {
-    ertm_info.preferred_mode = p_chnl_cfg->fcr_opt.mode;
-    ertm_info.allowed_modes = (1 << p_chnl_cfg->fcr_opt.mode);
-    ertm_info.user_rx_buf_size = p_chnl_cfg->user_rx_buf_size;
-    ertm_info.user_tx_buf_size = p_chnl_cfg->user_tx_buf_size;
-    ertm_info.fcr_rx_buf_size = p_chnl_cfg->fcr_rx_buf_size;
-    ertm_info.fcr_tx_buf_size = p_chnl_cfg->fcr_tx_buf_size;
-  } else {
-    ertm_info.preferred_mode = mca_l2c_fcr_opts_def.mode;
-    ertm_info.allowed_modes = L2CAP_FCR_CHAN_OPT_ERTM;
-    ertm_info.user_rx_buf_size = MCA_USER_RX_BUF_SIZE;
-    ertm_info.user_tx_buf_size = MCA_USER_TX_BUF_SIZE;
-    ertm_info.fcr_rx_buf_size = MCA_FCR_RX_BUF_SIZE;
-    ertm_info.fcr_tx_buf_size = MCA_FCR_TX_BUF_SIZE;
-  }
-  return L2CA_ErtmConnectReq(psm, bd_addr, &ertm_info);
-}
diff --git a/stack/mcap/mca_main.cc b/stack/mcap/mca_main.cc
deleted file mode 100644
index 0185721..0000000
--- a/stack/mcap/mca_main.cc
+++ /dev/null
@@ -1,570 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This is the implementation file for the MCAP Main Control Block and
- *  Utility functions.
- *
- ******************************************************************************/
-#include <base/logging.h>
-#include <string.h>
-
-#include "bt_common.h"
-#include "bt_target.h"
-#include "l2c_api.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "mca_int.h"
-
-/* Main Control block for MCA */
-tMCA_CB mca_cb;
-
-/*****************************************************************************
- * constants
- ****************************************************************************/
-
-/* table of standard opcode message size */
-const uint8_t mca_std_msg_len[MCA_NUM_STANDARD_OPCODE] = {
-    4, /* MCA_OP_ERROR_RSP         */
-    5, /* MCA_OP_MDL_CREATE_REQ    */
-    5, /* MCA_OP_MDL_CREATE_RSP    */
-    3, /* MCA_OP_MDL_RECONNECT_REQ */
-    4, /* MCA_OP_MDL_RECONNECT_RSP */
-    3, /* MCA_OP_MDL_ABORT_REQ     */
-    4, /* MCA_OP_MDL_ABORT_RSP     */
-    3, /* MCA_OP_MDL_DELETE_REQ    */
-    4  /* MCA_OP_MDL_DELETE_RSP    */
-};
-
-/*******************************************************************************
- *
- * Function         mca_handle_by_cpsm
- *
- * Description      This function returns the handle for the given control
- *                  channel PSM. 0, if not found.
- *
- * Returns          the MCA handle.
- *
- ******************************************************************************/
-tMCA_HANDLE mca_handle_by_cpsm(uint16_t psm) {
-  int i;
-  tMCA_HANDLE handle = 0;
-  tMCA_RCB* p_rcb = &mca_cb.rcb[0];
-
-  for (i = 0; i < MCA_NUM_REGS; i++, p_rcb++) {
-    if (p_rcb->p_cback && p_rcb->reg.ctrl_psm == psm) {
-      handle = i + 1;
-      break;
-    }
-  }
-  return handle;
-}
-
-/*******************************************************************************
- *
- * Function         mca_handle_by_dpsm
- *
- * Description      This function returns the handle for the given data
- *                  channel PSM. 0, if not found.
- *
- * Returns          the MCA handle.
- *
- ******************************************************************************/
-tMCA_HANDLE mca_handle_by_dpsm(uint16_t psm) {
-  int i;
-  tMCA_HANDLE handle = 0;
-  tMCA_RCB* p_rcb = &mca_cb.rcb[0];
-
-  for (i = 0; i < MCA_NUM_REGS; i++, p_rcb++) {
-    if (p_rcb->p_cback && p_rcb->reg.data_psm == psm) {
-      handle = i + 1;
-      break;
-    }
-  }
-  return handle;
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_tbl_calloc
- *
- * Description      This function allocates a transport table for the given
- *                  control channel.
- *
- * Returns          The tranport table.
- *
- ******************************************************************************/
-tMCA_TC_TBL* mca_tc_tbl_calloc(tMCA_CCB* p_ccb) {
-  tMCA_TC_TBL* p_tbl = mca_cb.tc.tc_tbl;
-  int i;
-
-  /* find next free entry in tc table */
-  for (i = 0; i < MCA_NUM_TC_TBL; i++, p_tbl++) {
-    if (p_tbl->state == MCA_TC_ST_UNUSED) {
-      break;
-    }
-  }
-
-  /* sanity check */
-  CHECK(i != MCA_NUM_TC_TBL);
-
-  /* initialize entry */
-  p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
-  p_tbl->cfg_flags = 0;
-  p_tbl->cb_idx = mca_ccb_to_hdl(p_ccb);
-  p_tbl->tcid = MCA_CTRL_TCID;
-  p_tbl->my_mtu = MCA_CTRL_MTU;
-  p_tbl->state = MCA_TC_ST_IDLE;
-  p_tbl->lcid = p_ccb->lcid;
-  mca_cb.tc.lcid_tbl[p_ccb->lcid - L2CAP_BASE_APPL_CID] = i;
-
-  MCA_TRACE_DEBUG("%s() - cb_idx: %d", __func__, p_tbl->cb_idx);
-  return p_tbl;
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_tbl_dalloc
- *
- * Description      This function allocates a transport table for the given
- *                  data channel.
- *
- * Returns          The tranport table.
- *
- ******************************************************************************/
-tMCA_TC_TBL* mca_tc_tbl_dalloc(tMCA_DCB* p_dcb) {
-  tMCA_TC_TBL* p_tbl = mca_cb.tc.tc_tbl;
-  int i;
-
-  /* find next free entry in tc table */
-  for (i = 0; i < MCA_NUM_TC_TBL; i++, p_tbl++) {
-    if (p_tbl->state == MCA_TC_ST_UNUSED) {
-      break;
-    }
-  }
-
-  /* sanity check */
-  CHECK(i != MCA_NUM_TC_TBL);
-
-  /* initialize entry */
-  p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
-  p_tbl->cfg_flags = 0;
-  p_tbl->cb_idx = mca_dcb_to_hdl(p_dcb);
-  p_tbl->tcid = p_dcb->p_cs->type + 1;
-  p_tbl->my_mtu = p_dcb->p_chnl_cfg->data_mtu;
-  p_tbl->state = MCA_TC_ST_IDLE;
-  p_tbl->lcid = p_dcb->lcid;
-  mca_cb.tc.lcid_tbl[p_dcb->lcid - L2CAP_BASE_APPL_CID] = i;
-
-  MCA_TRACE_DEBUG("%s() - tcid: %d, cb_idx: %d", __func__, p_tbl->tcid,
-                  p_tbl->cb_idx);
-  return p_tbl;
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_tbl_by_lcid
- *
- * Description      Find the transport channel table entry by LCID.
- *
- *
- * Returns          The tranport table.
- *
- ******************************************************************************/
-tMCA_TC_TBL* mca_tc_tbl_by_lcid(uint16_t lcid) {
-  uint8_t idx;
-
-  if (lcid >= L2CAP_BASE_APPL_CID) {
-    idx = mca_cb.tc.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
-
-    if (idx < MCA_NUM_TC_TBL) {
-      return &mca_cb.tc.tc_tbl[idx];
-    }
-  }
-  return NULL;
-}
-
-/*******************************************************************************
- *
- * Function         mca_free_tc_tbl_by_lcid
- *
- * Description      Find the  transport table entry by LCID
- *                  and free the tc_tbl
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_free_tc_tbl_by_lcid(uint16_t lcid) {
-  uint8_t idx;
-
-  if (lcid >= L2CAP_BASE_APPL_CID) {
-    idx = mca_cb.tc.lcid_tbl[lcid - L2CAP_BASE_APPL_CID];
-
-    if (idx < MCA_NUM_TC_TBL) {
-      mca_cb.tc.tc_tbl[idx].state = MCA_TC_ST_UNUSED;
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_set_cfg_by_tbl
- *
- * Description      Set the L2CAP configuration information
- *
- * Returns          none.
- *
- ******************************************************************************/
-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;
-  tMCA_FCS_OPT fcs = MCA_FCS_NONE;
-
-  if (p_tbl->tcid == MCA_CTRL_TCID) {
-    p_opt = &mca_l2c_fcr_opts_def;
-  } else {
-    p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
-    if (p_dcb) {
-      p_opt = &p_dcb->p_chnl_cfg->fcr_opt;
-      fcs = p_dcb->p_chnl_cfg->fcs;
-    }
-  }
-  memset(p_cfg, 0, sizeof(tL2CAP_CFG_INFO));
-  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 (fcs & MCA_FCS_PRESNT_MASK) {
-    p_cfg->fcs_present = true;
-    p_cfg->fcs = (fcs & MCA_FCS_USE_MASK);
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_close_ind
- *
- * Description      This function is called by the L2CAP interface when the
- *                  L2CAP channel is closed.  It looks up the CCB or DCB for
- *                  the channel and sends it a close event.  The reason
- *                  parameter is the same value passed by the L2CAP
- *                  callback function.
- *
- * Returns          Nothing.
- *
- ******************************************************************************/
-void mca_tc_close_ind(tMCA_TC_TBL* p_tbl, uint16_t reason) {
-  tMCA_CCB* p_ccb;
-  tMCA_DCB* p_dcb;
-
-  MCA_TRACE_DEBUG("%s() - tcid: %d, cb_idx:%d, old: %d", __func__, p_tbl->tcid,
-                  p_tbl->cb_idx, p_tbl->state);
-
-  /* Check if the transport channel is in use */
-  if (p_tbl->state == MCA_TC_ST_UNUSED) return;
-
-  tMCA_CLOSE close;
-
-  close.param = MCA_ACP;
-  close.reason = reason;
-  close.lcid = p_tbl->lcid;
-
-  /* clear mca_tc_tbl entry */
-  if (p_tbl->cfg_flags & MCA_L2C_CFG_DISCN_INT) close.param = MCA_INT;
-  p_tbl->cfg_flags = 0;
-  p_tbl->peer_mtu = L2CAP_DEFAULT_MTU;
-
-  /* if control channel, notify ccb of the channel close */
-  if (p_tbl->tcid == MCA_CTRL_TCID) {
-    p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-    tMCA_CCB_EVT mca_ccb_evt;
-    mca_ccb_evt.close = close;
-    mca_ccb_event(p_ccb, MCA_CCB_LL_CLOSE_EVT, &mca_ccb_evt);
-  } else {
-    /* notify dcb of the channel close */
-    p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
-    if (p_dcb != NULL) {
-      tMCA_DCB_EVT mca_dcb_evt;
-      mca_dcb_evt.close = close;
-      mca_dcb_event(p_dcb, MCA_DCB_TC_CLOSE_EVT, &mca_dcb_evt);
-    }
-  }
-  p_tbl->state = MCA_TC_ST_UNUSED;
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_open_ind
- *
- * Description      This function is called by the L2CAP interface when
- *                  the L2CAP channel is opened.  It looks up the CCB or DCB
- *                  for the channel and sends it an open event.
- *
- * Returns          Nothing.
- *
- ******************************************************************************/
-void mca_tc_open_ind(tMCA_TC_TBL* p_tbl) {
-  tMCA_CCB* p_ccb;
-  tMCA_DCB* p_dcb;
-  tMCA_OPEN open;
-
-  MCA_TRACE_DEBUG("mca_tc_open_ind tcid: %d, cb_idx: %d", p_tbl->tcid,
-                  p_tbl->cb_idx);
-  p_tbl->state = MCA_TC_ST_OPEN;
-
-  open.peer_mtu = p_tbl->peer_mtu;
-  open.lcid = p_tbl->lcid;
-  /* use param to indicate the role of connection.
-   * MCA_ACP, if ACP */
-  open.param = MCA_INT;
-  if (p_tbl->cfg_flags & MCA_L2C_CFG_CONN_ACP) {
-    open.param = MCA_ACP;
-  }
-
-  /* if control channel, notify ccb that the channel is open */
-  if (p_tbl->tcid == MCA_CTRL_TCID) {
-    p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-    tMCA_CCB_EVT mca_ccb_evt;
-    mca_ccb_evt.open = open;
-    mca_ccb_event(p_ccb, MCA_CCB_LL_OPEN_EVT, &mca_ccb_evt);
-  } else {
-    /* must be data channel, notify dcb that the channel is open */
-    p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
-
-    /* put lcid in event data */
-    if (p_dcb != NULL) {
-      tMCA_DCB_EVT mca_dcb_evt;
-      mca_dcb_evt.open = open;
-      mca_dcb_event(p_dcb, MCA_DCB_TC_OPEN_EVT, &mca_dcb_evt);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_cong_ind
- *
- * Description      This function is called by the L2CAP interface layer when
- *                  L2CAP calls the congestion callback.  It looks up the CCB
- *                  or DCB for the channel and sends it a congestion event.
- *                  The is_congested parameter is the same value passed by
- *                  the L2CAP callback function.
- *
- *
- * Returns          Nothing.
- *
- ******************************************************************************/
-void mca_tc_cong_ind(tMCA_TC_TBL* p_tbl, bool is_congested) {
-  tMCA_CCB* p_ccb;
-  tMCA_DCB* p_dcb;
-
-  MCA_TRACE_DEBUG("%s() - tcid: %d, cb_idx: %d", __func__, p_tbl->tcid,
-                  p_tbl->cb_idx);
-
-  /* if control channel, notify ccb of congestion */
-  if (p_tbl->tcid == MCA_CTRL_TCID) {
-    p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-    tMCA_CCB_EVT mca_ccb_evt;
-    mca_ccb_evt.llcong = is_congested;
-    mca_ccb_event(p_ccb, MCA_CCB_LL_CONG_EVT, &mca_ccb_evt);
-  } else {
-    /* notify dcb that channel open */
-    p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
-    if (p_dcb != NULL) {
-      tMCA_DCB_EVT mca_dcb_evt;
-      mca_dcb_evt.llcong = is_congested;
-      mca_dcb_event(p_dcb, MCA_DCB_TC_CONG_EVT, &mca_dcb_evt);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_tc_data_ind
- *
- * Description      This function is called by the L2CAP interface layer when
- *                  incoming data is received from L2CAP.  It looks up the CCB
- *                  or DCB for the channel and routes the data accordingly.
- *
- * Returns          Nothing.
- *
- ******************************************************************************/
-void mca_tc_data_ind(tMCA_TC_TBL* p_tbl, BT_HDR* p_buf) {
-  tMCA_CCB* p_ccb;
-  tMCA_DCB* p_dcb;
-  uint8_t event = MCA_CCB_MSG_RSP_EVT;
-  uint8_t* p;
-  uint8_t rej_rsp_code = MCA_RSP_SUCCESS;
-
-  MCA_TRACE_DEBUG("%s: tcid: %d, cb_idx: %d", __func__, p_tbl->tcid,
-                  p_tbl->cb_idx);
-
-  /* if control channel, handle control message */
-  if (p_tbl->tcid == MCA_CTRL_TCID) {
-    p_ccb = mca_ccb_by_hdl((tMCA_CL)p_tbl->cb_idx);
-    if (p_ccb) {
-      p = (uint8_t*)(p_buf + 1) + p_buf->offset;
-      /* all the request opcode has bit 0 set. response code has bit 0 clear */
-      if ((*p) & 0x01) event = MCA_CCB_MSG_REQ_EVT;
-
-      if (*p < MCA_NUM_STANDARD_OPCODE) {
-        if (p_buf->len != mca_std_msg_len[*p]) {
-          MCA_TRACE_ERROR("%s: opcode 0x%02x required len: %d, got len: %d",
-                          __func__, *p, mca_std_msg_len[*p], p_buf->len);
-          rej_rsp_code = MCA_RSP_BAD_PARAM;
-        }
-      } else if ((*p >= MCA_FIRST_SYNC_OP) && (*p <= MCA_LAST_SYNC_OP)) {
-        MCA_TRACE_ERROR("%s: unsupported SYNC opcode: 0x%02x len:%d", __func__,
-                        *p, p_buf->len);
-        /* reject unsupported request */
-        rej_rsp_code = MCA_RSP_NO_SUPPORT;
-      } else {
-        MCA_TRACE_ERROR("%s: bad opcode: 0x%02x len:%d", __func__, *p,
-                        p_buf->len);
-        /* reject unsupported request */
-        rej_rsp_code = MCA_RSP_BAD_OPCODE;
-      }
-
-      p_buf->layer_specific = rej_rsp_code;
-      /* forward the request/response to state machine */
-      mca_ccb_event(p_ccb, event, (tMCA_CCB_EVT*)p_buf);
-    } else {
-      osi_free(p_buf);
-    }
-  } else {
-    /* send event to dcb */
-    p_dcb = mca_dcb_by_hdl(p_tbl->cb_idx);
-    if (p_dcb != NULL) {
-      mca_dcb_event(p_dcb, MCA_DCB_TC_DATA_EVT, (tMCA_DCB_EVT*)p_buf);
-    } else {
-      osi_free(p_buf);
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_rcb_alloc
- *
- * Description      This function allocates a registration control block.
- *                  If no free RCB is available, it returns NULL.
- *
- * Returns          tMCA_RCB *
- *
- ******************************************************************************/
-tMCA_RCB* mca_rcb_alloc(tMCA_REG* p_reg) {
-  int i;
-  tMCA_RCB* p_rcb = NULL;
-
-  for (i = 0; i < MCA_NUM_REGS; i++) {
-    if (mca_cb.rcb[i].p_cback == NULL) {
-      p_rcb = &mca_cb.rcb[i];
-      memcpy(&p_rcb->reg, p_reg, sizeof(tMCA_REG));
-      break;
-    }
-  }
-  return p_rcb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_rcb_dealloc
- *
- * Description      This function deallocates the RCB with the given handle.
- *
- * Returns          void.
- *
- ******************************************************************************/
-void mca_rcb_dealloc(tMCA_HANDLE handle) {
-  int i;
-  bool done = true;
-  tMCA_RCB* p_rcb;
-  tMCA_CCB* p_ccb;
-
-  if (handle && (handle <= MCA_NUM_REGS)) {
-    handle--;
-    p_rcb = &mca_cb.rcb[handle];
-    if (p_rcb->p_cback) {
-      p_ccb = &mca_cb.ccb[handle * MCA_NUM_LINKS];
-      /* check if all associated CCB are disconnected */
-      for (i = 0; i < MCA_NUM_LINKS; i++, p_ccb++) {
-        if (p_ccb->p_rcb) {
-          done = false;
-          mca_ccb_event(p_ccb, MCA_CCB_API_DISCONNECT_EVT, NULL);
-        }
-      }
-
-      if (done) {
-        memset(p_rcb, 0, sizeof(tMCA_RCB));
-        MCA_TRACE_DEBUG("%s() - reset MCA_RCB index=%d", __func__, handle);
-      }
-    }
-  }
-}
-
-/*******************************************************************************
- *
- * Function         mca_rcb_to_handle
- *
- * Description      This function converts a pointer to an RCB to
- *                  a handle (tMCA_HANDLE).  It returns the handle.
- *
- * Returns          void.
- *
- ******************************************************************************/
-tMCA_HANDLE mca_rcb_to_handle(tMCA_RCB* p_rcb) {
-  return (uint8_t)(p_rcb - mca_cb.rcb + 1);
-}
-
-/*******************************************************************************
- *
- * Function         mca_rcb_by_handle
- *
- * Description      This function finds the RCB for a handle (tMCA_HANDLE).
- *                  It returns a pointer to the RCB.  If no RCB matches the
- *                  handle it returns NULL.
- *
- * Returns          tMCA_RCB *
- *
- ******************************************************************************/
-tMCA_RCB* mca_rcb_by_handle(tMCA_HANDLE handle) {
-  tMCA_RCB* p_rcb = NULL;
-
-  if (handle && (handle <= MCA_NUM_REGS) && mca_cb.rcb[handle - 1].p_cback) {
-    p_rcb = &mca_cb.rcb[handle - 1];
-  }
-  return p_rcb;
-}
-
-/*******************************************************************************
- *
- * Function         mca_is_valid_dep_id
- *
- * Description      This function checks if the given dep_id is valid.
- *
- * Returns          true, if this is a valid local dep_id
- *
- ******************************************************************************/
-bool mca_is_valid_dep_id(tMCA_RCB* p_rcb, tMCA_DEP dep) {
-  bool valid = false;
-  if (dep < MCA_NUM_DEPS && p_rcb->dep[dep].p_data_cback) {
-    valid = true;
-  }
-  return valid;
-}
diff --git a/stack/rfcomm/port_api.cc b/stack/rfcomm/port_api.cc
index 1ae8667..0bb817d 100644
--- a/stack/rfcomm/port_api.cc
+++ b/stack/rfcomm/port_api.cc
@@ -118,7 +118,7 @@
   *p_handle = 0;
 
   if ((scn == 0) || (scn >= PORT_MAX_RFC_PORTS)) {
-    /* Server Channel Number(SCN) should be in range 1...30 */
+    // Server Channel Number (SCN) should be in range [1, 30]
     LOG(ERROR) << __func__ << ": Invalid SCN, bd_addr=" << bd_addr
                << ", scn=" << static_cast<int>(scn)
                << ", is_server=" << is_server
@@ -127,8 +127,8 @@
     return (PORT_INVALID_SCN);
   }
 
-  /* For client that originate connection on the existing none initiator */
-  /* multiplexer channel DLCI should be odd */
+  // For client that originates connection on the existing none initiator
+  // multiplexer channel, DLCI should be odd.
   uint8_t dlci;
   tRFC_MCB* p_mcb = port_find_mcb(bd_addr);
   if (p_mcb && !p_mcb->is_initiator && !is_server) {
@@ -137,13 +137,13 @@
     dlci = (scn << 1);
   }
 
-  /* For the server side always allocate a new port.  On the client side */
-  /* do not allow the same (dlci, bd_addr) to be opened twice by application */
+  // On the client side, do not allow the same (dlci, bd_addr) to be opened
+  // twice by application
   tPORT* p_port;
   if (!is_server) {
     p_port = port_find_port(dlci, bd_addr);
     if (p_port != nullptr) {
-      /* if existing port is also a client port */
+      // if existing port is also a client port, error out
       if (!p_port->is_server) {
         LOG(ERROR) << __func__ << ": already at opened state "
                    << static_cast<int>(p_port->state)
@@ -153,22 +153,26 @@
                    << ", bd_addr=" << bd_addr << ", scn=" << std::to_string(scn)
                    << ", is_server=" << is_server << ", mtu=" << mtu
                    << ", uuid=" << loghex(uuid) << ", dlci=" << +dlci
-                   << ", p_mcb=" << p_mcb << ", port=" << +p_port->inx;
-        *p_handle = p_port->inx;
+                   << ", p_mcb=" << p_mcb
+                   << ", port=" << std::to_string(p_port->handle);
+        *p_handle = p_port->handle;
         return (PORT_ALREADY_OPENED);
       }
     }
   }
 
+  // On the server side, always allocate a new port.
   p_port = port_allocate_port(dlci, bd_addr);
   if (p_port == nullptr) {
     LOG(ERROR) << __func__ << ": no resources, bd_addr=" << bd_addr
                << ", scn=" << std::to_string(scn) << ", is_server=" << is_server
                << ", mtu=" << mtu << ", uuid=" << loghex(uuid)
                << ", dlci=" << +dlci;
-    return (PORT_NO_RESOURCES);
+    return PORT_NO_RESOURCES;
   }
+  *p_handle = p_port->handle;
 
+  // Get default signal state
   switch (uuid) {
     case UUID_PROTOCOL_OBEX:
       p_port->default_signal_state = PORT_OBEX_DEFAULT_SIGNAL_STATE;
@@ -189,42 +193,35 @@
       break;
   }
 
-  *p_handle = p_port->inx;
-
+  // Assign port specific values
   p_port->state = PORT_STATE_OPENING;
   p_port->uuid = uuid;
   p_port->is_server = is_server;
   p_port->scn = scn;
   p_port->ev_mask = 0;
 
-  /* If the MTU is not specified (0), keep MTU decision until the
-   * PN frame has to be send
-   * at that time connection should be established and we
-   * will know for sure our prefered MTU
-   */
-
+  // Find MTU
+  // If the MTU is not specified (0), keep MTU decision until the PN frame has
+  // to be send at that time connection should be established and we will know
+  // for sure our prefered MTU
   uint16_t rfcomm_mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
-
   if (mtu) {
     p_port->mtu = (mtu < rfcomm_mtu) ? mtu : rfcomm_mtu;
   } else {
     p_port->mtu = rfcomm_mtu;
   }
 
-  /* server doesn't need to release port when closing */
+  // Other states
+  // server doesn't need to release port when closing
   if (is_server) {
     p_port->keep_port_handle = true;
-
-    /* keep mtu that user asked, p_port->mtu could be updated during param
-     * negotiation */
+    // keep mtu that user asked, p_port->mtu could be updated during param
+    // negotiation
     p_port->keep_mtu = p_port->mtu;
   }
-
   p_port->local_ctrl.modem_signal = p_port->default_signal_state;
   p_port->local_ctrl.fc = false;
-
   p_port->p_mgmt_callback = p_mgmt_cb;
-
   p_port->bd_addr = bd_addr;
 
   LOG(INFO) << __func__ << ": bd_addr=" << bd_addr
@@ -234,12 +231,12 @@
             << ", signal_state=" << loghex(p_port->default_signal_state)
             << ", p_port=" << p_port;
 
-  /* If this is not initiator of the connection need to just wait */
+  // If this is not initiator of the connection need to just wait
   if (p_port->is_server) {
     return (PORT_SUCCESS);
   }
 
-  /* Open will be continued after security checks are passed */
+  // Open will be continued after security checks are passed
   return port_open_continue(p_port);
 }
 
@@ -286,24 +283,21 @@
  *
  ******************************************************************************/
 int RFCOMM_RemoveServer(uint16_t handle) {
-  tPORT* p_port;
-
-  RFCOMM_TRACE_API("RFCOMM_RemoveServer() handle:%d", handle);
-
   /* Check if handle is valid to avoid crashing */
   if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
-    RFCOMM_TRACE_ERROR("RFCOMM_RemoveServer() BAD handle:%d", handle);
+    LOG(ERROR) << __func__ << ": bad handle " << handle;
     return (PORT_BAD_HANDLE);
   }
-  p_port = &rfc_cb.port.port[handle - 1];
+  tPORT* p_port = &rfc_cb.port.port[handle - 1];
 
   /* Do not report any events to the client any more. */
-  p_port->p_mgmt_callback = NULL;
+  p_port->p_mgmt_callback = nullptr;
 
   if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
-    RFCOMM_TRACE_EVENT("RFCOMM_RemoveServer() Not opened:%d", handle);
+    VLOG(1) << __func__ << ": handle " << handle << " not opened";
     return (PORT_SUCCESS);
   }
+  LOG(INFO) << __func__ << ": handle=" << handle;
 
   /* this port will be deallocated after closing */
   p_port->keep_port_handle = false;
@@ -486,18 +480,19 @@
  *                  p_lcid     - OUT L2CAP's LCID
  *
  ******************************************************************************/
-int PORT_CheckConnection(uint16_t handle, RawAddress& bd_addr,
+int PORT_CheckConnection(uint16_t handle, RawAddress* bd_addr,
                          uint16_t* p_lcid) {
-  tPORT* p_port;
-
-  RFCOMM_TRACE_API("PORT_CheckConnection() handle:%d", handle);
-
   /* Check if handle is valid to avoid crashing */
   if ((handle == 0) || (handle > MAX_RFC_PORTS)) {
     return (PORT_BAD_HANDLE);
   }
-
-  p_port = &rfc_cb.port.port[handle - 1];
+  tPORT* p_port = &rfc_cb.port.port[handle - 1];
+  RFCOMM_TRACE_DEBUG(
+      "%s: handle=%d, in_use=%d, port_state=%d, p_mcb=%p, peer_ready=%d, "
+      "rfc_state=%d",
+      __func__, handle, p_port->in_use, p_port->state, p_port->rfc.p_mcb,
+      (p_port->rfc.p_mcb ? p_port->rfc.p_mcb->peer_ready : -1),
+      p_port->rfc.state);
 
   if (!p_port->in_use || (p_port->state == PORT_STATE_CLOSED)) {
     return (PORT_NOT_OPENED);
@@ -508,7 +503,7 @@
     return (PORT_LINE_ERR);
   }
 
-  bd_addr = p_port->rfc.p_mcb->bd_addr;
+  *bd_addr = p_port->rfc.p_mcb->bd_addr;
   if (p_lcid) *p_lcid = p_port->rfc.p_mcb->lcid;
 
   return (PORT_SUCCESS);
@@ -525,28 +520,23 @@
  *                  bd_addr    - bd_addr of the peer
  *
  ******************************************************************************/
-bool PORT_IsOpening(RawAddress& bd_addr) {
-  uint8_t xx, yy;
-  tRFC_MCB* p_mcb = NULL;
-  tPORT* p_port;
-  bool found_port;
-
+bool PORT_IsOpening(RawAddress* bd_addr) {
   /* Check for any rfc_mcb which is in the middle of opening. */
-  for (xx = 0; xx < MAX_BD_CONNECTIONS; xx++) {
-    if ((rfc_cb.port.rfc_mcb[xx].state > RFC_MX_STATE_IDLE) &&
-        (rfc_cb.port.rfc_mcb[xx].state < RFC_MX_STATE_CONNECTED)) {
-      bd_addr = rfc_cb.port.rfc_mcb[xx].bd_addr;
+  for (auto& multiplexer_cb : rfc_cb.port.rfc_mcb) {
+    if ((multiplexer_cb.state > RFC_MX_STATE_IDLE) &&
+        (multiplexer_cb.state < RFC_MX_STATE_CONNECTED)) {
+      *bd_addr = multiplexer_cb.bd_addr;
       return true;
     }
 
-    if (rfc_cb.port.rfc_mcb[xx].state == RFC_MX_STATE_CONNECTED) {
-      found_port = false;
-      p_mcb = &rfc_cb.port.rfc_mcb[xx];
-      p_port = &rfc_cb.port.port[0];
+    if (multiplexer_cb.state == RFC_MX_STATE_CONNECTED) {
+      bool found_port = false;
+      tPORT* p_port = nullptr;
 
-      for (yy = 0; yy < MAX_RFC_PORTS; yy++, p_port++) {
-        if (p_port->rfc.p_mcb == p_mcb) {
+      for (tPORT& port : rfc_cb.port.port) {
+        if (port.rfc.p_mcb == &multiplexer_cb) {
           found_port = true;
+          p_port = &port;
           break;
         }
       }
@@ -554,7 +544,7 @@
       if ((!found_port) ||
           (found_port && (p_port->rfc.state < RFC_STATE_OPENED))) {
         /* Port is not established yet. */
-        bd_addr = rfc_cb.port.rfc_mcb[xx].bd_addr;
+        *bd_addr = multiplexer_cb.bd_addr;
         return true;
       }
     }
@@ -827,7 +817,7 @@
 
     events &= p_port->ev_mask;
     if (p_port->p_callback && events) {
-      p_port->p_callback(events, p_port->inx);
+      p_port->p_callback(events, p_port->handle);
     }
   }
   return (PORT_SUCCESS);
@@ -894,7 +884,7 @@
 
     events &= p_port->ev_mask;
     if (p_port->p_callback && events) {
-      p_port->p_callback(events, p_port->inx);
+      p_port->p_callback(events, p_port->handle);
     }
   }
   return (PORT_SUCCESS);
@@ -1118,7 +1108,7 @@
     events &= p_port->ev_mask;
 
     if ((p_port->p_callback != NULL) && events)
-      (p_port->p_callback)(events, p_port->inx);
+      (p_port->p_callback)(events, p_port->handle);
   }
 
   return (PORT_SUCCESS);
@@ -1306,7 +1296,7 @@
       osi_free(p_buf);
 
       if ((p_port->p_callback != NULL) && (p_port->ev_mask & PORT_EV_ERR))
-        p_port->p_callback(PORT_EV_ERR, p_port->inx);
+        p_port->p_callback(PORT_EV_ERR, p_port->handle);
 
       return (PORT_TX_FULL);
     }
@@ -1384,7 +1374,7 @@
   event &= p_port->ev_mask;
 
   /* Send event to the application */
-  if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->inx);
+  if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->handle);
 
   return (PORT_SUCCESS);
 }
@@ -1539,7 +1529,7 @@
   event &= p_port->ev_mask;
 
   /* Send event to the application */
-  if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->inx);
+  if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->handle);
 
   return (PORT_SUCCESS);
 }
@@ -1650,7 +1640,7 @@
   event &= p_port->ev_mask;
 
   /* Send event to the application */
-  if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->inx);
+  if (p_port->p_callback && event) (p_port->p_callback)(event, p_port->handle);
 
   return (PORT_SUCCESS);
 }
diff --git a/stack/rfcomm/port_int.h b/stack/rfcomm/port_int.h
index db7d0fd..ecd8fbc 100644
--- a/stack/rfcomm/port_int.h
+++ b/stack/rfcomm/port_int.h
@@ -90,8 +90,8 @@
 typedef struct {
   alarm_t* mcb_timer;   /* MCB timer */
   fixed_queue_t* cmd_q; /* Queue for command messages on this mux */
-  uint8_t port_inx[RFCOMM_MAX_DLCI + 1]; /* Array for quick access to  */
-                                         /* tPORT based on dlci        */
+  uint8_t port_handles[RFCOMM_MAX_DLCI + 1]; /* Array for quick access to  */
+  /* port handles based on dlci        */
   RawAddress bd_addr;                    /* BD ADDR of the peer if initiator */
   uint16_t lcid;                         /* Local cid used for this channel */
   uint16_t peer_l2cap_mtu; /* Max frame that can be sent to peer L2CAP */
@@ -139,7 +139,7 @@
  * Define control block containing information about PORT connection
 */
 typedef struct {
-  uint8_t inx; /* Index of this control block in the port_info array */
+  uint8_t handle;  // Starting from 1, unique for this object
   bool in_use; /* True when structure is allocated */
 
 #define PORT_STATE_CLOSED 0
diff --git a/stack/rfcomm/port_rfc.cc b/stack/rfcomm/port_rfc.cc
index 5ec5631..3228f64 100644
--- a/stack/rfcomm/port_rfc.cc
+++ b/stack/rfcomm/port_rfc.cc
@@ -56,13 +56,11 @@
  *
  ******************************************************************************/
 int port_open_continue(tPORT* p_port) {
-  tRFC_MCB* p_mcb;
-
   RFCOMM_TRACE_EVENT("port_open_continue, p_port:%p", p_port);
 
   /* Check if multiplexer channel has already been established */
-  p_mcb = rfc_alloc_multiplexer_channel(p_port->bd_addr, true);
-  if (p_mcb == NULL) {
+  tRFC_MCB* p_mcb = rfc_alloc_multiplexer_channel(p_port->bd_addr, true);
+  if (p_mcb == nullptr) {
     RFCOMM_TRACE_WARNING("port_open_continue no mx channel");
     port_release_port(p_port);
     return (PORT_NO_RESOURCES);
@@ -70,24 +68,22 @@
 
   p_port->rfc.p_mcb = p_mcb;
 
-  p_mcb->port_inx[p_port->dlci] = p_port->inx;
+  p_mcb->port_handles[p_port->dlci] = p_port->handle;
 
   /* Connection is up and we know local and remote features, select MTU */
   port_select_mtu(p_port);
 
   if (p_mcb->state == RFC_MX_STATE_CONNECTED) {
-    RFCOMM_ParNegReq(p_mcb, p_port->dlci, p_port->mtu);
+    RFCOMM_ParameterNegotiationRequest(p_mcb, p_port->dlci, p_port->mtu);
   } else if ((p_mcb->state == RFC_MX_STATE_IDLE) ||
              (p_mcb->state == RFC_MX_STATE_DISC_WAIT_UA)) {
-    /* In RFC_MX_STATE_IDLE state, MX state machine will create connection */
-    /* In RFC_MX_STATE_DISC_WAIT_UA state, MX state machine will recreate
-     * connection */
-    /*    after disconnecting is completed */
+    // In RFC_MX_STATE_IDLE state, MX state machine will create connection
+    // In RFC_MX_STATE_DISC_WAIT_UA state, MX state machine will recreate
+    // connection after disconnecting is completed
     RFCOMM_StartReq(p_mcb);
   } else {
-    /* MX state machine ignores RFC_MX_EVENT_START_REQ in these states */
-    /* When it enters RFC_MX_STATE_CONNECTED, it will check any openning ports
-     */
+    // MX state machine ignores RFC_MX_EVENT_START_REQ in these states
+    // When it enters RFC_MX_STATE_CONNECTED, it will check any openning ports
     RFCOMM_TRACE_DEBUG(
         "port_open_continue: mx state(%d) mx channel is openning",
         p_mcb->state);
@@ -128,7 +124,8 @@
 
   if (p_mcb == NULL) return;
 
-  RFCOMM_PortNegReq(p_mcb, p_port->dlci, &p_port->user_port_pars);
+  RFCOMM_PortParameterNegotiationRequest(p_mcb, p_port->dlci,
+                                         &p_port->user_port_pars);
 }
 
 /*******************************************************************************
@@ -162,14 +159,14 @@
   if (p_port->ev_mask & PORT_EV_ERR) events |= PORT_EV_ERR;
 
   if ((p_port->p_callback != NULL) && events)
-    p_port->p_callback(events, p_port->inx);
+    p_port->p_callback(events, p_port->handle);
 
   /* Check if RFCOMM side has been closed while the message was queued */
   if ((p_mcb == NULL) || (p_port->rfc.state == RFC_STATE_CLOSED)) {
     /* Call management callback function before calling port_release_port() to
      * clear tPort */
     if (p_port->p_mgmt_callback)
-      p_port->p_mgmt_callback(PORT_CLOSED, p_port->inx);
+      p_port->p_mgmt_callback(PORT_CLOSED, p_port->handle);
 
     port_release_port(p_port);
   } else {
@@ -188,37 +185,39 @@
  *
  ******************************************************************************/
 void PORT_StartCnf(tRFC_MCB* p_mcb, uint16_t result) {
-  tPORT* p_port;
-  int i;
   bool no_ports_up = true;
 
-  RFCOMM_TRACE_EVENT("PORT_StartCnf result:%d", result);
+  RFCOMM_TRACE_EVENT("%s: result %d", __func__, result);
 
-  p_port = &rfc_cb.port.port[0];
-  for (i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
+  tPORT* p_port = &rfc_cb.port.port[0];
+  for (int i = 0; i < MAX_RFC_PORTS; i++, p_port++) {
     if (p_port->rfc.p_mcb == p_mcb) {
       no_ports_up = false;
 
-      if (result == RFCOMM_SUCCESS)
-        RFCOMM_ParNegReq(p_mcb, p_port->dlci, p_port->mtu);
-      else {
-        RFCOMM_TRACE_WARNING("PORT_StartCnf failed result:%d", result);
+      if (result == RFCOMM_SUCCESS) {
+        RFCOMM_TRACE_EVENT("%s: dlci %d", __func__, p_port->dlci);
+        RFCOMM_ParameterNegotiationRequest(p_mcb, p_port->dlci, p_port->mtu);
+      } else {
+        RFCOMM_TRACE_WARNING("%s: failed result:%d", __func__, result);
 
         /* Warning: result is also set to 4 when l2cap connection
            fails due to l2cap connect cnf (no_resources) */
-        if (result == HCI_ERR_PAGE_TIMEOUT)
+        if (result == HCI_ERR_PAGE_TIMEOUT) {
           p_port->error = PORT_PAGE_TIMEOUT;
-        else
+        } else {
           p_port->error = PORT_START_FAILED;
+        }
 
         rfc_release_multiplexer_channel(p_mcb);
 
         /* Send event to the application */
-        if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR))
-          (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->inx);
+        if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECT_ERR)) {
+          (p_port->p_callback)(PORT_EV_CONNECT_ERR, p_port->handle);
+        }
 
-        if (p_port->p_mgmt_callback)
-          p_port->p_mgmt_callback(PORT_START_FAILED, p_port->inx);
+        if (p_port->p_mgmt_callback) {
+          p_port->p_mgmt_callback(PORT_START_FAILED, p_port->handle);
+        }
 
         port_release_port(p_port);
       }
@@ -272,12 +271,9 @@
  ******************************************************************************/
 void PORT_ParNegInd(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl,
                     uint8_t k) {
+  RFCOMM_TRACE_EVENT("%s: bd_addr=%s, dlci=%d, mtu=%d", __func__,
+                     p_mcb->bd_addr.ToString().c_str(), dlci, mtu);
   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
-  uint8_t our_cl;
-  uint8_t our_k;
-
-  RFCOMM_TRACE_EVENT("PORT_ParNegInd dlci:%d mtu:%d", dlci, mtu);
-
   if (!p_port) {
     /* This can be a first request for this port */
     p_port = port_find_dlci_port(dlci);
@@ -292,9 +288,9 @@
       rfc_check_mcb_active(p_mcb);
       return;
     }
-    RFCOMM_TRACE_EVENT("%s: port_inx[dlci:%d]:%d->%d", __func__, dlci,
-                       p_mcb->port_inx[dlci], p_port->inx);
-    p_mcb->port_inx[dlci] = p_port->inx;
+    RFCOMM_TRACE_EVENT("%s: port_handles[dlci:%d]:%d->%d", __func__, dlci,
+                       p_mcb->port_handles[dlci], p_port->handle);
+    p_mcb->port_handles[dlci] = p_port->handle;
   }
 
   p_port->bd_addr = p_mcb->bd_addr;
@@ -329,6 +325,8 @@
   /* after the DLCI is already established-- the PN in that case must have cl =
    * 0. */
   /* See RFCOMM spec 5.5.3 */
+  uint8_t our_cl;
+  uint8_t our_k;
   if (cl == RFCOMM_PN_CONV_LAYER_TYPE_1) {
     our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
     our_k = 0;
@@ -346,7 +344,7 @@
     our_cl = RFCOMM_PN_CONV_LAYER_TYPE_1;
     our_k = 0;
   }
-  RFCOMM_ParNegRsp(p_mcb, dlci, p_port->mtu, our_cl, our_k);
+  RFCOMM_ParameterNegotiationResponse(p_mcb, dlci, p_port->mtu, our_cl, our_k);
 }
 
 /*******************************************************************************
@@ -362,12 +360,13 @@
  ******************************************************************************/
 void PORT_ParNegCnf(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl,
                     uint8_t k) {
-  tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
-
   RFCOMM_TRACE_EVENT("PORT_ParNegCnf dlci:%d mtu:%d cl: %d k: %d", dlci, mtu,
                      cl, k);
-
-  if (!p_port) return;
+  tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
+  if (!p_port) {
+    LOG(WARNING) << __func__ << ": port is null for " << p_mcb->bd_addr;
+    return;
+  }
 
   /* Flow control mechanism not set yet.  Negotiate flow control mechanism. */
   if (p_mcb->flow == PORT_FC_UNDEFINED) {
@@ -377,19 +376,17 @@
     if ((PORT_FC_DEFAULT == PORT_FC_TS710) &&
         (cl == RFCOMM_PN_CONV_LAYER_CBFC_R)) {
       RFCOMM_TRACE_WARNING("%s, negotiation fails, index=%d", __func__,
-                           p_port->inx);
+                           p_port->handle);
       rfc_send_disc(p_mcb, p_port->dlci);
       rfc_port_closed(p_port);
       return;
-    }
-    /* Our stack is configured for credit-based and they responded with
-       credit-based. */
-    else if (cl == RFCOMM_PN_CONV_LAYER_CBFC_R) {
+    } else if (cl == RFCOMM_PN_CONV_LAYER_CBFC_R) {
+      // Our stack is configured for credit-based and they responded with
+      // credit-based.
       p_mcb->flow = PORT_FC_CREDIT;
-    }
-    /* They responded with any other value.  Treat this as negotiation to
-       TS07.10. */
-    else {
+    } else {
+      // They responded with any other value.  Treat this as negotiation to
+      // TS07.10.
       p_mcb->flow = PORT_FC_TS710;
     }
   }
@@ -436,7 +433,7 @@
       RFCOMM_DlcEstablishRsp(p_mcb, dlci, 0, RFCOMM_ERROR);
       return;
     }
-    p_mcb->port_inx[dlci] = p_port->inx;
+    p_mcb->port_handles[dlci] = p_port->handle;
   }
 
   /* If L2CAP's mtu less then RFCOMM's take it */
@@ -450,10 +447,10 @@
   /* This is the server side.  If application wants to know when connection */
   /* is established, thats the place */
   if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED))
-    (p_port->p_callback)(PORT_EV_CONNECTED, p_port->inx);
+    (p_port->p_callback)(PORT_EV_CONNECTED, p_port->handle);
 
   if (p_port->p_mgmt_callback)
-    p_port->p_mgmt_callback(PORT_SUCCESS, p_port->inx);
+    p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
 
   p_port->state = PORT_STATE_OPENED;
 }
@@ -490,10 +487,10 @@
   rfc_timer_stop(p_mcb);
 
   if (p_port->p_callback && (p_port->ev_mask & PORT_EV_CONNECTED))
-    (p_port->p_callback)(PORT_EV_CONNECTED, p_port->inx);
+    (p_port->p_callback)(PORT_EV_CONNECTED, p_port->handle);
 
   if (p_port->p_mgmt_callback)
-    p_port->p_mgmt_callback(PORT_SUCCESS, p_port->inx);
+    p_port->p_mgmt_callback(PORT_SUCCESS, p_port->handle);
 
   p_port->state = PORT_STATE_OPENED;
 
@@ -501,7 +498,8 @@
    */
   if ((p_port->uuid == UUID_SERVCLASS_DIALUP_NETWORKING) ||
       (p_port->uuid == UUID_SERVCLASS_FAX))
-    RFCOMM_PortNegReq(p_port->rfc.p_mcb, p_port->dlci, NULL);
+    RFCOMM_PortParameterNegotiationRequest(p_port->rfc.p_mcb, p_port->dlci,
+                                           NULL);
   else
     RFCOMM_ControlReq(p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
 }
@@ -527,15 +525,15 @@
     /* This can be a first request for this port */
     p_port = port_find_dlci_port(dlci);
     if (!p_port) {
-      RFCOMM_PortNegRsp(p_mcb, dlci, p_pars, 0);
+      RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_pars, 0);
       return;
     }
-    p_mcb->port_inx[dlci] = p_port->inx;
+    p_mcb->port_handles[dlci] = p_port->handle;
   }
 
   /* Check if the flow control is acceptable on local side */
   p_port->peer_port_pars = *p_pars;
-  RFCOMM_PortNegRsp(p_mcb, dlci, p_pars, param_mask);
+  RFCOMM_PortParameterNegotiationResponse(p_mcb, dlci, p_pars, param_mask);
 }
 
 /*******************************************************************************
@@ -596,9 +594,9 @@
 
   p_port->peer_ctrl = *p_pars;
 
-  if (!(p_port->port_ctrl & PORT_CTRL_REQ_SENT))
+  if (!(p_port->port_ctrl & PORT_CTRL_REQ_SENT)) {
     RFCOMM_ControlReq(p_port->rfc.p_mcb, p_port->dlci, &p_port->local_ctrl);
-  else {
+  } else {
     /* If this is the first time we received control RFCOMM is connected */
     if (!(p_port->port_ctrl & PORT_CTRL_IND_RECEIVED)) {
       event |= (PORT_EV_CONNECTED & p_port->ev_mask);
@@ -615,7 +613,7 @@
 
   /* execute call back function only if the application is registered for events
    */
-  if (event && p_port->p_callback) (p_port->p_callback)(event, p_port->inx);
+  if (event && p_port->p_callback) (p_port->p_callback)(event, p_port->handle);
 
   RFCOMM_TRACE_EVENT(
       "PORT_ControlInd DTR_DSR : %d, RTS_CTS : %d, RI : %d, DCD : %d",
@@ -655,7 +653,7 @@
 
   /* execute call back function only if the application is registered for events
    */
-  if (event && p_port->p_callback) (p_port->p_callback)(event, p_port->inx);
+  if (event && p_port->p_callback) (p_port->p_callback)(event, p_port->handle);
 }
 
 /*******************************************************************************
@@ -683,7 +681,7 @@
   if (line_status & ~(PORT_ERR_OVERRUN | PORT_ERR_BREAK)) event |= PORT_EV_ERR;
 
   if ((p_port->p_callback != NULL) && (p_port->ev_mask & event))
-    p_port->p_callback((p_port->ev_mask & event), p_port->inx);
+    p_port->p_callback((p_port->ev_mask & event), p_port->handle);
 }
 
 /*******************************************************************************
@@ -695,12 +693,10 @@
  *
  ******************************************************************************/
 void PORT_DlcReleaseInd(tRFC_MCB* p_mcb, uint8_t dlci) {
+  VLOG(1) << __func__ << ": dlci=" << std::to_string(dlci)
+          << ", bd_addr=" << p_mcb->bd_addr;
   tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
-
-  RFCOMM_TRACE_EVENT("PORT_DlcReleaseInd");
-
   if (!p_port) return;
-
   port_rfc_closed(p_port, PORT_CLOSED);
 }
 
@@ -775,7 +771,7 @@
    * receive data */
   if (p_port->p_data_co_callback) {
     /* Another packet is delivered to user.  Send credits to peer if required */
-    if (p_port->p_data_co_callback(p_port->inx, (uint8_t*)p_buf, -1,
+    if (p_port->p_data_co_callback(p_port->handle, (uint8_t*)p_buf, -1,
                                    DATA_CO_CALLBACK_TYPE_INCOMING)) {
       port_flow_control_peer(p_port, true, 1);
     } else {
@@ -788,8 +784,8 @@
   if (p_port->p_data_callback) {
     /* Another packet is delivered to user.  Send credits to peer if required */
     port_flow_control_peer(p_port, true, 1);
-    p_port->p_data_callback(p_port->inx, (uint8_t*)(p_buf + 1) + p_buf->offset,
-                            p_buf->len);
+    p_port->p_data_callback(p_port->handle,
+                            (uint8_t*)(p_buf + 1) + p_buf->offset, p_buf->len);
     osi_free(p_buf);
     return;
   }
@@ -837,7 +833,7 @@
   /* Mask out all events that are not of interest to user */
   events &= p_port->ev_mask;
 
-  if (p_port->p_callback && events) p_port->p_callback(events, p_port->inx);
+  if (p_port->p_callback && events) p_port->p_callback(events, p_port->handle);
 }
 
 /*******************************************************************************
@@ -884,7 +880,8 @@
     events &= p_port->ev_mask;
 
     /* Send event to the application */
-    if (p_port->p_callback && events) (p_port->p_callback)(events, p_port->inx);
+    if (p_port->p_callback && events)
+      (p_port->p_callback)(events, p_port->handle);
 
     /* If DLCI is not 0 event applies to one port only */
     if (dlci != 0) break;
@@ -962,7 +959,7 @@
     p_port->rfc.state = RFC_STATE_CLOSED;
 
     if (p_mcb) {
-      p_mcb->port_inx[p_port->dlci] = 0;
+      p_mcb->port_handles[p_port->dlci] = 0;
 
       /* If there are no more ports opened on this MCB release it */
       rfc_check_mcb_active(p_mcb);
@@ -993,17 +990,19 @@
   }
 
   if ((p_port->p_callback != NULL) && events)
-    p_port->p_callback(events, p_port->inx);
+    p_port->p_callback(events, p_port->handle);
 
-  if (p_port->p_mgmt_callback) p_port->p_mgmt_callback(res, p_port->inx);
+  if (p_port->p_mgmt_callback) p_port->p_mgmt_callback(res, p_port->handle);
 
   p_port->rfc.state = RFC_STATE_CLOSED;
 
-  RFCOMM_TRACE_WARNING(
-      "%s: RFCOMM connection closed, index=%d, state=%d reason=%s[%d], "
-      "UUID=%04X, bd_addr=%s, is_server=%d",
-      __func__, p_port->inx, p_port->state, PORT_GetResultString(res), res,
-      p_port->uuid, p_port->bd_addr.ToString().c_str(), p_port->is_server);
+  LOG(INFO) << __func__ << ": RFCOMM connection closed, index="
+            << std::to_string(p_port->handle)
+            << ", state=" << std::to_string(p_port->state)
+            << ", reason=" << PORT_GetResultString(res) << "["
+            << std::to_string(res) << "], UUID=" << loghex(p_port->uuid)
+            << ", bd_addr=" << p_port->bd_addr
+            << ", is_server=" << p_port->is_server;
 
   port_release_port(p_port);
 }
diff --git a/stack/rfcomm/port_utils.cc b/stack/rfcomm/port_utils.cc
index e9a9036..7798375 100644
--- a/stack/rfcomm/port_utils.cc
+++ b/stack/rfcomm/port_utils.cc
@@ -61,36 +61,36 @@
  *
  ******************************************************************************/
 tPORT* port_allocate_port(uint8_t dlci, const RawAddress& bd_addr) {
-  tPORT* p_port = &rfc_cb.port.port[0];
-  uint8_t xx, yy;
-
-  for (xx = 0, yy = rfc_cb.rfc.last_port + 1; xx < MAX_RFC_PORTS; xx++, yy++) {
-    if (yy >= MAX_RFC_PORTS) yy = 0;
-
-    p_port = &rfc_cb.port.port[yy];
+  uint8_t port_index = rfc_cb.rfc.last_port_index + static_cast<uint8_t>(1);
+  // Loop at most MAX_RFC_PORTS items
+  for (int loop_counter = 0; loop_counter < MAX_RFC_PORTS;
+       loop_counter++, port_index++) {
+    if (port_index >= MAX_RFC_PORTS) {
+      port_index = 0;
+    }
+    tPORT* p_port = &rfc_cb.port.port[port_index];
     if (!p_port->in_use) {
+      // Assume that we already called port_release_port on this
       memset(p_port, 0, sizeof(tPORT));
-
       p_port->in_use = true;
-      p_port->inx = yy + 1;
-
-      /* During the open set default state for the port connection */
+      // handle is a port handle starting from 1
+      p_port->handle = port_index + static_cast<uint8_t>(1);
+      // During the open set default state for the port connection
       port_set_defaults(p_port);
-
       p_port->rfc.port_timer = alarm_new("rfcomm_port.port_timer");
-      rfc_cb.rfc.last_port = yy;
-
       p_port->dlci = dlci;
       p_port->bd_addr = bd_addr;
-
-      RFCOMM_TRACE_DEBUG("rfc_cb.port.port[%d]:%p allocated, last_port:%d", yy,
-                         p_port, rfc_cb.rfc.last_port);
-      VLOG(1) << __func__ << ": bd_addr:" << bd_addr;
-      return (p_port);
+      rfc_cb.rfc.last_port_index = port_index;
+      RFCOMM_TRACE_DEBUG(
+          "%s: rfc_cb.port.port[%d]:%p chosen, "
+          "last_port_index:%d, bd_addr=%s",
+          __func__, port_index, p_port, rfc_cb.rfc.last_port_index,
+          bd_addr.ToString().c_str());
+      return p_port;
     }
   }
-
-  /* If here, no free PORT found */
+  LOG(WARNING) << __func__ << ": running out of free ports for dlci "
+               << std::to_string(dlci) << ", bd_addr " << bd_addr;
   return nullptr;
 }
 
@@ -146,7 +146,7 @@
     packet_size = btm_get_max_packet_size(p_port->bd_addr);
     if (packet_size == 0) {
       /* something is very wrong */
-      RFCOMM_TRACE_WARNING("port_select_mtu bad packet size");
+      LOG(WARNING) << __func__ << ": bad packet size 0 for" << p_port->bd_addr;
       p_port->mtu = RFCOMM_DEFAULT_MTU;
     } else {
       /* We try to negotiate MTU that each packet can be split into whole
@@ -166,17 +166,16 @@
         p_port->mtu = ((L2CAP_MTU_SIZE + L2CAP_PKT_OVERHEAD) / packet_size *
                        packet_size) -
                       RFCOMM_DATA_OVERHEAD - L2CAP_PKT_OVERHEAD;
-        RFCOMM_TRACE_DEBUG(
-            "port_select_mtu selected %d based on connection speed",
-            p_port->mtu);
+        RFCOMM_TRACE_DEBUG("%s: selected %d based on connection speed",
+                           __func__, p_port->mtu);
       } else {
         p_port->mtu = L2CAP_MTU_SIZE - RFCOMM_DATA_OVERHEAD;
-        RFCOMM_TRACE_DEBUG(
-            "port_select_mtu selected %d based on l2cap PDU size", p_port->mtu);
+        RFCOMM_TRACE_DEBUG("%s: selected %d based on l2cap PDU size", __func__,
+                           p_port->mtu);
       }
     }
   } else {
-    RFCOMM_TRACE_DEBUG("port_select_mtu application selected %d", p_port->mtu);
+    RFCOMM_TRACE_DEBUG("%s: application selected %d", __func__, p_port->mtu);
   }
   p_port->credit_rx_max = (PORT_RX_HIGH_WM / p_port->mtu);
   if (p_port->credit_rx_max > PORT_RX_BUF_HIGH_WM)
@@ -188,7 +187,7 @@
   if (p_port->rx_buf_critical > PORT_RX_BUF_CRITICAL_WM)
     p_port->rx_buf_critical = PORT_RX_BUF_CRITICAL_WM;
   RFCOMM_TRACE_DEBUG(
-      "port_select_mtu credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d",
+      "%s: credit_rx_max %d, credit_rx_low %d, rx_buf_critical %d", __func__,
       p_port->credit_rx_max, p_port->credit_rx_low, p_port->rx_buf_critical);
 }
 
@@ -226,7 +225,7 @@
 
   if (p_port->rfc.state == RFC_STATE_CLOSED) {
     if (p_port->rfc.p_mcb) {
-      p_port->rfc.p_mcb->port_inx[p_port->dlci] = 0;
+      p_port->rfc.p_mcb->port_handles[p_port->dlci] = 0;
 
       /* If there are no more ports opened on this MCB release it */
       rfc_check_mcb_active(p_port->rfc.p_mcb);
@@ -242,7 +241,8 @@
     mutex_global_unlock();
 
     if (p_port->keep_port_handle) {
-      RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__, p_port->inx);
+      RFCOMM_TRACE_DEBUG("%s Re-initialize handle: %d", __func__,
+                         p_port->handle);
 
       /* save event mask and callback */
       uint32_t mask = p_port->ev_mask;
@@ -264,7 +264,7 @@
       p_port->local_ctrl.modem_signal = p_port->default_signal_state;
       p_port->bd_addr = RawAddress::kAny;
     } else {
-      RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->inx);
+      RFCOMM_TRACE_DEBUG("%s Clean-up handle: %d", __func__, p_port->handle);
       alarm_free(p_port->rfc.port_timer);
       memset(p_port, 0, sizeof(tPORT));
     }
@@ -317,14 +317,14 @@
     return nullptr;
   }
 
-  uint8_t inx = p_mcb->port_inx[dlci];
-  if (inx == 0) {
+  uint8_t handle = p_mcb->port_handles[dlci];
+  if (handle == 0) {
     LOG(INFO) << __func__ << ": Cannot find allocated RFCOMM app port for DLCI "
               << std::to_string(dlci) << " on " << p_mcb->bd_addr
               << ", p_mcb=" << p_mcb;
     return nullptr;
   }
-  return &rfc_cb.port.port[inx - 1];
+  return &rfc_cb.port.port[handle - 1];
 }
 
 /*******************************************************************************
diff --git a/stack/rfcomm/rfc_int.h b/stack/rfcomm/rfc_int.h
index 05afa9d..22aab66 100644
--- a/stack/rfcomm/rfc_int.h
+++ b/stack/rfcomm/rfc_int.h
@@ -56,18 +56,23 @@
 
 extern void RFCOMM_DlcReleaseReq(tRFC_MCB* p_mcb, uint8_t dlci);
 
-extern void RFCOMM_ParNegReq(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu);
-extern void RFCOMM_ParNegRsp(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu,
-                             uint8_t cl, uint8_t k);
+extern void RFCOMM_ParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci,
+                                               uint16_t mtu);
+extern void RFCOMM_ParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci,
+                                                uint16_t mtu, uint8_t cl,
+                                                uint8_t k);
 
 extern void RFCOMM_TestReq(uint8_t* p_data, uint16_t len);
 
 extern void RFCOMM_FlowReq(tRFC_MCB* p_mcb, uint8_t dlci, bool state);
 
-extern void RFCOMM_PortNegReq(tRFC_MCB* p_mcb, uint8_t dlci,
-                              tPORT_STATE* p_pars);
-extern void RFCOMM_PortNegRsp(tRFC_MCB* p_mcb, uint8_t dlci,
-                              tPORT_STATE* p_pars, uint16_t param_mask);
+extern void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb,
+                                                   uint8_t dlci,
+                                                   tPORT_STATE* p_pars);
+extern void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb,
+                                                    uint8_t dlci,
+                                                    tPORT_STATE* p_pars,
+                                                    uint16_t param_mask);
 
 extern void RFCOMM_ControlReq(tRFC_MCB* p_mcb, uint8_t dlci,
                               tPORT_CTRL* p_pars);
@@ -221,7 +226,7 @@
   tRFC_MCB* p_rfc_lcid_mcb[MAX_L2CAP_CHANNELS];
   bool peer_rx_disabled; /* If true peer sent FCOFF */
   uint8_t last_mux;      /* Last mux allocated */
-  uint8_t last_port;     /* Last port allocated */
+  uint8_t last_port_index;  // Index of last port allocated in rfc_cb.port
 } tRFCOMM_CB;
 
 /* Main Control Block for the RFCOMM Layer (PORT and RFC) */
diff --git a/stack/rfcomm/rfc_l2cap_if.cc b/stack/rfcomm/rfc_l2cap_if.cc
index a20f399..3dc4ec2 100644
--- a/stack/rfcomm/rfc_l2cap_if.cc
+++ b/stack/rfcomm/rfc_l2cap_if.cc
@@ -26,10 +26,11 @@
 #include "bt_target.h"
 
 #include "bt_common.h"
+#include "common/time_util.h"
 #include "osi/include/osi.h"
-#include "osi/include/time.h"
 
 #include "bt_utils.h"
+#include "hci/include/btsnoop.h"
 #include "l2c_api.h"
 #include "l2cdefs.h"
 #include "port_api.h"
@@ -73,7 +74,7 @@
   p_l2c->pL2CA_CongestionStatus_Cb = RFCOMM_CongestionStatusInd;
   p_l2c->pL2CA_TxComplete_Cb = NULL;
 
-  L2CA_Register(BT_PSM_RFCOMM, p_l2c);
+  L2CA_Register(BT_PSM_RFCOMM, p_l2c, true /* enable_snoop */);
 }
 
 /*******************************************************************************
@@ -105,19 +106,21 @@
           "LCID(0x%x), acceptor's LCID(0x%x)",
           p_mcb->lcid, p_mcb->pending_lcid);
 
-      rfc_timer_start(p_mcb, (uint16_t)(time_get_os_boottime_ms() % 10 + 2));
+      rfc_timer_start(
+          p_mcb,
+          (uint16_t)(bluetooth::common::time_get_os_boottime_ms() % 10 + 2));
       return;
     } else {
       /* we cannot accept connection request from peer at this state */
       /* don't update lcid */
-      p_mcb = NULL;
+      p_mcb = nullptr;
     }
   } else {
     /* store mcb even if null */
     rfc_save_lcid_mcb(p_mcb, lcid);
   }
 
-  if (p_mcb == NULL) {
+  if (p_mcb == nullptr) {
     L2CA_ConnectRsp(bd_addr, id, lcid, L2CAP_CONN_NO_RESOURCES, 0);
     return;
   }
@@ -163,13 +166,13 @@
 
       /* update direction bit */
       for (int i = 0; i < RFCOMM_MAX_DLCI; i += 2) {
-        uint8_t idx = p_mcb->port_inx[i];
-        if (idx != 0) {
-          p_mcb->port_inx[i] = 0;
-          p_mcb->port_inx[i + 1] = idx;
-          rfc_cb.port.port[idx - 1].dlci += 1;
-          RFCOMM_TRACE_DEBUG("RFCOMM MX, port_handle=%d, DLCI[%d->%d]", idx, i,
-                             rfc_cb.port.port[idx - 1].dlci);
+        uint8_t handle = p_mcb->port_handles[i];
+        if (handle != 0) {
+          p_mcb->port_handles[i] = 0;
+          p_mcb->port_handles[i + 1] = handle;
+          rfc_cb.port.port[handle - 1].dlci += 1;
+          RFCOMM_TRACE_DEBUG("RFCOMM MX, port_handle=%d, DLCI[%d->%d]", handle,
+                             i, rfc_cb.port.port[handle - 1].dlci);
         }
       }
 
@@ -254,17 +257,16 @@
  *
  ******************************************************************************/
 void RFCOMM_DisconnectInd(uint16_t lcid, bool is_conf_needed) {
+  VLOG(1) << __func__ << ": lcid=" << loghex(lcid)
+          << ", is_conf_needed=" << is_conf_needed;
   tRFC_MCB* p_mcb = rfc_find_lcid_mcb(lcid);
-
   if (is_conf_needed) {
     L2CA_DisconnectRsp(lcid);
   }
-
   if (!p_mcb) {
-    RFCOMM_TRACE_WARNING("RFCOMM_DisconnectInd LCID:0x%x", lcid);
+    LOG(WARNING) << __func__ << ": no mcb for lcid " << loghex(lcid);
     return;
   }
-
   rfc_mx_sm_execute(p_mcb, RFC_MX_EVENT_DISC_IND, nullptr);
 }
 
@@ -299,7 +301,7 @@
   }
 
   if (rfc_cb.rfc.rx_frame.dlci == RFCOMM_MX_DLCI) {
-    RFCOMM_TRACE_DEBUG("%s: Handle multiplexer event %d, p_mcb=%p", __func__,
+    RFCOMM_TRACE_DEBUG("%s: handle multiplexer event %d, p_mcb=%p", __func__,
                        event, p_mcb);
     /* Take special care of the Multiplexer Control Messages */
     if (event == RFC_EVENT_UIH) {
@@ -341,10 +343,11 @@
       osi_free(p_buf);
       return;
     }
-    RFCOMM_TRACE_DEBUG("%s: port_inx[dlci=%d]:%d->%d, p_mcb=%p", __func__,
+    RFCOMM_TRACE_DEBUG("%s: port_handles[dlci=%d]:%d->%d, p_mcb=%p", __func__,
                        rfc_cb.rfc.rx_frame.dlci,
-                       p_mcb->port_inx[rfc_cb.rfc.rx_frame.dlci], p_port->inx);
-    p_mcb->port_inx[rfc_cb.rfc.rx_frame.dlci] = p_port->inx;
+                       p_mcb->port_handles[rfc_cb.rfc.rx_frame.dlci],
+                       p_port->handle);
+    p_mcb->port_handles[rfc_cb.rfc.rx_frame.dlci] = p_port->handle;
     p_port->rfc.p_mcb = p_mcb;
   }
 
@@ -419,6 +422,14 @@
  *
  ******************************************************************************/
 void rfc_save_lcid_mcb(tRFC_MCB* p_mcb, uint16_t lcid) {
-  if (lcid < L2CAP_BASE_APPL_CID) return;
-  rfc_cb.rfc.p_rfc_lcid_mcb[lcid - L2CAP_BASE_APPL_CID] = p_mcb;
+  if (lcid < L2CAP_BASE_APPL_CID) {
+    LOG(ERROR) << __func__ << ": LCID " << lcid << " is too small";
+    return;
+  }
+  auto mcb_index = static_cast<size_t>(lcid - L2CAP_BASE_APPL_CID);
+  if (mcb_index >= MAX_L2CAP_CHANNELS) {
+    LOG(ERROR) << __func__ << ": LCID " << lcid << " is too large";
+    return;
+  }
+  rfc_cb.rfc.p_rfc_lcid_mcb[mcb_index] = p_mcb;
 }
diff --git a/stack/rfcomm/rfc_mx_fsm.cc b/stack/rfcomm/rfc_mx_fsm.cc
index dfab62f..d1da01e 100644
--- a/stack/rfcomm/rfc_mx_fsm.cc
+++ b/stack/rfcomm/rfc_mx_fsm.cc
@@ -69,6 +69,9 @@
  *
  ******************************************************************************/
 void rfc_mx_sm_execute(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
+  CHECK(p_mcb != nullptr) << __func__ << ": NULL mcb for event " << event;
+  VLOG(1) << __func__ << ": bd_addr=" << p_mcb->bd_addr
+          << ", state=" << std::to_string(p_mcb->state) << ", event=" << event;
   switch (p_mcb->state) {
     case RFC_MX_STATE_IDLE:
       rfc_mx_sm_state_idle(p_mcb, event, p_data);
@@ -112,7 +115,7 @@
  *
  ******************************************************************************/
 void rfc_mx_sm_state_idle(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_state_idle - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: evt %d", __func__, event);
   switch (event) {
     case RFC_MX_EVENT_START_REQ: {
       /* Initialize L2CAP MTU */
@@ -120,7 +123,9 @@
 
       uint16_t lcid = L2CA_ConnectReq(BT_PSM_RFCOMM, p_mcb->bd_addr);
       if (lcid == 0) {
-        rfc_save_lcid_mcb(NULL, p_mcb->lcid);
+        LOG(ERROR) << __func__ << ": failed to open L2CAP channel for "
+                   << p_mcb->bd_addr;
+        rfc_save_lcid_mcb(nullptr, p_mcb->lcid);
         p_mcb->lcid = 0;
         PORT_StartCnf(p_mcb, RFCOMM_ERROR);
         return;
@@ -182,7 +187,7 @@
  ******************************************************************************/
 void rfc_mx_sm_state_wait_conn_cnf(tRFC_MCB* p_mcb, uint16_t event,
                                    void* p_data) {
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_state_wait_conn_cnf - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: evt %d", __func__, event);
   switch (event) {
     case RFC_MX_EVENT_START_REQ:
       RFCOMM_TRACE_ERROR("Mx error state %d event %d", p_mcb->state, event);
@@ -218,7 +223,7 @@
       /* we gave up outgoing connection request then try peer's request */
       if (p_mcb->pending_lcid) {
         uint16_t i;
-        uint8_t idx;
+        uint8_t handle;
 
         RFCOMM_TRACE_DEBUG(
             "RFCOMM MX retry as acceptor in collision case - evt:%d in "
@@ -233,13 +238,13 @@
 
         /* update direction bit */
         for (i = 0; i < RFCOMM_MAX_DLCI; i += 2) {
-          idx = p_mcb->port_inx[i];
-          if (idx != 0) {
-            p_mcb->port_inx[i] = 0;
-            p_mcb->port_inx[i + 1] = idx;
-            rfc_cb.port.port[idx - 1].dlci += 1;
+          handle = p_mcb->port_handles[i];
+          if (handle != 0) {
+            p_mcb->port_handles[i] = 0;
+            p_mcb->port_handles[i + 1] = handle;
+            rfc_cb.port.port[handle - 1].dlci += 1;
             RFCOMM_TRACE_DEBUG("RFCOMM MX - DLCI:%d -> %d", i,
-                               rfc_cb.port.port[idx - 1].dlci);
+                               rfc_cb.port.port[handle - 1].dlci);
           }
         }
 
@@ -264,7 +269,7 @@
  *
  ******************************************************************************/
 void rfc_mx_sm_state_configure(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_state_configure - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: event %d", __func__, event);
   switch (event) {
     case RFC_MX_EVENT_START_REQ:
     case RFC_MX_EVENT_CONN_CNF:
@@ -286,6 +291,8 @@
       return;
 
     case RFC_EVENT_TIMEOUT:
+      LOG(ERROR) << __func__ << ": L2CAP configuration timeout for "
+                 << p_mcb->bd_addr;
       p_mcb->state = RFC_MX_STATE_IDLE;
       L2CA_DisconnectReq(p_mcb->lcid);
 
@@ -308,7 +315,7 @@
  ******************************************************************************/
 void rfc_mx_sm_sabme_wait_ua(tRFC_MCB* p_mcb, uint16_t event,
                              UNUSED_ATTR void* p_data) {
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_sabme_wait_ua - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: event %d", __func__, event);
   switch (event) {
     case RFC_MX_EVENT_START_REQ:
     case RFC_MX_EVENT_CONN_CNF:
@@ -342,7 +349,7 @@
 
     case RFC_EVENT_DM:
       rfc_timer_stop(p_mcb);
-    /* Case falls through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
 
     case RFC_MX_EVENT_CONF_IND: /* workaround: we don't support reconfig */
     case RFC_MX_EVENT_CONF_CNF: /* workaround: we don't support reconfig */
@@ -368,7 +375,7 @@
  *
  ******************************************************************************/
 void rfc_mx_sm_state_wait_sabme(tRFC_MCB* p_mcb, uint16_t event, void* p_data) {
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_state_wait_sabme - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: event %d", __func__, event);
   switch (event) {
     case RFC_MX_EVENT_DISC_IND:
       p_mcb->state = RFC_MX_STATE_IDLE;
@@ -431,7 +438,7 @@
  ******************************************************************************/
 void rfc_mx_sm_state_connected(tRFC_MCB* p_mcb, uint16_t event,
                                UNUSED_ATTR void* p_data) {
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_state_connected - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: event %d", __func__, event);
 
   switch (event) {
     case RFC_EVENT_TIMEOUT:
@@ -475,7 +482,7 @@
                                   void* p_data) {
   BT_HDR* p_buf;
 
-  RFCOMM_TRACE_EVENT("rfc_mx_sm_state_disc_wait_ua - evt:%d", event);
+  RFCOMM_TRACE_EVENT("%s: event %d", __func__, event);
   switch (event) {
     case RFC_EVENT_UA:
     case RFC_EVENT_DM:
@@ -549,12 +556,8 @@
  *
  ******************************************************************************/
 static void rfc_mx_send_config_req(tRFC_MCB* p_mcb) {
-  tL2CAP_CFG_INFO cfg;
-
   RFCOMM_TRACE_EVENT("rfc_mx_send_config_req");
-
-  memset(&cfg, 0, sizeof(tL2CAP_CFG_INFO));
-
+  tL2CAP_CFG_INFO cfg = {};
   cfg.mtu_present = true;
   cfg.mtu = L2CAP_MTU_SIZE;
 
@@ -580,11 +583,15 @@
  *
  ******************************************************************************/
 static void rfc_mx_conf_cnf(tRFC_MCB* p_mcb, tL2CAP_CFG_INFO* p_cfg) {
-  RFCOMM_TRACE_EVENT("rfc_mx_conf_cnf p_cfg:%08x res:%d ", p_cfg,
+  RFCOMM_TRACE_EVENT("rfc_mx_conf_cnf p_cfg:%08x result:%d ", p_cfg,
                      (p_cfg) ? p_cfg->result : 0);
 
   if (p_cfg->result != L2CAP_CFG_OK) {
+    LOG(ERROR) << __func__ << ": failed to configure L2CAP for "
+               << p_mcb->bd_addr;
     if (p_mcb->is_initiator) {
+      LOG(ERROR) << __func__ << ": disconnect L2CAP due to config failure for "
+                 << p_mcb->bd_addr;
       PORT_StartCnf(p_mcb, p_cfg->result);
       L2CA_DisconnectReq(p_mcb->lcid);
     }
@@ -619,10 +626,11 @@
 static void rfc_mx_conf_ind(tRFC_MCB* p_mcb, tL2CAP_CFG_INFO* p_cfg) {
   /* Save peer L2CAP MTU if present */
   /* RFCOMM adds 3-4 bytes in the beginning and 1 bytes FCS */
-  if (p_cfg->mtu_present)
+  if (p_cfg->mtu_present) {
     p_mcb->peer_l2cap_mtu = p_cfg->mtu - RFCOMM_MIN_OFFSET - 1;
-  else
+  } else {
     p_mcb->peer_l2cap_mtu = L2CAP_DEFAULT_MTU - RFCOMM_MIN_OFFSET - 1;
+  }
 
   p_cfg->mtu_present = false;
   p_cfg->flush_to_present = false;
diff --git a/stack/rfcomm/rfc_port_fsm.cc b/stack/rfcomm/rfc_port_fsm.cc
index 4ff4628..1b82ddf 100644
--- a/stack/rfcomm/rfc_port_fsm.cc
+++ b/stack/rfcomm/rfc_port_fsm.cc
@@ -34,6 +34,14 @@
 #include "rfc_int.h"
 #include "rfcdefs.h"
 
+#include <set>
+#include "hci/include/btsnoop.h"
+
+static const std::set<uint16_t> uuid_logging_whitelist = {
+    UUID_SERVCLASS_HEADSET_AUDIO_GATEWAY,
+    UUID_SERVCLASS_AG_HANDSFREE,
+};
+
 /******************************************************************************/
 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /******************************************************************************/
@@ -64,11 +72,11 @@
  *
  ******************************************************************************/
 void rfc_port_sm_execute(tPORT* p_port, uint16_t event, void* p_data) {
-  if (!p_port) {
-    RFCOMM_TRACE_WARNING("NULL port event %d", event);
-    return;
-  }
-
+  CHECK(p_port != nullptr) << __func__ << ": NULL port event " << event;
+  VLOG(1) << __func__ << ": BD_ADDR=" << p_port->bd_addr
+          << ", PORT=" << std::to_string(p_port->handle)
+          << ", STATE=" << std::to_string(p_port->rfc.state)
+          << ", EVENT=" << event;
   switch (p_port->rfc.state) {
     case RFC_STATE_CLOSED:
       rfc_port_sm_state_closed(p_port, event, p_data);
@@ -143,7 +151,8 @@
       return;
 
     case RFC_EVENT_DM:
-      RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM, index=%d", __func__, p_port->inx);
+      RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM, index=%d", __func__,
+                           p_port->handle);
       rfc_port_closed(p_port);
       return;
 
@@ -194,7 +203,7 @@
 
     case RFC_EVENT_CLEAR:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_CLEAR, index=%d", __func__,
-                           p_port->inx);
+                           p_port->handle);
       rfc_port_closed(p_port);
       return;
 
@@ -205,12 +214,20 @@
     case RFC_EVENT_UA:
       rfc_port_timer_stop(p_port);
       p_port->rfc.state = RFC_STATE_OPENED;
+
+      if (uuid_logging_whitelist.find(p_port->uuid) !=
+          uuid_logging_whitelist.end()) {
+        btsnoop_get_interface()->whitelist_rfc_dlci(p_port->rfc.p_mcb->lcid,
+                                                    p_port->dlci);
+      }
+
       PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci,
                            p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_SUCCESS);
       return;
 
     case RFC_EVENT_DM:
-      RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM, index=%d", __func__, p_port->inx);
+      RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM, index=%d", __func__,
+                           p_port->handle);
       p_port->rfc.p_mcb->is_disc_initiator = true;
       PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci,
                            p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
@@ -219,7 +236,7 @@
 
     case RFC_EVENT_DISC:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DISC, index=%d", __func__,
-                           p_port->inx);
+                           p_port->handle);
       rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci);
       PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci,
                            p_port->rfc.p_mcb->peer_l2cap_mtu, RFCOMM_ERROR);
@@ -282,7 +299,7 @@
 
     case RFC_EVENT_CLEAR:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_CLEAR, index=%d", __func__,
-                           p_port->inx);
+                           p_port->handle);
       btm_sec_abort_access_req(p_port->rfc.p_mcb->bd_addr);
       rfc_port_closed(p_port);
       return;
@@ -315,6 +332,12 @@
       } else {
         rfc_send_ua(p_port->rfc.p_mcb, p_port->dlci);
         p_port->rfc.state = RFC_STATE_OPENED;
+
+        if (uuid_logging_whitelist.find(p_port->uuid) !=
+            uuid_logging_whitelist.end()) {
+          btsnoop_get_interface()->whitelist_rfc_dlci(p_port->rfc.p_mcb->lcid,
+                                                      p_port->dlci);
+        }
       }
       return;
   }
@@ -339,7 +362,8 @@
     case RFC_EVENT_SEC_COMPLETE:
       if (*((uint8_t*)p_data) != BTM_SUCCESS) {
         RFCOMM_TRACE_ERROR("%s, RFC_EVENT_SEC_COMPLETE, index=%d, result=%d",
-                           __func__, event, p_port->inx, *((uint8_t*)p_data));
+                           __func__, event, p_port->handle,
+                           *((uint8_t*)p_data));
         p_port->rfc.p_mcb->is_disc_initiator = true;
         PORT_DlcEstablishCnf(p_port->rfc.p_mcb, p_port->dlci, 0,
                              RFCOMM_SECURITY_ERR);
@@ -359,7 +383,7 @@
 
     case RFC_EVENT_CLOSE:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_CLOSE, index=%d", __func__,
-                           p_port->inx);
+                           p_port->handle);
       btm_sec_abort_access_req(p_port->rfc.p_mcb->bd_addr);
       rfc_port_closed(p_port);
       return;
@@ -403,7 +427,7 @@
 
     case RFC_EVENT_CLEAR:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_CLEAR, index=%d", __func__,
-                           p_port->inx);
+                           p_port->handle);
       rfc_port_closed(p_port);
       return;
 
@@ -435,7 +459,8 @@
       return;
 
     case RFC_EVENT_DM:
-      RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM, index=%d", __func__, p_port->inx);
+      RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM, index=%d", __func__,
+                           p_port->handle);
       PORT_DlcReleaseInd(p_port->rfc.p_mcb, p_port->dlci);
       rfc_port_closed(p_port);
       return;
@@ -484,7 +509,7 @@
 
     case RFC_EVENT_CLEAR:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_CLEAR, index=%d", __func__, event,
-                           p_port->inx);
+                           p_port->handle);
       rfc_port_closed(p_port);
       return;
 
@@ -494,11 +519,11 @@
 
     case RFC_EVENT_UA:
       p_port->rfc.p_mcb->is_disc_initiator = true;
-    /* Case falls through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
 
     case RFC_EVENT_DM:
       RFCOMM_TRACE_WARNING("%s, RFC_EVENT_DM|RFC_EVENT_UA[%d], index=%d",
-                           __func__, event, p_port->inx);
+                           __func__, event, p_port->handle);
       rfc_port_closed(p_port);
       return;
 
@@ -517,7 +542,7 @@
 
     case RFC_EVENT_TIMEOUT:
       RFCOMM_TRACE_ERROR("%s, RFC_EVENT_TIMEOUT, index=%d", __func__,
-                         p_port->inx);
+                         p_port->handle);
       rfc_port_closed(p_port);
       return;
   }
@@ -545,7 +570,9 @@
  *
  ******************************************************************************/
 void rfc_process_pn(tRFC_MCB* p_mcb, bool is_command, MX_FRAME* p_frame) {
-  tPORT* p_port;
+  RFCOMM_TRACE_DEBUG("%s: is_initiator=%d, is_cmd=%d, state=%d, bd_addr=%s",
+                     __func__, p_mcb->is_initiator, is_command, p_mcb->state,
+                     p_mcb->bd_addr.ToString().c_str());
   uint8_t dlci = p_frame->dlci;
 
   if (is_command) {
@@ -563,7 +590,7 @@
     return;
   }
   /* If we are not awaiting response just ignore it */
-  p_port = port_find_mcb_dlci_port(p_mcb, dlci);
+  tPORT* p_port = port_find_mcb_dlci_port(p_mcb, dlci);
   if ((p_port == nullptr) || !(p_port->rfc.expected_rsp & RFC_RSP_PN)) {
     LOG(WARNING) << ": Ignore unwanted response, p_mcb=" << p_mcb
                  << ", bd_addr=" << p_mcb->bd_addr
diff --git a/stack/rfcomm/rfc_port_if.cc b/stack/rfcomm/rfc_port_if.cc
index 2ce5f9e..097d774 100644
--- a/stack/rfcomm/rfc_port_if.cc
+++ b/stack/rfcomm/rfc_port_if.cc
@@ -115,7 +115,7 @@
 
 /*******************************************************************************
  *
- * Function         RFCOMM_ParNegReq
+ * Function         RFCOMM_ParameterNegotiationRequest
  *
  * Description      This function is called by the user app to start
  *                  DLC parameter negotiation.  Port emulation can send this
@@ -124,7 +124,8 @@
  *                  block.
  *
  ******************************************************************************/
-void RFCOMM_ParNegReq(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu) {
+void RFCOMM_ParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci,
+                                        uint16_t mtu) {
   uint8_t flow;
   uint8_t cl;
   uint8_t k;
@@ -166,14 +167,14 @@
 
 /*******************************************************************************
  *
- * Function         RFCOMM_ParNegRsp
+ * Function         RFCOMM_ParameterNegotiationResponse
  *
  * Description      This function is called by the user app to acknowledge
  *                  DLC parameter negotiation.
  *
  ******************************************************************************/
-void RFCOMM_ParNegRsp(tRFC_MCB* p_mcb, uint8_t dlci, uint16_t mtu, uint8_t cl,
-                      uint8_t k) {
+void RFCOMM_ParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci,
+                                         uint16_t mtu, uint8_t cl, uint8_t k) {
   if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
 
   /* Send Parameter Negotiation Response UIH frame */
@@ -182,7 +183,7 @@
 
 /*******************************************************************************
  *
- * Function         RFCOMM_PortNegReq
+ * Function         RFCOMM_PortParameterNegotiationRequest
  *
  * Description      This function is called by the user app to start
  *                  Remote Port parameter negotiation.  Port emulation can
@@ -191,7 +192,8 @@
  *                  control block.
  *
  ******************************************************************************/
-void RFCOMM_PortNegReq(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars) {
+void RFCOMM_PortParameterNegotiationRequest(tRFC_MCB* p_mcb, uint8_t dlci,
+                                            tPORT_STATE* p_pars) {
   if (p_mcb->state != RFC_MX_STATE_CONNECTED) {
     PORT_PortNegCnf(p_mcb, dlci, nullptr, RFCOMM_ERROR);
     return;
@@ -215,14 +217,15 @@
 
 /*******************************************************************************
  *
- * Function         RFCOMM_PortNegRsp
+ * Function         RFCOMM_PortParameterNegotiationResponse
  *
  * Description      This function is called by the user app to acknowledge
  *                  Port parameters negotiation.
  *
  ******************************************************************************/
-void RFCOMM_PortNegRsp(tRFC_MCB* p_mcb, uint8_t dlci, tPORT_STATE* p_pars,
-                       uint16_t param_mask) {
+void RFCOMM_PortParameterNegotiationResponse(tRFC_MCB* p_mcb, uint8_t dlci,
+                                             tPORT_STATE* p_pars,
+                                             uint16_t param_mask) {
   if (p_mcb->state != RFC_MX_STATE_CONNECTED) return;
 
   rfc_send_rpn(p_mcb, dlci, false, p_pars, param_mask);
diff --git a/stack/rfcomm/rfc_ts_frames.cc b/stack/rfcomm/rfc_ts_frames.cc
index e3b4b8f..7bc98a2 100644
--- a/stack/rfcomm/rfc_ts_frames.cc
+++ b/stack/rfcomm/rfc_ts_frames.cc
@@ -154,14 +154,19 @@
   uint8_t credits;
 
   p_buf->offset -= RFCOMM_CTRL_FRAME_LEN;
-  if (p_buf->len > 127) p_buf->offset--;
+  if (p_buf->len > 127) {
+    p_buf->offset--;
+  }
 
-  if (dlci)
+  if (dlci) {
     credits = (uint8_t)p_buf->layer_specific;
-  else
+  } else {
     credits = 0;
+  }
 
-  if (credits) p_buf->offset--;
+  if (credits) {
+    p_buf->offset--;
+  }
 
   p_data = (uint8_t*)(p_buf + 1) + p_buf->offset;
 
@@ -219,11 +224,11 @@
   ** We will use the fact that we reply in the same context so rx_frame can
   *still be used.
   */
-  if (is_command)
+  if (is_command) {
     *p_data++ = RFCOMM_PN_PRIORITY_0;
-  else
+  } else {
     *p_data++ = rfc_cb.rfc.rx_frame.u.pn.priority;
-
+  }
   *p_data++ = RFCOMM_T1_DSEC;
   *p_data++ = mtu & 0xFF;
   *p_data++ = mtu >> 8;
@@ -528,17 +533,27 @@
     return RFC_EVENT_BAD_FRAME;
   }
 
+  if (p_buf->len < (3 + !ead + !eal + 1)) {
+    android_errorWriteLog(0x534e4554, "120255805");
+    RFCOMM_TRACE_ERROR("Bad Length: %d", p_buf->len);
+    return RFC_EVENT_BAD_FRAME;
+  }
   p_buf->len -= (3 + !ead + !eal + 1); /* Additional 1 for FCS */
   p_buf->offset += (3 + !ead + !eal);
 
   /* handle credit if credit based flow control */
   if ((p_mcb->flow == PORT_FC_CREDIT) && (p_frame->type == RFCOMM_UIH) &&
       (p_frame->dlci != RFCOMM_MX_DLCI) && (p_frame->pf == 1)) {
+    if (p_buf->len < sizeof(uint8_t)) {
+      RFCOMM_TRACE_ERROR("Bad Length in flow control: %d", p_buf->len);
+      return RFC_EVENT_BAD_FRAME;
+    }
     p_frame->credit = *p_data++;
     p_buf->len--;
     p_buf->offset++;
-  } else
+  } else {
     p_frame->credit = 0;
+  }
 
   if (p_buf->len != len) {
     RFCOMM_TRACE_ERROR("Bad Length2 %d %d", p_buf->len, len);
@@ -599,8 +614,9 @@
         /* we assume that this is ok to allow bad implementations to work */
         RFCOMM_TRACE_ERROR("Bad UIH - response");
         return (RFC_EVENT_UIH);
-      } else
+      } else {
         return (RFC_EVENT_UIH);
+      }
   }
 
   return (RFC_EVENT_BAD_FRAME);
@@ -619,7 +635,6 @@
   MX_FRAME* p_rx_frame = &rfc_cb.rfc.rx_frame;
   uint16_t length = p_buf->len;
   uint8_t ea, cr, mx_len;
-  bool is_command;
 
   if (length < 2) {
     RFCOMM_TRACE_ERROR(
@@ -643,7 +658,7 @@
 
   length--;
 
-  is_command = p_rx_frame->cr;
+  bool is_command = p_rx_frame->cr;
 
   ea = *p_data & RFCOMM_EA;
 
@@ -669,8 +684,8 @@
     return;
   }
 
-  RFCOMM_TRACE_DEBUG("%s: type=%d, p_mcb=%p", __func__, p_rx_frame->type,
-                     p_mcb);
+  RFCOMM_TRACE_DEBUG("%s: type=0x%02x, bd_addr=%s", __func__, p_rx_frame->type,
+                     p_mcb->bd_addr.ToString().c_str());
   switch (p_rx_frame->type) {
     case RFCOMM_MX_PN:
       if (length != RFCOMM_MX_PN_LEN) {
diff --git a/stack/rfcomm/rfc_utils.cc b/stack/rfcomm/rfc_utils.cc
index 74e336a..3dee8a1 100644
--- a/stack/rfcomm/rfc_utils.cc
+++ b/stack/rfcomm/rfc_utils.cc
@@ -225,7 +225,7 @@
 void rfc_timer_start(tRFC_MCB* p_mcb, uint16_t timeout) {
   RFCOMM_TRACE_EVENT("%s - timeout:%d seconds", __func__, timeout);
 
-  period_ms_t interval_ms = timeout * 1000;
+  uint64_t interval_ms = timeout * 1000;
   alarm_set_on_mloop(p_mcb->mcb_timer, interval_ms, rfcomm_mcb_timer_timeout,
                      p_mcb);
 }
@@ -253,7 +253,7 @@
 void rfc_port_timer_start(tPORT* p_port, uint16_t timeout) {
   RFCOMM_TRACE_EVENT("%s - timeout:%d seconds", __func__, timeout);
 
-  period_ms_t interval_ms = timeout * 1000;
+  uint64_t interval_ms = timeout * 1000;
   alarm_set_on_mloop(p_port->rfc.port_timer, interval_ms,
                      rfcomm_port_timer_timeout, p_port);
 }
@@ -285,7 +285,7 @@
   uint16_t i;
 
   for (i = 0; i < RFCOMM_MAX_DLCI; i++) {
-    if (p_mcb->port_inx[i] != 0) {
+    if (p_mcb->port_handles[i] != 0) {
       p_mcb->is_disc_initiator = false;
       return;
     }
@@ -353,7 +353,7 @@
 
   /* If multiplexer channel was up mark it as down */
   if (p_mcb) {
-    p_mcb->port_inx[p_port->dlci] = 0;
+    p_mcb->port_handles[p_port->dlci] = 0;
 
     /* If there are no more ports opened on this MCB release it */
     rfc_check_mcb_active(p_mcb);
diff --git a/stack/sdp/sdp_db.cc b/stack/sdp/sdp_db.cc
index 769e7d8..ea5b84d 100644
--- a/stack/sdp/sdp_db.cc
+++ b/stack/sdp/sdp_db.cc
@@ -796,34 +796,33 @@
  ******************************************************************************/
 bool SDP_DeleteAttribute(uint32_t handle, uint16_t attr_id) {
 #if (SDP_SERVER_ENABLED == TRUE)
-  uint16_t xx, yy;
   tSDP_RECORD* p_rec = &sdp_cb.server_db.record[0];
   uint8_t* pad_ptr;
   uint32_t 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++) {
+  for (uint16_t 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++) {
+      for (uint16_t yy = 0; yy < p_rec->num_attributes; yy++, 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;
+            for (uint16_t zz = 0; zz < p_rec->num_attributes; zz++) {
+              if (p_rec->attribute[zz].value_ptr > pad_ptr)
+                p_rec->attribute[zz].value_ptr -= len;
             }
           }
 
           /* Found it. Shift everything up one */
           p_rec->num_attributes--;
 
-          for (yy = xx; yy < p_rec->num_attributes; yy++, p_attr++) {
+          for (uint16_t zz = xx; zz < p_rec->num_attributes; zz++, p_attr++) {
             *p_attr = *(p_attr + 1);
           }
 
@@ -831,7 +830,9 @@
           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);
+            for (uint16_t zz = 0; zz < xx; zz++, pad_ptr++) {
+              *pad_ptr = *(pad_ptr + len);
+            }
             p_rec->free_pad_ptr -= len;
           }
           return (true);
diff --git a/stack/sdp/sdp_discovery.cc b/stack/sdp/sdp_discovery.cc
index 7c55e8c..baadd7a 100644
--- a/stack/sdp/sdp_discovery.cc
+++ b/stack/sdp/sdp_discovery.cc
@@ -39,10 +39,6 @@
 
 using bluetooth::Uuid;
 
-#ifndef SDP_DEBUG_RAW
-#define SDP_DEBUG_RAW false
-#endif
-
 /******************************************************************************/
 /*            L O C A L    F U N C T I O N     P R O T O T Y P E S            */
 /******************************************************************************/
@@ -168,11 +164,6 @@
   /* Set the length of the SDP data in the buffer */
   p_cmd->len = (uint16_t)(p - p_start);
 
-#if (SDP_DEBUG_RAW == TRUE)
-  SDP_TRACE_WARNING("sdp_snd_service_search_req cont_len :%d disc_state:%d",
-                    cont_len, p_ccb->disc_state);
-#endif
-
   L2CA_DataWrite(p_ccb->connection_id, p_cmd);
 
   /* Start inactivity timer */
@@ -219,10 +210,6 @@
   uint8_t *p, rsp_pdu;
   bool invalid_pdu = true;
 
-#if (SDP_DEBUG_RAW == TRUE)
-  SDP_TRACE_WARNING("sdp_disc_server_rsp disc_state:%d", p_ccb->disc_state);
-#endif
-
   /* stop inactivity timer when we receive a response */
   alarm_cancel(p_ccb->sdp_conn_timer);
 
@@ -230,6 +217,12 @@
   p = (uint8_t*)(p_msg + 1) + p_msg->offset;
   uint8_t* p_end = p + p_msg->len;
 
+  if (p_msg->len < 1) {
+    android_errorWriteLog(0x534e4554, "79883568");
+    sdp_disconnect(p_ccb, SDP_GENERIC_ERROR);
+    return;
+  }
+
   BE_STREAM_TO_UINT8(rsp_pdu, p);
 
   p_msg->len--;
@@ -354,17 +347,6 @@
   uint8_t* p_end;
   uint8_t type;
 
-#if (SDP_DEBUG_RAW == TRUE)
-  uint8_t num_array[SDP_MAX_LIST_BYTE_COUNT];
-  uint32_t i;
-
-  for (i = 0; i < p_ccb->list_len; i++) {
-    snprintf((char*)&num_array[i * 2], sizeof(num_array) - i * 2, "%02X",
-             (uint8_t)(p_ccb->rsp_list[i]));
-  }
-  SDP_TRACE_WARNING("result :%s", num_array);
-#endif
-
   if (p_ccb->p_db->raw_data) {
     cpy_len = p_ccb->p_db->raw_size - p_ccb->p_db->raw_used;
     list_len = p_ccb->list_len;
@@ -394,11 +376,6 @@
       SDP_TRACE_WARNING("rem_len :%d less than cpy_len:%d", rem_len, cpy_len);
       cpy_len = rem_len;
     }
-    SDP_TRACE_WARNING(
-        "%s: list_len:%d cpy_len:%d p:%p p_ccb:%p p_db:%p raw_size:%d "
-        "raw_used:%d raw_data:%p",
-        __func__, list_len, cpy_len, p, p_ccb, p_ccb->p_db,
-        p_ccb->p_db->raw_size, p_ccb->p_db->raw_used, p_ccb->p_db->raw_data);
     memcpy(&p_ccb->p_db->raw_data[p_ccb->p_db->raw_used], p, cpy_len);
     p_ccb->p_db->raw_used += cpy_len;
   }
@@ -422,23 +399,18 @@
   uint16_t param_len, list_byte_count;
   bool cont_request_needed = false;
 
-#if (SDP_DEBUG_RAW == TRUE)
-  SDP_TRACE_WARNING("process_service_attr_rsp raw inc:%d",
-                    SDP_RAW_DATA_INCLUDED);
-#endif
   /* If p_reply is NULL, we were called after the records handles were read */
   if (p_reply) {
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
-                      p_reply[2], p_reply[3]);
-#endif
+    if (p_reply + 4 /* transaction ID and length */ + sizeof(list_byte_count) >
+        p_reply_end) {
+      sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
+      return;
+    }
+
     /* Skip transaction ID and length */
     p_reply += 4;
 
     BE_STREAM_TO_UINT16(list_byte_count, p_reply);
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("list_byte_count:%d", list_byte_count);
-#endif
 
     /* Copy the response to the scratchpad. First, a safety check on the length
      */
@@ -447,21 +419,11 @@
       return;
     }
 
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
-                      list_byte_count);
-#endif
     if (p_ccb->rsp_list == NULL)
       p_ccb->rsp_list = (uint8_t*)osi_malloc(SDP_MAX_LIST_BYTE_COUNT);
     memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, list_byte_count);
     p_ccb->list_len += list_byte_count;
     p_reply += list_byte_count;
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("list_len: %d(attr_rsp)", p_ccb->list_len);
-
-    /* Check if we need to request a continuation */
-    SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
-#endif
     if (*p_reply) {
       if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
         sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
@@ -542,6 +504,7 @@
     alarm_set_on_mloop(p_ccb->sdp_conn_timer, SDP_INACT_TIMEOUT_MS,
                        sdp_conn_timer_timeout, p_ccb);
   } else {
+    sdpu_log_attribute_metrics(p_ccb->device_address, p_ccb->p_db);
     sdp_disconnect(p_ccb, SDP_SUCCESS);
     return;
   }
@@ -565,9 +528,6 @@
   uint16_t param_len, lists_byte_count = 0;
   bool cont_request_needed = false;
 
-#if (SDP_DEBUG_RAW == TRUE)
-  SDP_TRACE_WARNING("process_service_search_attr_rsp");
-#endif
   /* If p_reply is NULL, we were called for the initial read */
   if (p_reply) {
     if (p_reply + 4 /* transaction ID and length */ + sizeof(lists_byte_count) >
@@ -577,17 +537,10 @@
       return;
     }
 
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("ID & len: 0x%02x-%02x-%02x-%02x", p_reply[0], p_reply[1],
-                      p_reply[2], p_reply[3]);
-#endif
     /* Skip transaction ID and length */
     p_reply += 4;
 
     BE_STREAM_TO_UINT16(lists_byte_count, p_reply);
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("lists_byte_count:%d", lists_byte_count);
-#endif
 
     /* Copy the response to the scratchpad. First, a safety check on the length
      */
@@ -596,11 +549,6 @@
       return;
     }
 
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("list_len: %d, list_byte_count: %d", p_ccb->list_len,
-                      lists_byte_count);
-#endif
-
     if (p_reply + lists_byte_count + 1 /* continuation */ > p_reply_end) {
       android_errorWriteLog(0x534e4554, "79884292");
       sdp_disconnect(p_ccb, SDP_INVALID_PDU_SIZE);
@@ -612,12 +560,6 @@
     memcpy(&p_ccb->rsp_list[p_ccb->list_len], p_reply, lists_byte_count);
     p_ccb->list_len += lists_byte_count;
     p_reply += lists_byte_count;
-#if (SDP_DEBUG_RAW == TRUE)
-    SDP_TRACE_WARNING("list_len: %d(search_attr_rsp)", p_ccb->list_len);
-
-    /* Check if we need to request a continuation */
-    SDP_TRACE_WARNING("*p_reply:%d(%d)", *p_reply, SDP_MAX_CONTINUATION_LEN);
-#endif
     if (*p_reply) {
       if (*p_reply > SDP_MAX_CONTINUATION_LEN) {
         sdp_disconnect(p_ccb, SDP_INVALID_CONT_STATE);
@@ -628,9 +570,6 @@
     }
   }
 
-#if (SDP_DEBUG_RAW == TRUE)
-  SDP_TRACE_WARNING("cont_request_needed:%d", cont_request_needed);
-#endif
   /* If continuation request (or first time request) */
   if ((cont_request_needed) || (!p_reply)) {
     BT_HDR* p_msg = (BT_HDR*)osi_malloc(SDP_DATA_BUF_SIZE);
@@ -737,6 +676,7 @@
   }
 
   /* Since we got everything we need, disconnect the call */
+  sdpu_log_attribute_metrics(p_ccb->device_address, p_ccb->p_db);
   sdp_disconnect(p_ccb, SDP_SUCCESS);
 }
 
@@ -927,7 +867,7 @@
           break;
         }
       }
-    /* Case falls through */
+      FALLTHROUGH_INTENDED; /* FALLTHROUGH */
 
     case TWO_COMP_INT_DESC_TYPE:
       switch (attr_len) {
diff --git a/stack/sdp/sdp_main.cc b/stack/sdp/sdp_main.cc
index 3df37c5..2211c39 100644
--- a/stack/sdp/sdp_main.cc
+++ b/stack/sdp/sdp_main.cc
@@ -121,7 +121,7 @@
   sdp_cb.reg_info.pL2CA_TxComplete_Cb = NULL;
 
   /* Now, register with L2CAP */
-  if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info)) {
+  if (!L2CA_Register(SDP_PSM, &sdp_cb.reg_info, true /* enable_snoop */)) {
     SDP_TRACE_ERROR("SDP Registration failed");
   }
 }
diff --git a/stack/sdp/sdp_server.cc b/stack/sdp/sdp_server.cc
index 386f62f..c9949b7 100644
--- a/stack/sdp/sdp_server.cc
+++ b/stack/sdp/sdp_server.cc
@@ -23,7 +23,7 @@
  *
  ******************************************************************************/
 
-#include <cutils/log.h>
+#include <log/log.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
diff --git a/stack/sdp/sdp_utils.cc b/stack/sdp/sdp_utils.cc
index c2c6b27..33f30b0 100644
--- a/stack/sdp/sdp_utils.cc
+++ b/stack/sdp/sdp_utils.cc
@@ -26,6 +26,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <utility>
+#include <vector>
 
 #include "bt_common.h"
 #include "bt_types.h"
@@ -38,12 +40,251 @@
 #include "sdpint.h"
 
 #include "btu.h"
+#include "common/metrics.h"
 
 using bluetooth::Uuid;
 static const uint8_t sdp_base_uuid[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                                         0x10, 0x00, 0x80, 0x00, 0x00, 0x80,
                                         0x5F, 0x9B, 0x34, 0xFB};
 
+template <typename T>
+static std::array<char, sizeof(T)> to_little_endian_array(T x) {
+  static_assert(std::is_integral<T>::value,
+                "to_little_endian_array parameter must be integral.");
+  std::array<char, sizeof(T)> array = {};
+  for (size_t i = 0; i < array.size(); i++) {
+    array[i] = static_cast<char>((x >> (8 * i)) & 0xFF);
+  }
+  return array;
+}
+
+/**
+ * Find the list of profile versions from Bluetooth Profile Descriptor list
+ * attribute in a SDP record
+ *
+ * @param p_rec SDP record to search
+ * @return a vector of <UUID, VERSION> pairs, empty if not found
+ */
+static std::vector<std::pair<uint16_t, uint16_t>> sdpu_find_profile_version(
+    tSDP_DISC_REC* p_rec) {
+  std::vector<std::pair<uint16_t, uint16_t>> result;
+  for (tSDP_DISC_ATTR* p_attr = p_rec->p_first_attr; p_attr != nullptr;
+       p_attr = p_attr->p_next_attr) {
+    // Find the profile descriptor list */
+    if (p_attr->attr_id != ATTR_ID_BT_PROFILE_DESC_LIST ||
+        SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) != DATA_ELE_SEQ_DESC_TYPE) {
+      continue;
+    }
+    // Walk through the protocol descriptor list
+    for (tSDP_DISC_ATTR* p_sattr = p_attr->attr_value.v.p_sub_attr;
+         p_sattr != nullptr; p_sattr = p_sattr->p_next_attr) {
+      // Safety check - each entry should itself be a sequence
+      if (SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type) !=
+          DATA_ELE_SEQ_DESC_TYPE) {
+        LOG(WARNING) << __func__ << ": Descriptor type is not sequence: "
+                     << loghex(SDP_DISC_ATTR_TYPE(p_sattr->attr_len_type));
+        return std::vector<std::pair<uint16_t, uint16_t>>();
+      }
+      // Now, see if the entry contains the profile UUID we are interested in
+      for (tSDP_DISC_ATTR* p_ssattr = p_sattr->attr_value.v.p_sub_attr;
+           p_ssattr != nullptr; p_ssattr = p_ssattr->p_next_attr) {
+        if (SDP_DISC_ATTR_TYPE(p_ssattr->attr_len_type) != UUID_DESC_TYPE ||
+            SDP_DISC_ATTR_LEN(p_ssattr->attr_len_type) != 2) {
+          continue;
+        }
+        uint16_t uuid = p_ssattr->attr_value.v.u16;
+        // Next attribute should be the version attribute
+        tSDP_DISC_ATTR* version_attr = p_ssattr->p_next_attr;
+        if (SDP_DISC_ATTR_TYPE(version_attr->attr_len_type) != UINT_DESC_TYPE ||
+            SDP_DISC_ATTR_LEN(version_attr->attr_len_type) != 2) {
+          LOG(WARNING) << __func__ << ": Bad version type "
+                       << loghex(
+                              SDP_DISC_ATTR_TYPE(version_attr->attr_len_type))
+                       << ", or length "
+                       << SDP_DISC_ATTR_LEN(version_attr->attr_len_type);
+          return std::vector<std::pair<uint16_t, uint16_t>>();
+        }
+        // High order 8 bits is the major number, low order is the
+        // minor number (big endian)
+        uint16_t version = version_attr->attr_value.v.u16;
+        result.emplace_back(uuid, version);
+      }
+    }
+  }
+  return result;
+}
+
+/**
+ * Find the most specific 16-bit service uuid represented by a SDP record
+ *
+ * @param p_rec pointer to a SDP record
+ * @return most specific 16-bit service uuid, 0 if not found
+ */
+static uint16_t sdpu_find_most_specific_service_uuid(tSDP_DISC_REC* p_rec) {
+  for (tSDP_DISC_ATTR* p_attr = p_rec->p_first_attr; p_attr != nullptr;
+       p_attr = p_attr->p_next_attr) {
+    if (p_attr->attr_id == ATTR_ID_SERVICE_CLASS_ID_LIST &&
+        SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == DATA_ELE_SEQ_DESC_TYPE) {
+      tSDP_DISC_ATTR* p_first_attr = p_attr->attr_value.v.p_sub_attr;
+      if (SDP_DISC_ATTR_TYPE(p_first_attr->attr_len_type) == UUID_DESC_TYPE &&
+          SDP_DISC_ATTR_LEN(p_first_attr->attr_len_type) == 2) {
+        return p_first_attr->attr_value.v.u16;
+      } else if (SDP_DISC_ATTR_TYPE(p_first_attr->attr_len_type) ==
+                 DATA_ELE_SEQ_DESC_TYPE) {
+        // Workaround for Toyota G Block car kit:
+        // It incorrectly puts an extra data element sequence in this attribute
+        for (tSDP_DISC_ATTR* p_extra_sattr =
+                 p_first_attr->attr_value.v.p_sub_attr;
+             p_extra_sattr != nullptr;
+             p_extra_sattr = p_extra_sattr->p_next_attr) {
+          // Return the first UUID data element
+          if (SDP_DISC_ATTR_TYPE(p_extra_sattr->attr_len_type) ==
+                  UUID_DESC_TYPE &&
+              SDP_DISC_ATTR_LEN(p_extra_sattr->attr_len_type) == 2) {
+            return p_extra_sattr->attr_value.v.u16;
+          }
+        }
+      } else {
+        LOG(WARNING) << __func__ << ": Bad Service Class ID list attribute";
+        return 0;
+      }
+    } else if (p_attr->attr_id == ATTR_ID_SERVICE_ID) {
+      if (SDP_DISC_ATTR_TYPE(p_attr->attr_len_type) == UUID_DESC_TYPE &&
+          SDP_DISC_ATTR_LEN(p_attr->attr_len_type) == 2) {
+        return p_attr->attr_value.v.u16;
+      }
+    }
+  }
+  return 0;
+}
+
+void sdpu_log_attribute_metrics(const RawAddress& bda,
+                                tSDP_DISCOVERY_DB* p_db) {
+  CHECK_NE(p_db, nullptr);
+  bool has_di_record = false;
+  for (tSDP_DISC_REC* p_rec = p_db->p_first_rec; p_rec != nullptr;
+       p_rec = p_rec->p_next_rec) {
+    uint16_t service_uuid = sdpu_find_most_specific_service_uuid(p_rec);
+    if (service_uuid == 0) {
+      LOG(INFO) << __func__ << ": skipping record without service uuid " << bda;
+      continue;
+    }
+    // Log the existence of a profile role
+    // This can be different from Bluetooth Profile Descriptor List
+    bluetooth::common::LogSdpAttribute(bda, service_uuid, 0, 0, nullptr);
+    // Log profile version from Bluetooth Profile Descriptor List
+    auto uuid_version_array = sdpu_find_profile_version(p_rec);
+    for (const auto& uuid_version_pair : uuid_version_array) {
+      uint16_t profile_uuid = uuid_version_pair.first;
+      uint16_t version = uuid_version_pair.second;
+      auto version_array = to_little_endian_array(version);
+      bluetooth::common::LogSdpAttribute(
+          bda, profile_uuid, ATTR_ID_BT_PROFILE_DESC_LIST, version_array.size(),
+          version_array.data());
+    }
+    // Log protocol version from Protocol Descriptor List
+    uint16_t protocol_uuid = 0;
+    switch (service_uuid) {
+      case UUID_SERVCLASS_AUDIO_SOURCE:
+      case UUID_SERVCLASS_AUDIO_SINK:
+        protocol_uuid = UUID_PROTOCOL_AVDTP;
+        break;
+      case UUID_SERVCLASS_AV_REMOTE_CONTROL:
+      case UUID_SERVCLASS_AV_REM_CTRL_CONTROL:
+      case UUID_SERVCLASS_AV_REM_CTRL_TARGET:
+        protocol_uuid = UUID_PROTOCOL_AVCTP;
+        break;
+      case UUID_SERVCLASS_PANU:
+      case UUID_SERVCLASS_GN:
+        protocol_uuid = UUID_PROTOCOL_BNEP;
+        break;
+    }
+    if (protocol_uuid != 0) {
+      tSDP_PROTOCOL_ELEM protocol_elements = {};
+      if (SDP_FindProtocolListElemInRec(p_rec, protocol_uuid,
+                                        &protocol_elements)) {
+        if (protocol_elements.num_params >= 1) {
+          uint16_t version = protocol_elements.params[0];
+          auto version_array = to_little_endian_array(version);
+          bluetooth::common::LogSdpAttribute(
+              bda, protocol_uuid, ATTR_ID_PROTOCOL_DESC_LIST,
+              version_array.size(), version_array.data());
+        }
+      }
+    }
+    // Log profile supported features from various supported feature attributes
+    switch (service_uuid) {
+      case UUID_SERVCLASS_AG_HANDSFREE:
+      case UUID_SERVCLASS_HF_HANDSFREE:
+      case UUID_SERVCLASS_AV_REMOTE_CONTROL:
+      case UUID_SERVCLASS_AV_REM_CTRL_CONTROL:
+      case UUID_SERVCLASS_AV_REM_CTRL_TARGET:
+      case UUID_SERVCLASS_AUDIO_SOURCE:
+      case UUID_SERVCLASS_AUDIO_SINK: {
+        tSDP_DISC_ATTR* p_attr =
+            SDP_FindAttributeInRec(p_rec, ATTR_ID_SUPPORTED_FEATURES);
+        if (p_attr == nullptr) {
+          break;
+        }
+        uint16_t supported_features = p_attr->attr_value.v.u16;
+        auto version_array = to_little_endian_array(supported_features);
+        bluetooth::common::LogSdpAttribute(
+            bda, service_uuid, ATTR_ID_SUPPORTED_FEATURES, version_array.size(),
+            version_array.data());
+        break;
+      }
+      case UUID_SERVCLASS_MESSAGE_NOTIFICATION:
+      case UUID_SERVCLASS_MESSAGE_ACCESS: {
+        tSDP_DISC_ATTR* p_attr =
+            SDP_FindAttributeInRec(p_rec, ATTR_ID_MAP_SUPPORTED_FEATURES);
+        if (p_attr == nullptr) {
+          break;
+        }
+        uint32_t map_supported_features = p_attr->attr_value.v.u32;
+        auto features_array = to_little_endian_array(map_supported_features);
+        bluetooth::common::LogSdpAttribute(
+            bda, service_uuid, ATTR_ID_MAP_SUPPORTED_FEATURES,
+            features_array.size(), features_array.data());
+        break;
+      }
+      case UUID_SERVCLASS_PBAP_PCE:
+      case UUID_SERVCLASS_PBAP_PSE: {
+        tSDP_DISC_ATTR* p_attr =
+            SDP_FindAttributeInRec(p_rec, ATTR_ID_PBAP_SUPPORTED_FEATURES);
+        if (p_attr == nullptr) {
+          break;
+        }
+        uint32_t pbap_supported_features = p_attr->attr_value.v.u32;
+        auto features_array = to_little_endian_array(pbap_supported_features);
+        bluetooth::common::LogSdpAttribute(
+            bda, service_uuid, ATTR_ID_PBAP_SUPPORTED_FEATURES,
+            features_array.size(), features_array.data());
+        break;
+      }
+    }
+    if (service_uuid == UUID_SERVCLASS_PNP_INFORMATION) {
+      has_di_record = true;
+    }
+  }
+  // Log the first DI record if there is one
+  if (has_di_record) {
+    tSDP_DI_GET_RECORD di_record = {};
+    if (SDP_GetDiRecord(1, &di_record, p_db) == SDP_SUCCESS) {
+      auto version_array = to_little_endian_array(di_record.spec_id);
+      bluetooth::common::LogSdpAttribute(
+          bda, UUID_SERVCLASS_PNP_INFORMATION, ATTR_ID_SPECIFICATION_ID,
+          version_array.size(), version_array.data());
+      std::stringstream ss;
+      // [N - native]::SDP::[DIP - Device ID Profile]
+      ss << "N:SDP::DIP::" << loghex(di_record.rec.vendor_id_source);
+      bluetooth::common::LogManufacturerInfo(
+          bda, android::bluetooth::DeviceInfoSrcEnum::DEVICE_INFO_INTERNAL,
+          ss.str(), loghex(di_record.rec.vendor), loghex(di_record.rec.product),
+          loghex(di_record.rec.version), "");
+    }
+  }
+}
+
 /*******************************************************************************
  *
  * Function         sdpu_find_ccb_by_cid
diff --git a/stack/sdp/sdpint.h b/stack/sdp/sdpint.h
index e00a8ca..20c6fbd 100644
--- a/stack/sdp/sdpint.h
+++ b/stack/sdp/sdpint.h
@@ -247,6 +247,8 @@
 
 /* Functions provided by sdp_utils.cc
  */
+extern void sdpu_log_attribute_metrics(const RawAddress& bda,
+                                       tSDP_DISCOVERY_DB* p_db);
 extern tCONN_CB* sdpu_find_ccb_by_cid(uint16_t cid);
 extern tCONN_CB* sdpu_find_ccb_by_db(tSDP_DISCOVERY_DB* p_db);
 extern tCONN_CB* sdpu_allocate_ccb(void);
diff --git a/stack/smp/crypto_toolbox.h b/stack/smp/crypto_toolbox.h
new file mode 100644
index 0000000..d3fceff
--- /dev/null
+++ b/stack/smp/crypto_toolbox.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "stack/include/bt_types.h"
+
+/* Functions below implement cryptographic toolbox, as described in BT Spec
+ * Ver 5.0 | Vol 3, Part H CRYPTOGRAPHIC TOOLBOX. Please see the spec for
+ * description.
+ *
+ * Example of usage is avaliable in cryptographic_toolbox_test.cc */
+
+extern Octet16 smp_calculate_f4(uint8_t* u, uint8_t* v, const Octet16& x,
+                                uint8_t z);
+extern uint32_t smp_calculate_g2(uint8_t* u, uint8_t* v, const Octet16& x,
+                                 const Octet16& y);
+extern void smp_calculate_f5(uint8_t* w, const Octet16& n1, const Octet16& n2,
+                             uint8_t* a1, uint8_t* a2, Octet16* mac_key,
+                             Octet16* ltk);
+extern Octet16 smp_calculate_f6(const Octet16& w, const Octet16& n1,
+                                const Octet16& n2, const Octet16& r,
+                                uint8_t* iocap, uint8_t* a1, uint8_t* a2);
+extern Octet16 smp_calculate_h6(const Octet16& w, std::array<uint8_t, 4> keyid);
+extern Octet16 smp_calculate_h7(const Octet16& salt, const Octet16& w);
+extern Octet16 smp_calculate_ltk_to_link_key(const Octet16& ltk, bool use_h7);
+extern Octet16 smp_calculate_link_key_to_ltk(const Octet16& link_key,
+                                             bool use_h7);
diff --git a/stack/smp/smp_act.cc b/stack/smp/smp_act.cc
index b775d5d..21b960b 100644
--- a/stack/smp/smp_act.cc
+++ b/stack/smp/smp_act.cc
@@ -16,8 +16,11 @@
  *
  ******************************************************************************/
 
+#include <cutils/log.h>
+#include <log/log.h>
 #include <string.h>
 #include "btif_common.h"
+#include "btif_storage.h"
 #include "device/include/interop.h"
 #include "internal_include/bt_target.h"
 #include "stack/btm/btm_int.h"
@@ -105,7 +108,7 @@
       case SMP_IO_CAP_REQ_EVT:
         cb_data.io_req.auth_req = p_cb->peer_auth_req;
         cb_data.io_req.oob_data = SMP_OOB_NONE;
-        cb_data.io_req.io_cap = SMP_DEFAULT_IO_CAPS;
+        cb_data.io_req.io_cap = btif_storage_get_local_io_caps_ble();
         cb_data.io_req.max_key_size = SMP_MAX_ENC_KEY_SIZE;
         cb_data.io_req.init_keys = p_cb->local_i_key;
         cb_data.io_req.resp_keys = p_cb->local_r_key;
@@ -350,7 +353,7 @@
   smp_send_cmd(SMP_OPCODE_MASTER_ID, p_cb);
 
   /* save the DIV and key size information when acting as slave device */
-  memcpy(le_key.lenc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+  le_key.lenc_key.ltk = p_cb->ltk;
   le_key.lenc_key.div = p_cb->div;
   le_key.lenc_key.key_size = p_cb->loc_enc_size;
   le_key.lenc_key.sec_level = p_cb->sec_level;
@@ -384,10 +387,7 @@
   smp_key_distribution_by_transport(p_cb, NULL);
 }
 
-/*******************************************************************************
- * Function     smp_send_csrk_info
- * Description  send CSRK command.
- ******************************************************************************/
+/**  send CSRK command. */
 void smp_send_csrk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   tBTM_LE_KEY_VALUE key;
   SMP_TRACE_DEBUG("%s", __func__);
@@ -397,7 +397,7 @@
     key.lcsrk_key.div = p_cb->div;
     key.lcsrk_key.sec_level = p_cb->sec_level;
     key.lcsrk_key.counter = 0; /* initialize the local counter */
-    memcpy(key.lcsrk_key.csrk, p_cb->csrk, BT_OCTET16_LEN);
+    key.lcsrk_key.csrk = p_cb->csrk;
     btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_LCSRK, &key, true);
   }
 
@@ -410,8 +410,11 @@
  ******************************************************************************/
 void smp_send_ltk_reply(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("%s", __func__);
+
+  Octet16 stk;
+  memcpy(stk.data(), p_data->key.p_data, stk.size());
   /* send stk as LTK response */
-  btm_ble_ltk_request_reply(p_cb->pairing_bda, true, p_data->key.p_data);
+  btm_ble_ltk_request_reply(p_cb->pairing_bda, true, stk);
 }
 
 /*******************************************************************************
@@ -419,7 +422,7 @@
  * Description  process security request.
  ******************************************************************************/
 void smp_proc_sec_req(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-  tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ*)p_data;
+  tBTM_LE_AUTH_REQ auth_req = *(tBTM_LE_AUTH_REQ*)p_data->p_data;
   tBTM_BLE_SEC_REQ_ACT sec_req_act;
 
   SMP_TRACE_DEBUG("%s: auth_req=0x%x", __func__, auth_req);
@@ -486,7 +489,15 @@
  ******************************************************************************/
 void smp_proc_pair_fail(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("%s", __func__);
-  p_cb->status = p_data->status;
+
+  if (p_cb->rcvd_cmd_len < 2) {
+    android_errorWriteLog(0x534e4554, "111214739");
+    SMP_TRACE_WARNING("%s: rcvd_cmd_len %d too short: must be at least 2",
+                      __func__, p_cb->rcvd_cmd_len);
+    p_cb->status = SMP_INVALID_PARAMETERS;
+  } else {
+    p_cb->status = p_data->status;
+  }
 
   /* Cancel pending auth complete timer if set */
   alarm_cancel(p_cb->delayed_auth_timer_ent);
@@ -509,6 +520,14 @@
 
   p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
 
+  if (smp_command_has_invalid_length(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111850706");
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   STREAM_TO_UINT8(p_cb->peer_io_caps, p);
   STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
   STREAM_TO_UINT8(p_cb->peer_auth_req, p);
@@ -583,13 +602,8 @@
   }
 }
 
-/*******************************************************************************
- * Function     smp_proc_confirm
- * Description  process pairing confirm from peer device
- ******************************************************************************/
+/** process pairing confirm from peer device */
 void smp_proc_confirm(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-  uint8_t* p = p_data->p_data;
-
   SMP_TRACE_DEBUG("%s", __func__);
 
   if (smp_command_has_invalid_parameters(p_cb)) {
@@ -599,18 +613,18 @@
     return;
   }
 
-  if (p != NULL) {
-    /* save the SConfirm for comparison later */
-    STREAM_TO_ARRAY(p_cb->rconfirm, p, BT_OCTET16_LEN);
+  if (p_data) {
+    uint8_t* p = p_data->p_data;
+    if (p != NULL) {
+      /* save the SConfirm for comparison later */
+      STREAM_TO_ARRAY(p_cb->rconfirm.data(), p, OCTET16_LEN);
+    }
   }
 
   p_cb->flags |= SMP_PAIR_FLAGS_CMD_CONFIRM;
 }
 
-/*******************************************************************************
- * Function     smp_proc_init
- * Description  process pairing initializer from peer device
- ******************************************************************************/
+/** process pairing initializer from peer device */
 void smp_proc_init(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
 
@@ -624,7 +638,7 @@
   }
 
   /* save the SRand for comparison */
-  STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
+  STREAM_TO_ARRAY(p_cb->rrand.data(), p, OCTET16_LEN);
 }
 
 /*******************************************************************************
@@ -644,7 +658,7 @@
   }
 
   /* save the SRand for comparison */
-  STREAM_TO_ARRAY(p_cb->rrand, p, BT_OCTET16_LEN);
+  STREAM_TO_ARRAY(p_cb->rrand.data(), p, OCTET16_LEN);
 }
 
 /*******************************************************************************
@@ -706,7 +720,7 @@
   p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_COMM;
 
   if (p != NULL) {
-    STREAM_TO_ARRAY(p_cb->remote_commitment, p, BT_OCTET16_LEN);
+    STREAM_TO_ARRAY(p_cb->remote_commitment.data(), p, OCTET16_LEN);
   }
 }
 
@@ -727,7 +741,7 @@
   }
 
   if (p != NULL) {
-    STREAM_TO_ARRAY(p_cb->remote_dhkey_check, p, BT_OCTET16_LEN);
+    STREAM_TO_ARRAY(p_cb->remote_dhkey_check.data(), p, OCTET16_LEN);
   }
 
   p_cb->flags |= SMP_PAIR_FLAG_HAVE_PEER_DHK_CHK;
@@ -782,6 +796,14 @@
 
   p_cb->flags |= SMP_PAIR_FLAG_ENC_AFTER_PAIR;
 
+  if (smp_command_has_invalid_length(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111213909");
+    smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   STREAM_TO_UINT8(p_cb->peer_io_caps, p);
   STREAM_TO_UINT8(p_cb->peer_oob_flag, p);
   STREAM_TO_UINT8(p_cb->peer_auth_req, p);
@@ -906,10 +928,7 @@
   }
 }
 
-/*******************************************************************************
- * Function     smp_proc_enc_info
- * Description  process encryption information from peer device
- ******************************************************************************/
+/** process encryption information from peer device */
 void smp_proc_enc_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
 
@@ -923,14 +942,12 @@
     return;
   }
 
-  STREAM_TO_ARRAY(p_cb->ltk, p, BT_OCTET16_LEN);
+  STREAM_TO_ARRAY(p_cb->ltk.data(), p, OCTET16_LEN);
 
   smp_key_distribution(p_cb, NULL);
 }
-/*******************************************************************************
- * Function     smp_proc_master_id
- * Description  process master ID from slave device
- ******************************************************************************/
+
+/** process master ID from slave device */
 void smp_proc_master_id(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
   tBTM_LE_KEY_VALUE le_key;
@@ -950,7 +967,7 @@
   STREAM_TO_ARRAY(le_key.penc_key.rand, p, BT_OCTET8_LEN);
 
   /* store the encryption keys from peer device */
-  memcpy(le_key.penc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+  le_key.penc_key.ltk = p_cb->ltk;
   le_key.penc_key.sec_level = p_cb->sec_level;
   le_key.penc_key.key_size = p_cb->loc_enc_size;
 
@@ -961,10 +978,7 @@
   smp_key_distribution(p_cb, NULL);
 }
 
-/*******************************************************************************
- * Function     smp_proc_id_info
- * Description  process identity information from peer device
- ******************************************************************************/
+/** process identity information from peer device */
 void smp_proc_id_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
 
@@ -978,29 +992,35 @@
     return;
   }
 
-  STREAM_TO_ARRAY(p_cb->tk, p, BT_OCTET16_LEN); /* reuse TK for IRK */
+  STREAM_TO_ARRAY(p_cb->tk.data(), p, OCTET16_LEN); /* reuse TK for IRK */
   smp_key_distribution_by_transport(p_cb, NULL);
 }
 
-/*******************************************************************************
- * Function     smp_proc_id_addr
- * Description  process identity address from peer device
- ******************************************************************************/
+/** process identity address from peer device */
 void smp_proc_id_addr(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t* p = p_data->p_data;
   tBTM_LE_KEY_VALUE pid_key;
 
   SMP_TRACE_DEBUG("%s", __func__);
+
+  if (smp_command_has_invalid_parameters(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111214770");
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_ID, true);
 
-  STREAM_TO_UINT8(pid_key.pid_key.addr_type, p);
-  STREAM_TO_BDADDR(pid_key.pid_key.static_addr, p);
-  memcpy(pid_key.pid_key.irk, p_cb->tk, BT_OCTET16_LEN);
+  STREAM_TO_UINT8(pid_key.pid_key.identity_addr_type, p);
+  STREAM_TO_BDADDR(pid_key.pid_key.identity_addr, p);
+  pid_key.pid_key.irk = p_cb->tk;
 
   /* to use as BD_ADDR for lk derived from ltk */
   p_cb->id_addr_rcvd = true;
-  p_cb->id_addr_type = pid_key.pid_key.addr_type;
-  p_cb->id_addr = pid_key.pid_key.static_addr;
+  p_cb->id_addr_type = pid_key.pid_key.identity_addr_type;
+  p_cb->id_addr = pid_key.pid_key.identity_addr;
 
   /* store the ID key from peer device */
   if ((p_cb->peer_auth_req & SMP_AUTH_BOND) &&
@@ -1009,21 +1029,28 @@
   smp_key_distribution_by_transport(p_cb, NULL);
 }
 
-/*******************************************************************************
- * Function     smp_proc_srk_info
- * Description  process security information from peer device
- ******************************************************************************/
+/* process security information from peer device */
 void smp_proc_srk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   tBTM_LE_KEY_VALUE le_key;
 
   SMP_TRACE_DEBUG("%s", __func__);
+
+  if (smp_command_has_invalid_parameters(p_cb)) {
+    tSMP_INT_DATA smp_int_data;
+    smp_int_data.status = SMP_INVALID_PARAMETERS;
+    android_errorWriteLog(0x534e4554, "111214470");
+    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
+    return;
+  }
+
   smp_update_key_mask(p_cb, SMP_SEC_KEY_TYPE_CSRK, true);
 
   /* save CSRK to security record */
   le_key.pcsrk_key.sec_level = p_cb->sec_level;
 
   /* get peer CSRK */
-  maybe_non_aligned_memcpy(le_key.pcsrk_key.csrk, p_data->p_data, BT_OCTET16_LEN);
+  maybe_non_aligned_memcpy(le_key.pcsrk_key.csrk.data(), p_data->p_data,
+                           OCTET16_LEN);
 
   /* initialize the peer counter */
   le_key.pcsrk_key.counter = 0;
@@ -1040,7 +1067,7 @@
  ******************************************************************************/
 void smp_proc_compare(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("%s", __func__);
-  if (!memcmp(p_cb->rconfirm, p_data->key.p_data, BT_OCTET16_LEN)) {
+  if (!memcmp(p_cb->rconfirm.data(), p_data->key.p_data, OCTET16_LEN)) {
     /* compare the max encryption key size, and save the smaller one for the
      * link */
     if (p_cb->peer_enc_size < p_cb->loc_enc_size)
@@ -1090,10 +1117,12 @@
   tBTM_STATUS cmd;
 
   SMP_TRACE_DEBUG("%s", __func__);
-  if (p_data != NULL)
-    cmd = btm_ble_start_encrypt(p_cb->pairing_bda, true, p_data->key.p_data);
-  else
+  if (p_data != NULL) {
+    cmd = btm_ble_start_encrypt(p_cb->pairing_bda, true,
+                                (Octet16*)p_data->key.p_data);
+  } else {
     cmd = btm_ble_start_encrypt(p_cb->pairing_bda, false, NULL);
+  }
 
   if (cmd != BTM_CMD_STARTED && cmd != BTM_BUSY) {
     tSMP_INT_DATA smp_int_data;
@@ -1278,10 +1307,10 @@
 
         tSMP_KEY key;
         key.key_type = SMP_KEY_TYPE_TK;
-        key.p_data = p_cb->tk;
+        key.p_data = p_cb->tk.data();
         smp_int_data.key = key;
 
-        memset(p_cb->tk, 0, BT_OCTET16_LEN);
+        p_cb->tk = {0};
         /* TK, ready  */
         int_evt = SMP_KEY_READY_EVT;
       }
@@ -1439,18 +1468,6 @@
 }
 
 /*******************************************************************************
- * Function     smp_fast_conn_param
- * Description  apply default connection parameter for pairing process
- ******************************************************************************/
-void smp_fast_conn_param(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-  /* Disable L2CAP connection parameter updates while bonding since
-     some peripherals are not able to revert to fast connection parameters
-     during the start of service discovery. Connection paramter updates
-     get enabled again once service discovery completes. */
-  L2CA_EnableUpdateBleConnParams(p_cb->pairing_bda, false);
-}
-
-/*******************************************************************************
  * Function     smp_both_have_public_keys
  * Description  The function is called when both local and peer public keys are
  *              saved.
@@ -1494,7 +1511,7 @@
   switch (p_cb->selected_association_model) {
     case SMP_MODEL_SEC_CONN_JUSTWORKS:
     case SMP_MODEL_SEC_CONN_NUM_COMP:
-      memset(p_cb->local_random, 0, BT_OCTET16_LEN);
+      p_cb->local_random = {0};
       smp_start_nonce_generation(p_cb);
       break;
     case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
@@ -1684,10 +1701,10 @@
  *              received from the peer DHKey check value.
  ******************************************************************************/
 void smp_match_dhkey_checks(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
-
   SMP_TRACE_DEBUG("%s", __func__);
 
-  if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check, BT_OCTET16_LEN)) {
+  if (memcmp(p_data->key.p_data, p_cb->remote_dhkey_check.data(),
+             OCTET16_LEN)) {
     SMP_TRACE_WARNING("dhkey chcks do no match");
     tSMP_INT_DATA smp_int_data;
     smp_int_data.status = SMP_DHKEY_CHK_FAIL;
@@ -1773,10 +1790,10 @@
   uint8_t* p = NULL;
 
   SMP_TRACE_DEBUG("%s", __func__);
-  p = p_cb->local_random;
+  p = p_cb->local_random.data();
   UINT32_TO_STREAM(p, p_data->passkey);
 
-  p = p_cb->peer_random;
+  p = p_cb->peer_random.data();
   UINT32_TO_STREAM(p, p_data->passkey);
 
   p_cb->round = 0;
@@ -1793,21 +1810,18 @@
 
   tSMP_SC_OOB_DATA* p_sc_oob_data = &p_cb->sc_oob_data;
   if (p_sc_oob_data->loc_oob_data.present) {
-    memcpy(p_cb->local_random, p_sc_oob_data->loc_oob_data.randomizer,
-           sizeof(p_cb->local_random));
+    p_cb->local_random = p_sc_oob_data->loc_oob_data.randomizer;
   } else {
     SMP_TRACE_EVENT("%s: local OOB randomizer is absent", __func__);
-    memset(p_cb->local_random, 0, sizeof(p_cb->local_random));
+    p_cb->local_random = {0};
   }
 
   if (!p_sc_oob_data->peer_oob_data.present) {
     SMP_TRACE_EVENT("%s: peer OOB data is absent", __func__);
-    memset(p_cb->peer_random, 0, sizeof(p_cb->peer_random));
+    p_cb->peer_random = {0};
   } else {
-    memcpy(p_cb->peer_random, p_sc_oob_data->peer_oob_data.randomizer,
-           sizeof(p_cb->peer_random));
-    memcpy(p_cb->remote_commitment, p_sc_oob_data->peer_oob_data.commitment,
-           sizeof(p_cb->remote_commitment));
+    p_cb->peer_random = p_sc_oob_data->peer_oob_data.randomizer;
+    p_cb->remote_commitment = p_sc_oob_data->peer_oob_data.commitment;
 
     /* check commitment */
     if (!smp_check_commitment(p_cb)) {
@@ -1823,7 +1837,7 @@
       SMP_TRACE_EVENT(
           "%s: peer didn't receive local OOB data, set local randomizer to 0",
           __func__);
-      memset(p_cb->local_random, 0, sizeof(p_cb->local_random));
+      p_cb->local_random = {0};
     }
   }
 
@@ -1855,12 +1869,12 @@
  ******************************************************************************/
 void smp_set_local_oob_random_commitment(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("%s", __func__);
-  memcpy(p_cb->sc_oob_data.loc_oob_data.randomizer, p_cb->rand, BT_OCTET16_LEN);
+  p_cb->sc_oob_data.loc_oob_data.randomizer = p_cb->rand;
 
-  smp_calculate_f4(p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
-                   p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
-                   p_cb->sc_oob_data.loc_oob_data.randomizer, 0,
-                   p_cb->sc_oob_data.loc_oob_data.commitment);
+  p_cb->sc_oob_data.loc_oob_data.commitment =
+      crypto_toolbox::f4(p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+                         p_cb->sc_oob_data.loc_oob_data.publ_key_used.x,
+                         p_cb->sc_oob_data.loc_oob_data.randomizer, 0);
 
 #if (SMP_DEBUG == TRUE)
   uint8_t* p_print = NULL;
@@ -1878,9 +1892,9 @@
   smp_debug_print_nbyte_little_endian(p_print, "publ_key_used.y",
                                       BT_OCTET32_LEN);
   p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.randomizer;
-  smp_debug_print_nbyte_little_endian(p_print, "randomizer", BT_OCTET16_LEN);
+  smp_debug_print_nbyte_little_endian(p_print, "randomizer", OCTET16_LEN);
   p_print = (uint8_t*)&p_cb->sc_oob_data.loc_oob_data.commitment;
-  smp_debug_print_nbyte_little_endian(p_print, "commitment", BT_OCTET16_LEN);
+  smp_debug_print_nbyte_little_endian(p_print, "commitment", OCTET16_LEN);
   SMP_TRACE_DEBUG("");
 #endif
 
@@ -1922,6 +1936,11 @@
   }
 }
 
+void smp_cancel_start_encryption_attempt() {
+  SMP_TRACE_ERROR("%s: Encryption request cancelled", __func__);
+  smp_sm_event(&smp_cb, SMP_DISCARD_SEC_REQ_EVT, NULL);
+}
+
 /*******************************************************************************
  *
  * Function         smp_proc_ltk_request
diff --git a/stack/smp/smp_api.cc b/stack/smp/smp_api.cc
index d096da5..baa41cf 100644
--- a/stack/smp/smp_api.cc
+++ b/stack/smp/smp_api.cc
@@ -328,7 +328,7 @@
     smp_int_data.passkey = passkey;
     smp_sm_event(&smp_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
   } else {
-    smp_convert_string_to_tk(p_cb->tk, passkey);
+    smp_convert_string_to_tk(&p_cb->tk, passkey);
   }
 
   return;
@@ -406,12 +406,12 @@
     smp_int_data.status = SMP_OOB_FAIL;
     smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
   } else {
-    if (len > BT_OCTET16_LEN) len = BT_OCTET16_LEN;
+    if (len > OCTET16_LEN) len = OCTET16_LEN;
 
-    memcpy(p_cb->tk, p_data, len);
+    memcpy(p_cb->tk.data(), p_data, len);
 
     key.key_type = SMP_KEY_TYPE_TK;
-    key.p_data = p_cb->tk;
+    key.p_data = p_cb->tk.data();
 
     tSMP_INT_DATA smp_int_data;
     smp_int_data.key = key;
@@ -484,31 +484,6 @@
 
 /*******************************************************************************
  *
- * Function         SMP_Encrypt
- *
- * Description      This function is called to encrypt the data with the
- *                  specified key
- *
- * Parameters:      key                 - Pointer to key key[0] conatins the MSB
- *                  key_len             - key length
- *                  plain_text          - Pointer to data to be encrypted
- *                                        plain_text[0] conatins the MSB
- *                  pt_len              - plain text length
- *                  p_out                - output of the encrypted texts
- *
- *  Returns         Boolean - request is successful
- ******************************************************************************/
-bool SMP_Encrypt(uint8_t* key, uint8_t key_len, uint8_t* plain_text,
-                 uint8_t pt_len, tSMP_ENC* p_out)
-
-{
-  bool status = false;
-  status = smp_encrypt_data(key, key_len, plain_text, pt_len, p_out);
-  return status;
-}
-
-/*******************************************************************************
- *
  * Function         SMP_KeypressNotification
  *
  * Description      This function is called to notify Security Manager about
diff --git a/stack/smp/smp_cmac.cc b/stack/smp/smp_cmac.cc
deleted file mode 100644
index 42f91a0..0000000
--- a/stack/smp/smp_cmac.cc
+++ /dev/null
@@ -1,313 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2008-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.
- *
- ******************************************************************************/
-
-/******************************************************************************
- *
- *  This file contains the implementation of the AES128 CMAC algorithm.
- *
- ******************************************************************************/
-
-#include "bt_target.h"
-
-#include <stdio.h>
-#include <string.h>
-
-#include "btm_ble_api.h"
-#include "hcimsgs.h"
-#include "smp_int.h"
-
-typedef struct {
-  uint8_t* text;
-  uint16_t len;
-  uint16_t round;
-} tCMAC_CB;
-
-tCMAC_CB cmac_cb;
-
-/* Rb for AES-128 as block cipher, LSB as [0] */
-BT_OCTET16 const_Rb = {0x87, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-                       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-void print128(BT_OCTET16 x, const uint8_t* key_name) {
-#if (SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE)
-  uint8_t* p = (uint8_t*)x;
-  uint8_t i;
-
-  SMP_TRACE_WARNING("%s(MSB ~ LSB) = ", key_name);
-
-  for (i = 0; i < 4; i++) {
-    SMP_TRACE_WARNING("%02x %02x %02x %02x", p[BT_OCTET16_LEN - i * 4 - 1],
-                      p[BT_OCTET16_LEN - i * 4 - 2],
-                      p[BT_OCTET16_LEN - i * 4 - 3],
-                      p[BT_OCTET16_LEN - i * 4 - 4]);
-  }
-#endif
-}
-
-/*******************************************************************************
- *
- * Function         padding
- *
- * Description      utility function to padding the given text to be a 128 bits
- *                  data. The parameter dest is input and output parameter, it
- *                  must point to a BT_OCTET16_LEN memory space; where include
- *                  length bytes valid data.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void padding(BT_OCTET16 dest, uint8_t length) {
-  uint8_t i, *p = dest;
-  /* original last block */
-  for (i = length; i < BT_OCTET16_LEN; i++)
-    p[BT_OCTET16_LEN - i - 1] = (i == length) ? 0x80 : 0;
-}
-/*******************************************************************************
- *
- * Function         leftshift_onebit
- *
- * Description      utility function to left shift one bit for a 128 bits value.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void leftshift_onebit(uint8_t* input, uint8_t* output) {
-  uint8_t i, overflow = 0, next_overflow = 0;
-  SMP_TRACE_EVENT("leftshift_onebit ");
-  /* input[0] is LSB */
-  for (i = 0; i < BT_OCTET16_LEN; i++) {
-    next_overflow = (input[i] & 0x80) ? 1 : 0;
-    output[i] = (input[i] << 1) | overflow;
-    overflow = next_overflow;
-  }
-  return;
-}
-/*******************************************************************************
- *
- * Function         cmac_aes_cleanup
- *
- * Description      clean up function for AES_CMAC algorithm.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void cmac_aes_cleanup(void) {
-  osi_free(cmac_cb.text);
-  memset(&cmac_cb, 0, sizeof(tCMAC_CB));
-}
-
-/*******************************************************************************
- *
- * Function         cmac_aes_k_calculate
- *
- * Description      This function is the calculation of block cipher using
- *                  AES-128.
- *
- * Returns          void
- *
- ******************************************************************************/
-static bool cmac_aes_k_calculate(BT_OCTET16 key, uint8_t* p_signature,
-                                 uint16_t tlen) {
-  tSMP_ENC output;
-  uint8_t i = 1, err = 0;
-  uint8_t x[16] = {0};
-  uint8_t* p_mac;
-
-  SMP_TRACE_EVENT("cmac_aes_k_calculate ");
-
-  while (i <= cmac_cb.round) {
-    smp_xor_128(&cmac_cb.text[(cmac_cb.round - i) * BT_OCTET16_LEN],
-                x); /* Mi' := Mi (+) X  */
-
-    if (!SMP_Encrypt(key, BT_OCTET16_LEN,
-                     &cmac_cb.text[(cmac_cb.round - i) * BT_OCTET16_LEN],
-                     BT_OCTET16_LEN, &output)) {
-      err = 1;
-      break;
-    }
-
-    memcpy(x, output.param_buf, BT_OCTET16_LEN);
-    i++;
-  }
-
-  if (!err) {
-    p_mac = output.param_buf + (BT_OCTET16_LEN - tlen);
-    memcpy(p_signature, p_mac, tlen);
-
-    SMP_TRACE_DEBUG("tlen = %d p_mac = %d", tlen, p_mac);
-    SMP_TRACE_DEBUG(
-        "p_mac[0] = 0x%02x p_mac[1] = 0x%02x p_mac[2] = 0x%02x p_mac[3] = "
-        "0x%02x",
-        *p_mac, *(p_mac + 1), *(p_mac + 2), *(p_mac + 3));
-    SMP_TRACE_DEBUG(
-        "p_mac[4] = 0x%02x p_mac[5] = 0x%02x p_mac[6] = 0x%02x p_mac[7] = "
-        "0x%02x",
-        *(p_mac + 4), *(p_mac + 5), *(p_mac + 6), *(p_mac + 7));
-
-    return true;
-
-  } else
-    return false;
-}
-/*******************************************************************************
- *
- * Function         cmac_prepare_last_block
- *
- * Description      This function proceeed to prepare the last block of message
- *                  Mn depending on the size of the message.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void cmac_prepare_last_block(BT_OCTET16 k1, BT_OCTET16 k2) {
-  //    uint8_t     x[16] = {0};
-  bool flag;
-
-  SMP_TRACE_EVENT("cmac_prepare_last_block ");
-  /* last block is a complete block set flag to 1 */
-  flag =
-      ((cmac_cb.len % BT_OCTET16_LEN) == 0 && cmac_cb.len != 0) ? true : false;
-
-  SMP_TRACE_WARNING("flag = %d round = %d", flag, cmac_cb.round);
-
-  if (flag) { /* last block is complete block */
-    smp_xor_128(&cmac_cb.text[0], k1);
-  } else /* padding then xor with k2 */
-  {
-    padding(&cmac_cb.text[0], (uint8_t)(cmac_cb.len % 16));
-
-    smp_xor_128(&cmac_cb.text[0], k2);
-  }
-}
-/*******************************************************************************
- *
- * Function         cmac_subkey_cont
- *
- * Description      This is the callback function when CIPHk(0[128]) is
- *                  completed.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void cmac_subkey_cont(tSMP_ENC* p) {
-  uint8_t k1[BT_OCTET16_LEN], k2[BT_OCTET16_LEN];
-  uint8_t* pp = p->param_buf;
-  SMP_TRACE_EVENT("cmac_subkey_cont ");
-  print128(pp, (const uint8_t*)"K1 before shift");
-
-  /* If MSB(L) = 0, then K1 = L << 1 */
-  if ((pp[BT_OCTET16_LEN - 1] & 0x80) != 0) {
-    /* Else K1 = ( L << 1 ) (+) Rb */
-    leftshift_onebit(pp, k1);
-    smp_xor_128(k1, const_Rb);
-  } else {
-    leftshift_onebit(pp, k1);
-  }
-
-  if ((k1[BT_OCTET16_LEN - 1] & 0x80) != 0) {
-    /* K2 =  (K1 << 1) (+) Rb */
-    leftshift_onebit(k1, k2);
-    smp_xor_128(k2, const_Rb);
-  } else {
-    /* If MSB(K1) = 0, then K2 = K1 << 1 */
-    leftshift_onebit(k1, k2);
-  }
-
-  print128(k1, (const uint8_t*)"K1");
-  print128(k2, (const uint8_t*)"K2");
-
-  cmac_prepare_last_block(k1, k2);
-}
-/*******************************************************************************
- *
- * Function         cmac_generate_subkey
- *
- * Description      This is the function to generate the two subkeys.
- *
- * Parameters       key - CMAC key, expect SRK when used by SMP.
- *
- * Returns          void
- *
- ******************************************************************************/
-static bool cmac_generate_subkey(BT_OCTET16 key) {
-  BT_OCTET16 z = {0};
-  bool ret = true;
-  tSMP_ENC output;
-  SMP_TRACE_EVENT(" cmac_generate_subkey");
-
-  if (SMP_Encrypt(key, BT_OCTET16_LEN, z, BT_OCTET16_LEN, &output)) {
-    cmac_subkey_cont(&output);
-    ;
-  } else
-    ret = false;
-
-  return ret;
-}
-/*******************************************************************************
- *
- * Function         aes_cipher_msg_auth_code
- *
- * Description      This is the AES-CMAC Generation Function with tlen
- *                  implemented.
- *
- * Parameters       key - CMAC key in little endian order, expect SRK when used
- *                        by SMP.
- *                  input - text to be signed in little endian byte order.
- *                  length - length of the input in byte.
- *                  tlen - lenth of mac desired
- *                  p_signature - data pointer to where signed data to be
- *                                stored, tlen long.
- *
- * Returns          false if out of resources, true in other cases.
- *
- ******************************************************************************/
-bool aes_cipher_msg_auth_code(BT_OCTET16 key, uint8_t* input, uint16_t length,
-                              uint16_t tlen, uint8_t* p_signature) {
-  uint16_t len, diff;
-  uint16_t n = (length + BT_OCTET16_LEN - 1) /
-               BT_OCTET16_LEN; /* n is number of rounds */
-  bool ret = false;
-
-  SMP_TRACE_EVENT("%s", __func__);
-
-  if (n == 0) n = 1;
-  len = n * BT_OCTET16_LEN;
-
-  SMP_TRACE_WARNING("AES128_CMAC started, allocate buffer size = %d", len);
-  /* allocate a memory space of multiple of 16 bytes to hold text  */
-  cmac_cb.text = (uint8_t*)osi_calloc(len);
-  cmac_cb.round = n;
-  diff = len - length;
-
-  if (input != NULL && length > 0) {
-    memcpy(&cmac_cb.text[diff], input, (int)length);
-    cmac_cb.len = length;
-  } else {
-    cmac_cb.len = 0;
-  }
-
-  /* prepare calculation for subkey s and last block of data */
-  if (cmac_generate_subkey(key)) {
-    /* start calculation */
-    ret = cmac_aes_k_calculate(key, p_signature, tlen);
-  }
-  /* clean up */
-  cmac_aes_cleanup();
-
-  return ret;
-}
diff --git a/stack/smp/smp_int.h b/stack/smp/smp_int.h
index 1685ffe..72fdf55 100644
--- a/stack/smp/smp_int.h
+++ b/stack/smp/smp_int.h
@@ -28,6 +28,7 @@
 #include "btm_ble_api.h"
 #include "btu.h"
 #include "smp_api.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
 
 /* Legacy mode */
 #define SMP_MODEL_ENCRYPTION_ONLY 0 /* Just Works model */
@@ -244,10 +245,6 @@
 /* check if authentication requirement need MITM protection */
 #define SMP_NO_MITM_REQUIRED(x) (((x)&SMP_AUTH_YN_BIT) == 0)
 
-#define SMP_ENCRYT_KEY_SIZE 16
-#define SMP_ENCRYT_DATA_SIZE 16
-#define SMP_ECNCRPYT_STATUS HCI_SUCCESS
-
 typedef struct {
   RawAddress bd_addr;
   BT_HDR* p_copy;
@@ -273,18 +270,18 @@
   uint8_t cb_evt;
   tSMP_SEC_LEVEL sec_level;
   bool connect_initialized;
-  BT_OCTET16 confirm;
-  BT_OCTET16 rconfirm;
-  BT_OCTET16 rrand; /* for SC this is peer nonce */
-  BT_OCTET16 rand;  /* for SC this is local nonce */
+  Octet16 confirm;
+  Octet16 rconfirm;
+  Octet16 rrand; /* for SC this is peer nonce */
+  Octet16 rand;  /* for SC this is local nonce */
   BT_OCTET32 private_key;
   BT_OCTET32 dhkey;
-  BT_OCTET16 commitment;
-  BT_OCTET16 remote_commitment;
-  BT_OCTET16 local_random; /* local randomizer - passkey or OOB randomizer */
-  BT_OCTET16 peer_random;  /* peer randomizer - passkey or OOB randomizer */
-  BT_OCTET16 dhkey_check;
-  BT_OCTET16 remote_dhkey_check;
+  Octet16 commitment;
+  Octet16 remote_commitment;
+  Octet16 local_random; /* local randomizer - passkey or OOB randomizer */
+  Octet16 peer_random;  /* peer randomizer - passkey or OOB randomizer */
+  Octet16 dhkey_check;
+  Octet16 remote_dhkey_check;
   tSMP_PUBLIC_KEY loc_publ_key;
   tSMP_PUBLIC_KEY peer_publ_key;
   tSMP_OOB_DATA_TYPE req_oob_type;
@@ -307,7 +304,7 @@
   uint8_t
       round; /* authentication stage 1 round for passkey association model */
   uint32_t number_to_display;
-  BT_OCTET16 mac_key;
+  Octet16 mac_key;
   uint8_t peer_enc_size;
   uint8_t loc_enc_size;
   uint8_t peer_i_key;
@@ -315,10 +312,10 @@
   uint8_t local_i_key;
   uint8_t local_r_key;
 
-  BT_OCTET16 tk;
-  BT_OCTET16 ltk;
+  Octet16 tk;
+  Octet16 ltk;
   uint16_t div;
-  BT_OCTET16 csrk; /* storage for local CSRK */
+  Octet16 csrk; /* storage for local CSRK */
   uint16_t ediv;
   BT_OCTET8 enc_rand;
   uint8_t addr_type;
@@ -345,29 +342,6 @@
 extern void smp_sm_event(tSMP_CB* p_cb, tSMP_EVENT event,
                          tSMP_INT_DATA* p_data);
 
-extern void smp_proc_sec_request(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
-extern void smp_set_fail_nc(bool enable);
-extern void smp_set_fail_conf(bool enable);
-extern void smp_set_passk_entry_fail(bool enable);
-extern void smp_set_oob_fail(bool enable);
-extern void smp_set_peer_sc_notif(bool enable);
-extern void smp_aes_cmac_rfc4493_chk(uint8_t* key, uint8_t* msg,
-                                     uint8_t msg_len, uint8_t mac_len,
-                                     uint8_t* mac);
-extern void smp_f4_calc_chk(uint8_t* U, uint8_t* V, uint8_t* X, uint8_t* Z,
-                            uint8_t* mac);
-extern void smp_g2_calc_chk(uint8_t* U, uint8_t* V, uint8_t* X, uint8_t* Y);
-extern void smp_h6_calc_chk(uint8_t* key, uint8_t* key_id, uint8_t* mac);
-extern void smp_f5_key_calc_chk(uint8_t* w, uint8_t* mac);
-extern void smp_f5_mackey_or_ltk_calc_chk(uint8_t* t, uint8_t* counter,
-                                          uint8_t* key_id, uint8_t* n1,
-                                          uint8_t* n2, uint8_t* a1, uint8_t* a2,
-                                          uint8_t* length, uint8_t* mac);
-extern void smp_f5_calc_chk(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* a1,
-                            uint8_t* a2, uint8_t* mac_key, uint8_t* ltk);
-extern void smp_f6_calc_chk(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* r,
-                            uint8_t* iocap, uint8_t* a1, uint8_t* a2,
-                            uint8_t* mac);
 extern tSMP_STATE smp_get_state(void);
 extern void smp_set_state(tSMP_STATE state);
 
@@ -419,7 +393,6 @@
 extern void smp_key_distribution(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_proc_srk_info(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_generate_csrk(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
-extern void smp_fast_conn_param(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_key_pick_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_both_have_public_keys(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_start_secure_connection_phase1(tSMP_CB* p_cb,
@@ -467,17 +440,17 @@
 extern void smp_data_ind(const RawAddress& bd_addr, BT_HDR* p_buf);
 
 /* smp_util.cc */
+extern void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing,
+                            const uint8_t* p_buf, size_t buf_len);
 extern bool smp_send_cmd(uint8_t cmd_code, tSMP_CB* p_cb);
 extern void smp_cb_cleanup(tSMP_CB* p_cb);
 extern void smp_reset_control_value(tSMP_CB* p_cb);
 extern void smp_proc_pairing_cmpl(tSMP_CB* p_cb);
-extern void smp_convert_string_to_tk(BT_OCTET16 tk, uint32_t passkey);
-extern void smp_mask_enc_key(uint8_t loc_enc_size, uint8_t* p_data);
+extern void smp_convert_string_to_tk(Octet16* tk, uint32_t passkey);
+extern void smp_mask_enc_key(uint8_t loc_enc_size, Octet16* p_data);
 extern void smp_rsp_timeout(void* data);
 extern void smp_delayed_auth_complete_timeout(void* data);
-extern void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b);
-extern bool smp_encrypt_data(uint8_t* key, uint8_t key_len, uint8_t* plain_text,
-                             uint8_t pt_len, tSMP_ENC* p_out);
+extern bool smp_command_has_invalid_length(tSMP_CB* p_cb);
 extern bool smp_command_has_invalid_parameters(tSMP_CB* p_cb);
 extern void smp_reject_unexpected_pairing_command(const RawAddress& bd_addr);
 extern tSMP_ASSO_MODEL smp_select_association_model(tSMP_CB* p_cb);
@@ -489,7 +462,7 @@
 extern void smp_collect_peer_ble_address(uint8_t* le_addr, tSMP_CB* p_cb);
 extern bool smp_check_commitment(tSMP_CB* p_cb);
 extern void smp_save_secure_connections_long_term_key(tSMP_CB* p_cb);
-extern bool smp_calculate_f5_mackey_and_long_term_key(tSMP_CB* p_cb);
+extern void smp_calculate_f5_mackey_and_long_term_key(tSMP_CB* p_cb);
 extern void smp_remove_fixed_channel(tSMP_CB* p_cb);
 extern bool smp_request_oob_data(tSMP_CB* p_cb);
 
@@ -505,7 +478,7 @@
 extern void smp_use_oob_private_key(tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_compute_dhkey(tSMP_CB* p_cb);
 extern void smp_calculate_local_commitment(tSMP_CB* p_cb);
-extern void smp_calculate_peer_commitment(tSMP_CB* p_cb, BT_OCTET16 output_buf);
+extern Octet16 smp_calculate_peer_commitment(tSMP_CB* p_cb);
 extern void smp_calculate_numeric_comparison_display_number(
     tSMP_CB* p_cb, tSMP_INT_DATA* p_data);
 extern void smp_calculate_local_dhkey_check(tSMP_CB* p_cb,
@@ -515,31 +488,21 @@
 extern void smp_start_nonce_generation(tSMP_CB* p_cb);
 extern bool smp_calculate_link_key_from_long_term_key(tSMP_CB* p_cb);
 extern bool smp_calculate_long_term_key_from_link_key(tSMP_CB* p_cb);
-extern void smp_calculate_f4(uint8_t* u, uint8_t* v, uint8_t* x, uint8_t z,
-                             uint8_t* c);
-extern uint32_t smp_calculate_g2(uint8_t* u, uint8_t* v, uint8_t* x,
-                                 uint8_t* y);
-extern bool smp_calculate_f5(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* a1,
-                             uint8_t* a2, uint8_t* mac_key, uint8_t* ltk);
-extern bool smp_calculate_f5_mackey_or_long_term_key(
-    uint8_t* t, uint8_t* counter, uint8_t* key_id, uint8_t* n1, uint8_t* n2,
-    uint8_t* a1, uint8_t* a2, uint8_t* length, uint8_t* mac);
-extern bool smp_calculate_f5_key(uint8_t* w, uint8_t* t);
-extern bool smp_calculate_f6(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* r,
-                             uint8_t* iocap, uint8_t* a1, uint8_t* a2,
-                             uint8_t* f3);
-extern bool smp_calculate_h6(uint8_t* w, uint8_t* keyid, uint8_t* h2);
-extern bool smp_calculate_h7(uint8_t* salt, uint8_t* w, uint8_t* h2);
+
 #if (SMP_DEBUG == TRUE)
 extern void smp_debug_print_nbyte_little_endian(uint8_t* p,
                                                 const char* key_name,
                                                 uint8_t len);
+
+inline void smp_debug_print_nbyte_little_endian(const Octet16& p,
+                                                const char* key_name,
+                                                uint8_t len) {
+  smp_debug_print_nbyte_little_endian(const_cast<uint8_t*>(p.data()), key_name,
+                                      len);
+}
 #endif
 
-/* smp_cmac.cc */
-extern bool aes_cipher_msg_auth_code(BT_OCTET16 key, uint8_t* input,
-                                     uint16_t length, uint16_t tlen,
-                                     uint8_t* p_signature);
-extern void print128(BT_OCTET16 x, const uint8_t* key_name);
+extern void print128(const Octet16& x, const uint8_t* key_name);
+extern void smp_xor_128(Octet16* a, const Octet16& b);
 
 #endif /* SMP_INT_H */
diff --git a/stack/smp/smp_keys.cc b/stack/smp/smp_keys.cc
index 6be1da4..da8d0f4 100644
--- a/stack/smp/smp_keys.cc
+++ b/stack/smp/smp_keys.cc
@@ -28,7 +28,6 @@
 #endif
 #include <base/bind.h>
 #include <string.h>
-#include "aes.h"
 #include "bt_utils.h"
 #include "btm_ble_api.h"
 #include "btm_ble_int.h"
@@ -38,16 +37,19 @@
 #include "osi/include/osi.h"
 #include "p_256_ecc_pp.h"
 #include "smp_int.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
+
+#include <algorithm>
 
 using base::Bind;
+using crypto_toolbox::aes_128;
 
 #ifndef SMP_MAX_ENC_REPEAT
 #define SMP_MAX_ENC_REPEAT 3
 #endif
 
-static void smp_process_stk(tSMP_CB* p_cb, tSMP_ENC* p);
-static bool smp_calculate_legacy_short_term_key(tSMP_CB* p_cb,
-                                                tSMP_ENC* output);
+static void smp_process_stk(tSMP_CB* p_cb, Octet16* p);
+static Octet16 smp_calculate_legacy_short_term_key(tSMP_CB* p_cb);
 static void smp_process_private_key(tSMP_CB* p_cb);
 
 #define SMP_PASSKEY_MASK 0xfff00000
@@ -75,6 +77,13 @@
 #endif
 }
 
+inline void smp_debug_print_nbyte_little_endian(const Octet16& p,
+                                                const char* key_name,
+                                                uint8_t len) {
+  smp_debug_print_nbyte_little_endian(const_cast<uint8_t*>(p.data()), key_name,
+                                      len);
+}
+
 void smp_debug_print_nbyte_big_endian(uint8_t* p, const char* key_name,
                                       uint8_t len) {
 #if (SMP_DEBUG == TRUE)
@@ -98,80 +107,9 @@
 #endif
 }
 
-/*******************************************************************************
- *
- * Function         smp_encrypt_data
- *
- * Description      This function is called to encrypt data.
- *                  It uses AES-128 encryption algorithm.
- *                  Plain_text is encrypted using key, the result is at p_out.
- *
- * Returns          void
- *
- ******************************************************************************/
-bool smp_encrypt_data(uint8_t* key, uint8_t key_len, uint8_t* plain_text,
-                      uint8_t pt_len, tSMP_ENC* p_out) {
-  aes_context ctx;
-  uint8_t* p_start = NULL;
-  uint8_t* p = NULL;
-  uint8_t* p_rev_data = NULL;   /* input data in big endilan format */
-  uint8_t* p_rev_key = NULL;    /* input key in big endilan format */
-  uint8_t* p_rev_output = NULL; /* encrypted output in big endilan format */
-
-  SMP_TRACE_DEBUG("%s", __func__);
-  if ((p_out == NULL) || (key_len != SMP_ENCRYT_KEY_SIZE)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    return false;
-  }
-
-  p_start = (uint8_t*)osi_calloc(SMP_ENCRYT_DATA_SIZE * 4);
-
-  if (pt_len > SMP_ENCRYT_DATA_SIZE) pt_len = SMP_ENCRYT_DATA_SIZE;
-
-  p = p_start;
-  ARRAY_TO_STREAM(p, plain_text, pt_len);          /* byte 0 to byte 15 */
-  p_rev_data = p = p_start + SMP_ENCRYT_DATA_SIZE; /* start at byte 16 */
-  REVERSE_ARRAY_TO_STREAM(p, p_start,
-                          SMP_ENCRYT_DATA_SIZE);        /* byte 16 to byte 31 */
-  p_rev_key = p;                                        /* start at byte 32 */
-  REVERSE_ARRAY_TO_STREAM(p, key, SMP_ENCRYT_KEY_SIZE); /* byte 32 to byte 47 */
-
-#if (SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE)
-  smp_debug_print_nbyte_little_endian(key, "Key", SMP_ENCRYT_KEY_SIZE);
-  smp_debug_print_nbyte_little_endian(p_start, "Plain text",
-                                      SMP_ENCRYT_DATA_SIZE);
-#endif
-  p_rev_output = p;
-  aes_set_key(p_rev_key, SMP_ENCRYT_KEY_SIZE, &ctx);
-  aes_encrypt(p_rev_data, p, &ctx); /* outputs in byte 48 to byte 63 */
-
-  p = p_out->param_buf;
-  REVERSE_ARRAY_TO_STREAM(p, p_rev_output, SMP_ENCRYT_DATA_SIZE);
-#if (SMP_DEBUG == TRUE && SMP_DEBUG_VERBOSE == TRUE)
-  smp_debug_print_nbyte_little_endian(p_out->param_buf, "Encrypted text",
-                                      SMP_ENCRYT_KEY_SIZE);
-#endif
-
-  p_out->param_len = SMP_ENCRYT_KEY_SIZE;
-  p_out->status = HCI_SUCCESS;
-  p_out->opcode = HCI_BLE_ENCRYPT;
-
-  osi_free(p_start);
-
-  return true;
-}
-
-/*******************************************************************************
- *
- * Function         smp_proc_passkey
- *
- * Description      This function is called to process a passkey.
- *
- * Returns          void
- *
- ******************************************************************************/
+/** This function is called to process a passkey. */
 void smp_proc_passkey(tSMP_CB* p_cb, BT_OCTET8 rand) {
-  uint8_t* tt = p_cb->tk;
+  uint8_t* tt = p_cb->tk.data();
   uint32_t passkey; /* 19655 test number; */
   uint8_t* pp = rand;
 
@@ -183,7 +121,7 @@
   while (passkey > BTM_MAX_PASSKEY_VAL) passkey >>= 1;
 
   /* save the TK */
-  memset(p_cb->tk, 0, BT_OCTET16_LEN);
+  p_cb->tk = {0};
   UINT32_TO_STREAM(tt, passkey);
 
   if (p_cb->p_callback) {
@@ -200,7 +138,7 @@
   } else {
     tSMP_KEY key;
     key.key_type = SMP_KEY_TYPE_TK;
-    key.p_data = p_cb->tk;
+    key.p_data = p_cb->tk.data();
     tSMP_INT_DATA smp_int_data;
     smp_int_data.key = key;
     smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
@@ -234,22 +172,15 @@
  *
  ******************************************************************************/
 void smp_generate_stk(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
-  tSMP_ENC output;
+  Octet16 output;
 
   SMP_TRACE_DEBUG("%s", __func__);
 
   if (p_cb->le_secure_connections_mode_is_used) {
     SMP_TRACE_WARNING("FOR LE SC LTK IS USED INSTEAD OF STK");
-    output.param_len = SMP_ENCRYT_KEY_SIZE;
-    output.status = HCI_SUCCESS;
-    output.opcode = HCI_BLE_ENCRYPT;
-    memcpy(output.param_buf, p_cb->ltk, SMP_ENCRYT_DATA_SIZE);
-  } else if (!smp_calculate_legacy_short_term_key(p_cb, &output)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    tSMP_INT_DATA smp_int_data;
-    smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
-    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
-    return;
+    output = p_cb->ltk;
+  } else {
+    output = smp_calculate_legacy_short_term_key(p_cb);
   }
 
   smp_process_stk(p_cb, &output);
@@ -259,33 +190,20 @@
  * This function is called to calculate CSRK
  */
 void smp_compute_csrk(uint16_t div, tSMP_CB* p_cb) {
-  BT_OCTET16 er;
   uint8_t buffer[4]; /* for (r || DIV)  r=1*/
   uint16_t r = 1;
   uint8_t* p = buffer;
-  tSMP_ENC output;
 
   p_cb->div = div;
 
   SMP_TRACE_DEBUG("%s: div=%x", __func__, p_cb->div);
-  BTM_GetDeviceEncRoot(er);
+  const Octet16& er = BTM_GetDeviceEncRoot();
   /* CSRK = d1(ER, DIV, 1) */
   UINT16_TO_STREAM(p, p_cb->div);
   UINT16_TO_STREAM(p, r);
 
-  if (!SMP_Encrypt(er, BT_OCTET16_LEN, buffer, 4, &output)) {
-    SMP_TRACE_ERROR("smp_generate_csrk failed");
-    tSMP_INT_DATA smp_int_data;
-    smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
-    if (p_cb->smp_over_br) {
-      smp_br_state_machine_event(p_cb, SMP_BR_AUTH_CMPL_EVT, &smp_int_data);
-    } else {
-      smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
-    }
-  } else {
-    memcpy((void*)p_cb->csrk, output.param_buf, BT_OCTET16_LEN);
-    smp_send_csrk_info(p_cb, NULL);
-  }
+  p_cb->csrk = aes_128(er, buffer, 4);
+  smp_send_csrk_info(p_cb, NULL);
 }
 
 /**
@@ -349,22 +267,16 @@
   *p_data = p;
 }
 
-/*******************************************************************************
- *
- * Function         smp_gen_p1_4_confirm
- *
- * Description      Generate Confirm/Compare Step1:
+/** Generate Confirm/Compare Step1:
  *                  p1 = (MSB) pres || preq || rat' || iat' (LSB)
  *                  Fill in values LSB first thus
  *                  p1 = iat' || rat' || preq || pres
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_gen_p1_4_confirm(tSMP_CB* p_cb, tBLE_ADDR_TYPE remote_bd_addr_type,
-                          BT_OCTET16 p1) {
+ */
+Octet16 smp_gen_p1_4_confirm(tSMP_CB* p_cb,
+                             tBLE_ADDR_TYPE remote_bd_addr_type) {
   SMP_TRACE_DEBUG("%s", __func__);
-  uint8_t* p = (uint8_t*)p1;
+  Octet16 p1;
+  uint8_t* p = p1.data();
   if (p_cb->role == HCI_ROLE_MASTER) {
     /* iat': initiator's (local) address type */
     UINT8_TO_STREAM(p, p_cb->addr_type);
@@ -384,28 +296,23 @@
     /* pres : Pairing Response (local) command */
     smp_concatenate_local(p_cb, &p, SMP_OPCODE_PAIRING_RSP);
   }
-  smp_debug_print_nbyte_little_endian((uint8_t*)p1,
-                                      "p1 = iat' || rat' || preq || pres", 16);
+  smp_debug_print_nbyte_little_endian(p1, "p1 = iat' || rat' || preq || pres",
+                                      16);
+
+  return p1;
 }
 
-/*******************************************************************************
- *
- * Function         smp_gen_p2_4_confirm
- *
- * Description      Generate Confirm/Compare Step2:
+/** Generate Confirm/Compare Step2:
  *                  p2 = (MSB) padding || ia || ra (LSB)
  *                  Fill values LSB first and thus:
  *                  p2 = ra || ia || padding
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_gen_p2_4_confirm(tSMP_CB* p_cb, const RawAddress& remote_bda,
-                          BT_OCTET16 p2) {
+ */
+Octet16 smp_gen_p2_4_confirm(tSMP_CB* p_cb, const RawAddress& remote_bda) {
   SMP_TRACE_DEBUG("%s", __func__);
-  uint8_t* p = (uint8_t*)p2;
+  Octet16 p2{0};
+  uint8_t* p = p2.data();
   /* 32-bit Padding */
-  memset(p, 0, sizeof(BT_OCTET16));
+  memset(p, 0, OCTET16_LEN);
   if (p_cb->role == HCI_ROLE_MASTER) {
     /* ra : Responder's (remote) address */
     BDADDR_TO_STREAM(p, remote_bda);
@@ -418,6 +325,7 @@
     BDADDR_TO_STREAM(p, remote_bda);
   }
   smp_debug_print_nbyte_little_endian(p2, "p2 = ra || ia || padding", 16);
+  return p2;
 }
 
 /*******************************************************************************
@@ -429,8 +337,8 @@
  * Returns          tSMP_STATUS status of confirmation calculation
  *
  ******************************************************************************/
-tSMP_STATUS smp_calculate_comfirm(tSMP_CB* p_cb, BT_OCTET16 rand,
-                                  tSMP_ENC* output) {
+tSMP_STATUS smp_calculate_comfirm(tSMP_CB* p_cb, const Octet16& rand,
+                                  Octet16* output) {
   SMP_TRACE_DEBUG("%s", __func__);
   RawAddress remote_bda;
   tBLE_ADDR_TYPE remote_bd_addr_type = 0;
@@ -443,31 +351,21 @@
   /* get local connection specific bluetooth address */
   BTM_ReadConnectionAddr(p_cb->pairing_bda, p_cb->local_bda, &p_cb->addr_type);
   /* generate p1 = pres || preq || rat' || iat' */
-  BT_OCTET16 p1;
-  smp_gen_p1_4_confirm(p_cb, remote_bd_addr_type, p1);
+  Octet16 p1 = smp_gen_p1_4_confirm(p_cb, remote_bd_addr_type);
   /* p1' = rand XOR p1 */
-  smp_xor_128(p1, rand);
-  smp_debug_print_nbyte_little_endian((uint8_t*)p1, "p1' = p1 XOR r", 16);
+  smp_xor_128(&p1, rand);
+  smp_debug_print_nbyte_little_endian(p1, "p1' = p1 XOR r", 16);
   /* calculate e1 = e(k, p1'), where k = TK */
-  smp_debug_print_nbyte_little_endian(p_cb->tk, "TK", 16);
-  memset(output, 0, sizeof(tSMP_ENC));
-  if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p1, BT_OCTET16_LEN, output)) {
-    SMP_TRACE_ERROR("%s: failed encryption at e1 = e(k, p1')");
-    return SMP_PAIR_FAIL_UNKNOWN;
-  }
-  smp_debug_print_nbyte_little_endian(output->param_buf, "e1 = e(k, p1')", 16);
+  smp_debug_print_nbyte_little_endian(p_cb->tk.data(), "TK", 16);
+  Octet16 e1 = aes_128(p_cb->tk, p1);
+  smp_debug_print_nbyte_little_endian(e1.data(), "e1 = e(k, p1')", 16);
   /* generate p2 = padding || ia || ra */
-  BT_OCTET16 p2;
-  smp_gen_p2_4_confirm(p_cb, remote_bda, p2);
+  Octet16 p2 = smp_gen_p2_4_confirm(p_cb, remote_bda);
   /* calculate p2' = (p2 XOR e1) */
-  smp_xor_128(p2, output->param_buf);
-  smp_debug_print_nbyte_little_endian((uint8_t*)p2, "p2' = p2 XOR e1", 16);
+  smp_xor_128(&p2, e1);
+  smp_debug_print_nbyte_little_endian(p2, "p2' = p2 XOR e1", 16);
   /* calculate: c1 = e(k, p2') */
-  memset(output, 0, sizeof(tSMP_ENC));
-  if (!SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, p2, BT_OCTET16_LEN, output)) {
-    SMP_TRACE_ERROR("%s: failed encryption at e1 = e(k, p2')");
-    return SMP_PAIR_FAIL_UNKNOWN;
-  }
+  *output = aes_128(p_cb->tk, p2);
   return SMP_SUCCESS;
 }
 
@@ -484,8 +382,8 @@
  ******************************************************************************/
 static void smp_generate_confirm(tSMP_CB* p_cb) {
   SMP_TRACE_DEBUG("%s", __func__);
-  smp_debug_print_nbyte_little_endian((uint8_t*)p_cb->rand, "local_rand", 16);
-  tSMP_ENC output;
+  smp_debug_print_nbyte_little_endian(p_cb->rand.data(), "local_rand", 16);
+  Octet16 output;
   tSMP_STATUS status = smp_calculate_comfirm(p_cb, p_cb->rand, &output);
   if (status != SMP_SUCCESS) {
     tSMP_INT_DATA smp_int_data;
@@ -494,11 +392,11 @@
     return;
   }
   tSMP_KEY key;
-  memcpy(p_cb->confirm, output.param_buf, BT_OCTET16_LEN);
+  p_cb->confirm = output;
   smp_debug_print_nbyte_little_endian(p_cb->confirm, "Local Confirm generated",
                                       16);
   key.key_type = SMP_KEY_TYPE_CFM;
-  key.p_data = output.param_buf;
+  key.p_data = output.data();
   tSMP_INT_DATA smp_int_data;
   smp_int_data.key = key;
   smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
@@ -521,7 +419,7 @@
   /* generate MRand or SRand */
   btsnd_hcic_ble_rand(Bind(
       [](tSMP_CB* p_cb, BT_OCTET8 rand) {
-        memcpy((void*)p_cb->rand, rand, 8);
+        memcpy(p_cb->rand.data(), rand, 8);
 
         /* generate 64 MSB of MRand or SRand */
         btsnd_hcic_ble_rand(Bind(
@@ -548,8 +446,8 @@
  ******************************************************************************/
 void smp_generate_compare(tSMP_CB* p_cb, UNUSED_ATTR tSMP_INT_DATA* p_data) {
   SMP_TRACE_DEBUG("smp_generate_compare ");
-  smp_debug_print_nbyte_little_endian((uint8_t*)p_cb->rrand, "peer rand", 16);
-  tSMP_ENC output;
+  smp_debug_print_nbyte_little_endian(p_cb->rrand, "peer rand", 16);
+  Octet16 output;
   tSMP_STATUS status = smp_calculate_comfirm(p_cb, p_cb->rrand, &output);
   if (status != SMP_SUCCESS) {
     tSMP_INT_DATA smp_int_data;
@@ -558,48 +456,38 @@
     return;
   }
   tSMP_KEY key;
-  smp_debug_print_nbyte_little_endian(output.param_buf,
-                                      "Remote Confirm generated", 16);
+  smp_debug_print_nbyte_little_endian(output.data(), "Remote Confirm generated",
+                                      16);
   key.key_type = SMP_KEY_TYPE_CMP;
-  key.p_data = output.param_buf;
+  key.p_data = output.data();
   tSMP_INT_DATA smp_int_data;
   smp_int_data.key = key;
   smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
 }
 
-/*******************************************************************************
- *
- * Function         smp_process_stk
- *
- * Description      This function is called when STK is generated
- *                  proceed to send the encrypt the link using STK.
- *
- * Returns          void
- *
- ******************************************************************************/
-static void smp_process_stk(tSMP_CB* p_cb, tSMP_ENC* p) {
+/** This function is called when STK is generated proceed to send the encrypt
+ * the link using STK. */
+static void smp_process_stk(tSMP_CB* p_cb, Octet16* p) {
   tSMP_KEY key;
 
   SMP_TRACE_DEBUG("smp_process_stk ");
 #if (SMP_DEBUG == TRUE)
   SMP_TRACE_ERROR("STK Generated");
 #endif
-  smp_mask_enc_key(p_cb->loc_enc_size, p->param_buf);
+  smp_mask_enc_key(p_cb->loc_enc_size, p);
 
   key.key_type = SMP_KEY_TYPE_STK;
-  key.p_data = p->param_buf;
+  key.p_data = p->data();
 
   tSMP_INT_DATA smp_int_data;
   smp_int_data.key = key;
   smp_sm_event(p_cb, SMP_KEY_READY_EVT, &smp_int_data);
 }
 
-/**
- * This function is to calculate EDIV = Y xor DIV
- */
-static void smp_process_ediv(tSMP_CB* p_cb, tSMP_ENC* p) {
+/** This function calculates EDIV = Y xor DIV */
+static void smp_process_ediv(tSMP_CB* p_cb, Octet16& p) {
   tSMP_KEY key;
-  uint8_t* pp = p->param_buf;
+  uint8_t* pp = p.data();
   uint16_t y;
 
   SMP_TRACE_DEBUG("smp_process_ediv ");
@@ -610,7 +498,7 @@
   /* send LTK ready */
   SMP_TRACE_ERROR("LTK ready");
   key.key_type = SMP_KEY_TYPE_LTK;
-  key.p_data = p->param_buf;
+  key.p_data = p.data();
 
   tSMP_INT_DATA smp_int_data;
   smp_int_data.key = key;
@@ -623,19 +511,11 @@
 static void smp_generate_y(tSMP_CB* p_cb, BT_OCTET8 rand) {
   SMP_TRACE_DEBUG("%s ", __func__);
 
-  BT_OCTET16 dhk;
-  BTM_GetDeviceDHK(dhk);
+  const Octet16& dhk = BTM_GetDeviceDHK();
 
   memcpy(p_cb->enc_rand, rand, BT_OCTET8_LEN);
-  tSMP_ENC output;
-  if (!SMP_Encrypt(dhk, BT_OCTET16_LEN, rand, BT_OCTET8_LEN, &output)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    tSMP_INT_DATA smp_int_data;
-    smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
-    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
-  } else {
-    smp_process_ediv(p_cb, &output);
-  }
+  Octet16 output = aes_128(dhk, rand, BT_OCTET8_LEN);
+  smp_process_ediv(p_cb, output);
 }
 
 /**
@@ -645,25 +525,16 @@
   p_cb->div = div;
 
   SMP_TRACE_DEBUG("%s", __func__);
-  BT_OCTET16 er;
-  BTM_GetDeviceEncRoot(er);
+  const Octet16& er = BTM_GetDeviceEncRoot();
 
-  tSMP_ENC output;
   /* LTK = d1(ER, DIV, 0)= e(ER, DIV)*/
-  if (!SMP_Encrypt(er, BT_OCTET16_LEN, (uint8_t*)&p_cb->div, sizeof(uint16_t),
-                   &output)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    tSMP_INT_DATA smp_int_data;
-    smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
-    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
-  } else {
-    /* mask the LTK */
-    smp_mask_enc_key(p_cb->loc_enc_size, output.param_buf);
-    memcpy((void*)p_cb->ltk, output.param_buf, BT_OCTET16_LEN);
+  Octet16 ltk = aes_128(er, (uint8_t*)&p_cb->div, sizeof(uint16_t));
+  /* mask the LTK */
+  smp_mask_enc_key(p_cb->loc_enc_size, &ltk);
+  p_cb->ltk = ltk;
 
-    /* generate EDIV and rand now */
-    btsnd_hcic_ble_rand(Bind(&smp_generate_y, p_cb));
-  }
+  /* generate EDIV and rand now */
+  btsnd_hcic_ble_rand(Bind(&smp_generate_y, p_cb));
 }
 
 /*******************************************************************************
@@ -710,36 +581,21 @@
   }
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_legacy_short_term_key
- *
- * Description      The function calculates legacy STK.
- *
- * Returns          false if out of resources, true in other cases.
- *
- ******************************************************************************/
-bool smp_calculate_legacy_short_term_key(tSMP_CB* p_cb, tSMP_ENC* output) {
+/* The function calculates legacy STK */
+Octet16 smp_calculate_legacy_short_term_key(tSMP_CB* p_cb) {
   SMP_TRACE_DEBUG("%s", __func__);
 
-  BT_OCTET16 ptext;
-  uint8_t* p = ptext;
-  memset(p, 0, BT_OCTET16_LEN);
+  Octet16 text{0};
   if (p_cb->role == HCI_ROLE_MASTER) {
-    memcpy(p, p_cb->rand, BT_OCTET8_LEN);
-    memcpy(&p[BT_OCTET8_LEN], p_cb->rrand, BT_OCTET8_LEN);
+    memcpy(text.data(), p_cb->rand.data(), BT_OCTET8_LEN);
+    memcpy(text.data() + BT_OCTET8_LEN, p_cb->rrand.data(), BT_OCTET8_LEN);
   } else {
-    memcpy(p, p_cb->rrand, BT_OCTET8_LEN);
-    memcpy(&p[BT_OCTET8_LEN], p_cb->rand, BT_OCTET8_LEN);
+    memcpy(text.data(), p_cb->rrand.data(), BT_OCTET8_LEN);
+    memcpy(text.data() + BT_OCTET8_LEN, p_cb->rand.data(), BT_OCTET8_LEN);
   }
 
   /* generate STK = Etk(rand|rrand)*/
-  bool encrypted =
-      SMP_Encrypt(p_cb->tk, BT_OCTET16_LEN, ptext, BT_OCTET16_LEN, output);
-  if (!encrypted) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-  }
-  return encrypted;
+  return aes_128(p_cb->tk, text);
 }
 
 /*******************************************************************************
@@ -889,15 +745,7 @@
                                       BT_OCTET32_LEN);
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_local_commitment
- *
- * Description      The function calculates and saves local commmitment in CB.
- *
- * Returns          void
- *
- ******************************************************************************/
+/** The function calculates and saves local commmitment in CB. */
 void smp_calculate_local_commitment(tSMP_CB* p_cb) {
   uint8_t random_input;
 
@@ -910,21 +758,22 @@
         SMP_TRACE_WARNING(
             "local commitment calc on master is not expected "
             "for Just Works/Numeric Comparison models");
-      smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand,
-                       0, p_cb->commitment);
+      p_cb->commitment = crypto_toolbox::f4(
+          p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand, 0);
       break;
     case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
     case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
       random_input =
-          smp_calculate_random_input(p_cb->local_random, p_cb->round);
-      smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand,
-                       random_input, p_cb->commitment);
+          smp_calculate_random_input(p_cb->local_random.data(), p_cb->round);
+      p_cb->commitment =
+          crypto_toolbox::f4(p_cb->loc_publ_key.x, p_cb->peer_publ_key.x,
+                             p_cb->rand, random_input);
       break;
     case SMP_MODEL_SEC_CONN_OOB:
       SMP_TRACE_WARNING(
           "local commitment calc is expected for OOB model BEFORE pairing");
-      smp_calculate_f4(p_cb->loc_publ_key.x, p_cb->loc_publ_key.x,
-                       p_cb->local_random, 0, p_cb->commitment);
+      p_cb->commitment = crypto_toolbox::f4(
+          p_cb->loc_publ_key.x, p_cb->loc_publ_key.x, p_cb->local_random, 0);
       break;
     default:
       SMP_TRACE_ERROR("Association Model = %d is not used in LE SC",
@@ -935,21 +784,12 @@
   SMP_TRACE_EVENT("local commitment calculation is completed");
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_peer_commitment
- *
- * Description      The function calculates and saves peer commmitment at the
- *                  provided output buffer.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_calculate_peer_commitment(tSMP_CB* p_cb, BT_OCTET16 output_buf) {
+/** The function calculates peer commmitment */
+Octet16 smp_calculate_peer_commitment(tSMP_CB* p_cb) {
   uint8_t ri;
 
   SMP_TRACE_DEBUG("%s", __func__);
-
+  Octet16 output;
   switch (p_cb->selected_association_model) {
     case SMP_MODEL_SEC_CONN_JUSTWORKS:
     case SMP_MODEL_SEC_CONN_NUM_COMP:
@@ -957,97 +797,27 @@
         SMP_TRACE_WARNING(
             "peer commitment calc on slave is not expected "
             "for Just Works/Numeric Comparison models");
-      smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand,
-                       0, output_buf);
+      output = crypto_toolbox::f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x,
+                                  p_cb->rrand, 0);
       break;
     case SMP_MODEL_SEC_CONN_PASSKEY_ENT:
     case SMP_MODEL_SEC_CONN_PASSKEY_DISP:
-      ri = smp_calculate_random_input(p_cb->peer_random, p_cb->round);
-      smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand,
-                       ri, output_buf);
+      ri = smp_calculate_random_input(p_cb->peer_random.data(), p_cb->round);
+      output = crypto_toolbox::f4(p_cb->peer_publ_key.x, p_cb->loc_publ_key.x,
+                                  p_cb->rrand, ri);
       break;
     case SMP_MODEL_SEC_CONN_OOB:
-      smp_calculate_f4(p_cb->peer_publ_key.x, p_cb->peer_publ_key.x,
-                       p_cb->peer_random, 0, output_buf);
+      output = crypto_toolbox::f4(p_cb->peer_publ_key.x, p_cb->peer_publ_key.x,
+                                  p_cb->peer_random, 0);
       break;
     default:
       SMP_TRACE_ERROR("Association Model = %d is not used in LE SC",
                       p_cb->selected_association_model);
-      return;
+      return output;
   }
 
   SMP_TRACE_EVENT("peer commitment calculation is completed");
-}
-
-/*******************************************************************************
- *
- * Function         smp_calculate_f4
- *
- * Description      The function calculates
- *                  C = f4(U, V, X, Z) = AES-CMAC (U||V||Z)
- *                                               X
- *                  where
- *                  input:  U is 256 bit,
- *                          V is 256 bit,
- *                          X is 128 bit,
- *                          Z is 8 bit,
- *                  output: C is 128 bit.
- *
- * Returns          void
- *
- * Note             The LSB is the first octet, the MSB is the last octet of
- *                  the AES-CMAC input/output stream.
- *
- ******************************************************************************/
-void smp_calculate_f4(uint8_t* u, uint8_t* v, uint8_t* x, uint8_t z,
-                      uint8_t* c) {
-  uint8_t msg_len = BT_OCTET32_LEN /* U size */ + BT_OCTET32_LEN /* V size */ +
-                    1 /* Z size */;
-  uint8_t msg[BT_OCTET32_LEN + BT_OCTET32_LEN + 1];
-  uint8_t key[BT_OCTET16_LEN];
-  uint8_t cmac[BT_OCTET16_LEN];
-  uint8_t* p = NULL;
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_prnt = NULL;
-#endif
-
-  SMP_TRACE_DEBUG("%s", __func__);
-
-#if (SMP_DEBUG == TRUE)
-  p_prnt = u;
-  smp_debug_print_nbyte_little_endian(p_prnt, "U", BT_OCTET32_LEN);
-  p_prnt = v;
-  smp_debug_print_nbyte_little_endian(p_prnt, "V", BT_OCTET32_LEN);
-  p_prnt = x;
-  smp_debug_print_nbyte_little_endian(p_prnt, "X", BT_OCTET16_LEN);
-  p_prnt = &z;
-  smp_debug_print_nbyte_little_endian(p_prnt, "Z", 1);
-#endif
-
-  p = msg;
-  UINT8_TO_STREAM(p, z);
-  ARRAY_TO_STREAM(p, v, BT_OCTET32_LEN);
-  ARRAY_TO_STREAM(p, u, BT_OCTET32_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = msg;
-  smp_debug_print_nbyte_little_endian(p_prnt, "M", msg_len);
-#endif
-
-  p = key;
-  ARRAY_TO_STREAM(p, x, BT_OCTET16_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = key;
-  smp_debug_print_nbyte_little_endian(p_prnt, "K", BT_OCTET16_LEN);
-#endif
-
-  aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = cmac;
-  smp_debug_print_nbyte_little_endian(p_prnt, "AES_CMAC", BT_OCTET16_LEN);
-#endif
-
-  p = c;
-  ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
+  return output;
 }
 
 /*******************************************************************************
@@ -1065,10 +835,10 @@
   SMP_TRACE_DEBUG("%s", __func__);
 
   if (p_cb->role == HCI_ROLE_MASTER) {
-    p_cb->number_to_display = smp_calculate_g2(
+    p_cb->number_to_display = crypto_toolbox::g2(
         p_cb->loc_publ_key.x, p_cb->peer_publ_key.x, p_cb->rand, p_cb->rrand);
   } else {
-    p_cb->number_to_display = smp_calculate_g2(
+    p_cb->number_to_display = crypto_toolbox::g2(
         p_cb->peer_publ_key.x, p_cb->loc_publ_key.x, p_cb->rrand, p_cb->rand);
   }
 
@@ -1089,398 +859,6 @@
   return;
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_g2
- *
- * Description      The function calculates
- *                  g2(U, V, X, Y) = AES-CMAC (U||V||Y) mod 2**32 mod 10**6
- *                                           X
- *                  and
- *                  Vres = g2(U, V, X, Y) mod 10**6
- *                  where
- *                  input:  U     is 256 bit,
- *                          V     is 256 bit,
- *                          X     is 128 bit,
- *                          Y     is 128 bit,
- *
- * Returns          Vres.
- *                  Expected value has to be in the range [0 - 999999] i.e.
- *                        [0 - 0xF423F].
- *                  Vres = 1000000 means that the calculation fails.
- *
- * Note             The LSB is the first octet, the MSB is the last octet of
- *                  the AES-CMAC input/output stream.
- *
- ******************************************************************************/
-uint32_t smp_calculate_g2(uint8_t* u, uint8_t* v, uint8_t* x, uint8_t* y) {
-  uint8_t msg_len = BT_OCTET32_LEN /* U size */ + BT_OCTET32_LEN /* V size */
-                    + BT_OCTET16_LEN /* Y size */;
-  uint8_t msg[BT_OCTET32_LEN + BT_OCTET32_LEN + BT_OCTET16_LEN];
-  uint8_t key[BT_OCTET16_LEN];
-  uint8_t cmac[BT_OCTET16_LEN];
-  uint8_t* p = NULL;
-  uint32_t vres;
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_prnt = NULL;
-#endif
-
-  SMP_TRACE_DEBUG("%s", __func__);
-
-  p = msg;
-  ARRAY_TO_STREAM(p, y, BT_OCTET16_LEN);
-  ARRAY_TO_STREAM(p, v, BT_OCTET32_LEN);
-  ARRAY_TO_STREAM(p, u, BT_OCTET32_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = u;
-  smp_debug_print_nbyte_little_endian(p_prnt, "U", BT_OCTET32_LEN);
-  p_prnt = v;
-  smp_debug_print_nbyte_little_endian(p_prnt, "V", BT_OCTET32_LEN);
-  p_prnt = x;
-  smp_debug_print_nbyte_little_endian(p_prnt, "X", BT_OCTET16_LEN);
-  p_prnt = y;
-  smp_debug_print_nbyte_little_endian(p_prnt, "Y", BT_OCTET16_LEN);
-#endif
-
-  p = key;
-  ARRAY_TO_STREAM(p, x, BT_OCTET16_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = key;
-  smp_debug_print_nbyte_little_endian(p_prnt, "K", BT_OCTET16_LEN);
-#endif
-
-  if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    return (BTM_MAX_PASSKEY_VAL + 1);
-  }
-
-#if (SMP_DEBUG == TRUE)
-  p_prnt = cmac;
-  smp_debug_print_nbyte_little_endian(p_prnt, "AES-CMAC", BT_OCTET16_LEN);
-#endif
-
-  /* vres = cmac mod 2**32 mod 10**6 */
-  p = &cmac[0];
-  STREAM_TO_UINT32(vres, p);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = (uint8_t*)&vres;
-  smp_debug_print_nbyte_little_endian(p_prnt, "cmac mod 2**32", 4);
-#endif
-
-  while (vres > BTM_MAX_PASSKEY_VAL) vres -= (BTM_MAX_PASSKEY_VAL + 1);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = (uint8_t*)&vres;
-  smp_debug_print_nbyte_little_endian(p_prnt, "cmac mod 2**32 mod 10**6", 4);
-#endif
-
-  SMP_TRACE_ERROR("Value for numeric comparison = %d", vres);
-  return vres;
-}
-
-/*******************************************************************************
- *
- * Function         smp_calculate_f5
- *
- * Description      The function provides two AES-CMAC that are supposed to be
- *                    used as
- *                  - MacKey (used in pairing DHKey check calculation);
- *                  - LTK (used to ecrypt the link after completion of Phase 2
- *                    and on reconnection, to derive BR/EDR LK).
- *                  The function inputs are W, N1, N2, A1, A2.
- *                  F5 rules:
- *                  - the value used as key in MacKey/LTK (T) is calculated
- *                    (function smp_calculate_f5_key(...));
- *                    The formula is:
- *                          T = AES-CMAC    (W)
- *                                      salt
- *                    where salt is internal parameter of
- *                    smp_calculate_f5_key(...).
- *                  - MacKey and LTK are calculated as AES-MAC values received
- *                    with the key T calculated in the previous step and the
- *                    plaintext message built from the external parameters N1,
- *                    N2, A1, A2 and the internal parameters counter, keyID,
- *                    length.
- *                    The function smp_calculate_f5_mackey_or_long_term_key(...)
- *                    is used in the calculations.
- *                    The same formula is used in calculation of MacKey and LTK
- *                    and the same parameter values except the value of the
- *                    internal parameter counter:
- *                    - in MacKey calculations the value is 0;
- *                    - in LTK calculations the value is 1.
- *                      MacKey  =
- *                       AES-CMAC (Counter=0||keyID||N1||N2||A1||A2||Length=256)
- *                               T
- *                      LTK     =
- *                       AES-CMAC (Counter=1||keyID||N1||N2||A1||A2||Length=256)
- *                               T
- *                  The parameters are
- *                  input:
- *                          W       is 256 bits,
- *                          N1      is 128 bits,
- *                          N2      is 128 bits,
- *                          A1 is 56 bit,
- *                          A2 is 56 bit.
- *                  internal:
- *                          Counter is 8 bits,  its value is 0 for MacKey,
- *                                                          1 for LTK;
- *                          KeyId   is 32 bits, its value is
- *                                              0x62746c65 (MSB~LSB);
- *                          Length  is 16 bits, its value is 0x0100
- *                                              (MSB~LSB).
- *                  output:
- *                          MacKey  is 128 bits;
- *                          LTK     is 128 bits
- *
- * 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.
- *
- ******************************************************************************/
-bool smp_calculate_f5(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* a1,
-                      uint8_t* a2, uint8_t* mac_key, uint8_t* ltk) {
-  BT_OCTET16 t; /* AES-CMAC output in smp_calculate_f5_key(...), key in */
-                /* smp_calculate_f5_mackey_or_long_term_key(...) */
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_prnt = NULL;
-#endif
-  /* internal parameters: */
-
-  /*
-      counter is 0 for MacKey,
-              is 1 for LTK
-  */
-  uint8_t counter_mac_key[1] = {0};
-  uint8_t counter_ltk[1] = {1};
-  /*
-      keyID   62746c65
-  */
-  uint8_t key_id[4] = {0x65, 0x6c, 0x74, 0x62};
-  /*
-      length  0100
-  */
-  uint8_t length[2] = {0x00, 0x01};
-
-  SMP_TRACE_DEBUG("%s", __func__);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = w;
-  smp_debug_print_nbyte_little_endian(p_prnt, "W", BT_OCTET32_LEN);
-  p_prnt = n1;
-  smp_debug_print_nbyte_little_endian(p_prnt, "N1", BT_OCTET16_LEN);
-  p_prnt = n2;
-  smp_debug_print_nbyte_little_endian(p_prnt, "N2", BT_OCTET16_LEN);
-  p_prnt = a1;
-  smp_debug_print_nbyte_little_endian(p_prnt, "A1", 7);
-  p_prnt = a2;
-  smp_debug_print_nbyte_little_endian(p_prnt, "A2", 7);
-#endif
-
-  if (!smp_calculate_f5_key(w, t)) {
-    SMP_TRACE_ERROR("%s failed to calc T", __func__);
-    return false;
-  }
-#if (SMP_DEBUG == TRUE)
-  p_prnt = t;
-  smp_debug_print_nbyte_little_endian(p_prnt, "T", BT_OCTET16_LEN);
-#endif
-
-  if (!smp_calculate_f5_mackey_or_long_term_key(t, counter_mac_key, key_id, n1,
-                                                n2, a1, a2, length, mac_key)) {
-    SMP_TRACE_ERROR("%s failed to calc MacKey", __func__);
-    return false;
-  }
-#if (SMP_DEBUG == TRUE)
-  p_prnt = mac_key;
-  smp_debug_print_nbyte_little_endian(p_prnt, "MacKey", BT_OCTET16_LEN);
-#endif
-
-  if (!smp_calculate_f5_mackey_or_long_term_key(t, counter_ltk, key_id, n1, n2,
-                                                a1, a2, length, ltk)) {
-    SMP_TRACE_ERROR("%s failed to calc LTK", __func__);
-    return false;
-  }
-#if (SMP_DEBUG == TRUE)
-  p_prnt = ltk;
-  smp_debug_print_nbyte_little_endian(p_prnt, "LTK", BT_OCTET16_LEN);
-#endif
-
-  return true;
-}
-
-/*******************************************************************************
- *
- * Function         smp_calculate_f5_mackey_or_long_term_key
- *
- * Description      The function calculates the value of MacKey or LTK by the
- *                  rules defined for f5 function.
- *                  At the moment exactly the same formula is used to calculate
- *                  LTK and MacKey.
- *                  The difference is the value of input parameter Counter:
- *                  - in MacKey calculations the value is 0;
- *                  - in LTK calculations the value is 1.
- *                  The formula:
- *                  mac = AES-CMAC (Counter||keyID||N1||N2||A1||A2||Length)
- *                                T
- *                  where
- *                  input:      T       is 256 bits;
- *                              Counter is 8 bits, its value is 0 for MacKey,
- *                                                              1 for LTK;
- *                              keyID   is 32 bits, its value is 0x62746c65;
- *                              N1      is 128 bits;
- *                              N2      is 128 bits;
- *                              A1      is 56 bits;
- *                              A2      is 56 bits;
- *                              Length  is 16 bits, its value is 0x0100
- *                  output:     LTK     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.
- *
- ******************************************************************************/
-bool smp_calculate_f5_mackey_or_long_term_key(uint8_t* t, uint8_t* counter,
-                                              uint8_t* key_id, uint8_t* n1,
-                                              uint8_t* n2, uint8_t* a1,
-                                              uint8_t* a2, uint8_t* length,
-                                              uint8_t* mac) {
-  uint8_t* p = NULL;
-  uint8_t cmac[BT_OCTET16_LEN];
-  uint8_t key[BT_OCTET16_LEN];
-  uint8_t msg_len = 1 /* Counter size */ + 4 /* keyID size */ +
-                    BT_OCTET16_LEN /* N1 size */ +
-                    BT_OCTET16_LEN /* N2 size */ + 7 /* A1 size*/ +
-                    7 /* A2 size*/ + 2 /* Length size */;
-  uint8_t msg[1 + 4 + BT_OCTET16_LEN + BT_OCTET16_LEN + 7 + 7 + 2];
-  bool ret = true;
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_prnt = NULL;
-#endif
-
-  SMP_TRACE_DEBUG("%s", __func__);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = t;
-  smp_debug_print_nbyte_little_endian(p_prnt, "T", BT_OCTET16_LEN);
-  p_prnt = counter;
-  smp_debug_print_nbyte_little_endian(p_prnt, "Counter", 1);
-  p_prnt = key_id;
-  smp_debug_print_nbyte_little_endian(p_prnt, "KeyID", 4);
-  p_prnt = n1;
-  smp_debug_print_nbyte_little_endian(p_prnt, "N1", BT_OCTET16_LEN);
-  p_prnt = n2;
-  smp_debug_print_nbyte_little_endian(p_prnt, "N2", BT_OCTET16_LEN);
-  p_prnt = a1;
-  smp_debug_print_nbyte_little_endian(p_prnt, "A1", 7);
-  p_prnt = a2;
-  smp_debug_print_nbyte_little_endian(p_prnt, "A2", 7);
-  p_prnt = length;
-  smp_debug_print_nbyte_little_endian(p_prnt, "Length", 2);
-#endif
-
-  p = key;
-  ARRAY_TO_STREAM(p, t, BT_OCTET16_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = key;
-  smp_debug_print_nbyte_little_endian(p_prnt, "K", BT_OCTET16_LEN);
-#endif
-  p = msg;
-  ARRAY_TO_STREAM(p, length, 2);
-  ARRAY_TO_STREAM(p, a2, 7);
-  ARRAY_TO_STREAM(p, a1, 7);
-  ARRAY_TO_STREAM(p, n2, BT_OCTET16_LEN);
-  ARRAY_TO_STREAM(p, n1, BT_OCTET16_LEN);
-  ARRAY_TO_STREAM(p, key_id, 4);
-  ARRAY_TO_STREAM(p, counter, 1);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = msg;
-  smp_debug_print_nbyte_little_endian(p_prnt, "M", msg_len);
-#endif
-
-  if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    ret = false;
-  }
-
-#if (SMP_DEBUG == TRUE)
-  p_prnt = cmac;
-  smp_debug_print_nbyte_little_endian(p_prnt, "AES-CMAC", BT_OCTET16_LEN);
-#endif
-
-  p = mac;
-  ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
-  return ret;
-}
-
-/*******************************************************************************
- *
- * Function         smp_calculate_f5_key
- *
- * Description      The function calculates key T used in calculation of
- *                  MacKey and LTK (f5 output is defined as MacKey || LTK).
- *                  T = AES-CMAC    (W)
- *                              salt
- *                  where
- *                  Internal:   salt    is 128 bit.
- *                  input:      W       is 256 bit.
- *                  Output:     T       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.
- *
- ******************************************************************************/
-bool smp_calculate_f5_key(uint8_t* w, uint8_t* t) {
-  uint8_t* p = NULL;
-  /* Please see 2.2.7 LE Secure Connections Key Generation Function f5 */
-  /*
-      salt:   6C88 8391 AAF5 A538 6037 0BDB 5A60 83BE
-  */
-  BT_OCTET16 salt = {0xBE, 0x83, 0x60, 0x5A, 0xDB, 0x0B, 0x37, 0x60,
-                     0x38, 0xA5, 0xF5, 0xAA, 0x91, 0x83, 0x88, 0x6C};
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_prnt = NULL;
-#endif
-
-  SMP_TRACE_DEBUG("%s", __func__);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = salt;
-  smp_debug_print_nbyte_little_endian(p_prnt, "salt", BT_OCTET16_LEN);
-  p_prnt = w;
-  smp_debug_print_nbyte_little_endian(p_prnt, "W", BT_OCTET32_LEN);
-#endif
-
-  BT_OCTET16 key;
-  BT_OCTET32 msg;
-
-  p = key;
-  ARRAY_TO_STREAM(p, salt, BT_OCTET16_LEN);
-  p = msg;
-  ARRAY_TO_STREAM(p, w, BT_OCTET32_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_prnt = key;
-  smp_debug_print_nbyte_little_endian(p_prnt, "K", BT_OCTET16_LEN);
-  p_prnt = msg;
-  smp_debug_print_nbyte_little_endian(p_prnt, "M", BT_OCTET32_LEN);
-#endif
-
-  BT_OCTET16 cmac;
-  bool ret = true;
-  if (!aes_cipher_msg_auth_code(key, msg, BT_OCTET32_LEN, BT_OCTET16_LEN,
-                                cmac)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    ret = false;
-  }
-
-#if (SMP_DEBUG == TRUE)
-  p_prnt = cmac;
-  smp_debug_print_nbyte_little_endian(p_prnt, "AES-CMAC", BT_OCTET16_LEN);
-#endif
-
-  p = t;
-  ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
-  return ret;
-}
 
 /*******************************************************************************
  *
@@ -1507,8 +885,8 @@
 
   smp_collect_local_ble_address(a, p_cb);
   smp_collect_peer_ble_address(b, p_cb);
-  smp_calculate_f6(p_cb->mac_key, p_cb->rand, p_cb->rrand, p_cb->peer_random,
-                   iocap, a, b, p_cb->dhkey_check);
+  p_cb->dhkey_check = crypto_toolbox::f6(p_cb->mac_key, p_cb->rand, p_cb->rrand,
+                                         p_cb->peer_random, iocap, a, b);
 
   SMP_TRACE_EVENT("local DHKey check calculation is completed");
 }
@@ -1524,8 +902,6 @@
  ******************************************************************************/
 void smp_calculate_peer_dhkey_check(tSMP_CB* p_cb, tSMP_INT_DATA* p_data) {
   uint8_t iocap[3], a[7], b[7];
-  BT_OCTET16 param_buf;
-  bool ret;
   tSMP_KEY key;
 
   SMP_TRACE_DEBUG("%s", __func__);
@@ -1534,119 +910,21 @@
 
   smp_collect_local_ble_address(a, p_cb);
   smp_collect_peer_ble_address(b, p_cb);
-  ret = smp_calculate_f6(p_cb->mac_key, p_cb->rrand, p_cb->rand,
-                         p_cb->local_random, iocap, b, a, param_buf);
+  Octet16 param_buf = crypto_toolbox::f6(p_cb->mac_key, p_cb->rrand, p_cb->rand,
+                                         p_cb->local_random, iocap, b, a);
 
-  if (ret) {
-    SMP_TRACE_EVENT("peer DHKey check calculation is completed");
+  SMP_TRACE_EVENT("peer DHKey check calculation is completed");
 #if (SMP_DEBUG == TRUE)
-    smp_debug_print_nbyte_little_endian(param_buf, "peer DHKey check",
-                                        BT_OCTET16_LEN);
+  smp_debug_print_nbyte_little_endian(param_buf, "peer DHKey check",
+                                      OCTET16_LEN);
 #endif
-    key.key_type = SMP_KEY_TYPE_PEER_DHK_CHCK;
-    key.p_data = param_buf;
-    tSMP_INT_DATA smp_int_data;
-    smp_int_data.key = key;
-    smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
-  } else {
-    SMP_TRACE_EVENT("peer DHKey check calculation failed");
-    tSMP_INT_DATA smp_int_data;
-    smp_int_data.status = SMP_PAIR_FAIL_UNKNOWN;
-    smp_sm_event(p_cb, SMP_AUTH_CMPL_EVT, &smp_int_data);
-  }
+  key.key_type = SMP_KEY_TYPE_PEER_DHK_CHCK;
+  key.p_data = param_buf.data();
+  tSMP_INT_DATA smp_int_data;
+  smp_int_data.key = key;
+  smp_sm_event(p_cb, SMP_SC_KEY_READY_EVT, &smp_int_data);
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_f6
- *
- * Description      The function calculates
- *                  C = f6(W, N1, N2, R, IOcap, A1, A2) =
- *                      AES-CMAC (N1||N2||R||IOcap||A1||A2)
- *                              W
- *                  where
- *                  input:  W is 128 bit,
- *                          N1 is 128 bit,
- *                          N2 is 128 bit,
- *                          R is 128 bit,
- *                          IOcap is 24 bit,
- *                          A1 is 56 bit,
- *                          A2 is 56 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.
- *
- ******************************************************************************/
-bool smp_calculate_f6(uint8_t* w, uint8_t* n1, uint8_t* n2, uint8_t* r,
-                      uint8_t* iocap, uint8_t* a1, uint8_t* a2, uint8_t* c) {
-  uint8_t* p = NULL;
-  uint8_t msg_len = BT_OCTET16_LEN /* N1 size */ +
-                    BT_OCTET16_LEN /* N2 size */ + BT_OCTET16_LEN /* R size */ +
-                    3 /* IOcap size */ + 7 /* A1 size*/
-                    + 7 /* A2 size*/;
-  uint8_t msg[BT_OCTET16_LEN + BT_OCTET16_LEN + BT_OCTET16_LEN + 3 + 7 + 7];
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_print = NULL;
-#endif
-
-  SMP_TRACE_DEBUG("%s", __func__);
-#if (SMP_DEBUG == TRUE)
-  p_print = w;
-  smp_debug_print_nbyte_little_endian(p_print, "W", BT_OCTET16_LEN);
-  p_print = n1;
-  smp_debug_print_nbyte_little_endian(p_print, "N1", BT_OCTET16_LEN);
-  p_print = n2;
-  smp_debug_print_nbyte_little_endian(p_print, "N2", BT_OCTET16_LEN);
-  p_print = r;
-  smp_debug_print_nbyte_little_endian(p_print, "R", BT_OCTET16_LEN);
-  p_print = iocap;
-  smp_debug_print_nbyte_little_endian(p_print, "IOcap", 3);
-  p_print = a1;
-  smp_debug_print_nbyte_little_endian(p_print, "A1", 7);
-  p_print = a2;
-  smp_debug_print_nbyte_little_endian(p_print, "A2", 7);
-#endif
-
-  uint8_t cmac[BT_OCTET16_LEN];
-  uint8_t key[BT_OCTET16_LEN];
-
-  p = key;
-  ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_print = key;
-  smp_debug_print_nbyte_little_endian(p_print, "K", BT_OCTET16_LEN);
-#endif
-
-  p = msg;
-  ARRAY_TO_STREAM(p, a2, 7);
-  ARRAY_TO_STREAM(p, a1, 7);
-  ARRAY_TO_STREAM(p, iocap, 3);
-  ARRAY_TO_STREAM(p, r, BT_OCTET16_LEN);
-  ARRAY_TO_STREAM(p, n2, BT_OCTET16_LEN);
-  ARRAY_TO_STREAM(p, n1, BT_OCTET16_LEN);
-#if (SMP_DEBUG == TRUE)
-  p_print = msg;
-  smp_debug_print_nbyte_little_endian(p_print, "M", msg_len);
-#endif
-
-  bool ret = true;
-  if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    ret = false;
-  }
-
-#if (SMP_DEBUG == TRUE)
-  p_print = cmac;
-  smp_debug_print_nbyte_little_endian(p_print, "AES-CMAC", BT_OCTET16_LEN);
-#endif
-
-  p = c;
-  ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
-  return ret;
-}
 
 /*******************************************************************************
  *
@@ -1662,8 +940,6 @@
   tBTM_SEC_DEV_REC* p_dev_rec;
   RawAddress 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__);
 
@@ -1686,79 +962,44 @@
     return false;
   }
 
-  BT_OCTET16 intermediate_link_key;
-  bool ret = true;
+  Octet16 link_key =
+      crypto_toolbox::ltk_to_link_key(p_cb->ltk, p_cb->key_derivation_h7_used);
 
-  if (p_cb->key_derivation_h7_used)
-    ret = smp_calculate_h7((uint8_t*)salt, p_cb->ltk, intermediate_link_key);
-  else
-    ret = smp_calculate_h6(p_cb->ltk, (uint8_t*)"1pmt" /* reversed "tmp1" */,
-                           intermediate_link_key);
-  if (!ret) {
-    SMP_TRACE_ERROR("%s failed to derive intermediate_link_key", __func__);
-    return ret;
-  }
-
-  BT_OCTET16 link_key;
-  ret = smp_calculate_h6(intermediate_link_key,
-                         (uint8_t*)"rbel" /* reversed "lebr" */, link_key);
-  if (!ret) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-  } else {
-    uint8_t link_key_type;
-    if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
-      /* Secure Connections Only Mode */
+  uint8_t link_key_type;
+  if (btm_cb.security_mode == BTM_SEC_MODE_SC) {
+    /* Secure Connections Only Mode */
+    link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
+  } else if (controller_get_interface()->supports_secure_connections()) {
+    /* both transports are SC capable */
+    if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
       link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
-    } else if (controller_get_interface()->supports_secure_connections()) {
-      /* both transports are SC capable */
-      if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
-        link_key_type = BTM_LKEY_TYPE_AUTH_COMB_P_256;
-      else
-        link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB_P_256;
-    } else if (btm_cb.security_mode == BTM_SEC_MODE_SP) {
-      /* BR/EDR transport is SSP capable */
-      if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
-        link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
-      else
-        link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
-    } else {
-      SMP_TRACE_ERROR(
-          "%s failed to update link_key. Sec Mode = %d, sm4 = 0x%02x", __func__,
-          btm_cb.security_mode, p_dev_rec->sm4);
-      return false;
-    }
-
-    link_key_type += BTM_LTK_DERIVED_LKEY_OFFSET;
-
-    uint8_t* p;
-    BT_OCTET16 notif_link_key;
-    p = notif_link_key;
-    ARRAY16_TO_STREAM(p, link_key);
-
-    btm_sec_link_key_notification(bda_for_lk, notif_link_key, link_key_type);
-
-    SMP_TRACE_EVENT("%s is completed", __func__);
+    else
+      link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB_P_256;
+  } else if (btm_cb.security_mode == BTM_SEC_MODE_SP) {
+    /* BR/EDR transport is SSP capable */
+    if (p_cb->sec_level == SMP_SEC_AUTHENTICATED)
+      link_key_type = BTM_LKEY_TYPE_AUTH_COMB;
+    else
+      link_key_type = BTM_LKEY_TYPE_UNAUTH_COMB;
+  } else {
+    SMP_TRACE_ERROR("%s failed to update link_key. Sec Mode = %d, sm4 = 0x%02x",
+                    __func__, btm_cb.security_mode, p_dev_rec->sm4);
+    return false;
   }
 
-  return ret;
+  link_key_type += BTM_LTK_DERIVED_LKEY_OFFSET;
+
+  Octet16 notif_link_key = link_key;
+  btm_sec_link_key_notification(bda_for_lk, notif_link_key, link_key_type);
+
+  SMP_TRACE_EVENT("%s is completed", __func__);
+
+  return true;
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_long_term_key_from_link_key
- *
- * Description      The function calculates and saves SC LTK derived from BR/EDR
- *                  link key.
- *
- * Returns          false if out of resources, true in other cases.
- *
- ******************************************************************************/
+/** The function calculates and saves SC LTK derived from BR/EDR link key. */
 bool smp_calculate_long_term_key_from_link_key(tSMP_CB* p_cb) {
-  bool ret = true;
   tBTM_SEC_DEV_REC* p_dev_rec;
-  uint8_t 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", __func__);
 
@@ -1782,153 +1023,17 @@
     return false;
   }
 
-  uint8_t* p1;
-  uint8_t* p2;
-  p1 = rev_link_key;
-  p2 = p_dev_rec->link_key;
-  REVERSE_ARRAY_TO_STREAM(p1, p2, 16);
+  Octet16 rev_link_key;
+  std::reverse_copy(p_dev_rec->link_key.begin(), p_dev_rec->link_key.end(),
+                    rev_link_key.begin());
+  p_cb->ltk = crypto_toolbox::link_key_to_ltk(rev_link_key,
+                                              p_cb->key_derivation_h7_used);
 
-  BT_OCTET16 intermediate_long_term_key;
-  if (p_cb->key_derivation_h7_used) {
-    ret = smp_calculate_h7((uint8_t*)salt, rev_link_key,
-                           intermediate_long_term_key);
-  } else {
-    /* "tmp2" obtained from the spec */
-    ret = smp_calculate_h6(rev_link_key, (uint8_t*)"2pmt" /* reversed "tmp2" */,
-                           intermediate_long_term_key);
-  }
-
-  if (!ret) {
-    SMP_TRACE_ERROR("%s failed to derive intermediate_long_term_key", __func__);
-    return ret;
-  }
-
-  /* "brle" obtained from the spec */
-  ret = smp_calculate_h6(intermediate_long_term_key,
-                         (uint8_t*)"elrb" /* reversed "brle" */, p_cb->ltk);
-
-  if (!ret) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-  } else {
-    p_cb->sec_level = (br_link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)
-                          ? SMP_SEC_AUTHENTICATED
-                          : SMP_SEC_UNAUTHENTICATE;
-    SMP_TRACE_EVENT("%s is completed", __func__);
-  }
-
-  return ret;
-}
-
-/*******************************************************************************
- *
- * Function         smp_calculate_h6
- *
- * Description      The function calculates
- *                  C = h6(W, KeyID) = AES-CMAC (KeyID)
- *                                             W
- *                  where
- *                  input:  W is 128 bit,
- *                          KeyId is 32 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.
- *
- ******************************************************************************/
-bool smp_calculate_h6(uint8_t* w, uint8_t* keyid, uint8_t* c) {
-#if (SMP_DEBUG == TRUE)
-  uint8_t* p_print = NULL;
-#endif
-
-  SMP_TRACE_DEBUG("%s", __func__);
-#if (SMP_DEBUG == TRUE)
-  p_print = w;
-  smp_debug_print_nbyte_little_endian(p_print, "W", BT_OCTET16_LEN);
-  p_print = keyid;
-  smp_debug_print_nbyte_little_endian(p_print, "keyID", 4);
-#endif
-
-  uint8_t* p = NULL;
-  uint8_t key[BT_OCTET16_LEN];
-
-  p = key;
-  ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
-
-#if (SMP_DEBUG == TRUE)
-  p_print = key;
-  smp_debug_print_nbyte_little_endian(p_print, "K", BT_OCTET16_LEN);
-#endif
-
-  uint8_t msg_len = 4 /* KeyID size */;
-  uint8_t msg[4];
-
-  p = msg;
-  ARRAY_TO_STREAM(p, keyid, 4);
-
-#if (SMP_DEBUG == TRUE)
-  p_print = msg;
-  smp_debug_print_nbyte_little_endian(p_print, "M", msg_len);
-#endif
-
-  bool ret = true;
-  uint8_t cmac[BT_OCTET16_LEN];
-  if (!aes_cipher_msg_auth_code(key, msg, msg_len, BT_OCTET16_LEN, cmac)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    ret = false;
-  }
-
-#if (SMP_DEBUG == TRUE)
-  p_print = cmac;
-  smp_debug_print_nbyte_little_endian(p_print, "AES-CMAC", BT_OCTET16_LEN);
-#endif
-
-  p = c;
-  ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
-  return ret;
-}
-
-/*******************************************************************************
-**
-** 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.
-**
-*******************************************************************************/
-bool smp_calculate_h7(uint8_t* salt, uint8_t* w, uint8_t* c) {
-  SMP_TRACE_DEBUG("%s", __FUNCTION__);
-
-  uint8_t key[BT_OCTET16_LEN];
-  uint8_t* p = key;
-  ARRAY_TO_STREAM(p, salt, BT_OCTET16_LEN);
-
-  uint8_t msg_len = BT_OCTET16_LEN /* msg size */;
-  uint8_t msg[BT_OCTET16_LEN];
-  p = msg;
-  ARRAY_TO_STREAM(p, w, BT_OCTET16_LEN);
-
-  bool ret = true;
-  uint8_t 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;
-  }
-
-  p = c;
-  ARRAY_TO_STREAM(p, cmac, BT_OCTET16_LEN);
-  return ret;
+  p_cb->sec_level = (br_link_key_type == BTM_LKEY_TYPE_AUTH_COMB_P_256)
+                        ? SMP_SEC_AUTHENTICATED
+                        : SMP_SEC_UNAUTHENTICATE;
+  SMP_TRACE_EVENT("%s is completed", __func__);
+  return true;
 }
 
 /**
@@ -1938,10 +1043,10 @@
   SMP_TRACE_DEBUG("%s", __func__);
   btsnd_hcic_ble_rand(Bind(
       [](tSMP_CB* p_cb, BT_OCTET8 rand) {
-        memcpy((void*)p_cb->rand, rand, BT_OCTET8_LEN);
+        memcpy(p_cb->rand.data(), rand, BT_OCTET8_LEN);
         btsnd_hcic_ble_rand(Bind(
             [](tSMP_CB* p_cb, BT_OCTET8 rand) {
-              memcpy((void*)&p_cb->rand[8], rand, BT_OCTET8_LEN);
+              memcpy(p_cb->rand.data() + 8, rand, BT_OCTET8_LEN);
               SMP_TRACE_DEBUG("%s round %d", __func__, p_cb->round);
               /* notifies SM that it has new nonce. */
               smp_sm_event(p_cb, SMP_HAVE_LOC_NONCE_EVT, NULL);
diff --git a/stack/smp/smp_l2c.cc b/stack/smp/smp_l2c.cc
index 1e0cb71..2daeb21 100644
--- a/stack/smp/smp_l2c.cc
+++ b/stack/smp/smp_l2c.cc
@@ -22,10 +22,12 @@
  *
  ******************************************************************************/
 
+#include <cutils/log.h>
 #include "bt_target.h"
 
 #include <string.h>
 #include "btm_ble_api.h"
+#include "common/metrics.h"
 #include "l2c_api.h"
 
 #include "smp_int.h"
@@ -141,6 +143,14 @@
   uint8_t* p = (uint8_t*)(p_buf + 1) + p_buf->offset;
   uint8_t cmd;
 
+  if (p_buf->len < 1) {
+    android_errorWriteLog(0x534e4554, "111215315");
+    SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
+                      __func__, p_buf->len);
+    osi_free(p_buf);
+    return;
+  }
+
   STREAM_TO_UINT8(cmd, p);
 
   SMP_TRACE_EVENT("%s: SMDBG l2c, cmd=0x%x", __func__, cmd);
@@ -172,6 +182,9 @@
     alarm_set_on_mloop(p_cb->smp_rsp_timer_ent, SMP_WAIT_FOR_RSP_TIMEOUT_MS,
                        smp_rsp_timeout, NULL);
 
+    smp_log_metrics(p_cb->pairing_bda, false /* incoming */,
+                    p_buf->data + p_buf->offset, p_buf->len);
+
     if (cmd == SMP_OPCODE_CONFIRM) {
       SMP_TRACE_DEBUG(
           "in %s cmd = 0x%02x, peer_auth_req = 0x%02x,"
@@ -282,6 +295,14 @@
   uint8_t cmd;
   SMP_TRACE_EVENT("SMDBG l2c %s", __func__);
 
+  if (p_buf->len < 1) {
+    android_errorWriteLog(0x534e4554, "111215315");
+    SMP_TRACE_WARNING("%s: smp packet length %d too short: must be at least 1",
+                      __func__, p_buf->len);
+    osi_free(p_buf);
+    return;
+  }
+
   STREAM_TO_UINT8(cmd, p);
 
   /* sanity check */
@@ -310,6 +331,9 @@
     alarm_set_on_mloop(p_cb->smp_rsp_timer_ent, SMP_WAIT_FOR_RSP_TIMEOUT_MS,
                        smp_rsp_timeout, NULL);
 
+    smp_log_metrics(p_cb->pairing_bda, false /* incoming */,
+                    p_buf->data + p_buf->offset, p_buf->len);
+
     p_cb->rcvd_cmd_code = cmd;
     p_cb->rcvd_cmd_len = (uint8_t)p_buf->len;
     tSMP_INT_DATA smp_int_data;
diff --git a/stack/smp/smp_main.cc b/stack/smp/smp_main.cc
index 9c4334a..89ecb4f 100644
--- a/stack/smp/smp_main.cc
+++ b/stack/smp/smp_main.cc
@@ -18,7 +18,7 @@
 
 #include "bt_target.h"
 
-#include <cutils/log.h>
+#include <log/log.h>
 #include <string.h>
 #include "smp_int.h"
 
@@ -155,7 +155,6 @@
   SMP_SET_LOCAL_OOB_KEYS,
   SMP_SET_LOCAL_OOB_RAND_COMMITMENT,
   SMP_IDLE_TERMINATE,
-  SMP_FAST_CONN_PARAM,
   SMP_SM_NO_ACTION
 };
 
@@ -219,8 +218,7 @@
     smp_process_secure_connection_oob_data,
     smp_set_local_oob_keys,
     smp_set_local_oob_random_commitment,
-    smp_idle_terminate,
-    smp_fast_conn_param};
+    smp_idle_terminate};
 
 /************ SMP Master FSM State/Event Indirection Table **************/
 static const uint8_t smp_master_entry_map[][SMP_STATE_MAX] = {
@@ -344,7 +342,7 @@
         /* SEC_GRANT */
         {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
         /* IO_RSP */
-        {SMP_SEND_PAIR_REQ, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
+        {SMP_SEND_PAIR_REQ, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
 
         /* TK ready */
         /* KEY_READY */
@@ -352,7 +350,7 @@
 
         /* start enc mode setup */
         /* ENC_REQ */
-        {SMP_START_ENC, SMP_FAST_CONN_PARAM, SMP_STATE_ENCRYPTION_PENDING},
+        {SMP_START_ENC, SMP_SM_NO_ACTION, SMP_STATE_ENCRYPTION_PENDING},
         /* DISCARD_SEC_REQ */
         {SMP_PROC_DISCARD, SMP_SM_NO_ACTION, SMP_STATE_IDLE}
         /* user confirms NC 'OK', i.e. phase 1 is completed */
@@ -630,7 +628,7 @@
     {
         /* Event                   Action                 Next State */
         /* IO_RSP */
-        {SMP_PROC_IO_RSP, SMP_FAST_CONN_PARAM, SMP_STATE_PAIR_REQ_RSP},
+        {SMP_PROC_IO_RSP, SMP_SM_NO_ACTION, SMP_STATE_PAIR_REQ_RSP},
         /* SEC_GRANT */
         {SMP_PROC_SEC_GRANT, SMP_SEND_APP_CBACK, SMP_STATE_WAIT_APP_RSP},
 
diff --git a/stack/smp/smp_utils.cc b/stack/smp/smp_utils.cc
index 5027e3d..b5da5ba 100644
--- a/stack/smp/smp_utils.cc
+++ b/stack/smp/smp_utils.cc
@@ -29,6 +29,7 @@
 #include "bt_utils.h"
 #include "btm_ble_api.h"
 #include "btm_int.h"
+#include "common/metrics.h"
 #include "device/include/controller.h"
 #include "hcidefs.h"
 #include "l2c_api.h"
@@ -37,20 +38,21 @@
 #include "smp_int.h"
 
 #define SMP_PAIRING_REQ_SIZE 7
-#define SMP_CONFIRM_CMD_SIZE (BT_OCTET16_LEN + 1)
-#define SMP_RAND_CMD_SIZE (BT_OCTET16_LEN + 1)
-#define SMP_INIT_CMD_SIZE (BT_OCTET16_LEN + 1)
-#define SMP_ENC_INFO_SIZE (BT_OCTET16_LEN + 1)
+#define SMP_CONFIRM_CMD_SIZE (OCTET16_LEN + 1)
+#define SMP_RAND_CMD_SIZE (OCTET16_LEN + 1)
+#define SMP_INIT_CMD_SIZE (OCTET16_LEN + 1)
+#define SMP_ENC_INFO_SIZE (OCTET16_LEN + 1)
 #define SMP_MASTER_ID_SIZE (BT_OCTET8_LEN + 2 + 1)
-#define SMP_ID_INFO_SIZE (BT_OCTET16_LEN + 1)
+#define SMP_ID_INFO_SIZE (OCTET16_LEN + 1)
 #define SMP_ID_ADDR_SIZE (BD_ADDR_LEN + 1 + 1)
-#define SMP_SIGN_INFO_SIZE (BT_OCTET16_LEN + 1)
+#define SMP_SIGN_INFO_SIZE (OCTET16_LEN + 1)
 #define SMP_PAIR_FAIL_SIZE 2
 #define SMP_SECURITY_REQUEST_SIZE 2
 #define SMP_PAIR_PUBL_KEY_SIZE (1 /* opcode */ + (2 * BT_OCTET32_LEN))
-#define SMP_PAIR_COMMITM_SIZE (1 /* opcode */ + BT_OCTET16_LEN /*Commitment*/)
+#define SMP_PAIR_COMMITM_SIZE (1 /* opcode */ + OCTET16_LEN /*Commitment*/)
 #define SMP_PAIR_DHKEY_CHECK_SIZE \
-  (1 /* opcode */ + BT_OCTET16_LEN /*DHKey Check*/)
+  (1 /* opcode */ + OCTET16_LEN /*DHKey \
+                                                                   Check*/)
 #define SMP_PAIR_KEYPR_NOTIF_SIZE (1 /* opcode */ + 1 /*Notif Type*/)
 
 /* SMP command sizes per spec */
@@ -294,6 +296,34 @@
 static tSMP_ASSO_MODEL smp_select_association_model_secure_connections(
     tSMP_CB* p_cb);
 
+/**
+ * Log metrics data for SMP command
+ *
+ * @param bd_addr current pairing address
+ * @param is_outgoing whether this command is outgoing
+ * @param p_buf buffer to the beginning of SMP command
+ * @param buf_len length available to read for p_buf
+ */
+void smp_log_metrics(const RawAddress& bd_addr, bool is_outgoing,
+                     const uint8_t* p_buf, size_t buf_len) {
+  if (buf_len < 1) {
+    LOG(WARNING) << __func__ << ": buffer is too small, size is " << buf_len;
+    return;
+  }
+  uint8_t cmd;
+  STREAM_TO_UINT8(cmd, p_buf);
+  buf_len--;
+  uint8_t failure_reason = 0;
+  if (cmd == SMP_OPCODE_PAIRING_FAILED && buf_len >= 1) {
+    STREAM_TO_UINT8(failure_reason, p_buf);
+  }
+  android::bluetooth::DirectionEnum direction =
+      is_outgoing ? android::bluetooth::DirectionEnum::DIRECTION_OUTGOING
+                  : android::bluetooth::DirectionEnum::DIRECTION_INCOMING;
+  bluetooth::common::LogSmpPairingEvent(bd_addr, cmd, direction,
+                                        failure_reason);
+}
+
 /*******************************************************************************
  *
  * Function         smp_send_msg_to_L2CAP
@@ -312,6 +342,9 @@
   SMP_TRACE_EVENT("%s", __func__);
   smp_cb.total_tx_unacked += 1;
 
+  smp_log_metrics(rem_bda, true /* outgoing */,
+                  p_toL2CAP->data + p_toL2CAP->offset, p_toL2CAP->len);
+
   l2cap_ret = L2CA_SendFixedChnlData(fixed_cid, rem_bda, p_toL2CAP);
   if (l2cap_ret == L2CAP_DW_FAILED) {
     smp_cb.total_tx_unacked -= 1;
@@ -453,7 +486,7 @@
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
   UINT8_TO_STREAM(p, SMP_OPCODE_CONFIRM);
-  ARRAY_TO_STREAM(p, p_cb->confirm, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, p_cb->confirm, OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_CONFIRM_CMD_SIZE;
@@ -477,7 +510,7 @@
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
   UINT8_TO_STREAM(p, SMP_OPCODE_RAND);
-  ARRAY_TO_STREAM(p, p_cb->rand, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, p_cb->rand, OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_RAND_CMD_SIZE;
@@ -502,7 +535,7 @@
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
   UINT8_TO_STREAM(p, SMP_OPCODE_ENCRYPT_INFO);
-  ARRAY_TO_STREAM(p, p_cb->ltk, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, p_cb->ltk, OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_ENC_INFO_SIZE;
@@ -546,7 +579,6 @@
 static BT_HDR* smp_build_identity_info_cmd(UNUSED_ATTR uint8_t cmd_code,
                                            UNUSED_ATTR tSMP_CB* p_cb) {
   uint8_t* p;
-  BT_OCTET16 irk;
   BT_HDR* p_buf =
       (BT_HDR*)osi_malloc(sizeof(BT_HDR) + SMP_ID_INFO_SIZE + L2CAP_MIN_OFFSET);
 
@@ -554,10 +586,10 @@
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
 
-  BTM_GetDeviceIDRoot(irk);
+  const Octet16& irk = BTM_GetDeviceIDRoot();
 
   UINT8_TO_STREAM(p, SMP_OPCODE_IDENTITY_INFO);
-  ARRAY_TO_STREAM(p, irk, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, irk.data(), OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_ID_INFO_SIZE;
@@ -608,7 +640,7 @@
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
   UINT8_TO_STREAM(p, SMP_OPCODE_SIGN_INFO);
-  ARRAY_TO_STREAM(p, p_cb->csrk, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, p_cb->csrk, OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_SIGN_INFO_SIZE;
@@ -715,7 +747,7 @@
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
   UINT8_TO_STREAM(p, SMP_OPCODE_CONFIRM);
-  ARRAY_TO_STREAM(p, p_cb->commitment, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, p_cb->commitment, OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_PAIR_COMMITM_SIZE;
@@ -740,7 +772,7 @@
 
   p = (uint8_t*)(p_buf + 1) + L2CAP_MIN_OFFSET;
   UINT8_TO_STREAM(p, SMP_OPCODE_PAIR_DHKEY_CHECK);
-  ARRAY_TO_STREAM(p, p_cb->dhkey_check, BT_OCTET16_LEN);
+  ARRAY_TO_STREAM(p, p_cb->dhkey_check, OCTET16_LEN);
 
   p_buf->offset = L2CAP_MIN_OFFSET;
   p_buf->len = SMP_PAIR_DHKEY_CHECK_SIZE;
@@ -773,66 +805,42 @@
   return p_buf;
 }
 
-/*******************************************************************************
- *
- * Function         smp_convert_string_to_tk
- *
- * Description      This function is called to convert a 6 to 16 digits numeric
- *                  character string into SMP TK.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_convert_string_to_tk(BT_OCTET16 tk, uint32_t passkey) {
-  uint8_t* p = tk;
+/** This function is called to convert a 6 to 16 digits numeric character string
+ * into SMP TK. */
+void smp_convert_string_to_tk(Octet16* tk, uint32_t passkey) {
+  uint8_t* p = tk->data();
   tSMP_KEY key;
   SMP_TRACE_EVENT("smp_convert_string_to_tk");
   UINT32_TO_STREAM(p, passkey);
 
   key.key_type = SMP_KEY_TYPE_TK;
-  key.p_data = tk;
+  key.p_data = tk->data();
 
   tSMP_INT_DATA smp_int_data;
   smp_int_data.key = key;
   smp_sm_event(&smp_cb, SMP_KEY_READY_EVT, &smp_int_data);
 }
 
-/*******************************************************************************
- *
- * Function         smp_mask_enc_key
- *
- * Description      This function is called to mask off the encryption key based
- *                  on the maximum encryption key size.
- *
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_mask_enc_key(uint8_t loc_enc_size, uint8_t* p_data) {
+/** This function is called to mask off the encryption key based on the maximum
+ * encryption key size. */
+void smp_mask_enc_key(uint8_t loc_enc_size, Octet16* p_data) {
   SMP_TRACE_EVENT("smp_mask_enc_key");
-  if (loc_enc_size < BT_OCTET16_LEN) {
-    for (; loc_enc_size < BT_OCTET16_LEN; loc_enc_size++)
-      *(p_data + loc_enc_size) = 0;
+  if (loc_enc_size < OCTET16_LEN) {
+    for (; loc_enc_size < OCTET16_LEN; loc_enc_size++)
+      (*p_data)[loc_enc_size] = 0;
   }
   return;
 }
 
-/*******************************************************************************
- *
- * Function         smp_xor_128
- *
- * Description      utility function to do an biteise exclusive-OR of two bit
- *                  strings of the length of BT_OCTET16_LEN.
- *
- * Returns          void
- *
- ******************************************************************************/
-void smp_xor_128(BT_OCTET16 a, BT_OCTET16 b) {
-  uint8_t i, *aa = a, *bb = b;
+/** utility function to do an biteise exclusive-OR of two bit strings of the
+ * length of OCTET16_LEN. Result is stored in first argument.
+ */
+void smp_xor_128(Octet16* a, const Octet16& b) {
+  CHECK(a);
+  uint8_t i, *aa = a->data();
+  const uint8_t* bb = b.data();
 
-  SMP_TRACE_EVENT("smp_xor_128");
-  for (i = 0; i < BT_OCTET16_LEN; i++) {
+  for (i = 0; i < OCTET16_LEN; i++) {
     aa[i] = aa[i] ^ bb[i];
   }
 }
@@ -947,6 +955,33 @@
 
 /*******************************************************************************
  *
+ * Function         smp_command_has_invalid_length
+ *
+ * Description      Checks if the received SMP command has invalid length
+ *                  It returns true if the command has invalid length.
+ *
+ * Returns          true if the command has invalid length, false otherwise.
+ *
+ ******************************************************************************/
+bool smp_command_has_invalid_length(tSMP_CB* p_cb) {
+  uint8_t cmd_code = p_cb->rcvd_cmd_code;
+
+  if ((cmd_code > (SMP_OPCODE_MAX + 1 /* for SMP_OPCODE_PAIR_COMMITM */)) ||
+      (cmd_code < SMP_OPCODE_MIN)) {
+    SMP_TRACE_WARNING("%s: Received command with RESERVED code 0x%02x",
+                      __func__, cmd_code);
+    return true;
+  }
+
+  if (!smp_command_has_valid_fixed_length(p_cb)) {
+    return true;
+  }
+
+  return false;
+}
+
+/*******************************************************************************
+ *
  * Function         smp_command_has_invalid_parameters
  *
  * Description      Checks if the received SMP command has invalid parameters
@@ -1408,15 +1443,14 @@
  *
  ******************************************************************************/
 bool smp_check_commitment(tSMP_CB* p_cb) {
-  BT_OCTET16 expected;
 
   SMP_TRACE_DEBUG("%s", __func__);
 
-  smp_calculate_peer_commitment(p_cb, expected);
+  Octet16 expected = smp_calculate_peer_commitment(p_cb);
   print128(expected, (const uint8_t*)"calculated peer commitment");
   print128(p_cb->remote_commitment, (const uint8_t*)"received peer commitment");
 
-  if (memcmp(p_cb->remote_commitment, expected, BT_OCTET16_LEN)) {
+  if (memcmp(p_cb->remote_commitment.data(), expected.data(), OCTET16_LEN)) {
     SMP_TRACE_WARNING("%s: Commitment check fails", __func__);
     return false;
   }
@@ -1440,7 +1474,7 @@
   tBTM_LE_KEY_VALUE ple_key;
 
   SMP_TRACE_DEBUG("%s-Save LTK as local LTK key", __func__);
-  memcpy(lle_key.lenc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+  lle_key.lenc_key.ltk = p_cb->ltk;
   lle_key.lenc_key.div = 0;
   lle_key.lenc_key.key_size = p_cb->loc_enc_size;
   lle_key.lenc_key.sec_level = p_cb->sec_level;
@@ -1449,52 +1483,38 @@
   SMP_TRACE_DEBUG("%s-Save LTK as peer LTK key", __func__);
   ple_key.penc_key.ediv = 0;
   memset(ple_key.penc_key.rand, 0, BT_OCTET8_LEN);
-  memcpy(ple_key.penc_key.ltk, p_cb->ltk, BT_OCTET16_LEN);
+  ple_key.penc_key.ltk = p_cb->ltk;
   ple_key.penc_key.sec_level = p_cb->sec_level;
   ple_key.penc_key.key_size = p_cb->loc_enc_size;
   btm_sec_save_le_key(p_cb->pairing_bda, BTM_LE_KEY_PENC, &ple_key, true);
 }
 
-/*******************************************************************************
- *
- * Function         smp_calculate_f5_mackey_and_long_term_key
- *
- * Description      The function calculates MacKey and LTK and saves them in CB.
- *                  To calculate MacKey and LTK it calls smp_calc_f5(...).
- *                  MacKey is used in dhkey calculation, LTK is used to encrypt
- *                  the link.
- *
- * Returns          false if out of resources, true otherwise.
- *
- ******************************************************************************/
-bool smp_calculate_f5_mackey_and_long_term_key(tSMP_CB* p_cb) {
+/** The function calculates MacKey and LTK and saves them in CB. To calculate
+ * MacKey and LTK it calls smp_calc_f5(...). MacKey is used in dhkey
+ * calculation, LTK is used to encrypt the link. */
+void smp_calculate_f5_mackey_and_long_term_key(tSMP_CB* p_cb) {
   uint8_t a[7];
   uint8_t b[7];
-  uint8_t* p_na;
-  uint8_t* p_nb;
+  Octet16 na;
+  Octet16 nb;
 
   SMP_TRACE_DEBUG("%s", __func__);
 
   if (p_cb->role == HCI_ROLE_MASTER) {
     smp_collect_local_ble_address(a, p_cb);
     smp_collect_peer_ble_address(b, p_cb);
-    p_na = p_cb->rand;
-    p_nb = p_cb->rrand;
+    na = p_cb->rand;
+    nb = p_cb->rrand;
   } else {
     smp_collect_local_ble_address(b, p_cb);
     smp_collect_peer_ble_address(a, p_cb);
-    p_na = p_cb->rrand;
-    p_nb = p_cb->rand;
+    na = p_cb->rrand;
+    nb = p_cb->rand;
   }
 
-  if (!smp_calculate_f5(p_cb->dhkey, p_na, p_nb, a, b, p_cb->mac_key,
-                        p_cb->ltk)) {
-    SMP_TRACE_ERROR("%s failed", __func__);
-    return false;
-  }
+  crypto_toolbox::f5(p_cb->dhkey, na, nb, a, b, &p_cb->mac_key, &p_cb->ltk);
 
   SMP_TRACE_EVENT("%s is completed", __func__);
-  return true;
 }
 
 /*******************************************************************************
@@ -1535,3 +1555,15 @@
 
   return true;
 }
+
+void print128(const Octet16& x, const uint8_t* key_name) {
+  if (VLOG_IS_ON(2) && DLOG_IS_ON(INFO)) {
+    uint8_t* p = (uint8_t*)x.data();
+
+    DVLOG(2) << key_name << " (MSB ~ LSB) = ";
+    for (int i = 0; i < 4; i++) {
+      DVLOG(2) << +p[OCTET16_LEN - i * 4 - 1] << +p[OCTET16_LEN - i * 4 - 2]
+               << +p[OCTET16_LEN - i * 4 - 3] << +p[OCTET16_LEN - i * 4 - 4];
+    }
+  }
+}
diff --git a/stack/srvc/srvc_battery.cc b/stack/srvc/srvc_battery.cc
deleted file mode 100644
index 8b5d93e..0000000
--- a/stack/srvc/srvc_battery.cc
+++ /dev/null
@@ -1,362 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 1999-2013 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.
- *
- ******************************************************************************/
-
-#include "bt_target.h"
-#include "bt_utils.h"
-#include "gatt_api.h"
-#include "gatt_int.h"
-#include "osi/include/osi.h"
-#include "srvc_battery_int.h"
-#include "srvc_eng_int.h"
-
-#define BA_MAX_CHAR_NUM 1
-
-/* max 3 descriptors, 1 desclration and 1 value */
-#define BA_MAX_ATTR_NUM (BA_MAX_CHAR_NUM * 5 + 1)
-
-#ifndef BATTER_LEVEL_PROP
-#define BATTER_LEVEL_PROP (GATT_CHAR_PROP_BIT_READ | GATT_CHAR_PROP_BIT_NOTIFY)
-#endif
-
-#ifndef BATTER_LEVEL_PERM
-#define BATTER_LEVEL_PERM (GATT_PERM_READ)
-#endif
-
-tBATTERY_CB battery_cb;
-
-/*******************************************************************************
- *   battery_valid_handle_range
- *
- *   validate a handle to be a DIS attribute handle or not.
- ******************************************************************************/
-bool battery_valid_handle_range(uint16_t handle) {
-  uint8_t i = 0;
-  tBA_INST* p_inst = &battery_cb.battery_inst[0];
-
-  for (; i < BA_MAX_INT_NUM; i++, p_inst++) {
-    if (handle == p_inst->ba_level_hdl || handle == p_inst->clt_cfg_hdl ||
-        handle == p_inst->rpt_ref_hdl || handle == p_inst->pres_fmt_hdl) {
-      return true;
-    }
-  }
-  return false;
-}
-/*******************************************************************************
- *   battery_s_write_attr_value
- *
- *   Process write DIS attribute request.
- ******************************************************************************/
-uint8_t battery_s_write_attr_value(uint8_t clcb_idx, tGATT_WRITE_REQ* p_value,
-                                   tGATT_STATUS* p_status) {
-  uint8_t *p = p_value->value, i;
-  uint16_t handle = p_value->handle;
-  tBA_INST* p_inst = &battery_cb.battery_inst[0];
-  tGATT_STATUS st = GATT_NOT_FOUND;
-  tBA_WRITE_DATA cfg;
-  uint8_t act = SRVC_ACT_RSP;
-
-  for (i = 0; i < BA_MAX_INT_NUM; i++, p_inst++) {
-    /* read battery level */
-    if (handle == p_inst->clt_cfg_hdl) {
-      cfg.remote_bda = srvc_eng_cb.clcb[clcb_idx].bda;
-      STREAM_TO_UINT16(cfg.clt_cfg, p);
-
-      if (p_inst->p_cback) {
-        p_inst->pending_clcb_idx = clcb_idx;
-        p_inst->pending_evt = BA_WRITE_CLT_CFG_REQ;
-        p_inst->pending_handle = handle;
-        cfg.need_rsp = p_value->need_rsp;
-        act = SRVC_ACT_PENDING;
-
-        (*p_inst->p_cback)(p_inst->app_id, BA_WRITE_CLT_CFG_REQ, &cfg);
-      }
-    } else /* all other handle is not writable */
-    {
-      st = GATT_WRITE_NOT_PERMIT;
-      break;
-    }
-  }
-  *p_status = st;
-
-  return act;
-}
-/*******************************************************************************
- *   BA Attributes Database Server Request callback
- ******************************************************************************/
-uint8_t battery_s_read_attr_value(uint8_t clcb_idx, uint16_t handle,
-                                  UNUSED_ATTR tGATT_VALUE* p_value,
-                                  bool is_long, tGATT_STATUS* p_status) {
-  uint8_t i;
-  tBA_INST* p_inst = &battery_cb.battery_inst[0];
-  tGATT_STATUS st = GATT_NOT_FOUND;
-  uint8_t act = SRVC_ACT_RSP;
-
-  for (i = 0; i < BA_MAX_INT_NUM; i++, p_inst++) {
-    /* read battery level */
-    if (handle == p_inst->ba_level_hdl || handle == p_inst->clt_cfg_hdl ||
-        handle == p_inst->rpt_ref_hdl || handle == p_inst->pres_fmt_hdl) {
-      if (is_long) st = GATT_NOT_LONG;
-
-      if (p_inst->p_cback) {
-        if (handle == p_inst->ba_level_hdl)
-          p_inst->pending_evt = BA_READ_LEVEL_REQ;
-        if (handle == p_inst->clt_cfg_hdl)
-          p_inst->pending_evt = BA_READ_CLT_CFG_REQ;
-        if (handle == p_inst->pres_fmt_hdl)
-          p_inst->pending_evt = BA_READ_PRE_FMT_REQ;
-        if (handle == p_inst->rpt_ref_hdl)
-          p_inst->pending_evt = BA_READ_RPT_REF_REQ;
-
-        p_inst->pending_clcb_idx = clcb_idx;
-        p_inst->pending_handle = handle;
-        act = SRVC_ACT_PENDING;
-
-        (*p_inst->p_cback)(p_inst->app_id, p_inst->pending_evt, NULL);
-      } else /* application is not registered */
-        st = GATT_ERR_UNLIKELY;
-      break;
-    }
-    /* else attribute not found */
-  }
-
-  *p_status = st;
-  return act;
-}
-
-/*******************************************************************************
- *
- * Function         battery_gatt_c_read_ba_req
- *
- * Description      Read remote device BA level attribute request.
- *
- * Returns          void
- *
- ******************************************************************************/
-bool battery_gatt_c_read_ba_req(UNUSED_ATTR uint16_t conn_id) { return true; }
-
-/*******************************************************************************
- *
- * Function         battery_c_cmpl_cback
- *
- * Description      Client operation complete callback.
- *
- * Returns          void
- *
- ******************************************************************************/
-void battery_c_cmpl_cback(UNUSED_ATTR tSRVC_CLCB* p_clcb,
-                          UNUSED_ATTR tGATTC_OPTYPE op,
-                          UNUSED_ATTR tGATT_STATUS status,
-                          UNUSED_ATTR tGATT_CL_COMPLETE* p_data) {}
-
-/*******************************************************************************
- *
- * Function         Battery_Instantiate
- *
- * Description      Instantiate a Battery service
- *
- ******************************************************************************/
-uint16_t Battery_Instantiate(uint8_t app_id, tBA_REG_INFO* p_reg_info) {
-  uint16_t srvc_hdl = 0;
-  tGATT_STATUS status = GATT_ERROR;
-  tBA_INST* p_inst;
-
-  if (battery_cb.inst_id == BA_MAX_INT_NUM) {
-    LOG(ERROR) << "MAX battery service has been reached";
-    return 0;
-  }
-
-  p_inst = &battery_cb.battery_inst[battery_cb.inst_id];
-
-  btgatt_db_element_t service[BA_MAX_ATTR_NUM] = {};
-
-  bluetooth::Uuid service_uuid =
-      bluetooth::Uuid::From16Bit(UUID_SERVCLASS_BATTERY);
-  service[0].type = /* p_reg_info->is_pri */ BTGATT_DB_PRIMARY_SERVICE;
-  service[0].uuid = service_uuid;
-
-  bluetooth::Uuid char_uuid =
-      bluetooth::Uuid::From16Bit(GATT_UUID_BATTERY_LEVEL);
-  service[1].type = BTGATT_DB_CHARACTERISTIC;
-  service[1].uuid = char_uuid;
-  service[1].properties = GATT_CHAR_PROP_BIT_READ;
-  if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY)
-    service[1].properties |= GATT_CHAR_PROP_BIT_NOTIFY;
-
-  int i = 2;
-  if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
-    bluetooth::Uuid desc_uuid =
-        bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_CLIENT_CONFIG);
-
-    service[i].type = BTGATT_DB_DESCRIPTOR;
-    service[i].uuid = desc_uuid;
-    service[i].permissions = (GATT_PERM_READ | GATT_PERM_WRITE);
-    i++;
-  }
-
-  /* need presentation format descriptor? */
-  if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
-    bluetooth::Uuid desc_uuid =
-        bluetooth::Uuid::From16Bit(GATT_UUID_CHAR_PRESENT_FORMAT);
-
-    service[i].type = BTGATT_DB_DESCRIPTOR;
-    service[i].uuid = desc_uuid;
-    service[i].permissions = GATT_PERM_READ;
-    i++;
-  }
-
-  /* need presentation format descriptor? */
-  if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
-    bluetooth::Uuid desc_uuid =
-        bluetooth::Uuid::From16Bit(GATT_UUID_RPT_REF_DESCR);
-
-    service[i].type = BTGATT_DB_DESCRIPTOR;
-    service[i].uuid = desc_uuid;
-    service[i].permissions = GATT_PERM_READ;
-    i++;
-  }
-
-  GATTS_AddService(srvc_eng_cb.gatt_if, service, i);
-
-  if (status != GATT_SUCCESS) {
-    battery_cb.inst_id--;
-    LOG(ERROR) << __func__ << " Failed to add battery servuce!";
-  }
-
-  battery_cb.inst_id++;
-
-  p_inst->app_id = app_id;
-  p_inst->p_cback = p_reg_info->p_cback;
-
-  srvc_hdl = service[0].attribute_handle;
-  p_inst->ba_level_hdl = service[1].attribute_handle;
-
-  i = 2;
-  if (p_reg_info->ba_level_descr & BA_LEVEL_NOTIFY) {
-    p_inst->clt_cfg_hdl = service[i].attribute_handle;
-    i++;
-  }
-
-  if (p_reg_info->ba_level_descr & BA_LEVEL_PRE_FMT) {
-    p_inst->pres_fmt_hdl = service[i].attribute_handle;
-    i++;
-  }
-
-  if (p_reg_info->ba_level_descr & BA_LEVEL_RPT_REF) {
-    p_inst->rpt_ref_hdl = service[i].attribute_handle;
-    i++;
-  }
-
-  return srvc_hdl;
-}
-/*******************************************************************************
- *
- * Function         Battery_Rsp
- *
- * Description      Respond to a battery service request
- *
- ******************************************************************************/
-void Battery_Rsp(uint8_t app_id, tGATT_STATUS st, uint8_t event,
-                 tBA_RSP_DATA* p_rsp) {
-  tBA_INST* p_inst = &battery_cb.battery_inst[0];
-  tGATTS_RSP rsp;
-  uint8_t* pp;
-
-  uint8_t i = 0;
-  while (i < BA_MAX_INT_NUM) {
-    if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) break;
-    i++;
-  }
-
-  if (i == BA_MAX_INT_NUM) return;
-
-  memset(&rsp, 0, sizeof(tGATTS_RSP));
-
-  if (p_inst->pending_evt == event) {
-    switch (event) {
-      case BA_READ_CLT_CFG_REQ:
-        rsp.attr_value.handle = p_inst->pending_handle;
-        rsp.attr_value.len = 2;
-        pp = rsp.attr_value.value;
-        UINT16_TO_STREAM(pp, p_rsp->clt_cfg);
-        srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
-        break;
-
-      case BA_READ_LEVEL_REQ:
-        rsp.attr_value.handle = p_inst->pending_handle;
-        rsp.attr_value.len = 1;
-        pp = rsp.attr_value.value;
-        UINT8_TO_STREAM(pp, p_rsp->ba_level);
-        srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
-        break;
-
-      case BA_WRITE_CLT_CFG_REQ:
-        srvc_sr_rsp(p_inst->pending_clcb_idx, st, NULL);
-        break;
-
-      case BA_READ_RPT_REF_REQ:
-        rsp.attr_value.handle = p_inst->pending_handle;
-        rsp.attr_value.len = 2;
-        pp = rsp.attr_value.value;
-        UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_id);
-        UINT8_TO_STREAM(pp, p_rsp->rpt_ref.rpt_type);
-        srvc_sr_rsp(p_inst->pending_clcb_idx, st, &rsp);
-        break;
-
-      default:
-        break;
-    }
-    p_inst->pending_clcb_idx = 0;
-    p_inst->pending_evt = 0;
-    p_inst->pending_handle = 0;
-  }
-  return;
-}
-/*******************************************************************************
- *
- * Function         Battery_Notify
- *
- * Description      Send battery level notification
- *
- ******************************************************************************/
-void Battery_Notify(uint8_t app_id, const RawAddress& remote_bda,
-                    uint8_t battery_level) {
-  tBA_INST* p_inst = &battery_cb.battery_inst[0];
-  uint8_t i = 0;
-
-  while (i < BA_MAX_INT_NUM) {
-    if (p_inst->app_id == app_id && p_inst->ba_level_hdl != 0) break;
-    i++;
-  }
-
-  if (i == BA_MAX_INT_NUM || p_inst->clt_cfg_hdl == 0) return;
-
-  srvc_sr_notify(remote_bda, p_inst->ba_level_hdl, 1, &battery_level);
-}
-/*******************************************************************************
- *
- * Function         Battery_ReadBatteryLevel
- *
- * Description      Read remote device Battery Level information.
- *
- * Returns          void
- *
- ******************************************************************************/
-bool Battery_ReadBatteryLevel(const RawAddress&) {
-  /* to be implemented */
-  return true;
-}
diff --git a/stack/srvc/srvc_battery_int.h b/stack/srvc/srvc_battery_int.h
deleted file mode 100644
index 2ffb85a..0000000
--- a/stack/srvc/srvc_battery_int.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 1999-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.
- *
- ******************************************************************************/
-
-#ifndef SRVC_BATTERY_INT_H
-#define SRVC_BATTERY_INT_H
-
-#include "bt_target.h"
-#include "gatt_api.h"
-#include "srvc_api.h"
-
-#ifndef BA_MAX_INT_NUM
-#define BA_MAX_INT_NUM 4
-#endif
-
-#define BATTERY_LEVEL_SIZE 1
-
-typedef struct {
-  uint8_t app_id;
-  uint16_t ba_level_hdl;
-  uint16_t clt_cfg_hdl;
-  uint16_t rpt_ref_hdl;
-  uint16_t pres_fmt_hdl;
-
-  tBA_CBACK* p_cback;
-
-  uint16_t pending_handle;
-  uint8_t pending_clcb_idx;
-  uint8_t pending_evt;
-
-} tBA_INST;
-
-typedef struct {
-  tBA_INST battery_inst[BA_MAX_INT_NUM];
-  uint8_t inst_id;
-  bool enabled;
-
-} tBATTERY_CB;
-
-/* Global GATT data */
-extern tBATTERY_CB battery_cb;
-
-extern bool battery_valid_handle_range(uint16_t handle);
-
-extern uint8_t battery_s_write_attr_value(uint8_t clcb_idx,
-                                          tGATT_WRITE_REQ* p_value,
-                                          tGATT_STATUS* p_status);
-extern uint8_t battery_s_read_attr_value(uint8_t clcb_idx, uint16_t handle,
-                                         tGATT_VALUE* p_value, bool is_long,
-                                         tGATT_STATUS* p_status);
-
-#endif
diff --git a/stack/srvc/srvc_eng.cc b/stack/srvc/srvc_eng.cc
index af57ff1..564a2ea 100644
--- a/stack/srvc/srvc_eng.cc
+++ b/stack/srvc/srvc_eng.cc
@@ -23,7 +23,6 @@
 #include "osi/include/osi.h"
 #include "srvc_eng_int.h"
 
-#include "srvc_battery_int.h"
 #include "srvc_dis_int.h"
 
 using base::StringPrintf;
@@ -213,12 +212,6 @@
   if (dis_valid_handle_range(p_data->handle))
     act = dis_read_attr_value(clcb_idx, p_data->handle, &p_rsp->attr_value,
                               p_data->is_long, p_status);
-
-  else if (battery_valid_handle_range(p_data->handle))
-    act =
-        battery_s_read_attr_value(clcb_idx, p_data->handle, &p_rsp->attr_value,
-                                  p_data->is_long, p_status);
-
   else
     *p_status = status;
   return act;
@@ -233,8 +226,6 @@
 
   if (dis_valid_handle_range(p_data->handle)) {
     act = dis_write_attr_value(p_data, p_status);
-  } else if (battery_valid_handle_range(p_data->handle)) {
-    act = battery_s_write_attr_value(clcb_idx, p_data, p_status);
   } else
     *p_status = GATT_NOT_FOUND;
 
diff --git a/stack/test/ble_advertiser_test.cc b/stack/test/ble_advertiser_test.cc
index 65a30d5..9c7d5a5 100644
--- a/stack/test/ble_advertiser_test.cc
+++ b/stack/test/ble_advertiser_test.cc
@@ -47,24 +47,16 @@
 uint16_t BTM_ReadDiscoverability(uint16_t* p_window, uint16_t* p_interval) {
   return true;
 }
-bool SMP_Encrypt(uint8_t* key, uint8_t key_len, uint8_t* plain_text,
-                 uint8_t pt_len, tSMP_ENC* p_out) {
-  return true;
-}
-void BTM_GetDeviceIDRoot(BT_OCTET16 irk) {}
-void btm_ble_update_dmt_flag_bits(uint8_t* flag_value,
-                                  const uint16_t connect_mode,
-                                  const uint16_t disc_mode) {}
 void btm_acl_update_conn_addr(uint16_t conn_handle, const RawAddress& address) {
 }
-void btm_gen_resolvable_private_addr(base::Callback<void(uint8_t[8])> cb) {
-  uint8_t fake_rand[8] = {0, 0, 0, 0, 0, 0, 0, 0};
-  cb.Run(fake_rand);
+void btm_gen_resolvable_private_addr(
+    base::Callback<void(const RawAddress& rpa)> cb) {
+  cb.Run(RawAddress::kEmpty);
 }
 
 alarm_callback_t last_alarm_cb = nullptr;
 void* last_alarm_data = nullptr;
-void alarm_set_on_mloop(alarm_t* alarm, period_ms_t interval_ms,
+void alarm_set_on_mloop(alarm_t* alarm, uint64_t interval_ms,
                         alarm_callback_t cb, void* data) {
   last_alarm_cb = cb;
   last_alarm_data = data;
diff --git a/stack/test/common/mock_btsnoop_module.cc b/stack/test/common/mock_btsnoop_module.cc
new file mode 100644
index 0000000..7a5c5ae
--- /dev/null
+++ b/stack/test/common/mock_btsnoop_module.cc
@@ -0,0 +1,42 @@
+/******************************************************************************
+ *
+ *  Copyright 2019 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "hci/include/btsnoop.h"
+
+static void capture(const BT_HDR*, bool) { /* do nothing */
+}
+
+static void whitelist_l2c_channel(uint16_t, uint16_t,
+                                  uint16_t) { /* do nothing */
+}
+
+static void whitelist_rfc_dlci(uint16_t, uint8_t) { /* do nothing */
+}
+
+static void add_rfc_l2c_channel(uint16_t, uint16_t, uint16_t) { /* do nothing */
+}
+
+static void clear_l2cap_whitelist(uint16_t, uint16_t,
+                                  uint16_t) { /* do nothing */
+}
+
+static const btsnoop_t fake_snoop = {capture, whitelist_l2c_channel,
+                                     whitelist_rfc_dlci, add_rfc_l2c_channel,
+                                     clear_l2cap_whitelist};
+
+const btsnoop_t* btsnoop_get_interface() { return &fake_snoop; }
diff --git a/stack/test/common/mock_btu_layer.cc b/stack/test/common/mock_btu_layer.cc
index f5bbf7a..6d7abe9 100644
--- a/stack/test/common/mock_btu_layer.cc
+++ b/stack/test/common/mock_btu_layer.cc
@@ -18,4 +18,4 @@
 
 #include <base/message_loop/message_loop.h>
 
-base::MessageLoop* get_message_loop() { return nullptr; }
\ No newline at end of file
+base::MessageLoop* get_main_message_loop() { return nullptr; }
\ No newline at end of file
diff --git a/stack/test/common/mock_l2cap_layer.cc b/stack/test/common/mock_l2cap_layer.cc
index 9f08d56..4756f17 100644
--- a/stack/test/common/mock_l2cap_layer.cc
+++ b/stack/test/common/mock_l2cap_layer.cc
@@ -24,9 +24,11 @@
   l2cap_interface = mock_l2cap_interface;
 }
 
-uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) {
-  VLOG(1) << __func__ << ": psm=" << psm << ", p_cb_info=" << p_cb_info;
-  return l2cap_interface->Register(psm, p_cb_info);
+uint16_t L2CA_Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                       bool enable_snoop) {
+  VLOG(1) << __func__ << ": psm=" << psm << ", p_cb_info=" << p_cb_info
+          << ", enable_snoop=" << enable_snoop;
+  return l2cap_interface->Register(psm, p_cb_info, enable_snoop);
 }
 
 uint16_t L2CA_ConnectReq(uint16_t psm, const RawAddress& bd_addr) {
diff --git a/stack/test/common/mock_l2cap_layer.h b/stack/test/common/mock_l2cap_layer.h
index 78c8a9c..ade7585 100644
--- a/stack/test/common/mock_l2cap_layer.h
+++ b/stack/test/common/mock_l2cap_layer.h
@@ -26,7 +26,8 @@
 
 class L2capInterface {
  public:
-  virtual uint16_t Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info) = 0;
+  virtual uint16_t Register(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                            bool enable_snoop) = 0;
   virtual uint16_t ConnectRequest(uint16_t psm, const RawAddress& bd_addr) = 0;
   virtual bool ConnectResponse(const RawAddress& bd_addr, uint8_t id,
                                uint16_t lcid, uint16_t result,
@@ -41,7 +42,8 @@
 
 class MockL2capInterface : public L2capInterface {
  public:
-  MOCK_METHOD2(Register, uint16_t(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info));
+  MOCK_METHOD3(Register, uint16_t(uint16_t psm, tL2CAP_APPL_INFO* p_cb_info,
+                                  bool enable_snoop));
   MOCK_METHOD2(ConnectRequest,
                uint16_t(uint16_t psm, const RawAddress& bd_addr));
   MOCK_METHOD5(ConnectResponse,
diff --git a/stack/test/crypto_toolbox_test.cc b/stack/test/crypto_toolbox_test.cc
new file mode 100644
index 0000000..727668d
--- /dev/null
+++ b/stack/test/crypto_toolbox_test.cc
@@ -0,0 +1,400 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+#include "stack/crypto_toolbox/aes.h"
+#include "stack/crypto_toolbox/crypto_toolbox.h"
+
+#include <base/logging.h>
+#include <base/strings/string_number_conversions.h>
+#include <vector>
+
+using ::testing::ElementsAreArray;
+
+namespace crypto_toolbox {
+
+// BT Spec 5.0 | Vol 3, Part H D.1
+TEST(CryptoToolboxTest, bt_spec_test_d_1_test) {
+  uint8_t k[] = {0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+                 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
+
+  uint8_t m[] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+  uint8_t aes_cmac_k_m[] = {0x7d, 0xf7, 0x6b, 0x0c, 0x1a, 0xb8, 0x99, 0xb3,
+                            0x3e, 0x42, 0xf0, 0x47, 0xb9, 0x1b, 0x54, 0x6f};
+
+  uint8_t output[16];
+  aes_context ctx;
+  aes_set_key(k, sizeof(k), &ctx);
+  aes_encrypt(m, output, &ctx); /* outputs in byte 48 to byte 63 */
+
+  EXPECT_THAT(output, ElementsAreArray(aes_cmac_k_m, OCTET16_LEN));
+
+  // useful for debugging
+  // LOG(INFO) << "k " << base::HexEncode(k, OCTET16_LEN);
+  // LOG(INFO) << "m " << base::HexEncode(m, sizeof(m));
+  // LOG(INFO) << "output " << base::HexEncode(output, OCTET16_LEN);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.1.1
+TEST(CryptoToolboxTest, bt_spec_example_d_1_1_test) {
+  Octet16 k{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+            0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
+
+  Octet16 aes_cmac_k_m{0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28,
+                       0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(k), std::end(k));
+  std::reverse(std::begin(aes_cmac_k_m), std::end(aes_cmac_k_m));
+
+  Octet16 output = aes_cmac(k, nullptr /* empty message */, 0);
+
+  EXPECT_EQ(output, aes_cmac_k_m);
+
+  // useful for debugging
+  // LOG(INFO) << "k " << base::HexEncode(k.data(), k.size());
+  // LOG(INFO) << "aes_cmac(k,nullptr) "
+  //           << base::HexEncode(output.data(), output.size());
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.1.2
+TEST(CryptoToolboxTest, bt_spec_example_d_1_2_test) {
+  Octet16 k{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+            0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
+
+  Octet16 m = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96,
+               0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a};
+
+  Octet16 aes_cmac_k_m{0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44,
+                       0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(k), std::end(k));
+  std::reverse(std::begin(m), std::end(m));
+  std::reverse(std::begin(aes_cmac_k_m), std::end(aes_cmac_k_m));
+
+  Octet16 output = aes_cmac(k, m);
+
+  EXPECT_EQ(output, aes_cmac_k_m);
+
+  // useful for debugging
+  // LOG(INFO) << "k " << base::HexEncode(k.data(), k.size());
+  // LOG(INFO) << "m " << base::HexEncode(m, sizeof(m));
+  // LOG(INFO) << "aes_cmac(k,m) "
+  //           << base::HexEncode(output.data(), output.size());
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.1.3
+TEST(CryptoToolboxTest, bt_spec_example_d_1_3_test) {
+  Octet16 k{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+            0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
+
+  uint8_t m[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d,
+                 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57,
+                 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf,
+                 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11};
+
+  Octet16 aes_cmac_k_m{0xdf, 0xa6, 0x67, 0x47, 0xde, 0x9a, 0xe6, 0x30,
+                       0x30, 0xca, 0x32, 0x61, 0x14, 0x97, 0xc8, 0x27};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(k), std::end(k));
+  std::reverse(std::begin(m), std::end(m));
+  std::reverse(std::begin(aes_cmac_k_m), std::end(aes_cmac_k_m));
+
+  Octet16 output = aes_cmac(k, m, sizeof(m));
+  EXPECT_EQ(output, aes_cmac_k_m);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.1.4
+TEST(CryptoToolboxTest, bt_spec_example_d_1_4_test) {
+  Octet16 k{0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6,
+            0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c};
+
+  uint8_t m[] = {0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, 0xe9, 0x3d,
+                 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, 0xae, 0x2d, 0x8a, 0x57,
+                 0x1e, 0x03, 0xac, 0x9c, 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf,
+                 0x8e, 0x51, 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11,
+                 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, 0xf6, 0x9f,
+                 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, 0xad, 0x2b, 0x41, 0x7b,
+                 0xe6, 0x6c, 0x37, 0x10};
+
+  Octet16 aes_cmac_k_m{0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92,
+                       0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(k), std::end(k));
+  std::reverse(std::begin(m), std::end(m));
+  std::reverse(std::begin(aes_cmac_k_m), std::end(aes_cmac_k_m));
+
+  Octet16 output = aes_cmac(k, m, sizeof(m));
+
+  EXPECT_EQ(output, aes_cmac_k_m);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.2
+TEST(CryptoToolboxTest, bt_spec_example_d_2_test) {
+  std::vector<uint8_t> u{0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c,
+                         0x5e, 0x2c, 0x83, 0xa7, 0xe9, 0xf9, 0xa5, 0xb9,
+                         0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb,
+                         0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6};
+  std::vector<uint8_t> v{0x55, 0x18, 0x8b, 0x3d, 0x32, 0xf6, 0xbb, 0x9a,
+                         0x90, 0x0a, 0xfc, 0xfb, 0xee, 0xd4, 0xe7, 0x2a,
+                         0x59, 0xcb, 0x9a, 0xc2, 0xf1, 0x9d, 0x7c, 0xfb,
+                         0x6b, 0x4f, 0xdd, 0x49, 0xf4, 0x7f, 0xc5, 0xfd};
+  Octet16 x{0xd5, 0xcb, 0x84, 0x54, 0xd1, 0x77, 0x73, 0x3e,
+            0xff, 0xff, 0xb2, 0xec, 0x71, 0x2b, 0xae, 0xab};
+  uint8_t z = 0x00;
+
+  Octet16 aes_cmac_k_m{0xf2, 0xc9, 0x16, 0xf1, 0x07, 0xa9, 0xbd, 0x1c,
+                       0xf1, 0xed, 0xa1, 0xbe, 0xa9, 0x74, 0x87, 0x2d};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(u), std::end(u));
+  std::reverse(std::begin(v), std::end(v));
+  std::reverse(std::begin(x), std::end(x));
+  std::reverse(std::begin(aes_cmac_k_m), std::end(aes_cmac_k_m));
+
+  Octet16 output = f4(u.data(), v.data(), x, z);
+
+  EXPECT_EQ(output, aes_cmac_k_m);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.3
+TEST(CryptoToolboxTest, bt_spec_example_d_3_test) {
+  std::array<uint8_t, 32> dhkey_w{
+      0xec, 0x02, 0x34, 0xa3, 0x57, 0xc8, 0xad, 0x05, 0x34, 0x10, 0x10,
+      0xa6, 0x0a, 0x39, 0x7d, 0x9b, 0x99, 0x79, 0x6b, 0x13, 0xb4, 0xf8,
+      0x66, 0xf1, 0x86, 0x8d, 0x34, 0xf3, 0x73, 0xbf, 0xa6, 0x98};
+  Octet16 n1{0xd5, 0xcb, 0x84, 0x54, 0xd1, 0x77, 0x73, 0x3e,
+             0xff, 0xff, 0xb2, 0xec, 0x71, 0x2b, 0xae, 0xab};
+  Octet16 n2{0xa6, 0xe8, 0xe7, 0xcc, 0x25, 0xa7, 0x5f, 0x6e,
+             0x21, 0x65, 0x83, 0xf7, 0xff, 0x3d, 0xc4, 0xcf};
+  std::array<uint8_t, 7> a1{0x00, 0x56, 0x12, 0x37, 0x37, 0xbf, 0xce};
+  std::array<uint8_t, 7> a2{0x00, 0xa7, 0x13, 0x70, 0x2d, 0xcf, 0xc1};
+
+  Octet16 expected_ltk{0x69, 0x86, 0x79, 0x11, 0x69, 0xd7, 0xcd, 0x23,
+                       0x98, 0x05, 0x22, 0xb5, 0x94, 0x75, 0x0a, 0x38};
+  Octet16 expected_mac_key{0x29, 0x65, 0xf1, 0x76, 0xa1, 0x08, 0x4a, 0x02,
+                           0xfd, 0x3f, 0x6a, 0x20, 0xce, 0x63, 0x6e, 0x20};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(dhkey_w), std::end(dhkey_w));
+  std::reverse(std::begin(n1), std::end(n1));
+  std::reverse(std::begin(n2), std::end(n2));
+  std::reverse(std::begin(a1), std::end(a1));
+  std::reverse(std::begin(a2), std::end(a2));
+  std::reverse(std::begin(expected_ltk), std::end(expected_ltk));
+  std::reverse(std::begin(expected_mac_key), std::end(expected_mac_key));
+
+  Octet16 mac_key, ltk;
+  f5(dhkey_w.data(), n1, n2, a1.data(), a2.data(), &mac_key, &ltk);
+
+  EXPECT_EQ(mac_key, expected_mac_key);
+  EXPECT_EQ(ltk, expected_ltk);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.4
+TEST(CryptoToolboxTest, bt_spec_example_d_4_test) {
+  Octet16 n1{0xd5, 0xcb, 0x84, 0x54, 0xd1, 0x77, 0x73, 0x3e,
+             0xff, 0xff, 0xb2, 0xec, 0x71, 0x2b, 0xae, 0xab};
+  Octet16 n2{0xa6, 0xe8, 0xe7, 0xcc, 0x25, 0xa7, 0x5f, 0x6e,
+             0x21, 0x65, 0x83, 0xf7, 0xff, 0x3d, 0xc4, 0xcf};
+  Octet16 r{0x12, 0xa3, 0x34, 0x3b, 0xb4, 0x53, 0xbb, 0x54,
+            0x08, 0xda, 0x42, 0xd2, 0x0c, 0x2d, 0x0f, 0xc8};
+  std::vector<uint8_t> IOcap{0x01, 0x01, 0x02};
+  std::vector<uint8_t> a1{0x00, 0x56, 0x12, 0x37, 0x37, 0xbf, 0xce};
+  std::vector<uint8_t> a2{0x00, 0xa7, 0x13, 0x70, 0x2d, 0xcf, 0xc1};
+
+  Octet16 MacKey{0x29, 0x65, 0xf1, 0x76, 0xa1, 0x08, 0x4a, 0x02,
+                 0xfd, 0x3f, 0x6a, 0x20, 0xce, 0x63, 0x6e, 0x20};
+
+  Octet16 expected_aes_cmac{0xe3, 0xc4, 0x73, 0x98, 0x9c, 0xd0, 0xe8, 0xc5,
+                            0xd2, 0x6c, 0x0b, 0x09, 0xda, 0x95, 0x8f, 0x61};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(n1), std::end(n1));
+  std::reverse(std::begin(n2), std::end(n2));
+  std::reverse(std::begin(r), std::end(r));
+  std::reverse(std::begin(IOcap), std::end(IOcap));
+  std::reverse(std::begin(a1), std::end(a1));
+  std::reverse(std::begin(a2), std::end(a2));
+  std::reverse(std::begin(MacKey), std::end(MacKey));
+  std::reverse(std::begin(expected_aes_cmac), std::end(expected_aes_cmac));
+
+  Octet16 aes_cmac = f6(MacKey, n1, n2, r, IOcap.data(), a1.data(), a2.data());
+
+  EXPECT_EQ(aes_cmac, expected_aes_cmac);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.5
+TEST(CryptoToolboxTest, bt_spec_example_d_5_test) {
+  std::array<uint8_t, 32> u{0x20, 0xb0, 0x03, 0xd2, 0xf2, 0x97, 0xbe, 0x2c,
+                            0x5e, 0x2c, 0x83, 0xa7, 0xe9, 0xf9, 0xa5, 0xb9,
+                            0xef, 0xf4, 0x91, 0x11, 0xac, 0xf4, 0xfd, 0xdb,
+                            0xcc, 0x03, 0x01, 0x48, 0x0e, 0x35, 0x9d, 0xe6};
+  std::array<uint8_t, 32> v{0x55, 0x18, 0x8b, 0x3d, 0x32, 0xf6, 0xbb, 0x9a,
+                            0x90, 0x0a, 0xfc, 0xfb, 0xee, 0xd4, 0xe7, 0x2a,
+                            0x59, 0xcb, 0x9a, 0xc2, 0xf1, 0x9d, 0x7c, 0xfb,
+                            0x6b, 0x4f, 0xdd, 0x49, 0xf4, 0x7f, 0xc5, 0xfd};
+
+  Octet16 x{0xd5, 0xcb, 0x84, 0x54, 0xd1, 0x77, 0x73, 0x3e,
+            0xff, 0xff, 0xb2, 0xec, 0x71, 0x2b, 0xae, 0xab};
+  Octet16 y{0xa6, 0xe8, 0xe7, 0xcc, 0x25, 0xa7, 0x5f, 0x6e,
+            0x21, 0x65, 0x83, 0xf7, 0xff, 0x3d, 0xc4, 0xcf};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(u), std::end(u));
+  std::reverse(std::begin(v), std::end(v));
+  std::reverse(std::begin(x), std::end(x));
+  std::reverse(std::begin(y), std::end(y));
+
+  uint32_t val = g2(u.data(), v.data(), x, y);
+
+  /* the returned value is already mod 1000000, so do mod on the test result
+   * value too */
+  EXPECT_EQ(val, 0x2f9ed5baU % 1000000);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.6
+TEST(CryptoToolboxTest, bt_spec_example_d_6_test) {
+  Octet16 key{0xec, 0x02, 0x34, 0xa3, 0x57, 0xc8, 0xad, 0x05,
+              0x34, 0x10, 0x10, 0xa6, 0x0a, 0x39, 0x7d, 0x9b};
+  std::array<uint8_t, 4> keyID{0x6c, 0x65, 0x62, 0x72};
+  Octet16 expected_aes_cmac{0x2d, 0x9a, 0xe1, 0x02, 0xe7, 0x6d, 0xc9, 0x1c,
+                            0xe8, 0xd3, 0xa9, 0xe2, 0x80, 0xb1, 0x63, 0x99};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(key), std::end(key));
+  std::reverse(std::begin(keyID), std::end(keyID));
+  std::reverse(std::begin(expected_aes_cmac), std::end(expected_aes_cmac));
+
+  Octet16 aes_cmac = h6(key, keyID);
+  EXPECT_EQ(aes_cmac, expected_aes_cmac);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.7
+TEST(CryptoToolboxTest, bt_spec_example_d_7_test) {
+  Octet16 IRK{0xec, 0x02, 0x34, 0xa3, 0x57, 0xc8, 0xad, 0x05,
+              0x34, 0x10, 0x10, 0xa6, 0x0a, 0x39, 0x7d, 0x9b};
+  Octet16 prand{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+                0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x81, 0x94};
+  Octet16 expected_aes_128{0x15, 0x9d, 0x5f, 0xb7, 0x2e, 0xbe, 0x23, 0x11,
+                           0xa4, 0x8c, 0x1b, 0xdc, 0xc4, 0x0d, 0xfb, 0xaa};
+  std::array<uint8_t, 3> expected_ah{0x0d, 0xfb, 0xaa};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(IRK), std::end(IRK));
+  std::reverse(std::begin(prand), std::end(prand));
+  std::reverse(std::begin(expected_aes_128), std::end(expected_aes_128));
+  std::reverse(std::begin(expected_ah), std::end(expected_ah));
+
+  Octet16 result = aes_128(IRK, prand.data(), 3);
+  EXPECT_EQ(expected_aes_128, result);
+
+  // little/big endian 24 bits
+  EXPECT_EQ(result[0], expected_ah[0]);
+  EXPECT_EQ(result[1], expected_ah[1]);
+  EXPECT_EQ(result[2], expected_ah[2]);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.8
+TEST(CryptoToolboxTest, bt_spec_example_d_8_test) {
+  Octet16 Key{0xec, 0x02, 0x34, 0xa3, 0x57, 0xc8, 0xad, 0x05,
+              0x34, 0x10, 0x10, 0xa6, 0x0a, 0x39, 0x7d, 0x9b};
+  Octet16 SALT{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+               0x00, 0x00, 0x00, 0x00, 0x74, 0x6D, 0x70, 0x31};
+  Octet16 expected_aes_cmac{0xfb, 0x17, 0x35, 0x97, 0xc6, 0xa3, 0xc0, 0xec,
+                            0xd2, 0x99, 0x8c, 0x2a, 0x75, 0xa5, 0x70, 0x11};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(Key), std::end(Key));
+  std::reverse(std::begin(SALT), std::end(SALT));
+  std::reverse(std::begin(expected_aes_cmac), std::end(expected_aes_cmac));
+
+  Octet16 aes_cmac = h7(SALT, Key);
+  EXPECT_EQ(expected_aes_cmac, aes_cmac);
+}
+
+extern Octet16 smp_calculate_ltk_to_link_key(const Octet16& ltk, bool use_h7);
+
+// BT Spec 5.0 | Vol 3, Part H D.9
+TEST(CryptoToolboxTest, bt_spec_example_d_9_test) {
+  Octet16 LTK{0x36, 0x8d, 0xf9, 0xbc, 0xe3, 0x26, 0x4b, 0x58,
+              0xbd, 0x06, 0x6c, 0x33, 0x33, 0x4f, 0xbf, 0x64};
+  Octet16 expected_link_key{0x28, 0x7a, 0xd3, 0x79, 0xdc, 0xa4, 0x02, 0x53,
+                            0x0a, 0x39, 0xf1, 0xf4, 0x30, 0x47, 0xb8, 0x35};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(LTK), std::end(LTK));
+  std::reverse(std::begin(expected_link_key), std::end(expected_link_key));
+
+  Octet16 link_key = ltk_to_link_key(LTK, true);
+  EXPECT_EQ(expected_link_key, link_key);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.10
+TEST(CryptoToolboxTest, bt_spec_example_d_10_test) {
+  Octet16 LTK{0x36, 0x8d, 0xf9, 0xbc, 0xe3, 0x26, 0x4b, 0x58,
+              0xbd, 0x06, 0x6c, 0x33, 0x33, 0x4f, 0xbf, 0x64};
+  Octet16 expected_link_key{0xbc, 0x1c, 0xa4, 0xef, 0x63, 0x3f, 0xc1, 0xbd,
+                            0x0d, 0x82, 0x30, 0xaf, 0xee, 0x38, 0x8f, 0xb0};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(LTK), std::end(LTK));
+  std::reverse(std::begin(expected_link_key), std::end(expected_link_key));
+
+  Octet16 link_key = ltk_to_link_key(LTK, false);
+  EXPECT_EQ(expected_link_key, link_key);
+}
+
+// // BT Spec 5.0 | Vol 3, Part H D.11
+TEST(CryptoToolboxTest, bt_spec_example_d_11_test) {
+  Octet16 link_key{0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x09, 0x08,
+                   0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
+  Octet16 expected_ltk{0xe8, 0x5e, 0x09, 0xeb, 0x5e, 0xcc, 0xb3, 0xe2,
+                       0x69, 0x41, 0x8a, 0x13, 0x32, 0x11, 0xbc, 0x79};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(link_key), std::end(link_key));
+  std::reverse(std::begin(expected_ltk), std::end(expected_ltk));
+
+  Octet16 ltk = link_key_to_ltk(link_key, true);
+  EXPECT_EQ(expected_ltk, ltk);
+}
+
+// BT Spec 5.0 | Vol 3, Part H D.12
+TEST(CryptoToolboxTest, bt_spec_example_d_12_test) {
+  Octet16 link_key{0x05, 0x04, 0x03, 0x02, 0x01, 0x00, 0x09, 0x08,
+                   0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00};
+  Octet16 expected_ltk{0xa8, 0x13, 0xfb, 0x72, 0xf1, 0xa3, 0xdf, 0xa1,
+                       0x8a, 0x2c, 0x9a, 0x43, 0xf1, 0x0d, 0x0a, 0x30};
+
+  // algorithm expect all input to be in little endian format, so reverse
+  std::reverse(std::begin(link_key), std::end(link_key));
+  std::reverse(std::begin(expected_ltk), std::end(expected_ltk));
+
+  Octet16 ltk = link_key_to_ltk(link_key, false);
+  EXPECT_EQ(expected_ltk, ltk);
+}
+
+}  // namespace crypto_toolbox
diff --git a/stack/test/gatt_connection_manager_test.cc b/stack/test/gatt_connection_manager_test.cc
new file mode 100644
index 0000000..eed3776
--- /dev/null
+++ b/stack/test/gatt_connection_manager_test.cc
@@ -0,0 +1,274 @@
+#include "stack/gatt/connection_manager.h"
+
+#include <base/bind.h>
+#include <base/callback.h>
+#include <base/location.h>
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include <memory>
+#include "osi/include/alarm.h"
+#include "osi/test/alarm_mock.h"
+
+using testing::_;
+using testing::Mock;
+using testing::Return;
+using testing::SaveArg;
+
+using connection_manager::tAPP_ID;
+
+namespace {
+// convinience mock, for verifying whitelist operaitons on lower layer are
+// actually scheduled
+class WhiteListMock {
+ public:
+  MOCK_METHOD1(WhiteListAdd, bool(const RawAddress&));
+  MOCK_METHOD1(WhiteListRemove, void(const RawAddress&));
+  MOCK_METHOD0(WhiteListClear, void());
+  MOCK_METHOD0(SetLeConnectionModeToFast, bool());
+  MOCK_METHOD0(SetLeConnectionModeToSlow, void());
+  MOCK_METHOD2(OnConnectionTimedOut, void(uint8_t, const RawAddress&));
+};
+
+std::unique_ptr<WhiteListMock> localWhiteListMock;
+}  // namespace
+
+RawAddress address1{{0x01, 0x01, 0x01, 0x01, 0x01, 0x01}};
+RawAddress address2{{0x22, 0x22, 0x02, 0x22, 0x33, 0x22}};
+
+constexpr tAPP_ID CLIENT1 = 1;
+constexpr tAPP_ID CLIENT2 = 2;
+constexpr tAPP_ID CLIENT3 = 3;
+constexpr tAPP_ID CLIENT10 = 10;
+
+// Implementation of btm_ble_bgconn.h API for test.
+bool BTM_WhiteListAdd(const RawAddress& address) {
+  return localWhiteListMock->WhiteListAdd(address);
+}
+
+void BTM_WhiteListRemove(const RawAddress& address) {
+  return localWhiteListMock->WhiteListRemove(address);
+}
+
+void BTM_WhiteListClear() { return localWhiteListMock->WhiteListClear(); }
+
+bool BTM_SetLeConnectionModeToFast() {
+  return localWhiteListMock->SetLeConnectionModeToFast();
+}
+
+void BTM_SetLeConnectionModeToSlow() {
+  localWhiteListMock->SetLeConnectionModeToSlow();
+}
+
+namespace connection_manager {
+class BleConnectionManager : public testing::Test {
+  virtual void SetUp() {
+    localWhiteListMock = std::make_unique<WhiteListMock>();
+  }
+
+  virtual void TearDown() {
+    connection_manager::reset(true);
+    AlarmMock::Reset();
+    localWhiteListMock.reset();
+  }
+};
+
+void on_connection_timed_out(uint8_t app_id, const RawAddress& address) {
+  localWhiteListMock->OnConnectionTimedOut(app_id, address);
+}
+
+/** Verify that app can add a device to white list, it is returned as interested
+ * app, and then can remove the device later. */
+TEST_F(BleConnectionManager, test_background_connection_add_remove) {
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(0);
+
+  EXPECT_TRUE(background_connect_add(CLIENT1, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  std::set<tAPP_ID> apps = get_apps_connecting_to(address1);
+  EXPECT_EQ(apps.size(), 1UL);
+  EXPECT_EQ(apps.count(CLIENT1), 1UL);
+
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(_)).Times(0);
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(address1)).Times(1);
+
+  EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
+
+  EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+}
+
+/** Verify that multiple clients adding same device multiple times, result in
+ * device being added to whtie list only once, also, that device is removed only
+ * after last client removes it. */
+TEST_F(BleConnectionManager, test_background_connection_multiple_clients) {
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(0);
+  EXPECT_TRUE(background_connect_add(CLIENT1, address1));
+  EXPECT_TRUE(background_connect_add(CLIENT1, address1));
+  EXPECT_TRUE(background_connect_add(CLIENT2, address1));
+  EXPECT_TRUE(background_connect_add(CLIENT3, address1));
+
+  EXPECT_EQ(get_apps_connecting_to(address1).size(), 3UL);
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(_)).Times(0);
+
+  // removing from nonexisting client, should fail
+  EXPECT_FALSE(background_connect_remove(CLIENT10, address1));
+
+  EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
+  // already removed,  removing from same client twice should return false;
+  EXPECT_FALSE(background_connect_remove(CLIENT1, address1));
+  EXPECT_TRUE(background_connect_remove(CLIENT2, address1));
+
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(address1)).Times(1);
+  EXPECT_TRUE(background_connect_remove(CLIENT3, address1));
+
+  EXPECT_EQ(get_apps_connecting_to(address1).size(), 0UL);
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+}
+
+/** Verify adding/removing device to direct connection. */
+TEST_F(BleConnectionManager, test_direct_connection_client) {
+  // Direct connect attempt: use faster scan parameters, add to white list,
+  // start 30 timeout
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToFast()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(0);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
+  EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
+
+  // App already doing a direct connection, attempt to re-add result in failure
+  EXPECT_FALSE(direct_connect_add(CLIENT1, address1));
+
+  // Client that don't do direct connection should fail attempt to stop it
+  EXPECT_FALSE(direct_connect_remove(CLIENT2, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToSlow()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
+
+  // Removal should lower the connection parameters, and free the alarm.
+  // Even though we call WhiteListRemove, it won't be executed over HCI until
+  // whitelist is in use, i.e. next connection attempt
+  EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+}
+
+/** Verify direct connection timeout does remove device from white list, and
+ * lower the connection scan parameters */
+TEST_F(BleConnectionManager, test_direct_connect_timeout) {
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToFast()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
+  alarm_callback_t alarm_callback = nullptr;
+  void* alarm_data = nullptr;
+
+  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _))
+      .Times(1)
+      .WillOnce(DoAll(SaveArg<2>(&alarm_callback), SaveArg<3>(&alarm_data)));
+
+  // Start direct connect attempt...
+  EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToSlow()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(1);
+  EXPECT_CALL(*localWhiteListMock, OnConnectionTimedOut(CLIENT1, address1)).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
+
+  // simulate timeout seconds passed, alarm executing
+  alarm_callback(alarm_data);
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+}
+
+/** Verify that we properly handle successfull direct connection */
+TEST_F(BleConnectionManager, test_direct_connection_success) {
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToFast()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
+
+  // Start direct connect attempt...
+  EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToSlow()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(address1)).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
+  // simulate event from lower layers - connections was established
+  // successfully.
+  on_connection_complete(address1);
+}
+
+/** Verify that we properly handle application unregistration */
+TEST_F(BleConnectionManager, test_app_unregister) {
+  /* Test scenario:
+   * - Client 1 connecting to address1 and address2.
+   * - Client 2 connecting to address2
+   * - unregistration of Client1 should trigger address1 removal from white list
+   * - unregistration of Client2 should trigger address2 removal
+   */
+
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address2))
+      .WillOnce(Return(true));
+  EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
+  EXPECT_TRUE(background_connect_add(CLIENT1, address2));
+  EXPECT_TRUE(direct_connect_add(CLIENT2, address2));
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(address1)).Times(1);
+  on_app_deregistered(CLIENT1);
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(address2)).Times(1);
+  on_app_deregistered(CLIENT2);
+}
+
+/** Verify adding device to both direct connection and background connection. */
+TEST_F(BleConnectionManager, test_direct_and_background_connect) {
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToFast()).Times(1);
+  EXPECT_CALL(*localWhiteListMock, WhiteListAdd(address1))
+      .WillOnce(Return(true));
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(0);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmNew(_)).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmSetOnMloop(_, _, _, _)).Times(1);
+  // add device as both direct and background connection
+  EXPECT_TRUE(direct_connect_add(CLIENT1, address1));
+  EXPECT_TRUE(background_connect_add(CLIENT1, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+
+  EXPECT_CALL(*localWhiteListMock, SetLeConnectionModeToSlow()).Times(1);
+  EXPECT_CALL(*AlarmMock::Get(), AlarmFree(_)).Times(1);
+  // not removing from white list yet, as the background connection is still
+  // pending.
+  EXPECT_TRUE(direct_connect_remove(CLIENT1, address1));
+
+  // remove from white list, because no more interest in device.
+  EXPECT_CALL(*localWhiteListMock, WhiteListRemove(_)).Times(1);
+  EXPECT_TRUE(background_connect_remove(CLIENT1, address1));
+
+  Mock::VerifyAndClearExpectations(localWhiteListMock.get());
+}
+
+}  // namespace connection_manager
diff --git a/stack/test/rfcomm/stack_rfcomm_test.cc b/stack/test/rfcomm/stack_rfcomm_test.cc
index 3d9da3f..52e1170 100644
--- a/stack/test/rfcomm/stack_rfcomm_test.cc
+++ b/stack/test/rfcomm/stack_rfcomm_test.cc
@@ -453,7 +453,7 @@
         &btm_security_internal_interface_);
     bluetooth::l2cap::SetMockInterface(&l2cap_interface_);
     rfcomm_callback = &rfcomm_callback_;
-    EXPECT_CALL(l2cap_interface_, Register(BT_PSM_RFCOMM, _))
+    EXPECT_CALL(l2cap_interface_, Register(BT_PSM_RFCOMM, _, _))
         .WillOnce(
             DoAll(SaveArgPointee<1>(&l2cap_appl_info_), Return(BT_PSM_RFCOMM)));
     RFCOMM_Init();
diff --git a/stack/test/stack_a2dp_test.cc b/stack/test/stack_a2dp_test.cc
index 63dfb28..fecb3ca 100644
--- a/stack/test/stack_a2dp_test.cc
+++ b/stack/test/stack_a2dp_test.cc
@@ -173,6 +173,7 @@
 static const char* APTX_ENCODER_LIB_NAME = "libaptX_encoder.so";
 static const char* APTX_HD_ENCODER_LIB_NAME = "libaptXHD_encoder.so";
 static const char* LDAC_ENCODER_LIB_NAME = "libldacBT_enc.so";
+static const char* LDAC_DECODER_LIB_NAME = "libldacBT_dec.so";
 
 static bool has_shared_library(const char* name) {
   void* lib_handle = dlopen(name, RTLD_NOW);
@@ -223,6 +224,11 @@
         case BTAV_A2DP_CODEC_INDEX_SINK_AAC:
           supported = true;
           break;
+        case BTAV_A2DP_CODEC_INDEX_SINK_LDAC:
+          // Codec LDAC is supported only if the device has the corresponding
+          // shared library installed.
+          supported = has_shared_library(LDAC_DECODER_LIB_NAME);
+          break;
         case BTAV_A2DP_CODEC_INDEX_MAX:
           // Needed to avoid using "default:" case so we can capture when
           // a new codec is added, and it can be included here.
diff --git a/stack/test/stack_btu_test.cc b/stack/test/stack_btu_test.cc
index 97e95d2..5976bb2 100644
--- a/stack/test/stack_btu_test.cc
+++ b/stack/test/stack_btu_test.cc
@@ -26,9 +26,9 @@
 #include <unistd.h>
 
 #include "btcore/include/module.h"
+#include "common/message_loop_thread.h"
 #include "osi/include/alarm.h"
 #include "osi/include/fixed_queue.h"
-#include "osi/include/thread.h"
 #include "stack/include/btu.h"
 
 class TimeoutHelper {
@@ -60,17 +60,17 @@
 TimeoutHelper helper;
 
 // External function definitions
-void btu_message_loop_run(void* context);
 void btu_task_start_up(void* context);
 void btu_task_shut_down(void* context);
 
 /* Below are methods and variables that must be implemented if we don't want to
  * compile the whole stack. They will be removed, or changed into mocks one by
  * one in the future, as the refactoring progresses */
-void btif_transfer_context(void (*)(unsigned short, char*), uint16_t, char*,
-                           int, void (*)(unsigned short, char*, char*)) {
+bt_status_t do_in_jni_thread(const base::Location& from_here,
+                             base::OnceClosure task) {
   helper.notify();
-};
+  return BT_STATUS_SUCCESS;
+}
 
 void btu_init_core(){};
 void btif_init_ok(unsigned short, char*){};
@@ -82,7 +82,7 @@
 bool module_init(module_t const*) { return true; };
 void module_clean_up(module_t const*){};
 
-thread_t* bt_workqueue_thread;
+bluetooth::common::MessageLoopThread bt_startup_thread("test alarm thread");
 
 class BtuMessageLoopTest : public testing::Test {
  public:
@@ -92,8 +92,7 @@
   virtual void SetUp() {
     // Initialize alarms to prevent btu_task_shut_down from crashing
     alarm_new("test alarm");
-    bt_workqueue_thread = thread_new("test alarm thread");
-
+    bt_startup_thread.StartUp();
     // btu_task_start_up calls btif_transfer_context to let the stack know
     // start up is finished
     btu_task_start_up(nullptr);
@@ -104,13 +103,14 @@
   virtual void TearDown() {
     btu_task_shut_down(nullptr);
     alarm_cleanup();
+    bt_startup_thread.ShutDown();
   }
 
   void Fail(std::string message) { FAIL() << message; }
 };
 
 TEST_F(BtuMessageLoopTest, send_message) {
-  message_loop = get_message_loop();
+  message_loop = get_main_message_loop();
   EXPECT_FALSE(message_loop == nullptr);
 
   EXPECT_CALL(*this, TestCallback()).Times(1);
diff --git a/stack/test/stack_smp_test.cc b/stack/test/stack_smp_test.cc
index 12c10f6..0b1f0a9 100644
--- a/stack/test/stack_smp_test.cc
+++ b/stack/test/stack_smp_test.cc
@@ -81,70 +81,58 @@
   va_end(args);
 }
 
-extern void smp_gen_p1_4_confirm(tSMP_CB* p_cb,
-                                 tBLE_ADDR_TYPE remote_bd_addr_type,
-                                 BT_OCTET16 p1);
+extern Octet16 smp_gen_p1_4_confirm(tSMP_CB* p_cb,
+                                    tBLE_ADDR_TYPE remote_bd_addr_type);
 
-extern void smp_gen_p2_4_confirm(tSMP_CB* p_cb, const RawAddress& remote_bda,
-                                 BT_OCTET16 p2);
+extern Octet16 smp_gen_p2_4_confirm(tSMP_CB* p_cb,
+                                    const RawAddress& remote_bda);
 
-extern tSMP_STATUS smp_calculate_comfirm(tSMP_CB* p_cb, BT_OCTET16 rand,
-                                         tSMP_ENC* output);
+extern tSMP_STATUS smp_calculate_comfirm(tSMP_CB* p_cb, const Octet16& rand,
+                                         Octet16* output);
 
 namespace testing {
 
-void dump_uint128(BT_OCTET16 a, char* buffer) {
-  for (unsigned int i = 0; i < sizeof(BT_OCTET16); ++i) {
+void dump_uint128(const Octet16& a, char* buffer) {
+  for (unsigned int i = 0; i < OCTET16_LEN; ++i) {
     snprintf(buffer, 3, "%02x", a[i]);
     buffer += 2;
   }
   *buffer = '\0';
 }
 
-void dump_uint128_reverse(BT_OCTET16 a, char* buffer) {
-  for (int i = (int)(sizeof(BT_OCTET16) - 1); i >= 0; --i) {
+void dump_uint128_reverse(const Octet16& a, char* buffer) {
+  for (int i = (int)(OCTET16_LEN - 1); i >= 0; --i) {
     snprintf(buffer, 3, "%02x", a[i]);
     buffer += 2;
   }
   *buffer = '\0';
 }
 
-void print_uint128(BT_OCTET16 a) {
-  for (unsigned int i = 0; i < sizeof(BT_OCTET16); ++i) {
+void print_uint128(const Octet16& a) {
+  for (unsigned int i = 0; i < OCTET16_LEN; ++i) {
     printf("%02x", a[i]);
   }
   printf("\n");
 }
 
-void parse_uint128(const char* input, BT_OCTET16 output) {
-  memset(output, 0, sizeof(BT_OCTET16));
-  for (unsigned int count = 0; count < sizeof(BT_OCTET16); count++) {
+Octet16 parse_uint128(const char* input) {
+  Octet16 output{0};
+  for (unsigned int count = 0; count < OCTET16_LEN; count++) {
     sscanf(input, "%2hhx", &output[count]);
     input += 2;
   }
-}
-
-void reverse_array_inplace(BT_OCTET16 a) {
-  uint8_t tmp;
-  uint8_t* a_end = a + sizeof(BT_OCTET16) - 1;
-  while (a_end > a) {
-    tmp = *a_end;
-    *a_end = *a;
-    *a = tmp;
-    ++a;
-    --a_end;
-  }
+  return output;
 }
 
 class SmpCalculateConfirmTest : public Test {
  protected:
   tSMP_CB p_cb_;
   // Set random to 0x5783D52156AD6F0E6388274EC6702EE0
-  BT_OCTET16 rand_ = {0x57, 0x83, 0xD5, 0x21, 0x56, 0xAD, 0x6F, 0x0E,
-                      0x63, 0x88, 0x27, 0x4E, 0xC6, 0x70, 0x2E, 0xE0};
+  Octet16 rand_{0x57, 0x83, 0xD5, 0x21, 0x56, 0xAD, 0x6F, 0x0E,
+                0x63, 0x88, 0x27, 0x4E, 0xC6, 0x70, 0x2E, 0xE0};
 
   void SetUp() {
-    memset(p_cb_.tk, 0, sizeof(p_cb_.tk));
+    p_cb_.tk = {0};
     // Set pairing request packet to 0x070710000001(01)
     p_cb_.local_io_capability = 0x01;
     p_cb_.loc_oob_flag = 0x00;
@@ -161,7 +149,7 @@
     p_cb_.peer_r_key = 0x05;
     // Set role to master
     p_cb_.role = HCI_ROLE_MASTER;
-    reverse_array_inplace(rand_);
+    std::reverse(rand_.begin(), rand_.end());
   }
   void TearDown() {}
 
@@ -170,59 +158,54 @@
 
 // Test smp_gen_p2_4_confirm function implementation
 TEST_F(SmpCalculateConfirmTest, test_smp_gen_p2_4_confirm_as_master) {
-  BT_OCTET16 p2;
   RawAddress remote_bda;
   tBLE_ADDR_TYPE remote_bd_addr_type = 0;
   BTM_ReadRemoteConnectionAddr(p_cb_.pairing_bda, remote_bda,
                                &remote_bd_addr_type);
   BTM_ReadConnectionAddr(p_cb_.pairing_bda, p_cb_.local_bda, &p_cb_.addr_type);
-  smp_gen_p2_4_confirm(&p_cb_, remote_bda, p2);
+  Octet16 p2 = smp_gen_p2_4_confirm(&p_cb_, remote_bda);
   // Correct p2 is 0x00000000a1a2a3a4a5a6b1b2b3b4b5b6
   const char expected_p2_str[] = "00000000a1a2a3a4a5a6b1b2b3b4b5b6";
-  char p2_str[2 * sizeof(BT_OCTET16) + 1];
+  char p2_str[2 * OCTET16_LEN + 1];
   dump_uint128_reverse(p2, p2_str);
   ASSERT_THAT(p2_str, StrEq(expected_p2_str));
 }
 
-// Test smp_gen_p1_4_confirm and SMP_Encrypt function implementation
-TEST_F(SmpCalculateConfirmTest, test_SMP_Encrypt_as_master) {
-  BT_OCTET16 p1;
+// Test smp_gen_p1_4_confirm and aes_128 function implementation
+TEST_F(SmpCalculateConfirmTest, test_aes_128_as_master) {
   RawAddress remote_bda;
   tBLE_ADDR_TYPE remote_bd_addr_type = 0;
   BTM_ReadRemoteConnectionAddr(p_cb_.pairing_bda, remote_bda,
                                &remote_bd_addr_type);
   BTM_ReadConnectionAddr(p_cb_.pairing_bda, p_cb_.local_bda, &p_cb_.addr_type);
-  smp_gen_p1_4_confirm(&p_cb_, remote_bd_addr_type, p1);
+  Octet16 p1 = smp_gen_p1_4_confirm(&p_cb_, remote_bd_addr_type);
   // Correct p1 is 0x05000800000302070710000001010001
   const char expected_p1_str[] = "05000800000302070710000001010001";
-  char p1_str[2 * sizeof(BT_OCTET16) + 1];
+  char p1_str[2 * OCTET16_LEN + 1];
   dump_uint128_reverse(p1, p1_str);
   ASSERT_THAT(p1_str, StrEq(expected_p1_str));
-  smp_xor_128(p1, rand_);
+  smp_xor_128(&p1, rand_);
   // Correct p1 xor r is 0x5283dd2156ae6d096498274ec7712ee1
   const char expected_p1_xor_r_str[] = "5283dd2156ae6d096498274ec7712ee1";
-  char p1_xor_r_str[2 * sizeof(BT_OCTET16) + 1];
+  char p1_xor_r_str[2 * OCTET16_LEN + 1];
   dump_uint128_reverse(p1, p1_xor_r_str);
   ASSERT_THAT(p1_xor_r_str, StrEq(expected_p1_xor_r_str));
-  tSMP_ENC output;
-  memset(&output, 0, sizeof(tSMP_ENC));
-  ASSERT_TRUE(
-      SMP_Encrypt(p_cb_.tk, BT_OCTET16_LEN, p1, BT_OCTET16_LEN, &output));
+  Octet16 output = crypto_toolbox::aes_128(p_cb_.tk, p1.data(), OCTET16_LEN);
   const char expected_p1_prime_str[] = "02c7aa2a9857ac866ff91232df0e3c95";
-  char p1_prime_str[2 * sizeof(BT_OCTET16) + 1];
-  dump_uint128_reverse(output.param_buf, p1_prime_str);
+  char p1_prime_str[2 * OCTET16_LEN + 1];
+  dump_uint128_reverse(output, p1_prime_str);
   ASSERT_THAT(p1_prime_str, StrEq(expected_p1_prime_str));
 }
 
 // Test smp_calculate_comfirm function implementation
 TEST_F(SmpCalculateConfirmTest, test_smp_calculate_comfirm_as_master) {
-  tSMP_ENC output;
+  Octet16 output;
   tSMP_STATUS status = smp_calculate_comfirm(&p_cb_, rand_, &output);
   EXPECT_EQ(status, SMP_SUCCESS);
   // Correct MConfirm is 0x1e1e3fef878988ead2a74dc5bef13b86
   const char expected_confirm_str[] = "1e1e3fef878988ead2a74dc5bef13b86";
-  char confirm_str[2 * sizeof(BT_OCTET16) + 1];
-  dump_uint128_reverse(output.param_buf, confirm_str);
+  char confirm_str[2 * OCTET16_LEN + 1];
+  dump_uint128_reverse(output, confirm_str);
   ASSERT_THAT(confirm_str, StrEq(expected_confirm_str));
 }
 
diff --git a/test/gen_coverage.py b/test/gen_coverage.py
new file mode 100755
index 0000000..3697c37
--- /dev/null
+++ b/test/gen_coverage.py
@@ -0,0 +1,412 @@
+#!/usr/bin/env python
+#
+# Copyright 2018, The Android Open Source Project
+#
+# 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.
+
+import argparse
+import datetime
+import logging
+import json
+import os
+import shutil
+import subprocess
+import sys
+import webbrowser
+
+from run_host_unit_tests import *
+
+"""
+This script is used to generate code coverage results host supported libraries.
+The script by default will generate an html report that summarizes the coverage
+results of the specified tests. The results can also be browsed to provide a
+report of which lines have been traveled upon execution of the binary.
+
+NOTE: Code that is compiled out or hidden by a #DEFINE will be listed as
+having been executed 0 times, thus reducing overall coverage.
+
+The steps in order to add coverage support to a new library and its
+corrisponding host test are as follows.
+
+1. Add "clang_file_coverage" (defined in //build/Android.bp) as a default to the
+   source library(s) you want statistics for.
+   NOTE: Forgoing this default will cause no coverage data to be generated for
+         the source files in the library.
+
+2. Add "clang_coverage_bin" as a default to the host supported test binary that
+   excercises the libraries that you covered in step 1.
+   NOTE: Forgetting to add this will cause there to be *NO* coverage data
+         generated when the binary is run.
+
+3. Add the host test binary name and the files/directories you want coverage
+   statistics for to the COVERAGE_TESTS variable defined below. You may add
+   individual filenames or a directory to be tested.
+   NOTE: Avoid using a / at the beginning of a covered_files entry as this
+         breaks how the coverage generator resolves filenames.
+
+TODO: Support generating XML data and printing results to standard out.
+"""
+
+COVERAGE_TESTS = [
+    {
+        "test_name": "net_test_avrcp",
+        "covered_files": [
+            "system/bt/profile/avrcp",
+        ],
+    }, {
+        "test_name": "bluetooth_test_sdp",
+        "covered_files": [
+            "system/bt/profile/sdp",
+        ],
+    }, {
+        "test_name": "test-vendor_test_host",
+        "covered_files": [
+            "system/bt/vendor_libs/test_vendor_lib/include",
+            "system/bt/vendor_libs/test_vendor_lib/src",
+        ],
+    }, {
+        "test_name": "rootcanal-packets_test_host",
+        "covered_files": [
+            "system/bt/vendor_libs/test_vendor_lib/packets",
+        ],
+    }, {
+        "test_name": "bluetooth_test_common",
+        "covered_files": [
+            "system/bt/common",
+        ],
+    },
+]
+
+WORKING_DIR = '/tmp/coverage'
+SOONG_UI_BASH = 'build/soong/soong_ui.bash'
+LLVM_DIR = 'prebuilts/clang/host/linux-x86/clang-r328903/bin'
+LLVM_MERGE = LLVM_DIR + '/llvm-profdata'
+LLVM_COV = LLVM_DIR + '/llvm-cov'
+
+def write_root_html_head(f):
+  # Write the header part of the root html file. This was pulled from the
+  # page source of one of the generated html files.
+  f.write("<!doctype html><html><head>" \
+    "<meta name='viewport' content='width=device-width,initial-scale=1'><met" \
+    "a charset='UTF-8'><link rel='stylesheet' type='text/css' href='style.cs" \
+    "s'></head><body><h2>Coverage Report</h2><h4>Created: " +
+    str(datetime.datetime.now().strftime('%Y-%m-%d %H:%M')) +
+    "</h4><p>Click <a href='http://clang.llvm.org/docs/SourceBasedCodeCovera" \
+    "ge.html#interpreting-reports'>here</a> for information about interpreti" \
+    "ng this report.</p><div class='centered'><table><tr><td class='column-e" \
+    "ntry-bold'>Filename</td><td class='column-entry-bold'>Function Coverage" \
+    "</td><td class='column-entry-bold'>Instantiation Coverage</td><td class" \
+    "='column-entry-bold'>Line Coverage</td><td class='column-entry-bold'>Re" \
+    "gion Coverage</td></tr>"
+  )
+
+
+def write_root_html_column(f, covered, count):
+  percent = covered * 100.0 / count
+  value = "%.2f%% (%d/%d) " % (percent, covered, count)
+  color = 'column-entry-yellow'
+  if percent == 100:
+    color = 'column-entry-green'
+  if percent < 80.0:
+    color = 'column-entry-red'
+  f.write("<td class=\'" + color + "\'><pre>" + value + "</pre></td>")
+
+
+def write_root_html_rows(f, tests):
+  totals = {
+      "functions":{
+          "covered": 0,
+          "count": 0
+      },
+      "instantiations":{
+          "covered": 0,
+          "count": 0
+      },
+      "lines":{
+          "covered": 0,
+          "count": 0
+      },
+      "regions":{
+          "covered": 0,
+          "count": 0
+      }
+  }
+
+  # Write the tests with their coverage summaries.
+  for test in tests:
+    test_name = test['test_name']
+    covered_files = test['covered_files']
+    json_results = generate_coverage_json(test)
+    test_totals = json_results['data'][0]['totals']
+
+    f.write("<tr class='light-row'><td><pre><a href=\'" +
+        os.path.join(test_name, "index.html") + "\'>" + test_name +
+        "</a></pre></td>")
+    for field_name in ['functions', 'instantiations', 'lines', 'regions']:
+      field = test_totals[field_name]
+      totals[field_name]['covered'] += field['covered']
+      totals[field_name]['count'] += field['count']
+      write_root_html_column(f, field['covered'], field['count'])
+    f.write("</tr>");
+
+  #Write the totals row.
+  f.write("<tr class='light-row-bold'><td><pre>Totals</a></pre></td>")
+  for field_name in ['functions', 'instantiations', 'lines', 'regions']:
+    field = totals[field_name]
+    write_root_html_column(f, field['covered'], field['count'])
+  f.write("</tr>");
+
+
+def write_root_html_tail(f):
+  # Pulled from the generated html coverage report.
+  f.write("</table></div><h5>Generated by llvm-cov -- llvm version 7.0.2svn<" \
+    "/h5></body></html>")
+
+
+def generate_root_html(tests):
+  # Copy the css file from one of the coverage reports.
+  source_file = os.path.join(os.path.join(WORKING_DIR, tests[0]['test_name']), "style.css")
+  dest_file = os.path.join(WORKING_DIR, "style.css")
+  shutil.copy2(source_file, dest_file)
+
+  # Write the root index.html file that sumarizes all the tests.
+  f = open(os.path.join(WORKING_DIR, "index.html"), "w")
+  write_root_html_head(f)
+  write_root_html_rows(f, tests)
+  write_root_html_tail(f)
+
+
+def get_profraw_for_test(test_name):
+  test_root = get_native_test_root_or_die()
+  test_cmd = os.path.join(os.path.join(test_root, test_name), test_name)
+  if not os.path.isfile(test_cmd):
+    logging.error('The test ' + test_name + ' does not exist, please compile first')
+    sys.exit(1)
+
+  profraw_file_name = test_name + ".profraw"
+  profraw_path = os.path.join(WORKING_DIR, os.path.join(test_name, profraw_file_name))
+  llvm_env_var = "LLVM_PROFILE_FILE=\"" + profraw_path + "\""
+
+  test_cmd = llvm_env_var + " " + test_cmd
+  logging.info('Generating profraw data for ' + test_name)
+  logging.debug('cmd: ' + test_cmd)
+  if subprocess.call(test_cmd, shell=True) != 0:
+    logging.error('Test ' + test_name + ' failed. Please fix the test before generating coverage.')
+    sys.exit(1)
+
+  if not os.path.isfile(profraw_path):
+    logging.error('Generating the profraw file failed. Did you remember to add the proper compiler flags to your build?')
+    sys.exit(1)
+
+  return profraw_file_name
+
+
+def merge_profraw_data(test_name):
+  cmd = []
+  cmd.append(os.path.join(get_android_root_or_die(), LLVM_MERGE + " merge "))
+
+  test_working_dir = os.path.join(WORKING_DIR, test_name);
+  cmd.append(os.path.join(test_working_dir, test_name + ".profraw"))
+  profdata_file = os.path.join(test_working_dir, test_name + ".profdata")
+
+  cmd.append('-o ' + profdata_file)
+  logging.info('Combining profraw files into profdata for ' + test_name)
+  logging.debug('cmd: ' + " ".join(cmd))
+  if subprocess.call(" ".join(cmd), shell=True) != 0:
+    logging.error('Failed to merge profraw files for ' + test_name)
+    sys.exit(1)
+
+
+def generate_coverage_html(test):
+  COVERAGE_ROOT = '/proc/self/cwd'
+
+  test_name = test['test_name']
+  file_list = test['covered_files']
+
+  test_working_dir = os.path.join(WORKING_DIR, test_name)
+  test_profdata_file = os.path.join(test_working_dir, test_name + ".profdata")
+
+  cmd = [
+    os.path.join(get_android_root_or_die(), LLVM_COV),
+    "show",
+    "-format=html",
+    "-summary-only",
+    "-show-line-counts-or-regions",
+    "-show-instantiation-summary",
+    "-instr-profile=" + test_profdata_file,
+    "-path-equivalence=\"" + COVERAGE_ROOT + "\",\"" +
+        get_android_root_or_die() + "\"",
+    "-output-dir=" + test_working_dir
+  ]
+
+  # We have to have one object file not as an argument otherwise we can't specify source files.
+  test_cmd = os.path.join(os.path.join(get_native_test_root_or_die(), test_name), test_name)
+  cmd.append(test_cmd)
+
+  # Filter out the specific files we want coverage for
+  for filename in file_list:
+    cmd.append(os.path.join(get_android_root_or_die(), filename))
+
+  logging.info('Generating coverage report for ' + test['test_name'])
+  logging.debug('cmd: ' + " ".join(cmd))
+  if subprocess.call(" ".join(cmd), shell=True) != 0:
+    logging.error('Failed to generate coverage for ' + test['test_name'])
+    sys.exit(1)
+
+
+def generate_coverage_json(test):
+  COVERAGE_ROOT = '/proc/self/cwd'
+  test_name = test['test_name']
+  file_list = test['covered_files']
+
+  test_working_dir = os.path.join(WORKING_DIR, test_name)
+  test_profdata_file = os.path.join(test_working_dir, test_name + ".profdata")
+
+  cmd = [
+    os.path.join(get_android_root_or_die(), LLVM_COV),
+    "export",
+    "-summary-only",
+    "-show-region-summary",
+    "-instr-profile=" + test_profdata_file,
+    "-path-equivalence=\"" + COVERAGE_ROOT + "\",\"" + get_android_root_or_die() + "\"",
+  ]
+
+  test_cmd = os.path.join(os.path.join(get_native_test_root_or_die(), test_name), test_name)
+  cmd.append(test_cmd)
+
+  # Filter out the specific files we want coverage for
+  for filename in file_list:
+    cmd.append(os.path.join(get_android_root_or_die(), filename))
+
+  logging.info('Generating coverage json for ' + test['test_name'])
+  logging.debug('cmd: ' + " ".join(cmd))
+
+  json_str = subprocess.check_output(" ".join(cmd), shell=True)
+  return json.loads(json_str)
+
+
+def write_json_summary(test):
+  test_name = test['test_name']
+  test_working_dir = os.path.join(WORKING_DIR, test_name)
+  test_json_summary_file = os.path.join(test_working_dir, test_name + '.json')
+  logging.debug('Writing json summary file: ' + test_json_summary_file)
+  json_file = open(test_json_summary_file, 'w')
+  json.dump(generate_coverage_json(test), json_file)
+  json_file.close()
+
+
+def list_tests():
+  for test in COVERAGE_TESTS:
+    print "Test Name: " + test['test_name']
+    print "Covered Files: "
+    for covered_file in test['covered_files']:
+        print "  " + covered_file
+    print
+
+
+def main():
+  parser = argparse.ArgumentParser(description='Generate code coverage for enabled tests.')
+  parser.add_argument(
+    '-l', '--list-tests',
+    action='store_true',
+    dest='list_tests',
+    help='List all the available tests to be run as well as covered files.')
+  parser.add_argument(
+    '-a', '--all',
+    action='store_true',
+    help='Runs all available tests and prints their outputs. If no tests ' \
+         'are specified via the -t option all tests will be run.')
+  parser.add_argument(
+    '-t', '--test',
+    dest='tests',
+    action='append',
+    type=str,
+    metavar='TESTNAME',
+    default=[],
+    help='Specifies a test to be run. Multiple tests can be specified by ' \
+         'using this option multiple times. ' \
+         'Example: \"gen_coverage.py -t test1 -t test2\"')
+  parser.add_argument(
+    '-o', '--output',
+    type=str,
+    metavar='DIRECTORY',
+    default='/tmp/coverage',
+    help='Specifies the directory to store all files. The directory will be ' \
+         'created if it does not exist. Default is \"/tmp/coverage\"')
+  parser.add_argument(
+    '-s', '--skip-html',
+    dest='skip_html',
+    action='store_true',
+    help='Skip opening up the results of the coverage report in a browser.')
+  parser.add_argument(
+    '-j', '--json-file',
+    dest='json_file',
+    action='store_true',
+    help='Write out summary results to json file in test directory.')
+
+  logging.basicConfig(stream=sys.stderr, level=logging.DEBUG, format='%(levelname)s %(message)s')
+  logging.addLevelName(logging.DEBUG, "[\033[1;34m%s\033[0m]" % logging.getLevelName(logging.DEBUG))
+  logging.addLevelName(logging.INFO, "[\033[1;34m%s\033[0m]" % logging.getLevelName(logging.INFO))
+  logging.addLevelName(logging.WARNING, "[\033[1;31m%s\033[0m]" % logging.getLevelName(logging.WARNING))
+  logging.addLevelName(logging.ERROR, "[\033[1;31m%s\033[0m]" % logging.getLevelName(logging.ERROR))
+
+  args = parser.parse_args()
+  logging.debug("Args: " + str(args))
+
+  # Set the working directory
+  global WORKING_DIR
+  WORKING_DIR = os.path.abspath(args.output)
+  logging.debug("Working Dir: " + WORKING_DIR)
+
+  # Print out the list of tests then exit
+  if args.list_tests:
+    list_tests()
+    sys.exit(0)
+
+  # Check to see if a test was specified and if so only generate coverage for
+  # that test.
+  if len(args.tests) == 0:
+    args.all = True
+
+  tests_to_run = []
+  for test in COVERAGE_TESTS:
+    if args.all or test['test_name'] in args.tests:
+      tests_to_run.append(test)
+    if test['test_name'] in args.tests:
+      args.tests.remove(test['test_name'])
+
+  # Error if a test was specified but doesn't exist.
+  if len(args.tests) != 0:
+    for test_name in args.tests:
+        logging.error('\"' + test_name + '\" was not found in the list of available tests.')
+    sys.exit(1)
+
+  # Generate the info for the tests
+  for test in tests_to_run:
+    logging.info('Getting coverage for ' + test['test_name'])
+    get_profraw_for_test(test['test_name'])
+    merge_profraw_data(test['test_name'])
+    if args.json_file:
+      write_json_summary(test)
+    generate_coverage_html(test)
+
+  # Generate the root index.html page that sumarizes all of the coverage reports.
+  generate_root_html(tests_to_run)
+
+  # Open the results in a browser.
+  if not args.skip_html:
+    webbrowser.open('file://' + os.path.join(WORKING_DIR, 'index.html'))
+
+
+if __name__ == '__main__':
+  main()
diff --git a/test/rootcanal/Android.bp b/test/rootcanal/Android.bp
index 7371c99..e312c0e 100644
--- a/test/rootcanal/Android.bp
+++ b/test/rootcanal/Android.bp
@@ -45,7 +45,7 @@
         "android.hardware.bluetooth-async",
         "android.hardware.bluetooth-hci",
         "libbt-rootcanal",
-        "libbluetooth-types",
+        "libbt-rootcanal-types",
     ],
     include_dirs: [
         "system/bt",
@@ -82,10 +82,10 @@
         "-DHAS_NO_BDROID_BUILDCFG",
     ],
     static_libs: [
-        "libbluetooth-types",
         "android.hardware.bluetooth-async",
         "android.hardware.bluetooth-hci",
         "libbt-rootcanal",
+        "libbt-rootcanal-types",
     ],
     include_dirs: [
         "system/bt",
diff --git a/test/rootcanal/bluetooth_hci.cc b/test/rootcanal/bluetooth_hci.cc
index b0281a0..e40a0c1 100644
--- a/test/rootcanal/bluetooth_hci.cc
+++ b/test/rootcanal/bluetooth_hci.cc
@@ -19,13 +19,13 @@
 #include "bluetooth_hci.h"
 
 #include <base/logging.h>
+#include <cutils/properties.h>
+#include <netdb.h>
+#include <netinet/in.h>
 #include <string.h>
 #include <utils/Log.h>
 
-#include "acl_packet.h"
-#include "event_packet.h"
 #include "hci_internals.h"
-#include "sco_packet.h"
 
 namespace android {
 namespace hardware {
@@ -34,37 +34,41 @@
 namespace sim {
 
 using android::hardware::hidl_vec;
-using test_vendor_lib::AclPacket;
-using test_vendor_lib::AsyncManager;
 using test_vendor_lib::AsyncTaskId;
-using test_vendor_lib::CommandPacket;
 using test_vendor_lib::DualModeController;
-using test_vendor_lib::EventPacket;
-using test_vendor_lib::ScoPacket;
 using test_vendor_lib::TaskCallback;
-using test_vendor_lib::TestChannelTransport;
+
+namespace {
+
+bool BtTestConsoleEnabled() {
+  // Assume enabled by default.
+  return property_get_bool("bt.rootcanal_test_console", true);
+}
+
+}  // namespace
 
 class BluetoothDeathRecipient : public hidl_death_recipient {
  public:
   BluetoothDeathRecipient(const sp<IBluetoothHci> hci) : mHci(hci) {}
 
-  virtual void serviceDied(
-      uint64_t /* cookie */,
-      const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
+  virtual void serviceDied(uint64_t /* cookie */, const wp<::android::hidl::base::V1_0::IBase>& /* who */) {
     ALOGE("BluetoothDeathRecipient::serviceDied - Bluetooth service died");
     has_died_ = true;
     mHci->close();
   }
   sp<IBluetoothHci> mHci;
-  bool getHasDied() const { return has_died_; }
-  void setHasDied(bool has_died) { has_died_ = has_died; }
+  bool getHasDied() const {
+    return has_died_;
+  }
+  void setHasDied(bool has_died) {
+    has_died_ = has_died;
+  }
 
  private:
   bool has_died_;
 };
 
-BluetoothHci::BluetoothHci()
-    : death_recipient_(new BluetoothDeathRecipient(this)) {}
+BluetoothHci::BluetoothHci() : death_recipient_(new BluetoothDeathRecipient(this)) {}
 
 Return<void> BluetoothHci::initialize(const sp<IBluetoothHciCallbacks>& cb) {
   ALOGI("%s", __func__);
@@ -77,60 +81,68 @@
   death_recipient_->setHasDied(false);
   cb->linkToDeath(death_recipient_, 0);
 
-  test_channel_transport_.RegisterCommandHandler(
-      [this](const std::string& name, const std::vector<std::string>& args) {
-        async_manager_.ExecAsync(
-            std::chrono::milliseconds(0), [this, name, args]() {
-              controller_.HandleTestChannelCommand(name, args);
-            });
-      });
+  test_channel_transport_.RegisterCommandHandler([this](const std::string& name, const std::vector<std::string>& args) {
+    async_manager_.ExecAsync(std::chrono::milliseconds(0),
+                             [this, name, args]() { test_channel_.HandleCommand(name, args); });
+  });
 
-  controller_.RegisterEventChannel([cb](std::unique_ptr<EventPacket> event) {
-    size_t header_bytes = event->GetHeaderSize();
-    size_t payload_bytes = event->GetPayloadSize();
-    hidl_vec<uint8_t> hci_event;
-    hci_event.resize(header_bytes + payload_bytes);
-    memcpy(hci_event.data(), event->GetHeader().data(), header_bytes);
-    memcpy(hci_event.data() + header_bytes, event->GetPayload().data(),
-           payload_bytes);
+  controller_ = std::make_shared<DualModeController>();
 
+  controller_->Initialize({"dmc", "3C:5A:B4:01:02:03"});
+
+  controller_->RegisterEventChannel([cb](std::shared_ptr<std::vector<uint8_t>> packet) {
+    hidl_vec<uint8_t> hci_event(packet->begin(), packet->end());
     cb->hciEventReceived(hci_event);
   });
 
-  controller_.RegisterAclChannel([cb](std::unique_ptr<AclPacket> packet) {
-    std::vector<uint8_t> acl_vector = packet->GetPacket();
-    hidl_vec<uint8_t> acl_packet = acl_vector;
-
+  controller_->RegisterAclChannel([cb](std::shared_ptr<std::vector<uint8_t>> packet) {
+    hidl_vec<uint8_t> acl_packet(packet->begin(), packet->end());
     cb->aclDataReceived(acl_packet);
   });
 
-  controller_.RegisterScoChannel([cb](std::unique_ptr<ScoPacket> packet) {
-    size_t header_bytes = packet->GetHeaderSize();
-    size_t payload_bytes = packet->GetPayloadSize();
-    hidl_vec<uint8_t> sco_packet;
-    sco_packet.resize(header_bytes + payload_bytes);
-    memcpy(sco_packet.data(), packet->GetHeader().data(), header_bytes);
-    memcpy(sco_packet.data() + header_bytes, packet->GetPayload().data(),
-           payload_bytes);
-
-    cb->scoDataReceived(sco_packet);
+  controller_->RegisterScoChannel([cb](std::shared_ptr<std::vector<uint8_t>> packet) {
+    hidl_vec<uint8_t> sco_packet(packet->begin(), packet->end());
+    cb->aclDataReceived(sco_packet);
   });
 
-  controller_.RegisterTaskScheduler(
-      [this](std::chrono::milliseconds delay, const TaskCallback& task) {
-        return async_manager_.ExecAsync(delay, task);
-      });
+  controller_->RegisterTaskScheduler([this](std::chrono::milliseconds delay, const TaskCallback& task) {
+    return async_manager_.ExecAsync(delay, task);
+  });
 
-  controller_.RegisterPeriodicTaskScheduler(
-      [this](std::chrono::milliseconds delay, std::chrono::milliseconds period,
-             const TaskCallback& task) {
+  controller_->RegisterPeriodicTaskScheduler(
+      [this](std::chrono::milliseconds delay, std::chrono::milliseconds period, const TaskCallback& task) {
         return async_manager_.ExecAsyncPeriodically(delay, period, task);
       });
 
-  controller_.RegisterTaskCancel(
-      [this](AsyncTaskId task) { async_manager_.CancelAsyncTask(task); });
+  controller_->RegisterTaskCancel([this](AsyncTaskId task) { async_manager_.CancelAsyncTask(task); });
 
-  SetUpTestChannel(6111);
+  test_model_.Reset();
+  // Add the controller as a device in the model.
+  test_model_.Add(controller_);
+
+  // Send responses to logcat if the test channel is not configured.
+  test_channel_.RegisterSendResponse([](const std::string& response) {
+    ALOGI("No test channel yet: %s", response.c_str());
+  });
+
+  if (BtTestConsoleEnabled()) {
+    SetUpTestChannel(6111);
+    SetUpHciServer(6211,
+                   [this](int fd) { test_model_.IncomingHciConnection(fd); });
+    SetUpLinkLayerServer(
+        6311, [this](int fd) { test_model_.IncomingLinkLayerConnection(fd); });
+  }
+
+  // Add some default devices for easier debugging
+  test_channel_.AddDefaults();
+
+  // This should be configurable in the future.
+  ALOGI("Adding Beacons so the scan list is not empty.");
+  test_channel_.Add({"beacon", "be:ac:10:00:00:01", "1000"});
+  test_channel_.AddDeviceToPhy({"1", "0"});
+  test_channel_.Add({"beacon", "be:ac:10:00:00:02", "1000"});
+  test_channel_.AddDeviceToPhy({"2", "0"});
+  test_channel_.SetTimerPeriod({"1000"});
 
   unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
     if (death_recipient->getHasDied())
@@ -150,53 +162,121 @@
 
 Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& packet) {
   async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() {
-    uint16_t opcode = packet[0] | (packet[1] << 8);
-    std::unique_ptr<CommandPacket> command =
-        std::unique_ptr<CommandPacket>(new CommandPacket(opcode));
-    for (size_t i = 3; i < packet.size(); i++)
-      command->AddPayloadOctets1(packet[i]);
-
-    controller_.HandleCommand(std::move(command));
+    std::shared_ptr<std::vector<uint8_t>> packet_copy =
+        std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>(packet));
+    controller_->HandleCommand(packet_copy);
   });
   return Void();
 }
 
 Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& packet) {
   async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() {
-    uint16_t channel = (packet[0] | (packet[1] << 8)) & 0xfff;
-    AclPacket::PacketBoundaryFlags boundary_flags =
-        static_cast<AclPacket::PacketBoundaryFlags>((packet[1] & 0x30) >> 4);
-    AclPacket::BroadcastFlags broadcast_flags =
-        static_cast<AclPacket::BroadcastFlags>((packet[1] & 0xC0) >> 6);
-
-    std::unique_ptr<AclPacket> acl = std::unique_ptr<AclPacket>(
-        new AclPacket(channel, boundary_flags, broadcast_flags));
-    for (size_t i = 4; i < packet.size(); i++)
-      acl->AddPayloadOctets1(packet[i]);
-
-    controller_.HandleAcl(std::move(acl));
+    std::shared_ptr<std::vector<uint8_t>> packet_copy =
+        std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>(packet));
+    controller_->HandleAcl(packet_copy);
   });
   return Void();
 }
 
 Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& packet) {
   async_manager_.ExecAsync(std::chrono::milliseconds(0), [this, packet]() {
-    uint16_t channel = (packet[0] | (packet[1] << 8)) & 0xfff;
-    ScoPacket::PacketStatusFlags packet_status =
-        static_cast<ScoPacket::PacketStatusFlags>((packet[1] & 0x30) >> 4);
-    std::unique_ptr<ScoPacket> sco =
-        std::unique_ptr<ScoPacket>(new ScoPacket(channel, packet_status));
-    for (size_t i = 3; i < packet.size(); i++)
-      sco->AddPayloadOctets1(packet[i]);
-
-    controller_.HandleSco(std::move(sco));
+    std::shared_ptr<std::vector<uint8_t>> packet_copy =
+        std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>(packet));
+    controller_->HandleSco(packet_copy);
   });
   return Void();
 }
 
+void BluetoothHci::SetUpHciServer(int port, const std::function<void(int)>& connection_callback) {
+  int socket_fd = remote_hci_transport_.SetUp(port);
+
+  test_channel_.RegisterSendResponse(
+      [](const std::string& response) { ALOGI("No HCI Response channel: %s", response.c_str()); });
+
+  if (socket_fd == -1) {
+    ALOGE("Remote HCI channel SetUp(%d) failed.", port);
+    return;
+  }
+
+  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
+    int conn_fd = remote_hci_transport_.Accept(socket_fd);
+    if (conn_fd < 0) {
+      ALOGE("Error watching remote HCI channel fd.");
+      return;
+    }
+    int flags = fcntl(conn_fd, F_GETFL, NULL);
+    int ret;
+    ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
+    CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno);
+
+    connection_callback(conn_fd);
+  });
+}
+
+void BluetoothHci::SetUpLinkLayerServer(int port, const std::function<void(int)>& connection_callback) {
+  int socket_fd = remote_link_layer_transport_.SetUp(port);
+
+  test_channel_.RegisterSendResponse(
+      [](const std::string& response) { ALOGI("No LinkLayer Response channel: %s", response.c_str()); });
+
+  if (socket_fd == -1) {
+    ALOGE("Remote LinkLayer channel SetUp(%d) failed.", port);
+    return;
+  }
+
+  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
+    int conn_fd = remote_link_layer_transport_.Accept(socket_fd);
+    if (conn_fd < 0) {
+      ALOGE("Error watching remote LinkLayer channel fd.");
+      return;
+    }
+    int flags = fcntl(conn_fd, F_GETFL, NULL);
+    int ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
+    CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno);
+
+    connection_callback(conn_fd);
+  });
+}
+
+int BluetoothHci::ConnectToRemoteServer(const std::string& server, int port) {
+  int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (socket_fd < 1) {
+    ALOGI("socket() call failed: %s", strerror(errno));
+    return -1;
+  }
+
+  struct hostent* host;
+  host = gethostbyname(server.c_str());
+  if (host == NULL) {
+    ALOGI("gethostbyname() failed for %s: %s", server.c_str(), strerror(errno));
+    return -1;
+  }
+
+  struct sockaddr_in serv_addr;
+  memset((void*)&serv_addr, 0, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_addr.s_addr = INADDR_ANY;
+  serv_addr.sin_port = htons(port);
+
+  int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
+  if (result < 0) {
+    ALOGI("connect() failed for %s@%d: %s", server.c_str(), port, strerror(errno));
+    return -1;
+  }
+
+  int flags = fcntl(socket_fd, F_GETFL, NULL);
+  int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);
+  CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno);
+
+  return socket_fd;
+}
+
 void BluetoothHci::SetUpTestChannel(int port) {
   int socket_fd = test_channel_transport_.SetUp(port);
 
+  test_channel_.RegisterSendResponse(
+      [](const std::string& response) { ALOGI("No test channel: %s", response.c_str()); });
+
   if (socket_fd == -1) {
     ALOGE("Test channel SetUp(%d) failed.", port);
     return;
@@ -210,10 +290,12 @@
       return;
     }
     ALOGI("Test channel connection accepted.");
+    test_channel_.RegisterSendResponse(
+        [this, conn_fd](const std::string& response) { test_channel_transport_.SendResponse(conn_fd, response); });
+
     async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) {
-      test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() {
-        async_manager_.StopWatchingFileDescriptor(conn_fd);
-      });
+      test_channel_transport_.OnCommandReady(conn_fd,
+                                             [this, conn_fd]() { async_manager_.StopWatchingFileDescriptor(conn_fd); });
     });
   });
 }
@@ -223,7 +305,7 @@
   return new BluetoothHci();
 }
 
-}  // namespace gce
+}  // namespace sim
 }  // namespace V1_0
 }  // namespace bluetooth
 }  // namespace hardware
diff --git a/test/rootcanal/bluetooth_hci.h b/test/rootcanal/bluetooth_hci.h
index 05ec206..96d0ed8 100644
--- a/test/rootcanal/bluetooth_hci.h
+++ b/test/rootcanal/bluetooth_hci.h
@@ -22,9 +22,11 @@
 
 #include "hci_packetizer.h"
 
-#include "async_manager.h"
-#include "dual_mode_controller.h"
-#include "test_channel_transport.h"
+#include "model/controller/dual_mode_controller.h"
+#include "model/setup/async_manager.h"
+#include "model/setup/test_channel_transport.h"
+#include "model/setup/test_command_handler.h"
+#include "model/setup/test_model.h"
 
 namespace android {
 namespace hardware {
@@ -38,17 +40,13 @@
  public:
   BluetoothHci();
 
-  ::android::hardware::Return<void> initialize(
-      const sp<IBluetoothHciCallbacks>& cb) override;
+  ::android::hardware::Return<void> initialize(const sp<IBluetoothHciCallbacks>& cb) override;
 
-  ::android::hardware::Return<void> sendHciCommand(
-      const ::android::hardware::hidl_vec<uint8_t>& packet) override;
+  ::android::hardware::Return<void> sendHciCommand(const ::android::hardware::hidl_vec<uint8_t>& packet) override;
 
-  ::android::hardware::Return<void> sendAclData(
-      const ::android::hardware::hidl_vec<uint8_t>& packet) override;
+  ::android::hardware::Return<void> sendAclData(const ::android::hardware::hidl_vec<uint8_t>& packet) override;
 
-  ::android::hardware::Return<void> sendScoData(
-      const ::android::hardware::hidl_vec<uint8_t>& packet) override;
+  ::android::hardware::Return<void> sendScoData(const ::android::hardware::hidl_vec<uint8_t>& packet) override;
 
   ::android::hardware::Return<void> close() override;
 
@@ -66,10 +64,31 @@
   test_vendor_lib::AsyncManager async_manager_;
 
   void SetUpTestChannel(int port);
+  void SetUpHciServer(int port, const std::function<void(int)>& on_connect);
+  void SetUpLinkLayerServer(int port, const std::function<void(int)>& on_connect);
+  int ConnectToRemoteServer(const std::string& server, int port);
 
-  test_vendor_lib::DualModeController controller_;
+  std::shared_ptr<test_vendor_lib::DualModeController> controller_;
 
   test_vendor_lib::TestChannelTransport test_channel_transport_;
+  test_vendor_lib::TestChannelTransport remote_hci_transport_;
+  test_vendor_lib::TestChannelTransport remote_link_layer_transport_;
+
+  test_vendor_lib::TestModel test_model_{
+      [this](std::chrono::milliseconds delay, const test_vendor_lib::TaskCallback& task) {
+        return async_manager_.ExecAsync(delay, task);
+      },
+
+      [this](std::chrono::milliseconds delay, std::chrono::milliseconds period,
+             const test_vendor_lib::TaskCallback& task) {
+        return async_manager_.ExecAsyncPeriodically(delay, period, task);
+      },
+
+      [this](test_vendor_lib::AsyncTaskId task) { async_manager_.CancelAsyncTask(task); },
+
+      [this](const std::string& server, int port) { return ConnectToRemoteServer(server, port); }};
+
+  test_vendor_lib::TestCommandHandler test_channel_{test_model_};
 };
 
 extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
diff --git a/test/rootcanal/service.cc b/test/rootcanal/service.cc
index e08f735..64fa9c7 100644
--- a/test/rootcanal/service.cc
+++ b/test/rootcanal/service.cc
@@ -23,11 +23,11 @@
 
 #include "bluetooth_hci.h"
 
+using ::android::sp;
 using ::android::hardware::configureRpcThreadpool;
+using ::android::hardware::joinRpcThreadpool;
 using ::android::hardware::bluetooth::V1_0::IBluetoothHci;
 using ::android::hardware::bluetooth::V1_0::sim::BluetoothHci;
-using ::android::hardware::joinRpcThreadpool;
-using ::android::sp;
 
 int main(int /* argc */, char** /* argv */) {
   sp<IBluetoothHci> bluetooth = new BluetoothHci;
diff --git a/test/run_benchmarks.sh b/test/run_benchmarks.sh
new file mode 100755
index 0000000..af4b012
--- /dev/null
+++ b/test/run_benchmarks.sh
@@ -0,0 +1,129 @@
+#!/bin/sh
+# A utility script that runs benchmark on Android device
+#
+# Note: Only one Android device can be connected when running this script
+#
+# Example usage:
+#   $ cd system/bt
+#   $ ./test/run_benchmarks.sh bluetooth_benchmark_example
+
+known_benchmarks=(
+  bluetooth_benchmark_thread_performance
+  bluetooth_benchmark_timer_performance
+)
+
+usage() {
+  binary="$(basename "$0")"
+  echo "Usage: ${binary} --help"
+  echo "       ${binary} [-i <iterations>] [-s <specific device>] [--all] [<benchmark name>[.<filter>] ...] [--<arg> ...]"
+  echo
+  echo "Unknown long arguments are passed to the benchmark."
+  echo
+  echo "Known benchmark names:"
+
+  for name in "${known_benchmarks[@]}"
+  do
+    echo "    ${name}"
+  done
+}
+
+iterations=1
+device=
+benchmarks=()
+benchmark_args=()
+while [ $# -gt 0 ]
+do
+  case "$1" in
+    -h|--help)
+      usage
+      exit 0
+      ;;
+    -i)
+      shift
+      if [ $# -eq 0 ]; then
+        echo "error: number of iterations expected" 1>&2
+        usage
+        exit 2
+      fi
+      iterations=$(( $1 ))
+      shift
+      ;;
+    -s)
+      shift
+      if [ $# -eq 0 ]; then
+        echo "error: no device specified" 1>&2
+        usage
+        exit 2
+      fi
+      device="$1"
+      shift
+      ;;
+    --all)
+      benchmarks+=( "${known_benchmarks[@]}" )
+      shift
+      ;;
+    --*)
+      benchmark_args+=( "$1" )
+      shift
+      ;;
+    *)
+      benchmarks+=( "$1" )
+      shift
+      ;;
+  esac
+done
+
+if [ "${#benchmarks[@]}" -eq 0 ]; then
+  benchmarks+=( "${known_benchmarks[@]}" )
+fi
+
+adb=( "adb" )
+if [ -n "${device}" ]; then
+  adb+=( "-s" "${device}" )
+fi
+
+source ${ANDROID_BUILD_TOP}/build/envsetup.sh
+target_arch=$(gettargetarch)
+
+failed_benchmarks=()
+for spec in "${benchmarks[@]}"
+do
+  name="${spec%%.*}"
+  if [[ $target_arch == *"64"* ]]; then
+    binary="/data/benchmarktest64/${name}/${name}"
+  else
+    binary="/data/benchmarktest/${name}/${name}"
+  fi
+
+  push_command=( "${adb[@]}" push {"${ANDROID_PRODUCT_OUT}",}"${binary}" )
+  benchmark_command=( "${adb[@]}" shell "${binary}" )
+  if [ "${name}" != "${spec}" ]; then
+    filter="${spec#*.}"
+    benchmark_command+=( "--benchmark_filter=${filter}" )
+  fi
+  benchmark_command+=( "${benchmark_args[@]}" )
+
+  echo "--- ${name} ---"
+  echo "pushing..."
+  "${push_command[@]}"
+  echo "running..."
+  failed_count=0
+  for i in $(seq 1 ${iterations})
+  do
+    "${benchmark_command[@]}" || failed_count=$(( $failed_count + 1 ))
+  done
+
+  if [ $failed_count != 0 ]; then
+    failed_benchmarks+=( "${name} ${failed_count}/${iterations}" )
+  fi
+done
+
+if [ "${#failed_benchmarks[@]}" -ne 0 ]; then
+  for failed_benchmark in "${failed_benchmarks[@]}"
+  do
+    echo "!!! FAILED TEST: ${failed_benchmark} !!!"
+  done
+  exit 1
+fi
+
+exit 0
diff --git a/test/run_host_unit_tests.py b/test/run_host_unit_tests.py
index a99140e..3d3f1c7 100755
--- a/test/run_host_unit_tests.py
+++ b/test/run_host_unit_tests.py
@@ -21,9 +21,9 @@
 # Registered host based unit tests
 # Must have 'host_supported: true'
 HOST_TESTS = [
+  'bluetooth_test_common',
   'bluetoothtbd_test',
   'net_test_avrcp',
-  'net_test_btif_state_machine',
   'net_test_btcore',
   'net_test_types',
   'net_test_btpackets',
@@ -200,6 +200,20 @@
       print 'TEST FAILLED: ' + HOST_TESTS[index]
     sys.exit(0)
   print 'TEST PASSED ' + str(len(test_results)) + ' tests were run'
+
+  dist_dir = get_android_dist_dir_or_die()
+  log_output_path = os.path.join(dist_dir, 'gtest/coverage')
+  cmd_path = os.path.join(get_android_root_or_die(), 'system/bt/test')
+  print cmd_path
+  cmd = [
+    os.path.join(cmd_path, 'gen_coverage.py'),
+    '--skip-html',
+    '--json-file',
+    '-o',
+    log_output_path,
+  ]
+  subprocess.call(cmd)
+
   sys.exit(0)
 
 
diff --git a/test/run_unit_tests.sh b/test/run_unit_tests.sh
index 066e8e1..8041afc 100755
--- a/test/run_unit_tests.sh
+++ b/test/run_unit_tests.sh
@@ -1,6 +1,9 @@
 #!/bin/sh
 
 known_tests=(
+  audio_bluetooth_hw_test
+  bluetooth-test-audio-hal-interface
+  bluetooth_test_common
   bluetoothtbd_test
   net_test_audio_a2dp_hw
   net_test_avrcp
@@ -9,7 +12,6 @@
   net_test_bta
   net_test_btif
   net_test_btif_profile_queue
-  net_test_btif_state_machine
   net_test_device
   net_test_hci
   net_test_stack
@@ -21,6 +23,7 @@
   net_test_osi
   net_test_performance
   net_test_stack_rfcomm
+  net_test_gatt_conn_multiplexing
 )
 
 known_remote_tests=(
diff --git a/test/suite/Android.bp b/test/suite/Android.bp
index 5193c4b..3967ecc 100644
--- a/test/suite/Android.bp
+++ b/test/suite/Android.bp
@@ -53,21 +53,3 @@
         "libbluetoothtbd_hal",
     ],
 }
-
-// Bluetooth test suite for target
-// ========================================================
-cc_test {
-    name: "net_test_performance",
-    defaults: ["fluoride_defaults"],
-    include_dirs: ["system/bt"],
-    srcs: [
-        "core/thread_performance_test.cc",
-    ],
-    shared_libs: [
-        "liblog",
-    ],
-    static_libs: [
-        "libgmock",
-        "libosi",
-    ],
-}
diff --git a/test/suite/AndroidTest.xml b/test/suite/AndroidTest.xml
deleted file mode 100644
index d7778e1..0000000
--- a/test/suite/AndroidTest.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Copyright 2017 The Android Open Source Project
-
-     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.
--->
-<configuration description="Config for net_test_bluetooth">
-    <target_preparer class="com.android.tradefed.targetprep.PushFilePreparer">
-        <option name="cleanup" value="true" />
-        <option name="push" value="net_test_bluetooth->/data/local/tmp/net_test_bluetooth" />
-    </target_preparer>
-    <target_preparer class="com.android.tradefed.targetprep.RunCommandTargetPreparer">
-        <option name="run-command" value="stop" />
-    </target_preparer>
-    <option name="test-suite-tag" value="apct" />
-    <test class="com.android.tradefed.testtype.GTest" >
-        <option name="native-test-device-path" value="/data/local/tmp" />
-        <option name="module-name" value="net_test_bluetooth" />
-    </test>
-</configuration>
diff --git a/test/suite/adapter/adapter_unittest.cc b/test/suite/adapter/adapter_unittest.cc
index 24ca3e5..7a26e28 100644
--- a/test/suite/adapter/adapter_unittest.cc
+++ b/test/suite/adapter/adapter_unittest.cc
@@ -35,7 +35,7 @@
   EXPECT_EQ(GetState(), BT_STATE_OFF)
       << "Test should be run with Adapter disabled";
 
-  EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+  EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
   semaphore_wait(adapter_state_changed_callback_sem_);
   EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
 
@@ -49,7 +49,7 @@
       << "Test should be run with Adapter disabled";
 
   for (int i = 0; i < kTestRepeatCount; ++i) {
-    EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+    EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
     semaphore_wait(adapter_state_changed_callback_sem_);
     EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
 
@@ -62,7 +62,7 @@
 TEST_F(BluetoothTest, AdapterSetGetName) {
   bt_property_t* new_name = property_new_name("BluetoothTestName1");
 
-  EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+  EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
   semaphore_wait(adapter_state_changed_callback_sem_);
   EXPECT_EQ(GetState(), BT_STATE_ON)
       << "Test should be run with Adapter enabled";
@@ -114,7 +114,7 @@
 }
 
 TEST_F(BluetoothTest, AdapterStartDiscovery) {
-  EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+  EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
   semaphore_wait(adapter_state_changed_callback_sem_);
   EXPECT_EQ(GetState(), BT_STATE_ON)
       << "Test should be run with Adapter enabled";
@@ -130,7 +130,7 @@
 }
 
 TEST_F(BluetoothTest, AdapterCancelDiscovery) {
-  EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+  EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
   semaphore_wait(adapter_state_changed_callback_sem_);
   EXPECT_EQ(GetState(), BT_STATE_ON)
       << "Test should be run with Adapter enabled";
@@ -155,7 +155,7 @@
   RawAddress bdaddr = {{0x22, 0x22, 0x22, 0x22, 0x22, 0x22}};
 
   for (int i = 0; i < kTestRepeatCount; ++i) {
-    EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+    EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
     semaphore_wait(adapter_state_changed_callback_sem_);
     EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
 
@@ -179,8 +179,8 @@
   ASSERT_TRUE(bt_callbacks != nullptr);
 
   for (int i = 0; i < kTestRepeatCount; ++i) {
-    bt_interface()->init(bt_callbacks);
-    EXPECT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+    bt_interface()->init(bt_callbacks, false, false);
+    EXPECT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
     semaphore_wait(adapter_state_changed_callback_sem_);
     EXPECT_EQ(GetState(), BT_STATE_ON) << "Adapter did not turn on.";
 
diff --git a/test/suite/adapter/bluetooth_test.cc b/test/suite/adapter/bluetooth_test.cc
index fdf4a9d..626ac42 100644
--- a/test/suite/adapter/bluetooth_test.cc
+++ b/test/suite/adapter/bluetooth_test.cc
@@ -21,7 +21,6 @@
 #include <stdio.h>
 #include <mutex>
 #include "btcore/include/property.h"
-#include "osi/include/properties.h"
 
 namespace {
 
@@ -71,8 +70,6 @@
   bt_hal_interface->RemoveObserver(this);
   bt_hal_interface->CleanUp();
   ASSERT_FALSE(bt_hal_interface->IsInitialized());
-
-  osi_property_set("debug.bluetooth.unittest", "false");
 }
 
 void BluetoothTest::ClearSemaphore(semaphore_t* sem) {
diff --git a/test/suite/core/thread_performance_test.cc b/test/suite/core/thread_performance_test.cc
deleted file mode 100644
index b3f7461..0000000
--- a/test/suite/core/thread_performance_test.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-#include <base/bind.h>
-#include <base/logging.h>
-#include <base/run_loop.h>
-#include <base/threading/thread.h>
-#include <gmock/gmock.h>
-#include <gtest/gtest.h>
-#include <unistd.h>
-#include <chrono>
-#include <iostream>
-
-#include "osi/include/fixed_queue.h"
-#include "osi/include/thread.h"
-
-#define NUM_MESSAGES_TO_SEND 1000000
-
-base::MessageLoop* message_loop;
-base::RunLoop* run_loop;
-thread_t* thread;
-
-volatile static int counter = 0;
-volatile bool loop_ready = false;
-
-void set_loop_ready() { loop_ready = true; }
-
-void callback(fixed_queue_t* queue, void* data) {
-  if (queue != nullptr) {
-    fixed_queue_dequeue(queue);
-  }
-
-  counter++;
-}
-
-void run_message_loop(void* UNUSED) {
-  message_loop = new base::MessageLoop();
-  run_loop = new base::RunLoop();
-
-  message_loop->task_runner()->PostTask(FROM_HERE, base::Bind(&set_loop_ready));
-
-  run_loop->Run();
-
-  delete message_loop;
-  message_loop = nullptr;
-
-  delete run_loop;
-  run_loop = nullptr;
-}
-
-class PerformanceTest : public testing::Test {
- public:
-  fixed_queue_t* bt_msg_queue;
-
-  void SetUp() override {
-    counter = 0;
-
-    bt_msg_queue = fixed_queue_new(SIZE_MAX);
-    thread = thread_new("performance test thread");
-    thread_post(thread, run_message_loop, nullptr);
-  }
-
-  void TearDown() override {
-    fixed_queue_free(bt_msg_queue, NULL);
-    bt_msg_queue = nullptr;
-
-    thread_free(thread);
-    thread = nullptr;
-  }
-};
-
-TEST_F(PerformanceTest, message_loop_speed_test) {
-  loop_ready = false;
-  int test_data = 0;
-
-  std::chrono::steady_clock::time_point start_time =
-      std::chrono::steady_clock::now();
-  while (!loop_ready) {
-  }
-  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
-    fixed_queue_enqueue(bt_msg_queue, (void*)&test_data);
-    message_loop->task_runner()->PostTask(
-        FROM_HERE, base::Bind(&callback, bt_msg_queue, nullptr));
-  }
-
-  message_loop->task_runner()->PostTask(FROM_HERE,
-                                        run_loop->QuitWhenIdleClosure());
-  while (counter < NUM_MESSAGES_TO_SEND) {
-  }
-
-  std::chrono::steady_clock::time_point end_time =
-      std::chrono::steady_clock::now();
-  std::chrono::milliseconds duration =
-      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
-                                                            start_time);
-
-  LOG(INFO) << "Message loop took " << duration.count() << "ms for "
-            << NUM_MESSAGES_TO_SEND << " messages";
-}
-
-TEST_F(PerformanceTest, reactor_thread_speed_test) {
-  counter = 0;
-  int test_data = 0;
-
-  thread = thread_new("queue performance test thread");
-  bt_msg_queue = fixed_queue_new(SIZE_MAX);
-  fixed_queue_register_dequeue(bt_msg_queue, thread_get_reactor(thread),
-                               callback, NULL);
-
-  std::chrono::steady_clock::time_point start_time =
-      std::chrono::steady_clock::now();
-  for (int i = 0; i < NUM_MESSAGES_TO_SEND; i++) {
-    fixed_queue_enqueue(bt_msg_queue, (void*)&test_data);
-  }
-
-  while (counter < NUM_MESSAGES_TO_SEND) {
-  };
-
-  std::chrono::steady_clock::time_point end_time =
-      std::chrono::steady_clock::now();
-  std::chrono::milliseconds duration =
-      std::chrono::duration_cast<std::chrono::milliseconds>(end_time -
-                                                            start_time);
-
-  LOG(INFO) << "Reactor thread took " << duration.count() << "ms for "
-            << NUM_MESSAGES_TO_SEND << " messages";
-
-  fixed_queue_free(bt_msg_queue, NULL);
-  bt_msg_queue = nullptr;
-
-  thread_free(thread);
-  thread = nullptr;
-}
diff --git a/test/suite/gatt/gatt_test.cc b/test/suite/gatt/gatt_test.cc
index e3546d3..8c8f1ab 100644
--- a/test/suite/gatt/gatt_test.cc
+++ b/test/suite/gatt/gatt_test.cc
@@ -33,7 +33,7 @@
   status_ = 0;
 
   BluetoothTest::SetUp();
-  ASSERT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+  ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
   semaphore_wait(adapter_state_changed_callback_sem_);
   EXPECT_TRUE(GetState() == BT_STATE_ON);
 
diff --git a/test/suite/rfcomm/rfcomm_test.cc b/test/suite/rfcomm/rfcomm_test.cc
index 01d9fed..d5baf35 100644
--- a/test/suite/rfcomm/rfcomm_test.cc
+++ b/test/suite/rfcomm/rfcomm_test.cc
@@ -28,7 +28,7 @@
 void RFCommTest::SetUp() {
   BluetoothTest::SetUp();
 
-  ASSERT_EQ(bt_interface()->enable(false), BT_STATUS_SUCCESS);
+  ASSERT_EQ(bt_interface()->enable(), BT_STATUS_SUCCESS);
   semaphore_wait(adapter_state_changed_callback_sem_);
   ASSERT_TRUE(GetState() == BT_STATE_ON);
   socket_interface_ =
diff --git a/tools/mcap_tool/Android.bp b/tools/mcap_tool/Android.bp
deleted file mode 100644
index eec750c..0000000
--- a/tools/mcap_tool/Android.bp
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-cc_binary {
-    name: "mcap_tool",
-    defaults : ["fluoride_defaults"],
-    srcs: [
-      "mcap_test_app.cc",
-      "mcap_test_mcl.cc",
-      "mcap_test_mdep.cc",
-      "mcap_test_mdl.cc",
-      "mcap_tool.cc",
-    ],
-    include_dirs: [
-      "system/bt",
-      "system/bt/internal_include",
-      "system/bt/stack/include",
-      "system/bt/btcore/include",
-    ],
-    tags: ["debug", "optional"],
-    shared_libs: [
-      "libcutils",
-      "libutils",
-    ],
-    static_libs: [
-      "libbtcore",
-      "libosi",
-    ]
-}
diff --git a/tools/mcap_tool/mcap_test_app.cc b/tools/mcap_tool/mcap_test_app.cc
deleted file mode 100644
index 9515f20..0000000
--- a/tools/mcap_tool/mcap_test_app.cc
+++ /dev/null
@@ -1,536 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include "mcap_test_app.h"
-#include "mca_defs.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-#define CASE_RETURN_STR(const) \
-  case const:                  \
-    return #const;
-
-static const char* dump_mcap_events(const uint8_t event) {
-  switch (event) {
-    CASE_RETURN_STR(MCA_ERROR_RSP_EVT)
-    CASE_RETURN_STR(MCA_CREATE_IND_EVT)
-    CASE_RETURN_STR(MCA_CREATE_CFM_EVT)
-    CASE_RETURN_STR(MCA_RECONNECT_IND_EVT)
-    CASE_RETURN_STR(MCA_RECONNECT_CFM_EVT)
-    CASE_RETURN_STR(MCA_ABORT_IND_EVT)
-    CASE_RETURN_STR(MCA_ABORT_CFM_EVT)
-    CASE_RETURN_STR(MCA_DELETE_IND_EVT)
-    CASE_RETURN_STR(MCA_DELETE_CFM_EVT)
-    CASE_RETURN_STR(MCA_SYNC_CAP_IND_EVT)
-    CASE_RETURN_STR(MCA_SYNC_CAP_CFM_EVT)
-    CASE_RETURN_STR(MCA_SYNC_SET_IND_EVT)
-    CASE_RETURN_STR(MCA_SYNC_SET_CFM_EVT)
-    CASE_RETURN_STR(MCA_SYNC_INFO_IND_EVT)
-    CASE_RETURN_STR(MCA_CONNECT_IND_EVT)
-    CASE_RETURN_STR(MCA_DISCONNECT_IND_EVT)
-    CASE_RETURN_STR(MCA_OPEN_IND_EVT)
-    CASE_RETURN_STR(MCA_OPEN_CFM_EVT)
-    CASE_RETURN_STR(MCA_CLOSE_IND_EVT)
-    CASE_RETURN_STR(MCA_CLOSE_CFM_EVT)
-    CASE_RETURN_STR(MCA_CONG_CHG_EVT)
-    CASE_RETURN_STR(MCA_RSP_TOUT_IND_EVT)
-    default:
-      return "Unknown event";
-  }
-}
-
-static void print_mcap_event(const tMCA_DISCONNECT_IND* mcap_disconnect_ind) {
-  printf("%s: peer_bd_addr=%s,l2cap_disconnect_reason=0x%04x\n", __func__,
-         mcap_disconnect_ind->bd_addr.ToString().c_str(),
-         mcap_disconnect_ind->reason);
-}
-
-static void print_mcap_event(const tMCA_CONNECT_IND* mcap_connect_ind) {
-  printf("%s: peer_bd_addr=%s, peer_mtu=%d \n", __func__,
-         mcap_connect_ind->bd_addr.ToString().c_str(), mcap_connect_ind->mtu);
-}
-
-static void print_mcap_event(const tMCA_RSP_EVT* mcap_rsp) {
-  printf("%s: response, mdl_id=%d, op_code=0x%02x, rsp_code=0x%02x\n", __func__,
-         mcap_rsp->mdl_id, mcap_rsp->op_code, mcap_rsp->rsp_code);
-}
-
-static void print_mcap_event(const tMCA_EVT_HDR* mcap_evt_hdr) {
-  printf("%s: event, mdl_id=%d, op_code=0x%02x\n", __func__,
-         mcap_evt_hdr->mdl_id, mcap_evt_hdr->op_code);
-}
-
-static void print_mcap_event(const tMCA_CREATE_IND* mcap_create_ind) {
-  printf("%s: mdl_id=%d, op_code=0x%02x, dep_id=%d, cfg=0x%02x\n", __func__,
-         mcap_create_ind->mdl_id, mcap_create_ind->op_code,
-         mcap_create_ind->dep_id, mcap_create_ind->cfg);
-}
-
-static void print_mcap_event(const tMCA_CREATE_CFM* mcap_create_cfm) {
-  printf("%s: mdl_id=%d, op_code=0x%02x, rsp_code=%d, cfg=0x%02x\n", __func__,
-         mcap_create_cfm->mdl_id, mcap_create_cfm->op_code,
-         mcap_create_cfm->rsp_code, mcap_create_cfm->cfg);
-}
-
-static void print_mcap_event(const tMCA_DL_OPEN* mcap_dl_open) {
-  printf("%s: mdl_id=%d, mdl_handle=%d, mtu=%d\n", __func__,
-         mcap_dl_open->mdl_id, mcap_dl_open->mdl, mcap_dl_open->mtu);
-}
-
-static void print_mcap_event(const tMCA_DL_CLOSE* mcap_dl_close) {
-  printf("%s: mdl_id=%d, mdl_handle=%d, l2cap_disconnect_reason=0x%04x\n",
-         __func__, mcap_dl_close->mdl_id, mcap_dl_close->mdl,
-         mcap_dl_close->reason);
-}
-
-static void print_mcap_event(const tMCA_CONG_CHG* mcap_congestion_change) {
-  printf("%s: mdl_id=%d, mdl_handle=%d, congested=%d\n", __func__,
-         mcap_congestion_change->mdl_id, mcap_congestion_change->mdl,
-         mcap_congestion_change->cong);
-}
-
-McapTestApp::McapTestApp(btmcap_test_interface_t* mcap_test_interface)
-    : _mcl_list(), _mdep_list() {
-  _mcap_test_interface = mcap_test_interface;
-}
-
-btmcap_test_interface_t* McapTestApp::GetInterface() {
-  return _mcap_test_interface;
-}
-
-bool McapTestApp::Register(uint16_t ctrl_psm, uint16_t data_psm,
-                           uint16_t sec_mask, tMCA_CTRL_CBACK* callback) {
-  if (!callback) {
-    LOG(ERROR) << "callback is null";
-    return false;
-  }
-  _mca_reg.rsp_tout = 5000;
-  _mca_reg.ctrl_psm = ctrl_psm;
-  _mca_reg.data_psm = data_psm;
-  _mca_reg.sec_mask = sec_mask;
-  _mcap_handle =
-      _mcap_test_interface->register_application(&_mca_reg, callback);
-  return _mcap_handle > 0;
-}
-
-void McapTestApp::Deregister() {
-  _mcap_test_interface->deregister_application(_mcap_handle);
-  _mcap_handle = 0;
-}
-
-bool McapTestApp::Registered() { return _mcap_handle > 0; }
-
-bool McapTestApp::ConnectMcl(const RawAddress& bd_addr, uint16_t ctrl_psm,
-                             uint16_t sec_mask) {
-  if (!Registered()) {
-    LOG(ERROR) << "Application not registered";
-    return false;
-  }
-  McapMcl* mcap_mcl = FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(INFO) << "MCL does not exist, creating new MCL";
-    _mcl_list.push_back(McapMcl(_mcap_test_interface, _mcap_handle, bd_addr));
-    mcap_mcl = &_mcl_list[_mcl_list.size() - 1];
-  }
-  if (mcap_mcl->GetHandle() != 0) {
-    LOG(ERROR) << "MCL is still active, cannot make another connection";
-    return false;
-  }
-  return mcap_mcl->Connect(ctrl_psm, sec_mask);
-}
-
-bool McapTestApp::CreateMdep(uint8_t type, uint8_t max_mdl,
-                             tMCA_DATA_CBACK* data_callback) {
-  if (!data_callback) {
-    LOG(ERROR) << "Data callback is null";
-    return false;
-  }
-  _mdep_list.push_back(McapMdep(_mcap_test_interface, _mcap_handle, type,
-                                max_mdl, data_callback));
-  return _mdep_list[_mdep_list.size() - 1].Create();
-}
-
-uint8_t McapTestApp::GetHandle() { return _mcap_handle; }
-
-McapMcl* McapTestApp::FindMclByPeerAddress(const RawAddress& bd_addr) {
-  for (McapMcl& mcl : _mcl_list) {
-    if (mcl.GetPeerAddress() == bd_addr) {
-      return &mcl;
-    }
-  }
-  return nullptr;
-}
-
-McapMcl* McapTestApp::FindMclByHandle(tMCA_CL mcl_handle) {
-  for (McapMcl& mcl : _mcl_list) {
-    if (mcl.GetHandle() == mcl_handle) {
-      return &mcl;
-    }
-  }
-  return nullptr;
-}
-
-McapMdep* McapTestApp::FindMdepByHandle(tMCA_DEP mdep_handle) {
-  for (McapMdep& mdep : _mdep_list) {
-    if (mdep.GetHandle() == mdep_handle) {
-      return &mdep;
-    }
-  }
-  return nullptr;
-}
-
-void McapTestApp::RemoveMclByHandle(tMCA_CL mcl_handle) {
-  LOG(INFO) << "Removing MCL handle " << (int)mcl_handle;
-  for (std::vector<McapMcl>::iterator it = _mcl_list.begin();
-       it != _mcl_list.end(); ++it) {
-    if (it->GetHandle() == mcl_handle) {
-      _mcl_list.erase(it);
-      LOG(INFO) << "Removed MCL handle " << (int)mcl_handle;
-      return;
-    }
-  }
-}
-
-bool McapTestApp::IsRegistered() { return _mcap_handle > 0; }
-
-void McapTestApp::ControlCallback(tMCA_HANDLE handle, tMCA_CL mcl,
-                                  uint8_t event, tMCA_CTRL* p_data) {
-  McapMcl* mcap_mcl = FindMclByHandle(mcl);
-  McapMdl* mcap_mdl = nullptr;
-  printf("%s: mcap_handle=%d, mcl_handle=%d, event=%s (0x%02x)\n", __func__,
-         handle, mcl, dump_mcap_events(event), event);
-  if (_mcap_handle != handle) {
-    LOG(ERROR) << "MCAP handle mismatch, self=" << _mcap_handle
-               << ", other=" << handle;
-    return;
-  }
-  switch (event) {
-    case MCA_ERROR_RSP_EVT:
-      print_mcap_event(&p_data->rsp);
-      break;
-
-    case MCA_CREATE_CFM_EVT:
-      // Called when MCA_CreateMdl succeeded step 1 when response is received
-      print_mcap_event(&p_data->create_cfm);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->create_cfm.mdl_id);
-      if (!mcap_mdl) {
-        LOG(ERROR) << "MDL not found for id " << p_data->create_cfm.mdl_id;
-        break;
-      }
-      if (mcap_mdl->GetResponseCode() >= 0) {
-        LOG(ERROR) << "MDL already got response " << mcap_mdl->GetResponseCode()
-                   << " for id " << p_data->create_cfm.mdl_id;
-        break;
-      }
-      mcap_mdl->SetResponseCode(p_data->create_cfm.rsp_code);
-      break;
-
-    case MCA_CREATE_IND_EVT: {
-      // Should be replied with MCA_CreateMdlRsp
-      print_mcap_event(&p_data->create_ind);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
-        break;
-      }
-      McapMdep* mcap_mdep = FindMdepByHandle(p_data->create_ind.dep_id);
-      if (!mcap_mdep) {
-        LOG(ERROR) << "MDEP ID " << (int)p_data->create_ind.dep_id
-                   << " does not exist";
-        _mcap_test_interface->create_mdl_response(
-            mcl, p_data->create_ind.dep_id, p_data->create_ind.mdl_id, 0,
-            MCA_RSP_BAD_MDEP, get_test_channel_config());
-        break;
-      }
-      bool ret = mcap_mcl->CreateMdlResponse(
-          mcap_mdep->GetHandle(), p_data->create_ind.mdl_id,
-          p_data->create_ind.dep_id, p_data->create_ind.cfg);
-      LOG(INFO) << (ret ? "SUCCESS" : "FAIL");
-      if (!ret) {
-        _mcap_test_interface->create_mdl_response(
-            mcl, p_data->create_ind.dep_id, p_data->create_ind.mdl_id, 0,
-            MCA_RSP_NO_RESOURCE, get_test_channel_config());
-      }
-      break;
-    }
-    case MCA_RECONNECT_IND_EVT: {
-      // Called when remote device asks to reconnect
-      // reply with MCA_ReconnectMdlRsp
-      print_mcap_event(&p_data->reconnect_ind);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->reconnect_ind.mdl_id);
-      if (mcap_mdl && !mcap_mdl->IsConnected()) {
-        LOG(INFO) << "Creating reconnect response for MDL "
-                  << (int)p_data->reconnect_ind.mdl_id;
-        mcap_mdl->ReconnectResponse();
-        break;
-      }
-      LOG_IF(WARNING, mcap_mdl && mcap_mdl->IsConnected())
-          << "MDL ID " << (int)p_data->reconnect_ind.mdl_id
-          << " is already connected";
-      LOG_IF(WARNING, !mcap_mdl) << "No MDL for mdl_id "
-                                 << p_data->reconnect_ind.mdl_id;
-      tMCA_DEP mdep_handle = 0;
-      if (_mdep_list.size() > 0) {
-        mdep_handle = _mdep_list[0].GetHandle();
-      } else {
-        LOG(ERROR) << "Cannot find any available MDEP";
-      }
-      tMCA_RESULT ret = _mcap_test_interface->reconnect_mdl_response(
-          mcl, mdep_handle, p_data->reconnect_ind.mdl_id, MCA_RSP_BAD_MDL,
-          get_test_channel_config());
-      LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << ret;
-      break;
-    }
-    case MCA_RECONNECT_CFM_EVT:
-      // Called when MCA_ReconnectMdl step 1, receives a response
-      print_mcap_event(&p_data->reconnect_cfm);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->reconnect_cfm.mdl_id);
-      if (!mcap_mdl) {
-        LOG(ERROR) << "MDL not found for id " << p_data->reconnect_cfm.mdl_id;
-        break;
-      }
-      if (mcap_mdl->GetResponseCode() >= 0) {
-        LOG(ERROR) << "MDL already got response " << mcap_mdl->GetResponseCode()
-                   << " for id " << p_data->reconnect_cfm.mdl_id;
-        break;
-      }
-      mcap_mdl->SetResponseCode(p_data->reconnect_cfm.rsp_code);
-      break;
-
-    case MCA_ABORT_IND_EVT:
-      print_mcap_event(&p_data->abort_ind);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->abort_ind.mdl_id);
-      if (!mcap_mdl) {
-        LOG(ERROR) << "MDL not found for id " << (int)p_data->abort_ind.mdl_id;
-        break;
-      }
-      if (mcap_mdl->IsConnected()) {
-        LOG(ERROR) << "MDL is already connected for id "
-                   << (int)p_data->abort_ind.mdl_id;
-      }
-      mcap_mcl->RemoveMdl(p_data->abort_ind.mdl_id);
-      break;
-
-    case MCA_ABORT_CFM_EVT:
-      // Called when MCA_Abort succeeded
-      print_mcap_event(&p_data->abort_cfm);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->abort_cfm.mdl_id);
-      if (!mcap_mdl) {
-        LOG(ERROR) << "MDL not found for id " << (int)p_data->abort_cfm.mdl_id;
-        break;
-      }
-      if (mcap_mdl->IsConnected()) {
-        LOG(ERROR) << "MDL is already connected for id "
-                   << (int)p_data->abort_cfm.mdl_id;
-      }
-      mcap_mcl->RemoveMdl(p_data->abort_cfm.mdl_id);
-      break;
-
-    case MCA_DELETE_IND_EVT:
-      print_mcap_event(&p_data->delete_ind);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
-        break;
-      }
-      if (p_data->delete_ind.mdl_id == MCA_ALL_MDL_ID) {
-        mcap_mcl->RemoveAllMdl();
-      } else {
-        mcap_mcl->RemoveMdl(p_data->delete_ind.mdl_id);
-      }
-      break;
-
-    case MCA_DELETE_CFM_EVT:
-      // Called when MCA_Delete succeeded
-      print_mcap_event(&p_data->delete_cfm);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL " << (int)mcl << " not connected";
-        break;
-      }
-      if (p_data->delete_cfm.rsp_code) {
-        LOG(ERROR) << "No success response " << (int)p_data->delete_cfm.rsp_code
-                   << " when deleting MDL_ID "
-                   << (int)p_data->delete_cfm.mdl_id;
-        break;
-      }
-      if (p_data->delete_cfm.mdl_id == MCA_ALL_MDL_ID) {
-        mcap_mcl->RemoveAllMdl();
-      } else {
-        mcap_mcl->RemoveMdl(p_data->delete_cfm.mdl_id);
-      }
-      break;
-
-    case MCA_CONNECT_IND_EVT: {
-      // Called when MCA_ConnectReq succeeded
-      print_mcap_event(&p_data->connect_ind);
-      LOG(INFO) << "Received MCL handle " << (int)mcl;
-      RawAddress bd_addr = p_data->connect_ind.bd_addr;
-      mcap_mcl = FindMclByPeerAddress(bd_addr);
-      if (!mcap_mcl) {
-        LOG(INFO) << "Creating new MCL for ID " << (int)mcl;
-        _mcl_list.push_back(
-            McapMcl(_mcap_test_interface, _mcap_handle, bd_addr));
-        mcap_mcl = &_mcl_list[_mcl_list.size() - 1];
-      }
-      if (mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL is already connected for handle " << (int)mcl;
-        break;
-      }
-      mcap_mcl->SetHandle(mcl);
-      mcap_mcl->SetMtu(p_data->connect_ind.mtu);
-      break;
-    }
-    case MCA_DISCONNECT_IND_EVT: {
-      // Called when MCA_ConnectReq failed or MCA_DisconnectReq succeeded
-      print_mcap_event(&p_data->disconnect_ind);
-      RawAddress bd_addr = p_data->disconnect_ind.bd_addr;
-      mcap_mcl = FindMclByPeerAddress(bd_addr);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for BD addr " << bd_addr;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(WARNING) << "MCL for " << bd_addr << " is already disconnected";
-      }
-      mcap_mcl->SetHandle(0);
-      mcap_mcl->SetMtu(0);
-      mcap_mcl->ResetAllMdl();
-      break;
-    }
-    case MCA_OPEN_IND_EVT:
-    // Called when MCA_CreateMdlRsp succeeded step 2, data channel is open
-    // Called when MCA_ReconnectMdlRsp succeeded step 2, data channel is open
-    case MCA_OPEN_CFM_EVT:
-      // Called when MCA_CreateMdl succeeded step 2, data channel is open
-      // Called when MCA_ReconnectMdl succeeded step 2, data channel is open
-      // Called when MCA_DataChnlCfg succeeded
-      print_mcap_event(&p_data->open_ind);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->open_ind.mdl_id);
-      if (mcap_mdl) {
-        if (mcap_mdl->IsConnected()) {
-          LOG(ERROR) << "MDL is already connected for mcl_handle "
-                     << (int)p_data->open_ind.mdl_id;
-          break;
-        }
-        mcap_mdl->SetMtu(p_data->open_ind.mtu);
-        mcap_mdl->SetHandle(p_data->open_ind.mdl);
-      } else {
-        LOG(ERROR) << "No MDL for mdl_id " << (int)p_data->reconnect_ind.mdl_id;
-      }
-      break;
-
-    case MCA_CLOSE_IND_EVT:
-    case MCA_CLOSE_CFM_EVT:
-      // Called when MCA_CloseReq is successful
-      print_mcap_event(&p_data->close_cfm);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
-        break;
-      }
-      mcap_mdl = mcap_mcl->FindMdlById(p_data->close_cfm.mdl_id);
-      if (mcap_mdl) {
-        mcap_mdl->SetMtu(0);
-        mcap_mdl->SetHandle(0);
-      } else {
-        LOG(WARNING) << "No MDL for mdl_id " << (int)p_data->close_cfm.mdl_id;
-      }
-      break;
-
-    case MCA_CONG_CHG_EVT:
-      print_mcap_event(&p_data->cong_chg);
-      if (!mcap_mcl) {
-        LOG(ERROR) << "No MCL for mcl_handle " << (int)mcl;
-        break;
-      }
-      if (!mcap_mcl->IsConnected()) {
-        LOG(ERROR) << "MCL not connected for mcl_handle " << (int)mcl;
-        break;
-      }
-      break;
-
-    case MCA_RSP_TOUT_IND_EVT:
-    case MCA_SYNC_CAP_IND_EVT:
-    case MCA_SYNC_CAP_CFM_EVT:
-    case MCA_SYNC_SET_IND_EVT:
-    case MCA_SYNC_SET_CFM_EVT:
-    case MCA_SYNC_INFO_IND_EVT:
-      print_mcap_event(&p_data->hdr);
-      break;
-  }
-}
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_app.h b/tools/mcap_tool/mcap_test_app.h
deleted file mode 100644
index db81657..0000000
--- a/tools/mcap_tool/mcap_test_app.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-#pragma once
-
-#include <functional>
-#include <iterator>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include <base/logging.h>
-
-#include "mca_api.h"
-
-#include "mcap_test_mcl.h"
-#include "mcap_test_mdep.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-extern const tMCA_CHNL_CFG MCAP_TEST_CHANNEL_CONFIG;
-
-class McapTestApp {
- public:
-  /**
-   * McapTestApp is the root node for an MCAP application
-   *
-   * @param mcap_test_interface interface to MCAP APIs on Bluetooth stack
-   *                            from get_test_interface()
-   */
-  McapTestApp(btmcap_test_interface_t* mcap_test_interface);
-  btmcap_test_interface_t* GetInterface();
-  /**
-   * Register an application with the Bluetooth stack
-   * @param ctrl_psm Control channel L2CAP PSM
-   * @param data_psm Data channel L2CAP PSM
-   * @param sec_mask Security Mask
-   * @param callback Control channel callback
-   * @return
-   */
-  bool Register(uint16_t ctrl_psm, uint16_t data_psm, uint16_t sec_mask,
-                tMCA_CTRL_CBACK* callback);
-  /**
-   * De-register the current application
-   */
-  void Deregister();
-  /**
-   * Check if current application is registered
-   * @return True if registered
-   */
-  bool Registered();
-  /**
-   * Create MCAP Communication Link
-   * @param bd_addr Peer Bluetooth Address
-   * @param ctrl_psm Control channel L2CAP PSM, should be the same as registered
-   *                 value for most cases
-   * @param sec_mask Security mask
-   * @return True on success
-   */
-  bool ConnectMcl(const RawAddress& bd_addr, uint16_t ctrl_psm,
-                  uint16_t sec_mask);
-  /**
-   * Create MCAP Data End Point
-   * @param type 0 - MCA_TDEP_ECHO, 1 - MCA_TDEP_DATA
-   * @param max_mdl Maximum number of data channels for this end point
-   * @param data_callback Data callback
-   * @return True on success
-   */
-  bool CreateMdep(uint8_t type, uint8_t max_mdl,
-                  tMCA_DATA_CBACK* data_callback);
-  // Simple methods that are self-explanatory
-  uint8_t GetHandle();
-  McapMcl* FindMclByPeerAddress(const RawAddress& bd_addr);
-  McapMcl* FindMclByHandle(tMCA_CL mcl_handle);
-  McapMdep* FindMdepByHandle(tMCA_DEP mdep_handle);
-  void RemoveMclByHandle(tMCA_CL mcl_handle);
-  bool IsRegistered();
-  /**
-   * Callback function for control channel, need to be called by an external
-   * function registered during McapTestApp::Register()
-   * @param handle MCAP application handle, should be the same as GetHandle()
-   * @param mcl MCL handle, FindMclByHandle(mcl) should return non-null value
-   * @param event Control event
-   * @param p_data Control data
-   */
-  void ControlCallback(tMCA_HANDLE handle, tMCA_CL mcl, uint8_t event,
-                       tMCA_CTRL* p_data);
-
- private:
-  // Initialized during start up
-  tMCA_REG _mca_reg;
-  btmcap_test_interface_t* _mcap_test_interface = nullptr;
-  std::vector<McapMcl> _mcl_list;
-  std::vector<McapMdep> _mdep_list;
-
-  // Initialized later
-  tMCA_HANDLE _mcap_handle = 0;
-};
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_mcl.cc b/tools/mcap_tool/mcap_test_mcl.cc
deleted file mode 100644
index 53cc329..0000000
--- a/tools/mcap_tool/mcap_test_mcl.cc
+++ /dev/null
@@ -1,216 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <cstring>
-
-#include <base/logging.h>
-
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "mcap_test_mcl.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-McapMcl::McapMcl(btmcap_test_interface_t* mcap_test_interface,
-                 tMCA_HANDLE mcap_handle, const RawAddress& peer_bd_addr)
-    : _mdl_list() {
-  _mcap_handle = mcap_handle;
-  _mcap_test_interface = mcap_test_interface;
-  memcpy(_peer_bd_addr.address, peer_bd_addr.address,
-         sizeof(_peer_bd_addr.address));
-}
-
-bool McapMcl::Connect(uint16_t ctrl_psm, uint16_t sec_mask) {
-  tMCA_RESULT ret = _mcap_test_interface->connect_mcl(
-      _mcap_handle, _peer_bd_addr, ctrl_psm, sec_mask);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMcl::Disconnect() {
-  if (!IsConnected()) {
-    LOG(ERROR) << "MCL is not connected";
-    return false;
-  }
-  tMCA_RESULT ret = _mcap_test_interface->disconnect_mcl(_mcl_handle);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-McapMdl* McapMcl::AllocateMdl(tMCA_DEP mdep_handle, uint16_t mdl_id,
-                              uint8_t dep_id, uint8_t cfg) {
-  if (!IsConnected()) {
-    LOG(ERROR) << "MCL is not connected";
-    return nullptr;
-  }
-  if (FindMdlById(mdl_id) != nullptr) {
-    LOG(ERROR) << "mdl_id=" << mdl_id << "already exists";
-    return nullptr;
-  }
-  if (!HasAvailableMdl()) {
-    LOG(ERROR) << "No more avaible MDL, currently " << _mdl_list.size();
-    return nullptr;
-  }
-  _mdl_list.push_back(McapMdl(_mcap_test_interface, _mcl_handle, mdep_handle,
-                              mdl_id, dep_id, cfg));
-  return &_mdl_list[_mdl_list.size() - 1];
-}
-
-bool McapMcl::CreateMdl(tMCA_DEP mdep_handle, uint16_t data_psm,
-                        uint16_t mdl_id, uint8_t peer_dep_id, uint8_t cfg,
-                        bool should_connect) {
-  if (!IsConnected()) {
-    LOG(ERROR) << "MCL is not connected";
-    return false;
-  }
-  McapMdl* mcap_mdl = FindMdlById(mdl_id);
-  if (!mcap_mdl) {
-    LOG(INFO) << "mdl_id=" << mdl_id << "does not exists, creating new one";
-    mcap_mdl = AllocateMdl(mdep_handle, mdl_id, peer_dep_id, cfg);
-    if (!mcap_mdl) {
-      return false;
-    }
-  }
-  if (mcap_mdl->IsConnected()) {
-    LOG(ERROR) << "mdl_id=" << mdl_id << "is already connected with handle "
-               << (int)mcap_mdl->GetHandle();
-    return false;
-  }
-  return mcap_mdl->Create(data_psm, should_connect);
-}
-
-bool McapMcl::DataChannelConfig() {
-  tMCA_RESULT ret = _mcap_test_interface->data_channel_config(
-      _mcl_handle, get_test_channel_config());
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMcl::CreateMdlResponse(tMCA_DEP mdep_handle, uint16_t mdl_id,
-                                uint8_t my_dep_id, uint8_t cfg) {
-  if (!IsConnected()) {
-    LOG(ERROR) << "MCL is not connected";
-    return false;
-  }
-  McapMdl* mcap_mdl = FindMdlById(mdl_id);
-  if (!mcap_mdl) {
-    LOG(INFO) << "mdl_id=" << mdl_id << " does not exists, creating new one";
-    mcap_mdl = AllocateMdl(mdep_handle, mdl_id, my_dep_id, cfg);
-    if (!mcap_mdl) {
-      LOG(ERROR) << "MDL cannot be created";
-      return false;
-    }
-  }
-  if (mcap_mdl->IsConnected()) {
-    LOG(INFO) << "mdl_id=" << mdl_id << " is already connected with handle "
-              << (int)mcap_mdl->GetHandle() << ", updating context";
-    mcap_mdl->UpdateContext(mdep_handle, my_dep_id, cfg);
-  }
-  return mcap_mdl->CreateResponse();
-}
-
-bool McapMcl::AbortMdl() {
-  tMCA_RESULT ret = _mcap_test_interface->abort_mdl(_mcl_handle);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMcl::DeleteMdl(uint16_t mdl_id) {
-  tMCA_RESULT ret = _mcap_test_interface->delete_mdl(_mcl_handle, mdl_id);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-RawAddress& McapMcl::GetPeerAddress() { return _peer_bd_addr; }
-
-void McapMcl::SetHandle(tMCA_CL handle) { _mcl_handle = handle; }
-
-tMCA_CL McapMcl::GetHandle() const { return _mcl_handle; }
-
-void McapMcl::SetMtu(uint16_t mtu) { _control_mtu = mtu; }
-
-uint16_t McapMcl::GetMtu() { return _control_mtu; }
-
-McapMdl* McapMcl::FindMdlById(uint16_t mdl_id) {
-  for (McapMdl& mdl : _mdl_list) {
-    if (mdl.GetId() == mdl_id) {
-      return &mdl;
-    }
-  }
-  return nullptr;
-}
-
-McapMdl* McapMcl::FindMdlByHandle(tMCA_DL mdl_handle) {
-  for (McapMdl& mdl : _mdl_list) {
-    if (mdl.GetHandle() == mdl_handle) {
-      return &mdl;
-    }
-  }
-  return nullptr;
-}
-
-void McapMcl::RemoveAllMdl() { _mdl_list.clear(); }
-
-void McapMcl::RemoveMdl(uint16_t mdl_id) {
-  LOG(INFO) << "Removing MDL id " << (int)mdl_id;
-  for (std::vector<McapMdl>::iterator it = _mdl_list.begin();
-       it != _mdl_list.end(); ++it) {
-    if (it->GetId() == mdl_id) {
-      _mdl_list.erase(it);
-      LOG(INFO) << "Removed MDL id " << (int)mdl_id;
-      return;
-    }
-  }
-}
-
-void McapMcl::ResetAllMdl() {
-  for (McapMdl& mcap_mdl : _mdl_list) {
-    mcap_mdl.SetHandle(0);
-    mcap_mdl.SetMtu(0);
-    mcap_mdl.SetResponseCode(-1);
-  }
-}
-
-void McapMcl::ResetMdl(uint16_t mdl_id) {
-  LOG(INFO) << "Closing MDL id " << (int)mdl_id;
-  McapMdl* mcap_mdl = FindMdlById(mdl_id);
-  if (!mcap_mdl) {
-    LOG(ERROR) << "Cannot find MDL for id " << (int)mdl_id;
-    return;
-  }
-  if (mcap_mdl->IsConnected()) {
-    LOG(ERROR) << "MDL " << (int)mdl_id << " is still connected";
-    return;
-  }
-  mcap_mdl->SetHandle(0);
-  mcap_mdl->SetMtu(0);
-  mcap_mdl->SetResponseCode(-1);
-}
-
-bool McapMcl::IsConnected() { return _mcl_handle > 0; }
-
-int McapMcl::ConnectedMdlCount() {
-  int count = 0;
-  for (McapMdl& mcap_mdl : _mdl_list) {
-    if (mcap_mdl.IsConnected()) {
-      count++;
-    }
-  }
-  return count;
-}
-
-bool McapMcl::HasAvailableMdl() { return ConnectedMdlCount() < MCA_NUM_MDLS; }
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_mcl.h b/tools/mcap_tool/mcap_test_mcl.h
deleted file mode 100644
index 6700fb1..0000000
--- a/tools/mcap_tool/mcap_test_mcl.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-#pragma once
-
-#include <vector>
-
-#include "mca_api.h"
-#include "mcap_test_mdl.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-class McapMcl {
- public:
-  /**
-   * A controller for a MCAP Communication Link (MCL)
-   * @param mcap_test_interface Underlining interface to Bluetooth stack
-   * @param mcap_handle Parent application handle
-   * @param peer_bd_addr Peer Bluetooth MAC address
-   */
-  McapMcl(btmcap_test_interface_t* mcap_test_interface, tMCA_HANDLE mcap_handle,
-          const RawAddress& peer_bd_addr);
-  /**
-   * Connect this MCL's control channel
-   * @param ctrl_psm Control channel L2CAP PSM
-   * @param sec_mask Security mask
-   * @return True on success
-   */
-  bool Connect(uint16_t ctrl_psm, uint16_t sec_mask);
-  /**
-   * Disconnect from control channel
-   * @return
-   */
-  bool Disconnect();
-  /**
-   * Close this MCL connection
-   * @return
-   */
-  bool Close();
-  /**
-   * Allocate an MCAP Data Link (MDL) object and save to this MCL object
-   * @param mdep_handle MDEP handle for data, MDEP must be prior created
-   * @param mdl_id Desired MDL ID, user supported
-   * @param dep_id Peer MDEP ID
-   * @param cfg Configuration flags
-   * @return True on success
-   */
-  McapMdl* AllocateMdl(tMCA_DEP mdep_handle, uint16_t mdl_id, uint8_t dep_id,
-                       uint8_t cfg);
-  /**
-   * Send CREATE_MDL message to peer device, will allocate an MDL if the MDL for
-   * corresponding MDL ID was not allocated before
-   * @param mdep_handle MDEP handle for data, MDEP must be prior created
-   * @param data_psm Data channel L2CAP PSM
-   * @param mdl_id Desired MDL ID, user supported
-   * @param peer_dep_id Peer MDEP ID
-   * @param cfg Configuration flags
-   * @param should_connect whether we should connect L2CAP immediately
-   * @return True on success
-   */
-  bool CreateMdl(tMCA_DEP mdep_handle, uint16_t data_psm, uint16_t mdl_id,
-                 uint8_t peer_dep_id, uint8_t cfg, bool should_connect);
-  /**
-   * Configure data channel, unblock any pending MDL L2CAP connection requests
-   * @return True on Success
-   */
-  bool DataChannelConfig();
-  /**
-   * Respond to CREATE_MDL message received from peer device, will allocate an
-   * MDL if the MDL for corresponding MDL ID was not allocated before
-   * @param mdep_handle MDEP handle for data, MDEP must be prior created
-   * @param mdl_id Desired MDL ID, peer supported
-   * @param my_dep_id My MDEP ID
-   * @param cfg Configuration flags
-   * @return True on success
-   */
-  bool CreateMdlResponse(tMCA_DEP mdep_handle, uint16_t mdl_id,
-                         uint8_t my_dep_id, uint8_t cfg);
-  /**
-   * Send ABORT_MDL request, aborting all pending CREATE_MDL requests
-   * @return
-   */
-  bool AbortMdl();
-  /**
-   * Send DELETE_MDL request to remote
-   * @param mdl_id None zero value mdl_id, 0xFFFF for all remote MDLs
-   * @return True on success
-   */
-  bool DeleteMdl(uint16_t mdl_id);
-  // Simple methods that are self-explanatory
-  RawAddress& GetPeerAddress();
-  void SetHandle(tMCA_CL handle);
-  tMCA_CL GetHandle() const;
-  void SetMtu(uint16_t mtu);
-  uint16_t GetMtu();
-  McapMdl* FindMdlById(uint16_t mdl_id);
-  McapMdl* FindMdlByHandle(tMCA_DL mdl_handle);
-  void RemoveAllMdl();
-  void RemoveMdl(uint16_t mdl_id);
-  void ResetAllMdl();
-  void ResetMdl(uint16_t mdl_id);
-  bool IsConnected();
-  int ConnectedMdlCount();
-  bool HasAvailableMdl();
-
- private:
-  // Initialized during start up
-  btmcap_test_interface_t* _mcap_test_interface;
-  tMCA_HANDLE _mcap_handle;
-  RawAddress _peer_bd_addr;
-  std::vector<McapMdl> _mdl_list;
-
-  // Initialized later
-  tMCA_CL _mcl_handle = 0;
-  uint16_t _control_mtu = 0;
-};
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_mdep.cc b/tools/mcap_tool/mcap_test_mdep.cc
deleted file mode 100644
index bd2ce23..0000000
--- a/tools/mcap_tool/mcap_test_mdep.cc
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <base/logging.h>
-
-#include "mcap_test_mdep.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-McapMdep::McapMdep(btmcap_test_interface_t* mcap_test_interface,
-                   tMCA_HANDLE mcap_handle, uint8_t type, uint8_t max_mdl,
-                   tMCA_DATA_CBACK* data_callback) {
-  _mcap_test_interface = mcap_test_interface;
-  _mcap_handle = mcap_handle;
-  _mca_cs.type = (0 == type) ? MCA_TDEP_ECHO : MCA_TDEP_DATA;
-  _mca_cs.max_mdl = max_mdl;
-  _mca_cs.p_data_cback = data_callback;
-}
-
-bool McapMdep::Create() {
-  tMCA_RESULT ret =
-      _mcap_test_interface->create_mdep(_mcap_handle, &_mdep_handle, &_mca_cs);
-  LOG(INFO) << "mdep_handle=" << (int)_mdep_handle;
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMdep::Delete() {
-  tMCA_RESULT ret =
-      _mcap_test_interface->create_mdep(_mcap_handle, &_mdep_handle, &_mca_cs);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-tMCA_DEP McapMdep::GetHandle() const { return _mdep_handle; }
-
-bool McapMdep::IsRegistered() { return _mdep_handle > 0; }
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_mdep.h b/tools/mcap_tool/mcap_test_mdep.h
deleted file mode 100644
index 2278781..0000000
--- a/tools/mcap_tool/mcap_test_mdep.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-#pragma once
-
-#include "mca_api.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-class McapMdep {
- public:
-  /**
-   * A control abstraction for a MCAP Data End Point (MDEP)
-   * @param mcap_test_interface Underlining MCAP interface to Bluetooth stack
-   * @param mcap_handle Parent MCAP application handle
-   * @param type 0 for Echo, 1 for Normal, nothing else
-   * @param max_mdl Maximum number of MDL's allowed
-   * @param data_callback Data channel callback function
-   */
-  McapMdep(btmcap_test_interface_t* mcap_test_interface,
-           tMCA_HANDLE mcap_handle, uint8_t type, uint8_t max_mdl,
-           tMCA_DATA_CBACK* data_callback);
-  /**
-   * Actually create the MDEP in the stack
-   * @return True if success
-   */
-  bool Create();
-  /**
-   * Destroy the MDEP in the stack
-   * @return True if success
-   */
-  bool Delete();
-  // Simple methods that are self-explanatory
-  tMCA_DEP GetHandle() const;
-  bool IsRegistered();
-
- private:
-  // Initialized during start up
-  btmcap_test_interface_t* _mcap_test_interface;
-  tMCA_HANDLE _mcap_handle;
-  tMCA_CS _mca_cs;
-
-  // Initialized later
-  tMCA_DEP _mdep_handle = 0;
-};
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_mdl.cc b/tools/mcap_tool/mcap_test_mdl.cc
deleted file mode 100644
index f0cd572..0000000
--- a/tools/mcap_tool/mcap_test_mdl.cc
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-#include <base/logging.h>
-
-#include "mca_defs.h"
-#include "mcap_test_mdl.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-/* Test MCAP Channel Configurations */
-const tMCA_CHNL_CFG MCAP_TEST_CHANNEL_CONFIG = {
-    .fcr_opt =
-        {
-            L2CAP_FCR_ERTM_MODE,
-            MCA_FCR_OPT_TX_WINDOW_SIZE, /* Tx window size */
-            /* Maximum transmissions before disconnecting */
-            MCA_FCR_OPT_MAX_TX_B4_DISCNT,
-            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 */
-        },
-    .user_rx_buf_size = BT_DEFAULT_BUFFER_SIZE,
-    .user_tx_buf_size = BT_DEFAULT_BUFFER_SIZE,
-    .fcr_rx_buf_size = BT_DEFAULT_BUFFER_SIZE,
-    .fcr_tx_buf_size = BT_DEFAULT_BUFFER_SIZE,
-    .fcs = MCA_FCS_NONE,
-    .data_mtu = 572 /* L2CAP MTU of the MCAP data channel */
-};
-
-const tMCA_CHNL_CFG* get_test_channel_config() {
-  return &MCAP_TEST_CHANNEL_CONFIG;
-}
-
-McapMdl::McapMdl(btmcap_test_interface_t* mcap_test_interface,
-                 tMCA_CL mcl_handle, tMCA_DEP mdep_handle, uint16_t mdl_id,
-                 uint8_t dep_id, uint8_t cfg) {
-  _mcap_test_interface = mcap_test_interface;
-  _mcl_handle = mcl_handle;
-  _mdep_handle = mdep_handle;
-  _mdl_id = mdl_id;
-  _dep_id = dep_id;
-  _cfg = cfg;
-}
-
-bool McapMdl::UpdateContext(tMCA_DEP mdep_handle, uint8_t dep_id, uint8_t cfg) {
-  if (!_mdl_handle) {
-    LOG(ERROR) << "MDL handle not initialized";
-  }
-  _mdep_handle = mdep_handle;
-  _dep_id = dep_id;
-  _cfg = cfg;
-  tMCA_RESULT ret = _mcap_test_interface->close_mdl_request(_mdl_handle);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  if (ret != MCA_SUCCESS) return false;
-  SetHandle(0);
-  SetResponseCode(-1);
-  SetMtu(0);
-  return true;
-}
-
-bool McapMdl::Create(uint16_t data_psm, bool should_connect) {
-  tMCA_RESULT ret = _mcap_test_interface->create_mdl_request(
-      _mcl_handle, _mdep_handle, data_psm, _mdl_id, _dep_id, _cfg,
-      should_connect ? &MCAP_TEST_CHANNEL_CONFIG : nullptr);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMdl::Close() {
-  if (!_mdl_handle) {
-    LOG(ERROR) << "MDL handle not initialized";
-    return false;
-  }
-  tMCA_RESULT ret = _mcap_test_interface->close_mdl_request(_mdl_handle);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMdl::Reconnect(uint16_t data_psm) {
-  tMCA_RESULT ret = _mcap_test_interface->reconnect_mdl_request(
-      _mcl_handle, _mdep_handle, data_psm, _mdl_id, &MCAP_TEST_CHANNEL_CONFIG);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMdl::ReconnectResponse() {
-  tMCA_RESULT ret = _mcap_test_interface->reconnect_mdl_response(
-      _mcl_handle, _mdep_handle, _mdl_id, MCA_RSP_SUCCESS,
-      &MCAP_TEST_CHANNEL_CONFIG);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMdl::CreateResponse() {
-  tMCA_RESULT ret = _mcap_test_interface->create_mdl_response(
-      _mcl_handle, _dep_id, _mdl_id, _cfg, MCA_SUCCESS,
-      &MCAP_TEST_CHANNEL_CONFIG);
-  LOG_IF(INFO, ret != MCA_SUCCESS) << "ret=" << (int)ret;
-  return ret == MCA_SUCCESS;
-}
-
-bool McapMdl::IsConnected() { return _mdl_handle > 0; }
-
-uint16_t McapMdl::GetId() { return _mdl_id; }
-
-int32_t McapMdl::GetResponseCode() { return _mdl_rsp_code; }
-
-void McapMdl::SetResponseCode(int32_t rsp_code) { _mdl_rsp_code = rsp_code; }
-
-void McapMdl::SetHandle(tMCA_DL mdl_handle) { _mdl_handle = mdl_handle; }
-
-tMCA_DL McapMdl::GetHandle() { return _mdl_handle; }
-
-void McapMdl::SetMtu(uint16_t mtu) { _data_mtu = mtu; }
-
-uint16_t McapMdl::GetMtu() { return _data_mtu; }
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_test_mdl.h b/tools/mcap_tool/mcap_test_mdl.h
deleted file mode 100644
index 56d8d8c..0000000
--- a/tools/mcap_tool/mcap_test_mdl.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-#pragma once
-
-#include "mca_api.h"
-
-namespace SYSTEM_BT_TOOLS_MCAP_TOOL {
-
-const tMCA_CHNL_CFG* get_test_channel_config();
-
-class McapMdl {
- public:
-  /**
-   * An abstraction for the MCAP Data Link (MDL)
-   * @param mcap_test_interface Underlining MCAP interface to Bluetooth stack
-   * @param mcl_handle Parent MCL handle
-   * @param mdep_handle Associated MDEP handle
-   * @param mdl_id Desired MDL ID, application supported
-   * @param dep_id Peer or self MDEP ID
-   * @param cfg Configuration flags
-   */
-  McapMdl(btmcap_test_interface_t* mcap_test_interface, tMCA_CL mcl_handle,
-          tMCA_DEP mdep_handle, uint16_t mdl_id, uint8_t dep_id, uint8_t cfg);
-  /**
-   * Update this MDL's context so that it can be reused for a new connection
-   * This will close this MDL connection at the same time
-   * @param mdep_handle Associated MDEP handle
-   * @param dep_id Peer or self MDEP ID
-   * @param cfg Configuration flags
-   * @return True on success
-   */
-  bool UpdateContext(tMCA_DEP mdep_handle, uint8_t dep_id, uint8_t cfg);
-  /**
-   * Request to create this MDL to remote device through MCL
-   * The create command won't initiate an L2CAP connection unless a non-null
-   * config is given
-   * @param data_psm Data channel L2CAP PSM
-   * @return True on success
-   */
-  bool Create(uint16_t data_psm, bool should_connect);
-  /**
-   * Connect this MDL to remote by configuring the data channel
-   * @return True on success
-   */
-  bool Connect();
-  /**
-   * Close this MDL connection
-   * @return True on success
-   */
-  bool Close();
-  /**
-   * Request to reconnect connect this MDL to remote device through MCL
-   * @param data_psm Data channel L2CAP PSM
-   * @return True on success
-   */
-  bool Reconnect(uint16_t data_psm);
-  /**
-   * Respond to a reconnect request from peer
-   * @return True on success
-   */
-  bool ReconnectResponse();
-  /**
-   * Respond to a connect request from peer
-   * @return True on success
-   */
-  bool CreateResponse();
-  bool IsConnected();
-  int32_t GetResponseCode();
-  void SetResponseCode(int32_t rsp_code);
-  uint16_t GetId();
-  void SetHandle(tMCA_DL mdl_handle);
-  tMCA_DL GetHandle();
-  void SetMtu(uint16_t mtu);
-  uint16_t GetMtu();
-
- private:
-  // Initialized at start up
-  btmcap_test_interface_t* _mcap_test_interface;
-  tMCA_CL _mcl_handle;
-  tMCA_DEP _mdep_handle;
-  uint16_t _mdl_id;
-  uint8_t _dep_id;
-  uint8_t _cfg;
-
-  // Initialized later
-  tMCA_DL _mdl_handle = 0;
-  uint16_t _data_mtu = 0;
-  int32_t _mdl_rsp_code = -1;
-};
-
-}  // namespace SYSTEM_BT_TOOLS_MCAP_TOOL
diff --git a/tools/mcap_tool/mcap_tool.cc b/tools/mcap_tool/mcap_tool.cc
deleted file mode 100644
index 6ed26aa..0000000
--- a/tools/mcap_tool/mcap_tool.cc
+++ /dev/null
@@ -1,959 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2015, The linux Foundation. All rights reserved.
- *
- *  Not a Contribution.
- *
- *  Copyright 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.cc
- *
- *  Description:   Fluoride MCAP Test Tool application
- *
- ***********************************************************************************/
-#include <pthread.h>
-#include <signal.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#ifndef OS_GENERIC
-#include <sys/capability.h>
-#endif
-#include <sys/prctl.h>
-#include <time.h>
-#include <unistd.h>
-
-#include <hardware/bluetooth.h>
-#ifndef OS_GENERIC
-#include <private/android_filesystem_config.h>
-#endif
-#include <base/logging.h>
-
-#include "bt_types.h"
-#include "l2c_api.h"
-#include "mca_api.h"
-#include "mca_defs.h"
-#include "osi/include/compat.h"
-#include "hal_util.h"
-#include "mcap_test_app.h"
-#include "mcap_test_mcl.h"
-#include "mcap_test_mdep.h"
-#include "mcap_test_mdl.h"
-
-using SYSTEM_BT_TOOLS_MCAP_TOOL::McapTestApp;
-using SYSTEM_BT_TOOLS_MCAP_TOOL::McapMcl;
-using SYSTEM_BT_TOOLS_MCAP_TOOL::McapMdep;
-using SYSTEM_BT_TOOLS_MCAP_TOOL::McapMdl;
-
-/******************************************************************************
- *  Constants & Macros
- *****************************************************************************/
-#define PID_FILE "/data/.bdt_pid"
-
-#ifndef MAX
-#define MAX(x, y) ((x) > (y) ? (x) : (y))
-#endif
-
-#ifndef MIN
-#define MIN(x, y) ((x) < (y) ? (x) : (y))
-#endif
-
-#define CASE_RETURN_STR(const) \
-  case const:                  \
-    return #const;
-
-#ifndef OS_GENERIC
-/* Permission Groups */
-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};
-#endif
-/******************************************************************************
- *  Static variables
- *****************************************************************************/
-/* Console loop states */
-static bool global_main_done = false;
-static bt_status_t global_status;
-static bool global_strict_mode = false;
-
-/* Device and Profile Interfaces */
-const bt_interface_t* sBtInterface = nullptr;
-static btmcap_test_interface_t* sMcapTestInterface = nullptr;
-static McapTestApp* sMcapTestApp = nullptr;
-
-/* Bluetooth stack states */
-static bool global_bt_enabled = false;
-static int global_adapter_state = BT_STATE_OFF;
-static int global_pair_state = BT_BOND_STATE_NONE;
-/************************************************************************************
-**  Static functions
-************************************************************************************/
-static void process_cmd(char* p, bool is_job);
-
-/*******************************************************************************
- ** Misc helper functions
- *******************************************************************************/
-static const char* dump_bt_status(const 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";
-  }
-}
-
-/************************************************************************************
-**  MCAP Callbacks
-************************************************************************************/
-static void mcap_ctrl_callback(tMCA_HANDLE handle, tMCA_CL mcl, uint8_t event,
-                               tMCA_CTRL* p_data) {
-  sMcapTestApp->ControlCallback(handle, mcl, event, p_data);
-}
-
-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",
-         __func__, mdl, p_pkt->event, p_pkt->len, p_pkt->offset,
-         p_pkt->layer_specific);
-  printf("%s: HEXDUMP OF DATA LENGTH %u:\n", __func__, p_pkt->len);
-  printf("=========================Begin=========================\n");
-  bool newline = false;
-  for (int i = 0; i < p_pkt->len; ++i) {
-    printf("%02x", p_pkt->data[i]);
-    if (i > 0 && (i % 25) == 0) {
-      printf("\n");
-      newline = true;
-    } else {
-      printf(" ");
-      newline = false;
-    }
-  }
-  if (!newline) printf("\n");
-  printf("=========================End===========================\n");
-}
-
-/************************************************************************************
-**  Shutdown helper functions
-************************************************************************************/
-
-static void console_shutdown(void) {
-  LOG(INFO) << __func__ << ": Shutdown Fluoride MCAP test app";
-  global_main_done = true;
-}
-
-/*****************************************************************************
-** Android's init.rc does not yet support applying linux capabilities
-*****************************************************************************/
-
-#ifndef OS_GENERIC
-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);
-}
-#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) {
-  return get_hex_any(p, DefaultValue, 8);
-}
-uint8_t get_hex_byte(char** p, int DefaultValue) {
-  return get_hex_any(p, DefaultValue, 2);
-}
-
-bool is_cmd(const char* cmd, const char* str) {
-  return (strlen(str) == strlen(cmd)) && (strncmp(cmd, str, strlen(str)) == 0);
-}
-
-typedef void(console_cmd_handler_t)(char* p);
-
-typedef struct {
-  const char* name;
-  console_cmd_handler_t* handler;
-  const char* help;
-  bool is_job;
-} cmd_t;
-
-extern const cmd_t console_cmd_list[];
-static int console_cmd_maxlen = 0;
-
-static void* cmdjob_handler(void* param) {
-  char* job_cmd = (char*)param;
-  LOG(INFO) << "cmdjob starting: " << job_cmd;
-  process_cmd(job_cmd, true);
-  LOG(INFO) << "cmdjob terminating";
-  free(job_cmd);
-  return nullptr;
-}
-
-static int create_cmdjob(char* cmd) {
-  CHECK(cmd);
-  char* job_cmd = (char*)calloc(1, strlen(cmd) + 1); /* freed in job handler */
-  if (job_cmd) {
-    strlcpy(job_cmd, cmd, strlen(job_cmd) + 1);
-    pthread_t thread_id;
-    int ret =
-        pthread_create(&thread_id, nullptr, cmdjob_handler, (void*)job_cmd);
-    LOG_IF(ERROR, ret != 0) << "Error during pthread_create";
-  } else {
-    LOG(INFO) << "Cannot Allocate memory for cmdjob: " << cmd;
-  }
-  return 0;
-}
-
-/*******************************************************************************
- ** Load stack lib
- *******************************************************************************/
-
-int HAL_load(void) {
-  LOG(INFO) << "Loading HAL library and extensions";
-  bt_interface_t* interface;
-  int err = hal_util_load_bt_library((const bt_interface_t**)&interface);
-  if (err) {
-    LOG(ERROR) << "Error loading HAL library: " << strerror(err);
-    return err;
-  }
-  sBtInterface = interface;
-  LOG(INFO) << "HAL library loaded";
-  return err;
-}
-
-int HAL_unload(void) {
-  int err = 0;
-  LOG(INFO) << "Unloading HAL lib";
-  sBtInterface = nullptr;
-  LOG(INFO) << "HAL library unloaded, status: " << strerror(err);
-  return err;
-}
-
-/*******************************************************************************
- ** HAL test functions & callbacks
- *******************************************************************************/
-
-void setup_test_env(void) {
-  int i = 0;
-  while (console_cmd_list[i].name) {
-    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) {
-    LOG(INFO) << "HAL REQUEST FAILED status : " << status << " ("
-              << dump_bt_status(status) << ")";
-  } else {
-    LOG(INFO) << "HAL REQUEST SUCCESS";
-  }
-}
-
-static void adapter_state_changed(bt_state_t state) {
-  int V1 = 1000, V2 = 2;
-  bt_property_t property = {BT_PROPERTY_ADAPTER_DISCOVERY_TIMEOUT, 4, &V1};
-  bt_property_t property1 = {BT_PROPERTY_ADAPTER_SCAN_MODE, 2, &V2};
-  bt_property_t property2 = {BT_PROPERTY_BDNAME, 6, (void*)"Fluoride_Test"};
-
-  global_adapter_state = state;
-
-  if (state == BT_STATE_ON) {
-    global_bt_enabled = true;
-    global_status = (bt_status_t)sBtInterface->set_adapter_property(&property1);
-    global_status = (bt_status_t)sBtInterface->set_adapter_property(&property);
-    global_status = (bt_status_t)sBtInterface->set_adapter_property(&property2);
-  } else {
-    global_bt_enabled = false;
-  }
-}
-
-static void adapter_properties_changed(bt_status_t status, int num_properties,
-                                       bt_property_t* properties) {
-  RawAddress bd_addr;
-  if (!properties) {
-    printf("properties is null\n");
-    return;
-  }
-  switch (properties->type) {
-    case BT_PROPERTY_BDADDR:
-      memcpy(bd_addr.address, properties->val,
-             MIN((size_t)properties->len, sizeof(bd_addr)));
-      LOG(INFO) << "Local Bd Addr = " << bd_addr;
-      break;
-    default:
-      break;
-  }
-  return;
-}
-
-static void discovery_state_changed(bt_discovery_state_t state) {
-  LOG(INFO) << "Discovery State Updated: "
-            << (state == BT_DISCOVERY_STOPPED ? "STOPPED" : "STARTED");
-}
-
-static void pin_request_cb(RawAddress* 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)) {
-    LOG(INFO) << "Pin Reply failed";
-  }
-}
-
-static void ssp_request_cb(RawAddress* remote_bd_addr, bt_bdname_t* bd_name,
-                           uint32_t cod, bt_ssp_variant_t pairing_variant,
-                           uint32_t pass_key) {
-  LOG(INFO) << __func__ << ": device_name:" << bd_name->name
-            << ", pairing_variant: " << (int)pairing_variant
-            << ", passkey: " << unsigned(pass_key);
-  if (BT_STATUS_SUCCESS !=
-      sBtInterface->ssp_reply(remote_bd_addr, pairing_variant, true,
-                              pass_key)) {
-    LOG(ERROR) << "SSP Reply failed";
-  }
-}
-
-static void bond_state_changed_cb(bt_status_t status,
-                                  RawAddress* remote_bd_addr,
-                                  bt_bond_state_t state) {
-  LOG(INFO) << "Bond State Changed = " << state;
-  global_pair_state = state;
-}
-
-static void acl_state_changed(bt_status_t status, RawAddress* remote_bd_addr,
-                              bt_acl_state_t state) {
-  LOG(INFO) << __func__ << ": remote_bd_addr=" << *remote_bd_addr
-            << ", acl status=" << (state == BT_ACL_STATE_CONNECTED
-                                       ? "ACL Connected"
-                                       : "ACL Disconnected");
-}
-
-static void dut_mode_recv(uint16_t opcode, uint8_t* buf, uint8_t len) {
-  LOG(INFO) << "DUT MODE RECV : NOT IMPLEMENTED";
-}
-
-static bt_callbacks_t bt_callbacks = {
-    sizeof(bt_callbacks_t),
-    adapter_state_changed,
-    adapter_properties_changed, /*adapter_properties_cb */
-    nullptr,                    /* remote_device_properties_cb */
-    nullptr,                    /* 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 */
-    nullptr,                    /* thread_evt_cb */
-    dut_mode_recv,              /*dut_mode_recv_cb */
-    nullptr,                    /* le_test_mode_cb */
-    nullptr                     /* energy_info_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, nullptr);
-
-  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 adapter_init(void) {
-  LOG(INFO) << __func__;
-  global_status = (bt_status_t)sBtInterface->init(&bt_callbacks);
-  if (global_status == BT_STATUS_SUCCESS) {
-    global_status = (bt_status_t)sBtInterface->set_os_callouts(&callouts);
-  }
-  check_return_status(global_status);
-}
-
-void adapter_enable(void) {
-  LOG(INFO) << __func__;
-  if (global_bt_enabled) {
-    LOG(INFO) << __func__ << ": Bluetooth is already enabled";
-    return;
-  }
-  global_status = (bt_status_t)sBtInterface->enable(global_strict_mode);
-  check_return_status(global_status);
-}
-
-void adapter_disable(void) {
-  LOG(INFO) << __func__;
-  if (!global_bt_enabled) {
-    LOG(INFO) << __func__ << ": Bluetooth is already disabled";
-    return;
-  }
-  global_status = (bt_status_t)sBtInterface->disable();
-  check_return_status(global_status);
-}
-void adapter_dut_mode_configure(char* p) {
-  LOG(INFO) << __func__;
-  if (!global_bt_enabled) {
-    LOG(INFO) << __func__
-              << ": Bluetooth must be enabled for test_mode to work.";
-    return;
-  }
-  int32_t mode = get_signed_int(&p, -1);  // arg1
-  if ((mode != 0) && (mode != 1)) {
-    LOG(INFO) << __func__ << "Please specify mode: 1 to enter, 0 to exit";
-    return;
-  }
-  global_status = (bt_status_t)sBtInterface->dut_mode_configure(mode);
-  check_return_status(global_status);
-}
-
-void adapter_cleanup(void) {
-  LOG(INFO) << __func__;
-  sBtInterface->cleanup();
-}
-
-/*******************************************************************************
- ** Console commands
- *******************************************************************************/
-
-void do_help(char* p) {
-  int i = 0;
-  char line[128];
-  int pos = 0;
-
-  while (console_cmd_list[i].name != nullptr) {
-    pos = snprintf(line, sizeof(line), "%s", (char*)console_cmd_list[i].name);
-    printf("%s %s\n", (char*)line, (char*)console_cmd_list[i].help);
-    i++;
-  }
-}
-
-void do_quit(char* p) { console_shutdown(); }
-
-/*******************************************************************
- *
- *  BT TEST  CONSOLE COMMANDS
- *
- *  Parses argument lists and passes to API test function
- *
- */
-
-void do_init(char* p) { adapter_init(); }
-
-void do_enable(char* p) { adapter_enable(); }
-
-void do_disable(char* p) { adapter_disable(); }
-
-void do_cleanup(char* p) { adapter_cleanup(); }
-
-/**
- * MCAP API commands
- */
-void do_mcap_register(char* p) {
-  uint16_t ctrl_psm = get_hex(&p, 0);  // arg1
-  uint16_t data_psm = get_hex(&p, 0);  // arg2
-  uint16_t sec_mask = get_int(&p, 0);  // arg3
-  printf("%s: ctrl_psm=0x%04x, data_psm=0x%04x, sec_mask=0x%04x\n", __func__,
-         ctrl_psm, data_psm, sec_mask);
-  if (!ctrl_psm || !data_psm) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  sMcapTestApp->Register(ctrl_psm, data_psm, sec_mask, mcap_ctrl_callback);
-  printf("%s: mcap_handle=%d\n", __func__, sMcapTestApp->GetHandle());
-}
-
-void do_mcap_deregister(char* p) {
-  printf("%s: mcap_handle=%d\n", __func__, sMcapTestApp->GetHandle());
-  sMcapTestApp->Deregister();
-  printf("%s: handle=%d\n", __func__, sMcapTestApp->GetHandle());
-}
-
-void do_mcap_create_mdep(char* p) {
-  int type = get_int(&p, -1);  // arg1
-  printf("%s: mcap_handle=%d, type=%d\n", __func__, sMcapTestApp->GetHandle(),
-         type);
-  bool ret = sMcapTestApp->CreateMdep(type, MCA_NUM_MDLS, mcap_data_cb);
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_delete_mdep(char* p) {
-  uint8_t mdep_handle = get_int(&p, 0);
-  printf("%s: mcap_handle=%d, mdep_handle=%d\n", __func__,
-         sMcapTestApp->GetHandle(), mdep_handle);
-  if (!mdep_handle) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMdep* mcap_mdep = sMcapTestApp->FindMdepByHandle(mdep_handle);
-  if (!mcap_mdep) {
-    LOG(ERROR) << "No MDEP for handle " << (int)mdep_handle;
-    return;
-  }
-  bool ret = mcap_mdep->Delete();
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_connect_mcl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  uint16_t ctrl_psm = get_hex(&p, 0);  // arg2
-  uint16_t sec_mask = get_int(&p, 0);  // arg3
-  printf("%s: mcap_handle=%d, ctrl_psm=0x%04x, secMask=0x%04x, bd_addr=%s\n",
-         __func__, sMcapTestApp->GetHandle(), ctrl_psm, sec_mask, buf);
-  if (!ctrl_psm || !valid_bd_addr) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  bool ret = sMcapTestApp->ConnectMcl(bd_addr, ctrl_psm, sec_mask);
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_disconnect_mcl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  printf("%s: bd_addr=%s\n", __func__, buf);
-  if (!valid_bd_addr) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  bool ret = mcap_mcl->Disconnect();
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_create_mdl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  uint16_t mdep_handle = get_int(&p, 0);  // arg2
-  uint16_t data_psm = get_hex(&p, 0);     // arg3
-  uint16_t mdl_id = get_int(&p, 0);       // arg4
-  uint8_t peer_dep_id = get_int(&p, 0);   // arg5
-  uint8_t cfg = get_hex(&p, 0);           // arg6
-  int do_not_connect = get_int(&p, 0);    // arg7
-  printf(
-      "%s: bd_addr=%s, mdep_handle=%d, data_psm=0x%04x, mdl_id=%d,"
-      " peer_dep_id=%d, cfg=0x%02x, do_not_connect=%d\n",
-      __func__, buf, mdep_handle, data_psm, mdl_id, peer_dep_id, cfg,
-      do_not_connect);
-  if (!data_psm || !peer_dep_id || !valid_bd_addr || !mdep_handle) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  bool ret = mcap_mcl->CreateMdl(mdep_handle, data_psm, mdl_id, peer_dep_id,
-                                 cfg, !do_not_connect);
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_data_channel_config(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  printf("%s: bd_addr=%s\n", __func__, buf);
-  if (!valid_bd_addr) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  bool ret = mcap_mcl->DataChannelConfig();
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_abort_mdl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  printf("%s: bd_addr=%s\n", __func__, buf);
-  if (!valid_bd_addr) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  bool ret = mcap_mcl->AbortMdl();
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_delete_mdl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  uint16_t mdl_id = get_int(&p, 0);  // arg2
-  printf("%s: bd_addr=%s, mdl_id=%d\n", __func__, buf, mdl_id);
-  if (!valid_bd_addr) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  bool ret = mcap_mcl->DeleteMdl(mdl_id);
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_close_mdl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  uint16_t mdl_id = get_int(&p, 0);  // arg2
-  printf("%s: bd_addr=%s, mdl_id=%d\n", __func__, buf, mdl_id);
-  if (!valid_bd_addr || !mdl_id) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  McapMdl* mcap_mdl = mcap_mcl->FindMdlById(mdl_id);
-  if (!mcap_mdl) {
-    LOG(ERROR) << "No MDL for ID " << (int)mdl_id;
-    return;
-  }
-  bool ret = mcap_mdl->Close();
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_mcap_reconnect_mdl(char* p) {
-  char buf[64];
-  get_str(&p, buf);  // arg1
-  RawAddress bd_addr;
-  bool valid_bd_addr = RawAddress::FromString(buf, bd_addr);
-  uint16_t data_psm = get_hex(&p, 0);  // arg1
-  uint16_t mdl_id = get_int(&p, 0);    // arg2
-  printf("%s: data_psm=0x%04x, mdl_id=%d\n", __func__, data_psm, mdl_id);
-  if (!valid_bd_addr) {
-    printf("%s: Invalid Parameters\n", __func__);
-    return;
-  }
-  McapMcl* mcap_mcl = sMcapTestApp->FindMclByPeerAddress(bd_addr);
-  if (!mcap_mcl) {
-    LOG(ERROR) << "No MCL for bd_addr " << buf;
-    return;
-  }
-  McapMdl* mcap_mdl = mcap_mcl->FindMdlById(mdl_id);
-  if (!mcap_mdl) {
-    LOG(ERROR) << "No MDL for ID " << (int)mdl_id;
-    return;
-  }
-  bool ret = mcap_mdl->Reconnect(data_psm);
-  printf("%s: %s\n", __func__, ret ? "SUCCESS" : "FAIL");
-}
-
-static void do_pairing(char* p) {
-  RawAddress bd_addr;
-  if (!RawAddress::FromString(p, bd_addr)) {
-    LOG(ERROR) << "Invalid Bluetooth address " << p;
-    return;
-  }
-  if (BT_STATUS_SUCCESS !=
-      sBtInterface->create_bond(&bd_addr, BT_TRANSPORT_BR_EDR)) {
-    LOG(ERROR) << "Failed to Initiate Pairing";
-    return;
-  }
-}
-
-/** CONSOLE COMMAND TABLE */
-
-const cmd_t console_cmd_list[] = {
-    /* INTERNAL */
-    {"help", do_help, "", 0},
-    {"quit", do_quit, "", 0},
-    /* API CONSOLE COMMANDS */
-    /* Init and Cleanup shall be called automatically */
-    {"enable_bluetooth", do_enable, "", 0},
-    {"disable_bluetooth", do_disable, "", 0},
-    {"pair", do_pairing, "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0},
-    {"register", do_mcap_register,
-     "ctrl_psm<hex> data_psm<hex> security_mask<0-10>", 0},
-    {"deregister", do_mcap_deregister, "", 0},
-    {"create_mdep", do_mcap_create_mdep, "type<0-Echo, 1-Normal>", 0},
-    {"delete_mdep", do_mcap_delete_mdep, "mdep_handle<int>", 0},
-    {"connect_mcl", do_mcap_connect_mcl,
-     "BD_ADDR<xx:xx:xx:xx:xx:xx> ctrl_psm<hex> security_mask<0-10>", 0},
-    {"disconnect_mcl", do_mcap_disconnect_mcl, "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0},
-    {"create_mdl", do_mcap_create_mdl,
-     "BD_ADDR<xx:xx:xx:xx:xx:xx> mdep_handle<int> data_psm<hex> mdl_id<int> "
-     "peer_dep_id<int> cfg<hex> "
-     "do_not_connect<0-connect,1-wait_for_data_channel_config>",
-     0},
-    {"data_channel_config", do_mcap_data_channel_config,
-     "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0},
-    {"abort_mdl", do_mcap_abort_mdl, "BD_ADDR<xx:xx:xx:xx:xx:xx>", 0},
-    {"close_mdl", do_mcap_close_mdl, "BD_ADDR<xx:xx:xx:xx:xx:xx> mdl_id<int>",
-     0},
-    {"delete_mdl", do_mcap_delete_mdl, "BD_ADDR<xx:xx:xx:xx:xx:xx> mdl_id<int>",
-     0},
-    {"reconnect_mdl", do_mcap_reconnect_mdl,
-     "BD_ADDR<xx:xx:xx:xx:xx:xx> data_psm<hex> mdl_id<int>", 0},
-    /* last entry */
-    {nullptr, nullptr, "", 0},
-};
-
-/** Main console command handler */
-
-static void process_cmd(char* p, bool is_job) {
-  char cmd[2048];
-  int i = 0;
-  char* p_saved = p;
-
-  get_str(&p, cmd);  // arg1
-
-  /* table commands */
-  while (console_cmd_list[i].name != nullptr) {
-    if (is_cmd(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++;
-  }
-  LOG(ERROR) << "Unknown command: " << p_saved;
-  do_help(nullptr);
-}
-
-int main(int argc, char* argv[]) {
-  setbuf(stdout, NULL);
-#if !defined(OS_GENERIC)
-  config_permissions();
-#endif
-  LOG(INFO) << "Fluoride MCAP test app is starting";
-
-  if (HAL_load() < 0) {
-    fprintf(stderr, "%s: HAL failed to initialize, exit\n", __func__);
-    unlink(PID_FILE);
-    exit(0);
-  }
-
-  setup_test_env();
-
-  /* Automatically perform the init */
-  adapter_init();
-  sleep(2);
-  adapter_enable();
-  sleep(2);
-  sMcapTestInterface =
-      (btmcap_test_interface_t*)sBtInterface->get_profile_interface(
-          BT_TEST_INTERFACE_MCAP_ID);
-  sMcapTestInterface->init();
-  sMcapTestApp = new McapTestApp(sMcapTestInterface);
-
-  /* Main loop */
-  char line[2048];
-  while (!global_main_done) {
-    memset(line, '\0', sizeof(line));
-    /* command prompt */
-    printf(">");
-    fflush(stdout);
-    fgets(line, sizeof(line), stdin);
-    if (line[0] != '\0') {
-      /* Remove line feed */
-      line[strlen(line) - 1] = 0;
-      if (strlen(line) != 0) process_cmd(line, false);
-    }
-  }
-  adapter_cleanup();
-  HAL_unload();
-  LOG(INFO) << "Fluoride MCAP test app is terminating";
-
-  return 0;
-}
diff --git a/tools/scripts/dump_hearingaid_audio.py b/tools/scripts/dump_hearingaid_audio.py
new file mode 100755
index 0000000..32d9a13
--- /dev/null
+++ b/tools/scripts/dump_hearingaid_audio.py
@@ -0,0 +1,531 @@
+#!/usr/bin/env python
+# Copyright 2018 The Android Open Source Project
+#
+# 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.
+#
+#
+#
+#
+# This script extracts Hearing Aid audio data from btsnoop.
+# Generates a valid audio file which can be played using player like smplayer.
+#
+# Audio File Name Format:
+# [PEER_ADDRESS]-[START TIMESTAMP]-[AUDIO_TYPE]-[SAMPLE_RATE].[CODEC]
+#
+# Player:
+# smplayer
+#
+# NOTE:
+# Please make sure you HCI Snoop data file includes the following frames:
+# HearingAid "LE Enhanced Connection Complete", GATT write for Audio Control
+# Point with "Start cmd", and the data frames.
+
+import argparse
+import os
+import struct
+import sys
+import time
+
+IS_SENT = "IS_SENT"
+PEER_ADDRESS = "PEER_ADDRESS"
+CONNECTION_HANDLE = "CONNECTION_HANDLE"
+AUDIO_CONTROL_ATTR_HANDLE = "AUDIO_CONTROL_ATTR_HANDLE"
+START = "START"
+TIMESTAMP = "TIMESTAMP"
+CODEC = "CODEC"
+SAMPLE_RATE = "SAMPLE_RATE"
+AUDIO_TYPE = "AUDIO_TYPE"
+AUDIO_DATA_B = "AUDIO_DATA_B"
+
+AUDIO_CONTROL_POINT_UUID = "f0d4de7e4a88476c9d9f1937b0996cc0"
+SEC_CONVERT = 1000000
+folder = None
+
+force_audio_control_attr_handle = None
+default_audio_control_attr_handle = 0x0079
+
+audio_data = {}
+
+#=======================================================================
+# Parse ACL Data Function
+#=======================================================================
+
+#-----------------------------------------------------------------------
+# Parse Hearing Aid Packet
+#-----------------------------------------------------------------------
+
+
+def parse_acl_ha_audio_data(data, result):
+  """This function extracts HA audio data."""
+  if len(data) < 2:
+    return
+  # Remove audio packet number
+  audio_data_b = data[1:]
+  update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                    AUDIO_DATA_B, audio_data_b)
+
+
+def parse_acl_ha_audio_type(data, result):
+  """This function parses HA audio control cmd audio type."""
+  audio_type, data = unpack_data(data, 1)
+  if audio_type is None:
+    return
+  elif audio_type == 0x01:
+    audio_type = "Ringtone"
+  elif audio_type == 0x02:
+    audio_type = "Phonecall"
+  elif audio_type == 0x03:
+    audio_type = "Media"
+  else:
+    audio_type = "Unknown"
+  update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                    AUDIO_TYPE, audio_type)
+
+
+def parse_acl_ha_codec(data, result):
+  """This function parses HA audio control cmd codec and sample rate."""
+  codec, data = unpack_data(data, 1)
+  if codec == 0x01:
+    codec = "G722"
+    sample_rate = "16KHZ"
+  elif codec == 0x02:
+    codec = "G722"
+    sample_rate = "24KHZ"
+  else:
+    codec = "Unknown"
+    sample_rate = "Unknown"
+  update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                    CODEC, codec)
+  update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                    SAMPLE_RATE, sample_rate)
+  parse_acl_ha_audio_type(data, result)
+
+
+def parse_acl_ha_audio_control_cmd(data, result):
+  """This function parses HA audio control cmd is start/stop."""
+  control_cmd, data = unpack_data(data, 1)
+  if control_cmd == 0x01:
+    update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                      START, True)
+    update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                      TIMESTAMP, result[TIMESTAMP])
+    parse_acl_ha_codec(data, result)
+  elif control_cmd == 0x02:
+    update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                      START, False)
+
+
+#-----------------------------------------------------------------------
+# Parse ACL Packet
+#-----------------------------------------------------------------------
+
+def parse_acl_att_long_uuid(data, result):
+  """This function parses ATT long UUID to get attr_handle."""
+  # len (1 byte) + start_attr_handle (2 bytes) + properties (1 byte) +
+  # attr_handle (2 bytes) + long_uuid (16 bytes) = 22 bytes
+  if len(data) < 22:
+    return
+  # skip unpack len, start_attr_handle, properties.
+  data = data[4:]
+  attr_handle, data = unpack_data(data, 2)
+  long_uuid_list = []
+  for p in range(0, 16):
+    long_uuid_list.append("{0:02x}".format(struct.unpack(">B", data[p])[0]))
+  long_uuid_list.reverse()
+  long_uuid = "".join(long_uuid_list)
+  # Check long_uuid is AUDIO_CONTROL_POINT uuid to get the attr_handle.
+  if long_uuid == AUDIO_CONTROL_POINT_UUID:
+    update_audio_data(CONNECTION_HANDLE, result[CONNECTION_HANDLE],
+                      AUDIO_CONTROL_ATTR_HANDLE, attr_handle)
+
+
+def parse_acl_opcode(data, result):
+  """This function parses acl data opcode."""
+  # opcode (1 byte) = 1 bytes
+  if len(data) < 1:
+    return
+  opcode, data = unpack_data(data, 1)
+  # Check opcode is 0x12 (write request) and attr_handle is
+  # audio_control_attr_handle for check it is HA audio control cmd.
+  if result[IS_SENT] and opcode == 0x12:
+    if len(data) < 2:
+      return
+    attr_handle, data = unpack_data(data, 2)
+    if attr_handle == \
+        get_audio_control_attr_handle(result[CONNECTION_HANDLE]):
+          parse_acl_ha_audio_control_cmd(data, result)
+  # Check opcode is 0x09 (read response) to parse ATT long UUID.
+  elif not result[IS_SENT] and opcode == 0x09:
+    parse_acl_att_long_uuid(data, result)
+
+
+def parse_acl_handle(data, result):
+  """This function parses acl data handle."""
+  # connection_handle (2 bytes) + total_len (2 bytes) + pdu (2 bytes)
+  # + channel_id (2 bytes) = 8 bytes
+  if len(data) < 8:
+    return
+  connection_handle, data = unpack_data(data, 2)
+  connection_handle = connection_handle & 0x0FFF
+  # skip unpack total_len
+  data = data[2:]
+  pdu, data = unpack_data(data, 2)
+  channel_id, data = unpack_data(data, 2)
+
+  # Check ATT packet or "Coc Data Packet" to get ATT information and audio
+  # data.
+  if connection_handle <= 0x0EFF:
+    if channel_id <= 0x003F:
+      result[CONNECTION_HANDLE] = connection_handle
+      parse_acl_opcode(data, result)
+    elif result[IS_SENT] and channel_id >= 0x0040 and channel_id <= 0x007F:
+      result[CONNECTION_HANDLE] = connection_handle
+      sdu, data = unpack_data(data, 2)
+      if pdu - 2 == sdu:
+        parse_acl_ha_audio_data(data, result)
+
+
+#=======================================================================
+# Parse HCI EVT Function
+#=======================================================================
+
+
+def parse_hci_evt_peer_address(data, result):
+  """This function parses peer address from hci event."""
+  peer_address_list = []
+  address_empty_list = ["00", "00", "00", "00", "00", "00"]
+  for n in range(0, 3):
+    if len(data) < 6:
+      return
+    for p in range(0, 6):
+      peer_address_list.append("{0:02x}".format(struct.unpack(">B",
+                                                              data[p])[0]))
+    # Check the address is empty or not.
+    if peer_address_list == address_empty_list:
+      del peer_address_list[:]
+      data = data[6:]
+    else:
+      break
+  peer_address_list.reverse()
+  peer_address = "_".join(peer_address_list)
+  update_audio_data("", "", PEER_ADDRESS, peer_address)
+  update_audio_data(PEER_ADDRESS, peer_address, CONNECTION_HANDLE,
+                    result[CONNECTION_HANDLE])
+
+
+def parse_hci_evt_code(data, result):
+  """This function parses hci event content."""
+  # hci_evt (1 byte) + param_total_len (1 byte) + sub_event (1 byte)
+  # + status (1 byte) + connection_handle (2 bytes) + role (1 byte)
+  # + address_type (1 byte) = 8 bytes
+  if len(data) < 8:
+    return
+  hci_evt, data = unpack_data(data, 1)
+  # skip unpack param_total_len.
+  data = data[1:]
+  sub_event, data = unpack_data(data, 1)
+  status, data = unpack_data(data, 1)
+  connection_handle, data = unpack_data(data, 2)
+  connection_handle = connection_handle & 0x0FFF
+  # skip unpack role, address_type.
+  data = data[2:]
+  # We will directly check it is LE Enhanced Connection Complete or not
+  # for get Connection Handle and Address.
+  if not result[IS_SENT] and hci_evt == 0x3E and sub_event == 0x0A \
+      and status == 0x00 and connection_handle <= 0x0EFF:
+        result[CONNECTION_HANDLE] = connection_handle
+        parse_hci_evt_peer_address(data, result)
+
+
+#=======================================================================
+# Common Parse Function
+#=======================================================================
+
+
+def parse_packet_data(data, result):
+  """This function parses packet type."""
+  packet_type, data = unpack_data(data, 1)
+  if packet_type == 0x02:
+    # Try to check HearingAid audio control packet and data packet.
+    parse_acl_handle(data, result)
+  elif packet_type == 0x04:
+    # Try to check HearingAid connection successful packet.
+    parse_hci_evt_code(data, result)
+
+
+def parse_packet(btsnoop_file):
+  """This function parses packet len, timestamp."""
+  packet_result = {}
+
+  # ori_len (4 bytes) + include_len (4 bytes) + packet_flag (4 bytes)
+  # + drop (4 bytes) + timestamp (8 bytes) = 24 bytes
+  packet_header = btsnoop_file.read(24)
+  if len(packet_header) != 24:
+    return False
+
+  ori_len, include_len, packet_flag, drop, timestamp = \
+      struct.unpack(">IIIIq", packet_header)
+
+  if ori_len == include_len:
+    packet_data = btsnoop_file.read(ori_len)
+    if len(packet_data) != ori_len:
+      return False
+    if packet_flag != 2 and drop == 0:
+      packet_result[IS_SENT] = (packet_flag == 0)
+      packet_result[TIMESTAMP] = convert_time_str(timestamp)
+      parse_packet_data(packet_data, packet_result)
+  else:
+    return False
+
+  return True
+
+
+#=======================================================================
+# Update and DumpData Function
+#=======================================================================
+
+
+def dump_audio_data(data):
+  """This function dumps audio data into file."""
+  file_type = "." + data[CODEC]
+  file_name_list = []
+  file_name_list.append(data[PEER_ADDRESS])
+  file_name_list.append(data[TIMESTAMP])
+  file_name_list.append(data[AUDIO_TYPE])
+  file_name_list.append(data[SAMPLE_RATE])
+  if folder is not None:
+    if not os.path.exists(folder):
+      os.makedirs(folder)
+    file_name = os.path.join(folder, "-".join(file_name_list) + file_type)
+  else:
+    file_name = "-".join(file_name_list) + file_type
+  sys.stdout.write("Start to dump audio file : " + file_name + "\n")
+  if data.has_key(AUDIO_DATA_B):
+    with open(file_name, "wb+") as g722_file:
+      g722_file.write(data[AUDIO_DATA_B])
+      sys.stdout.write("Finished to dump Audio File: %s\n\n" % file_name)
+  else:
+    sys.stdout.write("Fail to dump Audio File: %s\n" % file_name)
+    sys.stdout.write("There isn't any Hearing Aid audio data.\n\n")
+
+
+def update_audio_data(relate_key, relate_value, key, value):
+  """
+  This function records the dump audio file related information.
+  audio_data = {
+    PEER_ADDRESS:{
+      PEER_ADDRESS: PEER_ADDRESS,
+      CONNECTION_HANDLE: CONNECTION_HANDLE,
+      AUDIO_CONTROL_ATTR_HANDLE: AUDIO_CONTROL_ATTR_HANDLE,
+      START: True or False,
+      TIMESTAMP: START_TIMESTAMP,
+      CODEC: CODEC,
+      SAMPLE_RATE: SAMPLE_RATE,
+      AUDIO_TYPE: AUDIO_TYPE,
+      AUDIO_DATA_B: AUDIO_DATA_B
+    },
+    PEER_ADDRESS_2:{
+      PEER_ADDRESS: PEER_ADDRESS,
+      CONNECTION_HANDLE: CONNECTION_HANDLE,
+      AUDIO_CONTROL_ATTR_HANDLE: AUDIO_CONTROL_ATTR_HANDLE,
+      START: True or False,
+      TIMESTAMP: START_TIMESTAMP,
+      CODEC: CODEC,
+      SAMPLE_RATE: SAMPLE_RATE,
+      AUDIO_TYPE: AUDIO_TYPE,
+      AUDIO_DATA_B: AUDIO_DATA_B
+    }
+  }
+  """
+  if key == PEER_ADDRESS:
+    if audio_data.has_key(value):
+      # Dump audio data and clear previous data.
+      update_audio_data(key, value, START, False)
+      # Extra clear CONNECTION_HANDLE due to new connection create.
+      if audio_data[value].has_key(CONNECTION_HANDLE):
+        audio_data[value].pop(CONNECTION_HANDLE, "")
+    else:
+      device_audio_data = {key: value}
+      temp_audio_data = {value: device_audio_data}
+      audio_data.update(temp_audio_data)
+  else:
+    for i in audio_data:
+      if audio_data[i].has_key(relate_key) \
+          and audio_data[i][relate_key] == relate_value:
+            if key == START:
+              if audio_data[i].has_key(key) and audio_data[i][key]:
+                dump_audio_data(audio_data[i])
+              # Clear data except PEER_ADDRESS, CONNECTION_HANDLE and
+              # AUDIO_CONTROL_ATTR_HANDLE.
+              audio_data[i].pop(key, "")
+              audio_data[i].pop(TIMESTAMP, "")
+              audio_data[i].pop(CODEC, "")
+              audio_data[i].pop(SAMPLE_RATE, "")
+              audio_data[i].pop(AUDIO_TYPE, "")
+              audio_data[i].pop(AUDIO_DATA_B, "")
+            elif key == AUDIO_DATA_B:
+              if audio_data[i].has_key(START) and audio_data[i][START]:
+                if audio_data[i].has_key(AUDIO_DATA_B):
+                  ori_audio_data = audio_data[i].pop(AUDIO_DATA_B, "")
+                  value = ori_audio_data + value
+              else:
+                # Audio doesn't start, don't record.
+                return
+            device_audio_data = {key: value}
+            audio_data[i].update(device_audio_data)
+
+
+#=======================================================================
+# Tool Function
+#=======================================================================
+
+
+def get_audio_control_attr_handle(connection_handle):
+  """This function gets audio_control_attr_handle."""
+  # If force_audio_control_attr_handle is set, will use it first.
+  if force_audio_control_attr_handle is not None:
+    return force_audio_control_attr_handle
+
+  # Try to check the audio_control_attr_handle is record into audio_data.
+  for i in audio_data:
+    if audio_data[i].has_key(CONNECTION_HANDLE) \
+        and audio_data[i][CONNECTION_HANDLE] == connection_handle:
+          if audio_data[i].has_key(AUDIO_CONTROL_ATTR_HANDLE):
+            return audio_data[i][AUDIO_CONTROL_ATTR_HANDLE]
+
+  # Return default attr_handle if audio_data doesn't record it.
+  return default_audio_control_attr_handle
+
+
+def unpack_data(data, byte):
+  """This function unpacks data."""
+  if byte == 1:
+    value = struct.unpack(">B", data[0])[0]
+  elif byte == 2:
+    value = struct.unpack(">H", data[1]+data[0])[0]
+  else:
+    value = ""
+  data = data[byte:]
+  return value, data
+
+
+def convert_time_str(timestamp):
+  """This function converts time to string format."""
+  really_timestamp = float(timestamp) / SEC_CONVERT
+  local_timestamp = time.localtime(really_timestamp)
+  time_str = time.strftime("%m_%d__%H_%M_%S", local_timestamp)
+  dt = really_timestamp - long(really_timestamp)
+  ms_str = "{0:06}".format(int(round(dt * 1000000)))
+  full_time_str = time_str + "_" + ms_str
+  return full_time_str
+
+
+def set_config():
+  """This function is for set config by flag and check the argv is correct."""
+  argv_parser = argparse.ArgumentParser(
+      description="Extracts Hearing Aid audio data from BTSNOOP.")
+  argv_parser.add_argument("BTSNOOP", help="BLUETOOTH BTSNOOP file.")
+  argv_parser.add_argument("-f", "--folder", help="select output folder.",
+                           dest="folder")
+  argv_parser.add_argument("-c1", "--connection-handle1",
+                           help="set a fake connection handle 1 to capture \
+                           audio dump.", dest="connection_handle1", type=int)
+  argv_parser.add_argument("-c2", "--connection-handle2",
+                           help="set a fake connection handle 2 to capture \
+                           audio dump.", dest="connection_handle2", type=int)
+  argv_parser.add_argument("-ns", "--no-start", help="No audio 'Start' cmd is \
+                           needed before extracting audio data.",
+                           dest="no_start", default="False")
+  argv_parser.add_argument("-dc", "--default-codec", help="set a default \
+                           codec.", dest="codec", default="G722")
+  argv_parser.add_argument("-a", "--attr-handle",
+                           help="force to select audio control attr handle.",
+                           dest="audio_control_attr_handle", type=int)
+  arg = argv_parser.parse_args()
+
+  if arg.folder is not None:
+    global folder
+    folder = arg.folder
+
+  if arg.connection_handle1 is not None and arg.connection_handle2 is not None \
+      and arg.connection_handle1 == arg.connection_handle2:
+        argv_parser.error("connection_handle1 can't be same with \
+                          connection_handle2")
+        exit(1)
+
+  if not (arg.no_start.lower() == "true" or arg.no_start.lower() == "false"):
+    argv_parser.error("-ns/--no-start arg is invalid, it should be true/false.")
+    exit(1)
+
+  if arg.connection_handle1 is not None:
+    fake_name = "ConnectionHandle" + str(arg.connection_handle1)
+    update_audio_data("", "", PEER_ADDRESS, fake_name)
+    update_audio_data(PEER_ADDRESS, fake_name, CONNECTION_HANDLE,
+                      arg.connection_handle1)
+    if arg.no_start.lower() == "true":
+      update_audio_data(PEER_ADDRESS, fake_name, START, True)
+      update_audio_data(PEER_ADDRESS, fake_name, TIMESTAMP, "Unknown")
+      update_audio_data(PEER_ADDRESS, fake_name, CODEC, arg.codec)
+      update_audio_data(PEER_ADDRESS, fake_name, SAMPLE_RATE, "Unknown")
+      update_audio_data(PEER_ADDRESS, fake_name, AUDIO_TYPE, "Unknown")
+
+  if arg.connection_handle2 is not None:
+    fake_name = "ConnectionHandle" + str(arg.connection_handle2)
+    update_audio_data("", "", PEER_ADDRESS, fake_name)
+    update_audio_data(PEER_ADDRESS, fake_name, CONNECTION_HANDLE,
+                      arg.connection_handle2)
+    if arg.no_start.lower() == "true":
+      update_audio_data(PEER_ADDRESS, fake_name, START, True)
+      update_audio_data(PEER_ADDRESS, fake_name, TIMESTAMP, "Unknown")
+      update_audio_data(PEER_ADDRESS, fake_name, CODEC, arg.codec)
+      update_audio_data(PEER_ADDRESS, fake_name, SAMPLE_RATE, "Unknown")
+      update_audio_data(PEER_ADDRESS, fake_name, AUDIO_TYPE, "Unknown")
+
+  if arg.audio_control_attr_handle is not None:
+    global force_audio_control_attr_handle
+    force_audio_control_attr_handle = arg.audio_control_attr_handle
+
+  if os.path.isfile(arg.BTSNOOP):
+    return arg.BTSNOOP
+  else:
+    argv_parser.error("BTSNOOP file not found: %s" % arg.BTSNOOP)
+    exit(1)
+
+
+def main():
+  btsnoop_file_name = set_config()
+
+  with open(btsnoop_file_name, "rb") as btsnoop_file:
+    identification = btsnoop_file.read(8)
+    if identification != "btsnoop\0":
+      sys.stderr.write(
+          "Check identification fail. It is not correct btsnoop file.")
+      exit(1)
+
+    ver, data_link = struct.unpack(">II", btsnoop_file.read(4 + 4))
+    if (ver != 1) or (data_link != 1002):
+      sys.stderr.write(
+          "Check ver or dataLink fail. It is not correct btsnoop file.")
+      exit(1)
+
+    while True:
+      if not parse_packet(btsnoop_file):
+        break
+
+    for i in audio_data:
+      if audio_data[i].get(START, False):
+        dump_audio_data(audio_data[i])
+
+
+if __name__ == "__main__":
+  main()
diff --git a/tools/scripts/dump_metrics_ascii.py b/tools/scripts/dump_metrics_ascii.py
new file mode 100755
index 0000000..c24d299
--- /dev/null
+++ b/tools/scripts/dump_metrics_ascii.py
@@ -0,0 +1,140 @@
+#!/usr/bin/env python3
+# Copyright 2018 The Android Open Source Project
+#
+# 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.
+
+import base64
+import logging
+import os
+import subprocess
+import sys
+import tempfile
+from distutils.spawn import find_executable
+import google.protobuf.text_format as text_format
+from importlib import import_module
+
+def compile_proto(proto_path, output_dir):
+    """Invoke Protocol Compiler to generate python from given source .proto."""
+    # Find compiler path
+    protoc = None
+    if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
+        protoc = os.environ['PROTOC']
+    if not protoc:
+        protoc = find_executable('protoc')
+    if not protoc:
+        logging.error(
+            "Cannot find Protobuf compiler (>=3.0.0), please install"
+            "protobuf-compiler package. Prefer copying from <top>/prebuilts/tools"
+        )
+        logging.error("    prebuilts/tools/linux-x86_64/protoc/bin/protoc")
+        logging.error("If prebuilts are not available, use apt-get:")
+        logging.error("    sudo apt-get install protobuf-compiler")
+        return None
+    # Validate input proto path
+    if not os.path.exists(proto_path):
+        logging.error('Can\'t find required file: %s\n' % proto_path)
+        return None
+    # Validate output py-proto path
+    if not os.path.exists(output_dir):
+        os.mkdirs(output_dir)
+    elif not os.path.isdir(output_dir):
+        logging.error("Output path is not a valid directory: %s" %
+                      (output_dir))
+        return None
+    input_dir = os.path.dirname(proto_path)
+    output_filename = os.path.basename(proto_path).replace('.proto', '_pb2.py')
+    output_path = os.path.join(output_dir, output_filename)
+    protoc_command = [
+        protoc, '-I=%s' % (input_dir), '--python_out=%s' % (output_dir),
+        proto_path
+    ]
+    if subprocess.call(protoc_command, stderr=subprocess.STDOUT) != 0:
+        logging.error("Fail to compile proto")
+        return None
+    output_module_name = os.path.splitext(output_filename)[0]
+    return output_module_name
+
+
+def compile_import_proto(output_dir, proto_path):
+    """
+    Compile protobuf from PROTO_PATH and put the result in OUTPUT_DIR.
+    Return the imported module to caller.
+    :param output_dir: To store generated python proto library
+    :param proto_path: Path to the .proto file that needs to be compiled
+    :return: python proto module
+    """
+    output_module_name = compile_proto(proto_path, output_dir)
+    if not output_module_name:
+        return None
+    sys.path.append(output_dir)
+    output_module = None
+    try:
+        output_module = import_module(output_module_name)
+    except ImportError:
+        logging.error("Cannot import generated py-proto %s" %
+                      (output_module_name))
+    return output_module
+
+
+def parse_proto_to_ascii(binary_proto_msg):
+    """
+    Parse binary protobuf message to human readable ascii string
+    :param binary_proto_msg:
+    :return: ascii string of the message
+    """
+    return text_format.MessageToString(binary_proto_msg)
+
+def dump_metrics():
+    os.system('adb wait-for-device')
+    p = subprocess.Popen("adb shell dumpsys bluetooth_manager --proto-bin",
+        shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
+        stdin=subprocess.PIPE)
+    return p.communicate()
+
+def get_bluetooth_metrics(proto_native_str_64, bluetooth_proto_module):
+    bluetooth_log = bluetooth_proto_module.BluetoothLog()
+    proto_native_str = base64.b64decode(proto_native_str_64)
+    bluetooth_log.MergeFromString(proto_native_str)
+    return bluetooth_log
+
+def main():
+    root = logging.getLogger()
+    root.setLevel(logging.DEBUG)
+    log_handler = logging.StreamHandler(sys.stderr)
+    log_handler.setLevel(logging.DEBUG)
+    formatter = logging.Formatter(
+        "%(asctime)s %(levelname)s %(message)s")
+    log_handler.setFormatter(formatter)
+    root.addHandler(log_handler)
+    if len(sys.argv) < 2:
+        logging.error("Not enough arguments. Need at least 2")
+        logging.error("Usage: " + sys.argv[0] + " <path_to_metric_proto>")
+        sys.exit(1)
+    if sys.argv[1] == "-h":
+        logging.info("Usage: " + sys.argv[0] + " <path_to_metric_proto>")
+        logging.info("Requires Protobuf compiler, protoc, version >=3.0.0")
+        sys.exit(0)
+    bluetooth_proto_module = compile_import_proto(tempfile.gettempdir(),
+        sys.argv[1])
+    if not bluetooth_proto_module:
+        logging.error("Cannot compile " + sys.argv[1])
+        sys.exit(1)
+    stdout, stderr = dump_metrics()
+    stdout = stdout.strip()
+    stderr = stderr.strip()
+    bluetooth_log = get_bluetooth_metrics(stdout, bluetooth_proto_module)
+    bluetooth_log_ascii = parse_proto_to_ascii(bluetooth_log)
+    print(bluetooth_log_ascii)
+
+if __name__ == "__main__":
+    main()
diff --git a/types/Android.bp b/types/Android.bp
index 5867d63..444b6ff 100644
--- a/types/Android.bp
+++ b/types/Android.bp
@@ -16,6 +16,7 @@
     ],
     host_supported: true,
     srcs: [
+        "class_of_device.cc",
         "raw_address.cc",
         "bluetooth/uuid.cc",
     ],
@@ -30,6 +31,7 @@
     defaults: ["fluoride_defaults"],
     host_supported: true,
     srcs: [
+        "test/class_of_device_unittest.cc",
         "test/raw_address_unittest.cc",
         "test/bluetooth/uuid_unittest.cc",
     ],
diff --git a/types/BUILD.gn b/types/BUILD.gn
index 617bbb6..fa9a4af 100644
--- a/types/BUILD.gn
+++ b/types/BUILD.gn
@@ -20,8 +20,9 @@
   ]
 
   sources = [
-    "raw_address.cc",
     "bluetooth/uuid.cc",
+    "le_address.cc",
+    "raw_address.cc",
   ]
 
   include_dirs = [
diff --git a/types/class_of_device.cc b/types/class_of_device.cc
new file mode 100644
index 0000000..775a412
--- /dev/null
+++ b/types/class_of_device.cc
@@ -0,0 +1,78 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "class_of_device.h"
+
+#include <base/strings/string_split.h>
+#include <base/strings/stringprintf.h>
+#include <stdint.h>
+#include <algorithm>
+#include <vector>
+
+static_assert(sizeof(ClassOfDevice) == ClassOfDevice::kLength,
+              "ClassOfDevice must be 3 bytes long!");
+
+ClassOfDevice::ClassOfDevice(const uint8_t (&class_of_device)[kLength]) {
+  std::copy(class_of_device, class_of_device + kLength, cod);
+};
+
+std::string ClassOfDevice::ToString() const {
+  return base::StringPrintf("%03x-%01x-%02x",
+                            (static_cast<uint16_t>(cod[2]) << 4) | cod[1] >> 4,
+                            cod[1] & 0x0f, cod[0]);
+}
+
+bool ClassOfDevice::FromString(const std::string& from, ClassOfDevice& to) {
+  ClassOfDevice new_cod;
+  if (from.length() != 8) return false;
+
+  std::vector<std::string> byte_tokens =
+      base::SplitString(from, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (byte_tokens.size() != 3) return false;
+  if (byte_tokens[0].length() != 3) return false;
+  if (byte_tokens[1].length() != 1) return false;
+  if (byte_tokens[2].length() != 2) return false;
+
+  uint16_t values[3];
+
+  for (size_t i = 0; i < kLength; i++) {
+    const auto& token = byte_tokens[i];
+
+    char* temp = nullptr;
+    values[i] = strtol(token.c_str(), &temp, 16);
+    if (*temp != '\0') return false;
+  }
+
+  new_cod.cod[0] = values[2];
+  new_cod.cod[1] = values[1] | ((values[0] & 0xf) << 4);
+  new_cod.cod[2] = values[0] >> 4;
+
+  to = new_cod;
+  return true;
+}
+
+size_t ClassOfDevice::FromOctets(const uint8_t* from) {
+  std::copy(from, from + kLength, cod);
+  return kLength;
+};
+
+bool ClassOfDevice::IsValid(const std::string& cod) {
+  ClassOfDevice tmp;
+  return ClassOfDevice::FromString(cod, tmp);
+}
diff --git a/types/class_of_device.h b/types/class_of_device.h
new file mode 100644
index 0000000..8c2ab37
--- /dev/null
+++ b/types/class_of_device.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <string>
+
+/** Bluetooth Class of Device */
+class ClassOfDevice final {
+ public:
+  static constexpr unsigned int kLength = 3;
+
+  uint8_t cod[kLength];
+
+  ClassOfDevice() = default;
+  ClassOfDevice(const uint8_t (&class_of_device)[kLength]);
+
+  bool operator==(const ClassOfDevice& rhs) const {
+    return (std::memcmp(cod, rhs.cod, sizeof(cod)) == 0);
+  }
+
+  std::string ToString() const;
+
+  // Converts |string| to ClassOfDevice and places it in |to|. If |from| does
+  // not represent a Class of Device, |to| is not modified and this function
+  // returns false. Otherwise, it returns true.
+  static bool FromString(const std::string& from, ClassOfDevice& to);
+
+  // Copies |from| raw Class of Device octets to the local object.
+  // Returns the number of copied octets (always ClassOfDevice::kLength)
+  size_t FromOctets(const uint8_t* from);
+
+  static bool IsValid(const std::string& class_of_device);
+};
+
+inline std::ostream& operator<<(std::ostream& os, const ClassOfDevice& c) {
+  os << c.ToString();
+  return os;
+}
diff --git a/types/test/class_of_device_unittest.cc b/types/test/class_of_device_unittest.cc
new file mode 100644
index 0000000..5d652a5
--- /dev/null
+++ b/types/test/class_of_device_unittest.cc
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "class_of_device.h"
+
+static const char* test_class = "efc-d-ab";
+static const uint8_t test_bytes[]{0xab, 0xcd, 0xef};
+
+TEST(ClassOfDeviceUnittest, test_constructor_array) {
+  ClassOfDevice cod(test_bytes);
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceUnittest, test_to_from_str) {
+  ClassOfDevice cod;
+  ClassOfDevice::FromString(test_class, cod);
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceUnittest, test_from_octets) {
+  ClassOfDevice cod;
+  size_t expected_result = ClassOfDevice::kLength;
+  ASSERT_EQ(expected_result, cod.FromOctets(test_bytes));
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceTest, test_copy) {
+  ClassOfDevice cod1;
+  ClassOfDevice cod2;
+  ClassOfDevice::FromString(test_class, cod1);
+  cod2 = cod1;
+
+  ASSERT_EQ(cod1.cod[0], cod2.cod[0]);
+  ASSERT_EQ(cod1.cod[1], cod2.cod[1]);
+  ASSERT_EQ(cod1.cod[2], cod2.cod[2]);
+}
+
+TEST(ClassOfDeviceTest, IsValid) {
+  EXPECT_FALSE(ClassOfDevice::IsValid(""));
+  EXPECT_FALSE(ClassOfDevice::IsValid("000000"));
+  EXPECT_FALSE(ClassOfDevice::IsValid("00-00-00"));
+  EXPECT_FALSE(ClassOfDevice::IsValid("000-0-0"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("000-0-00"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("ABc-d-00"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("aBc-D-eF"));
+}
+
+TEST(ClassOfDeviceTest, classOfDeviceFromString) {
+  ClassOfDevice cod;
+
+  EXPECT_TRUE(ClassOfDevice::FromString("000-0-00", cod));
+  const ClassOfDevice result0 = {{0x00, 0x00, 0x00}};
+  EXPECT_EQ(0, memcmp(&cod, &result0, sizeof(cod)));
+
+  EXPECT_TRUE(ClassOfDevice::FromString("ab2-1-4C", cod));
+  const ClassOfDevice result1 = {{0x4c, 0x21, 0xab}};
+  EXPECT_EQ(0, memcmp(&cod, &result1, sizeof(cod)));
+}
diff --git a/udrv/BUILD.gn b/udrv/BUILD.gn
index 8a0fc92..3712bd4 100644
--- a/udrv/BUILD.gn
+++ b/udrv/BUILD.gn
@@ -26,5 +26,6 @@
     "//internal_include",
     "//stack/include",
     "//utils/include",
+    "//third_party/libchrome",
   ]
 }
diff --git a/udrv/ulinux/uipc.cc b/udrv/ulinux/uipc.cc
index e2f2950..24fa711 100644
--- a/udrv/ulinux/uipc.cc
+++ b/udrv/ulinux/uipc.cc
@@ -621,15 +621,15 @@
 uint32_t UIPC_Read(tUIPC_STATE& uipc, tUIPC_CH_ID ch_id,
                    UNUSED_ATTR uint16_t* p_msg_evt, uint8_t* p_buf,
                    uint32_t len) {
-  int n_read = 0;
-  int fd = uipc.ch[ch_id].fd;
-  struct pollfd pfd;
-
   if (ch_id >= UIPC_CH_NUM) {
     BTIF_TRACE_ERROR("UIPC_Read : invalid ch id %d", ch_id);
     return 0;
   }
 
+  int n_read = 0;
+  int fd = uipc.ch[ch_id].fd;
+  struct pollfd pfd;
+
   if (fd == UIPC_DISCONNECTED) {
     BTIF_TRACE_ERROR("UIPC_Read : channel %d closed", ch_id);
     return 0;
diff --git a/utils/Android.bp b/utils/Android.bp
index 6a6c510..3a40750 100644
--- a/utils/Android.bp
+++ b/utils/Android.bp
@@ -12,4 +12,7 @@
         "system/bt/stack/include",
     ],
     srcs: ["src/bt_utils.cc"],
+    shared_libs: [
+        "libprocessgroup",
+    ],
 }
diff --git a/utils/BUILD.gn b/utils/BUILD.gn
index c6e7dab..46b7236 100644
--- a/utils/BUILD.gn
+++ b/utils/BUILD.gn
@@ -23,5 +23,7 @@
     "include",
     "//",
     "//stack/include",
+    "//third_party/libchrome",
+    "//third_party/googletest/googletest/include/",
   ]
 }
diff --git a/utils/src/bt_utils.cc b/utils/src/bt_utils.cc
index 6d93ac4..fda47f6 100644
--- a/utils/src/bt_utils.cc
+++ b/utils/src/bt_utils.cc
@@ -39,7 +39,7 @@
 
 #define A2DP_RT_PRIORITY 1
 #ifndef OS_GENERIC
-#include <cutils/sched_policy.h>
+#include <processgroup/sched_policy.h>
 #endif
 
 #include "bt_types.h"
diff --git a/vendor_libs/linux/interface/bluetooth_hci.cc b/vendor_libs/linux/interface/bluetooth_hci.cc
index 8507f7a..8d7e3f7 100644
--- a/vendor_libs/linux/interface/bluetooth_hci.cc
+++ b/vendor_libs/linux/interface/bluetooth_hci.cc
@@ -39,7 +39,6 @@
 #define MGMT_EV_INDEX_ADDED 0x0004
 #define MGMT_EV_COMMAND_COMP 0x0001
 #define MGMT_EV_SIZE_MAX 1024
-#define MGMT_EV_POLL_TIMEOUT 3000 /* 3000ms */
 #define WRITE_NO_INTR(fn) \
   do {                  \
   } while ((fn) == -1 && errno == EINTR)
@@ -154,7 +153,7 @@
   /* validate mentioned hci interface is present and registered with sock system */
   while (1) {
     int n;
-    WRITE_NO_INTR(n = poll(fds, 1, MGMT_EV_POLL_TIMEOUT));
+    WRITE_NO_INTR(n = poll(fds, 1, -1));
     if (n == -1) {
       ALOGE( "Poll error: %s", strerror(errno));
       ret = -1;
diff --git a/vendor_libs/linux/sepolicy/file_contexts b/vendor_libs/linux/sepolicy/file_contexts
deleted file mode 100644
index 4300140..0000000
--- a/vendor_libs/linux/sepolicy/file_contexts
+++ /dev/null
@@ -1,2 +0,0 @@
-/sys/class/rfkill/rfkill[0-9]/state    u:object_r:sysfs_bluetooth_writable:s0
-/system/vendor/bin/hw/android\.hardware\.bluetooth@1\.0-service\.btlinux    u:object_r:hal_bluetooth_btlinux_exec:s0
diff --git a/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te b/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te
deleted file mode 100644
index 22d9cf0..0000000
--- a/vendor_libs/linux/sepolicy/hal_bluetooth_btlinux.te
+++ /dev/null
@@ -1,8 +0,0 @@
-type hal_bluetooth_btlinux, domain;
-type hal_bluetooth_btlinux_exec, exec_type, file_type, vendor_file_type;
-
-hal_server_domain(hal_bluetooth_btlinux, hal_bluetooth)
-init_daemon_domain(hal_bluetooth_btlinux)
-
-allow hal_bluetooth_btlinux self:socket { create bind read write };
-allow hal_bluetooth_btlinux self:bluetooth_socket { create bind read write };
diff --git a/vendor_libs/test_vendor_lib/Android.bp b/vendor_libs/test_vendor_lib/Android.bp
index ef927f4..aded1c3 100644
--- a/vendor_libs/test_vendor_lib/Android.bp
+++ b/vendor_libs/test_vendor_lib/Android.bp
@@ -3,30 +3,38 @@
 cc_library_static {
     name: "libbt-rootcanal",
     defaults: ["libchrome_support_defaults"],
+    host_supported: true,
     proprietary: true,
     srcs: [
-        "src/acl_packet.cc",
-        "src/async_manager.cc",
-        "src/beacon.cc",
-        "src/beacon_swarm.cc",
-        "src/broken_adv.cc",
-        "src/bt_address.cc",
-        "src/classic.cc",
-        "src/command_packet.cc",
-        "src/connection.cc",
-        "src/device.cc",
-        "src/device_factory.cc",
-        "src/device_properties.cc",
-        "src/dual_mode_controller.cc",
-        "src/event_packet.cc",
-        "src/hci_packet.cc",
-        "src/keyboard.cc",
-        "src/l2cap_packet.cc",
-        "src/l2cap_sdu.cc",
-        "src/packet.cc",
-        "src/packet_stream.cc",
-        "src/sco_packet.cc",
-        "src/test_channel_transport.cc",
+        "model/controller/acl_connection.cc",
+        "model/controller/acl_connection_handler.cc",
+        "model/controller/dual_mode_controller.cc",
+        "model/controller/link_layer_controller.cc",
+        "model/controller/security_manager.cc",
+        "model/devices/beacon.cc",
+        "model/devices/beacon_swarm.cc",
+        "model/devices/broken_adv.cc",
+        "model/devices/car_kit.cc",
+        "model/devices/classic.cc",
+        "model/devices/device.cc",
+        "model/devices/device_properties.cc",
+        "model/devices/h4_packetizer.cc",
+        "model/devices/h4_protocol.cc",
+        "model/devices/hci_packetizer.cc",
+        "model/devices/hci_protocol.cc",
+        "model/devices/hci_socket_device.cc",
+        "model/devices/keyboard.cc",
+        "model/devices/link_layer_socket_device.cc",
+        "model/devices/loopback.cc",
+        "model/devices/polled_socket.cc",
+        "model/devices/remote_loopback_device.cc",
+        "model/devices/sniffer.cc",
+        "model/setup/async_manager.cc",
+        "model/setup/device_boutique.cc",
+        "model/setup/phy_layer_factory.cc",
+        "model/setup/test_channel_transport.cc",
+        "model/setup/test_command_handler.cc",
+        "model/setup/test_model.cc",
     ],
     cflags: [
         "-fvisibility=hidden",
@@ -35,7 +43,10 @@
     local_include_dirs: [
         "include",
     ],
-    export_include_dirs: ["include"],
+    export_include_dirs: [
+        "include",
+        ".",
+    ],
     header_libs: [
         "libbluetooth_headers",
     ],
@@ -50,32 +61,26 @@
         "libbase",
         "liblog",
     ],
+    whole_static_libs: [
+        "libbt-rootcanal-packets",
+    ],
     static_libs: [
-        "libbluetooth-types",
-    ]
+        "libbt-rootcanal-types",
+    ],
 }
 
 // test-vendor unit tests for host
 // ========================================================
 cc_test_host {
     name: "test-vendor_test_host",
-    defaults: ["libchrome_support_defaults"],
+    defaults: [
+        "libchrome_support_defaults",
+        "clang_file_coverage",
+        "clang_coverage_bin",
+    ],
     srcs: [
-        "src/async_manager.cc",
-        "src/bt_address.cc",
-        "src/hci_packet.cc",
-        "src/command_packet.cc",
-        "src/event_packet.cc",
-        "src/packet.cc",
-        "src/packet_stream.cc",
-        "src/l2cap_packet.cc",
-        "src/l2cap_sdu.cc",
         "test/async_manager_unittest.cc",
-        "test/bt_address_unittest.cc",
-        "test/packet_stream_unittest.cc",
-        "test/iterator_test.cc",
-        "test/l2cap_test.cc",
-        "test/l2cap_sdu_test.cc",
+        "test/security_manager_unittest.cc",
     ],
     header_libs: [
         "libbluetooth_headers",
@@ -93,10 +98,43 @@
         "liblog",
     ],
     static_libs: [
-        "libbluetooth-types",
+        "libbt-rootcanal-types",
+        "libbt-rootcanal",
     ],
     cflags: [
         "-fvisibility=hidden",
         "-DLOG_NDEBUG=1",
     ],
 }
+
+// Linux RootCanal Executable
+// ========================================================
+cc_test_host {
+    name: "root-canal",
+    defaults: [
+        "libchrome_support_defaults",
+    ],
+    srcs: [
+        "desktop/root_canal_main.cc",
+        "desktop/test_environment.cc",
+    ],
+    header_libs: [
+        "libbluetooth_headers",
+    ],
+    local_include_dirs: [
+        "include",
+    ],
+    include_dirs: [
+        "system/bt",
+        "system/bt/utils/include",
+        "system/bt/hci/include",
+        "system/bt/stack/include",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libbt-rootcanal-types",
+        "libbt-rootcanal",
+    ],
+}
diff --git a/vendor_libs/test_vendor_lib/desktop/root_canal_main.cc b/vendor_libs/test_vendor_lib/desktop/root_canal_main.cc
new file mode 100644
index 0000000..5432292
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/desktop/root_canal_main.cc
@@ -0,0 +1,69 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#define LOG_TAG "root_canal"
+
+#include "test_environment.h"
+
+#include <base/logging.h>
+#include <utils/Log.h>
+#include <future>
+
+#include "hci_internals.h"
+
+using ::android::bluetooth::root_canal::TestEnvironment;
+
+constexpr uint16_t kTestPort = 6401;
+constexpr uint16_t kHciServerPort = 6402;
+constexpr uint16_t kLinkServerPort = 6403;
+
+int main(int argc, char** argv) {
+  ALOGI("main");
+  uint16_t test_port = kTestPort;
+  uint16_t hci_server_port = kHciServerPort;
+  uint16_t link_server_port = kLinkServerPort;
+
+  for (int arg = 0; arg < argc; arg++) {
+    int port = atoi(argv[arg]);
+    ALOGI("%d: %s (%d)", arg, argv[arg], port);
+    if (port < 0 || port > 0xffff) {
+      ALOGW("%s out of range", argv[arg]);
+    } else {
+      switch (arg) {
+        case 0:  // executable name
+          break;
+        case 1:
+          test_port = port;
+          break;
+        case 2:
+          hci_server_port = port;
+          break;
+        case 3:
+          link_server_port = port;
+          break;
+        default:
+          ALOGW("Ignored option %s", argv[arg]);
+      }
+    }
+  }
+
+  TestEnvironment root_canal(test_port, hci_server_port, link_server_port);
+  std::promise<void> barrier;
+  std::future<void> barrier_future = barrier.get_future();
+  root_canal.initialize(std::move(barrier));
+  barrier_future.wait();
+  root_canal.close();
+}
diff --git a/vendor_libs/test_vendor_lib/desktop/test_environment.cc b/vendor_libs/test_vendor_lib/desktop/test_environment.cc
new file mode 100644
index 0000000..542738d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/desktop/test_environment.cc
@@ -0,0 +1,178 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#define LOG_TAG "root_canal"
+
+#include "test_environment.h"
+
+#include <base/logging.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <utils/Log.h>
+
+#include "hci_internals.h"
+
+namespace android {
+namespace bluetooth {
+namespace root_canal {
+
+using test_vendor_lib::AsyncTaskId;
+using test_vendor_lib::DualModeController;
+using test_vendor_lib::TaskCallback;
+
+void TestEnvironment::initialize(std::promise<void> barrier) {
+  ALOGI("%s", __func__);
+
+  barrier_ = std::move(barrier);
+
+  test_channel_transport_.RegisterCommandHandler([this](const std::string& name, const std::vector<std::string>& args) {
+    async_manager_.ExecAsync(std::chrono::milliseconds(0),
+                             [this, name, args]() { test_channel_.HandleCommand(name, args); });
+  });
+
+  test_model_.Reset();
+
+  SetUpTestChannel();
+  SetUpHciServer([this](int fd) { test_model_.IncomingHciConnection(fd); });
+  SetUpLinkLayerServer([this](int fd) { test_model_.IncomingLinkLayerConnection(fd); });
+
+  ALOGI("%s: Finished", __func__);
+}
+
+void TestEnvironment::close() {
+  ALOGI("%s", __func__);
+}
+
+void TestEnvironment::SetUpHciServer(const std::function<void(int)>& connection_callback) {
+  int socket_fd = remote_hci_transport_.SetUp(hci_server_port_);
+
+  test_channel_.RegisterSendResponse(
+      [](const std::string& response) { ALOGI("No HCI Response channel: %s", response.c_str()); });
+
+  if (socket_fd == -1) {
+    ALOGE("Remote HCI channel SetUp(%d) failed.", hci_server_port_);
+    return;
+  }
+
+  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
+    int conn_fd = remote_hci_transport_.Accept(socket_fd);
+    if (conn_fd < 0) {
+      ALOGE("Error watching remote HCI channel fd.");
+      return;
+    }
+    int flags = fcntl(conn_fd, F_GETFL, NULL);
+    int ret;
+    ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
+    CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno);
+
+    connection_callback(conn_fd);
+  });
+}
+
+void TestEnvironment::SetUpLinkLayerServer(const std::function<void(int)>& connection_callback) {
+  int socket_fd = remote_link_layer_transport_.SetUp(link_server_port_);
+
+  test_channel_.RegisterSendResponse(
+      [](const std::string& response) { ALOGI("No LinkLayer Response channel: %s", response.c_str()); });
+
+  if (socket_fd == -1) {
+    ALOGE("Remote LinkLayer channel SetUp(%d) failed.", link_server_port_);
+    return;
+  }
+
+  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this, connection_callback](int socket_fd) {
+    int conn_fd = remote_link_layer_transport_.Accept(socket_fd);
+    if (conn_fd < 0) {
+      ALOGE("Error watching remote LinkLayer channel fd.");
+      return;
+    }
+    int flags = fcntl(conn_fd, F_GETFL, NULL);
+    int ret = fcntl(conn_fd, F_SETFL, flags | O_NONBLOCK);
+    CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno);
+
+    connection_callback(conn_fd);
+  });
+}
+
+int TestEnvironment::ConnectToRemoteServer(const std::string& server, int port) {
+  int socket_fd = socket(AF_INET, SOCK_STREAM, 0);
+  if (socket_fd < 1) {
+    ALOGI("socket() call failed: %s", strerror(errno));
+    return -1;
+  }
+
+  struct hostent* host;
+  host = gethostbyname(server.c_str());
+  if (host == NULL) {
+    ALOGI("gethostbyname() failed for %s: %s", server.c_str(), strerror(errno));
+    return -1;
+  }
+
+  struct sockaddr_in serv_addr;
+  memset((void*)&serv_addr, 0, sizeof(serv_addr));
+  serv_addr.sin_family = AF_INET;
+  serv_addr.sin_addr.s_addr = INADDR_ANY;
+  serv_addr.sin_port = htons(port);
+
+  int result = connect(socket_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
+  if (result < 0) {
+    ALOGI("connect() failed for %s@%d: %s", server.c_str(), port, strerror(errno));
+    return -1;
+  }
+
+  int flags = fcntl(socket_fd, F_GETFL, NULL);
+  int ret = fcntl(socket_fd, F_SETFL, flags | O_NONBLOCK);
+  CHECK(ret != -1) << "Error setting O_NONBLOCK " << strerror(errno);
+
+  return socket_fd;
+}
+
+void TestEnvironment::SetUpTestChannel() {
+  int socket_fd = test_channel_transport_.SetUp(test_port_);
+
+  test_channel_.RegisterSendResponse(
+      [](const std::string& response) { ALOGI("No test channel: %s", response.c_str()); });
+
+  if (socket_fd == -1) {
+    ALOGE("Test channel SetUp(%d) failed.", test_port_);
+    return;
+  }
+
+  ALOGI("Test channel SetUp() successful");
+  async_manager_.WatchFdForNonBlockingReads(socket_fd, [this](int socket_fd) {
+    int conn_fd = test_channel_transport_.Accept(socket_fd);
+    if (conn_fd < 0) {
+      ALOGE("Error watching test channel fd.");
+      barrier_.set_value();
+      return;
+    }
+    ALOGI("Test channel connection accepted.");
+    test_channel_.RegisterSendResponse(
+        [this, conn_fd](const std::string& response) { test_channel_transport_.SendResponse(conn_fd, response); });
+
+    async_manager_.WatchFdForNonBlockingReads(conn_fd, [this](int conn_fd) {
+      test_channel_transport_.OnCommandReady(conn_fd, [this, conn_fd]() {
+        async_manager_.StopWatchingFileDescriptor(conn_fd);
+        barrier_.set_value();
+      });
+    });
+  });
+}
+
+}  // namespace root_canal
+}  // namespace bluetooth
+}  // namespace android
diff --git a/vendor_libs/test_vendor_lib/desktop/test_environment.h b/vendor_libs/test_vendor_lib/desktop/test_environment.h
new file mode 100644
index 0000000..f48789b
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/desktop/test_environment.h
@@ -0,0 +1,78 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#pragma once
+
+#include <future>
+
+#include "model/controller/dual_mode_controller.h"
+#include "model/setup/async_manager.h"
+#include "model/setup/test_channel_transport.h"
+#include "model/setup/test_command_handler.h"
+#include "model/setup/test_model.h"
+
+namespace android {
+namespace bluetooth {
+namespace root_canal {
+
+class TestEnvironment {
+ public:
+  TestEnvironment(uint16_t test_port, uint16_t hci_server_port, uint16_t link_server_port)
+      : test_port_(test_port), hci_server_port_(hci_server_port), link_server_port_(link_server_port) {}
+
+  void initialize(std::promise<void> barrier);
+
+  void close();
+
+ private:
+  uint16_t test_port_;
+  uint16_t hci_server_port_;
+  uint16_t link_server_port_;
+  std::promise<void> barrier_;
+
+  test_vendor_lib::AsyncManager async_manager_;
+
+  void SetUpTestChannel();
+  void SetUpHciServer(const std::function<void(int)>& on_connect);
+  void SetUpLinkLayerServer(const std::function<void(int)>& on_connect);
+  int ConnectToRemoteServer(const std::string& server, int port);
+
+  std::shared_ptr<test_vendor_lib::DualModeController> controller_;
+
+  test_vendor_lib::TestChannelTransport test_channel_transport_;
+  test_vendor_lib::TestChannelTransport remote_hci_transport_;
+  test_vendor_lib::TestChannelTransport remote_link_layer_transport_;
+
+  test_vendor_lib::TestModel test_model_{
+      [this](std::chrono::milliseconds delay, const test_vendor_lib::TaskCallback& task) {
+        return async_manager_.ExecAsync(delay, task);
+      },
+
+      [this](std::chrono::milliseconds delay, std::chrono::milliseconds period,
+             const test_vendor_lib::TaskCallback& task) {
+        return async_manager_.ExecAsyncPeriodically(delay, period, task);
+      },
+
+      [this](test_vendor_lib::AsyncTaskId task) { async_manager_.CancelAsyncTask(task); },
+
+      [this](const std::string& server, int port) { return ConnectToRemoteServer(server, port); }};
+
+  test_vendor_lib::TestCommandHandler test_channel_{test_model_};
+};
+
+}  // namespace root_canal
+}  // namespace bluetooth
+}  // namespace android
diff --git a/vendor_libs/test_vendor_lib/include/acl.h b/vendor_libs/test_vendor_lib/include/acl.h
new file mode 100644
index 0000000..c7c7b34
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/acl.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+namespace test_vendor_lib {
+namespace acl {
+
+// ACL data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.2
+static constexpr uint16_t kReservedHandle = 0xF00;
+
+enum class PacketBoundaryFlagsType : uint8_t {
+  FIRST_NON_AUTOMATICALLY_FLUSHABLE = 0,
+  CONTINUING = 1,
+  FIRST_AUTOMATICALLY_FLUSHABLE = 2,
+  COMPLETE = 3
+};
+
+enum class BroadcastFlagsType : uint8_t {
+  POINT_TO_POINT = 0,
+  ACTIVE_SLAVE_BROADCAST = 1,
+  PARKED_SLAVE_BROADCAST = 2,
+  RESERVED = 3
+};
+}  // namespace acl
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/acl_packet.h b/vendor_libs/test_vendor_lib/include/acl_packet.h
deleted file mode 100644
index 30f3389..0000000
--- a/vendor_libs/test_vendor_lib/include/acl_packet.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-namespace test_vendor_lib {
-
-// ACL data packets are specified in the Bluetooth Core Specification Version
-// 4.2, Volume 2, Part E, Section 5.4.2
-class AclPacket {
- public:
-  typedef enum {
-    FirstNonAutomaticallyFlushable,
-    Continuing,
-    FirstAutomaticallyFlushable,
-    Complete
-  } PacketBoundaryFlags;
-  typedef enum {
-    PointToPoint,
-    ActiveSlaveBroadcast,
-    ParkedSlaveBroadcast,
-    Reserved
-  } BroadcastFlags;
-
-  virtual ~AclPacket() = default;
-
-  uint16_t GetChannel() const {
-    return (raw_packet_[0] | (raw_packet_[1] << 8)) & 0xfff;
-  }
-
-  PacketBoundaryFlags GetPacketBoundaryFlags() const {
-    return static_cast<PacketBoundaryFlags>((raw_packet_[1] & 0x30) >> 4);
-  }
-
-  BroadcastFlags GetBroadcastFlags() const {
-    return static_cast<BroadcastFlags>((raw_packet_[1] & 0xC0) >> 6);
-  }
-
-  explicit AclPacket(uint16_t channel,
-                     AclPacket::PacketBoundaryFlags boundary_flags,
-                     AclPacket::BroadcastFlags broadcast);
-
-  size_t GetPacketSize() const;
-
-  const std::vector<uint8_t>& GetPacket() const;
-
-  void AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes);
-
- private:
-  // Add |octets| bytes to the payload.
-  void AddPayloadOctets(size_t octets, uint64_t value);
-
-  static const size_t kHeaderSize = 4;
-
- public:
-  // Add type-checking versions
-  void AddPayloadOctets1(uint8_t value) { AddPayloadOctets(1, value); }
-  void AddPayloadOctets2(uint16_t value) { AddPayloadOctets(2, value); }
-  void AddPayloadOctets3(uint32_t value) { AddPayloadOctets(3, value); }
-  void AddPayloadOctets4(uint32_t value) { AddPayloadOctets(4, value); }
-  void AddPayloadOctets6(uint64_t value) { AddPayloadOctets(6, value); }
-  void AddPayloadOctets8(uint64_t value) { AddPayloadOctets(8, value); }
-
- private:
-  std::vector<uint8_t> raw_packet_;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/bt_address.h b/vendor_libs/test_vendor_lib/include/bt_address.h
deleted file mode 100644
index d656c34..0000000
--- a/vendor_libs/test_vendor_lib/include/bt_address.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-namespace test_vendor_lib {
-
-// Encapsulate handling for Bluetooth Addresses:
-// - store the address
-// - convert to/from strings and vectors of bytes
-// - check strings to see if they represent a valid address
-class BtAddress {
- public:
-  // Conversion constants
-  static const size_t kStringLength = 17;  // "XX:XX:XX:XX:XX:XX"
-  static const size_t kOctets = 6;         // "X0:X1:X2:X3:X4:X5"
-
-  BtAddress() : address_(0){};
-  virtual ~BtAddress() = default;
-
-  // Returns true if |addr| has the form "XX:XX:XX:XX:XX:XX":
-  // - the length of |addr| is >= kStringLength
-  // - every third character is ':'
-  // - each remaining character is a hexadecimal digit
-  static bool IsValid(const std::string& addr);
-
-  inline bool operator==(const BtAddress& right) const {
-    return address_ == right.address_;
-  }
-  inline bool operator!=(const BtAddress& right) const {
-    return address_ != right.address_;
-  }
-  inline bool operator<(const BtAddress& right) const {
-    return address_ < right.address_;
-  }
-  inline bool operator>(const BtAddress& right) const {
-    return address_ > right.address_;
-  }
-  inline bool operator<=(const BtAddress& right) const {
-    return address_ <= right.address_;
-  }
-  inline bool operator>=(const BtAddress& right) const {
-    return address_ >= right.address_;
-  }
-
-  inline void operator=(const BtAddress& right) { address_ = right.address_; }
-  inline void operator|=(const BtAddress& right) { address_ |= right.address_; }
-  inline void operator&=(const BtAddress& right) { address_ &= right.address_; }
-
-  // Set the address to the address represented by |str|.
-  // returns true if |str| represents a valid address, otherwise false.
-  bool FromString(const std::string& str);
-
-  // Set the address to the address represented by |str|.
-  // returns true if octets.size() >= kOctets, otherwise false.
-  bool FromVector(const std::vector<uint8_t>& octets);
-
-  // Appends the Bluetooth address to the vector |octets|.
-  void ToVector(std::vector<uint8_t>& octets) const;
-
-  // Return a string representation of the Bluetooth address, in this format:
-  // "xx:xx:xx:xx:xx:xx", where x represents a lowercase hexadecimal digit.
-  std::string ToString() const;
-
- private:
-  // The Bluetooth Address is stored in the lower 48 bits of a 64-bit value
-  uint64_t address_;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/command_packet.h b/vendor_libs/test_vendor_lib/include/command_packet.h
deleted file mode 100644
index 36ab8d2..0000000
--- a/vendor_libs/test_vendor_lib/include/command_packet.h
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <vector>
-
-#include "base/macros.h"
-#include "packet.h"
-
-namespace test_vendor_lib {
-
-// The following is specified in the Bluetooth Core Specification Version 4.2,
-// Volume 2, Part E, Section 5.4.1 (page 470). Command Packets begin with a 3
-// octet header formatted as follows:
-// - Opcode: 2 octets
-//   - Opcode Group Field (OGF): Upper bits 10-15
-//   - Opcode Command Field (OCF): Lower bits 0-9
-// - Payload size (in octets): 1 octet
-// The header is followed by the payload, which contains command specific
-// parameters and has a maximum size of 255 octets. Valid command opcodes are
-// defined in stack/include/hcidefs.h. The OGF ranges from 0x00 to 0x3F, with
-// 0x3F reserved for vendor-specific debug functions. The OCF ranges from
-// 0x0000 to 0x03FF. Note that the payload size is the size in octets of the
-// command parameters and not the number of parameters. Finally, although the
-// parameters contained in the payload are command specific (including the size
-// and number of parameters), each parameter will be an integer number of octets
-// in size.
-class CommandPacket : public Packet {
- public:
-  explicit CommandPacket(std::vector<uint8_t> header);
-  explicit CommandPacket(uint16_t opcode);
-  CommandPacket(std::vector<uint8_t> header, std::vector<uint8_t> payload);
-
-  CommandPacket(const CommandPacket&) = default;
-  CommandPacket& operator=(const CommandPacket&) = default;
-  CommandPacket(CommandPacket&&) = default;
-  CommandPacket& operator=(CommandPacket&&) = default;
-  virtual ~CommandPacket() override = default;
-
-  // Returns the command opcode as defined in stack/include/hcidefs.h.
-  // See the Bluetooth Core Specification Version 4.2, Volume 2, Part E,
-  // Section 7 for more information about each HCI commands and for a listing
-  // of their specific opcodes/OGF and OCF values.
-  uint16_t GetOpcode() const;
-
-  // Returns the 6 bit opcode group field that specifies the general category of
-  // the command. The OGF can be one of seven values:
-  // - 0x01: Link control commands
-  // - 0x02: Link policy commands
-  // - 0x03: Controller and baseband commands
-  // - 0x04: Informational parameters commands
-  // - 0x05: Status parameters commands
-  // - 0x06: Testing commands
-  // - 0x08: Low energy controller commands
-  // The upper 2 bits will be zero filled.
-  uint8_t GetOGF() const;
-
-  // Returns the 10 bit opcode command field that specifies an exact command
-  // within an opcode group field. The upper 6 bits will be zero filled.
-  uint16_t GetOCF() const;
-
-  // Size of a command packet header, which consists of a 2 octet opcode
-  static const size_t kCommandHeaderSize = 2;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/connection.h b/vendor_libs/test_vendor_lib/include/connection.h
deleted file mode 100644
index 2a4f662..0000000
--- a/vendor_libs/test_vendor_lib/include/connection.h
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <queue>
-#include <string>
-#include <vector>
-
-#include "async_manager.h"
-#include "device.h"
-
-#include "hci/include/hci_hal.h"
-
-namespace test_vendor_lib {
-
-// Model the connection of a device to the controller.
-class Connection {
- public:
-  Connection(std::shared_ptr<Device> dev, uint16_t handle)
-      : dev_(dev), handle_(handle), connected_(true), encrypted_(false) {}
-
-  virtual ~Connection() = default;
-
-  // Return a string representing the connection for logging.
-  const std::string ToString();
-
-  // Return a pointer to the device in the connection.
-  std::shared_ptr<Device> GetDevice() { return dev_; }
-
-  // Return true if the handle matches and the device is connected.
-  inline bool operator==(uint16_t handle) {
-    return (handle_ == handle) && connected_;
-  }
-
-  // Return true if the handle doesn't match or the device is not connected.
-  inline bool operator!=(uint16_t handle) {
-    return (handle_ != handle) || !connected_;
-  }
-
-  void Disconnect() { connected_ = false; };
-  bool Connected() { return connected_; };
-
-  void Encrypt() { encrypted_ = true; };
-  bool Encrypted() { return encrypted_; };
-
-  // Add an action to the connection queue.
-  void AddAction(const TaskCallback& task);
-
-  // Execute the next action in the connection queue to simulate packet
-  // exchange.
-  void SendToDevice();
-
-  // Add a message from the device.
-  void AddMessage(const std::vector<uint8_t>& message);
-
-  // Receive data from the device to simulate packet exchange.
-  bool ReceiveFromDevice(std::vector<uint8_t>& data);
-
- private:
-  // A shared pointer to the connected device
-  std::shared_ptr<Device> dev_;
-
-  // The connection handle
-  uint16_t handle_;
-
-  // State variables
-  bool connected_;
-  bool encrypted_;
-
-  // Actions for the next packet exchange.
-  std::queue<TaskCallback> actions_;
-
-  // Messages from the device for the next packet exchange.
-  std::queue<std::vector<uint8_t>> messages_;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/device.h b/vendor_libs/test_vendor_lib/include/device.h
deleted file mode 100644
index e2924c4..0000000
--- a/vendor_libs/test_vendor_lib/include/device.h
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <chrono>
-#include <cstdint>
-#include <string>
-#include <vector>
-
-#include "bt_address.h"
-
-#include "hci/include/hci_hal.h"
-#include "stack/include/btm_ble_api.h"
-
-namespace test_vendor_lib {
-
-// Represent a Bluetooth Device
-//  - Provide Get*() and Set*() functions for device attributes.
-class Device {
- public:
-  Device() : time_stamp_(std::chrono::steady_clock::now()) {}
-  virtual ~Device() = default;
-
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) = 0;
-
-  // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const = 0;
-
-  // Return the string representation of the device.
-  virtual std::string ToString() const;
-
-  // Return a reference to the address.
-  const BtAddress& GetBtAddress() const { return address_; }
-
-  // Set the address to the |addr|.
-  void SetBtAddress(const BtAddress& addr) { address_ = addr; }
-
-  // Return the address type.
-  uint8_t GetAddressType() const { return address_type_; }
-
-  // Decide whether to accept a connection request
-  // May need to be extended to check peer address & type, and other
-  // connection parameters.
-  // Return true if the device accepts the connection request.
-  virtual bool LeConnect() { return false; }
-
-  // Return the advertisement data.
-  const std::vector<uint8_t>& GetAdvertisement() const { return adv_data_; }
-
-  // Return the advertisement type.
-  uint8_t GetAdvertisementType() const { return advertising_type_; }
-
-  // Set the advertisement interval in milliseconds.
-  void SetAdvertisementInterval(std::chrono::milliseconds ms) {
-    advertising_interval_ms_ = ms;
-  }
-
-  // Return true if there is a scan response (allows for empty responses).
-  bool HasScanResponse() const { return scan_response_present_; }
-
-  // Return the scan response data.
-  const std::vector<uint8_t>& GetScanResponse() const { return scan_data_; }
-
-  // Returns true if the host could see an advertisement in the next
-  // |scan_time| milliseconds.
-  virtual bool IsAdvertisementAvailable(
-      std::chrono::milliseconds scan_time) const;
-
-  // Returns true if the host could see a page scan now.
-  virtual bool IsPageScanAvailable() const;
-
-  // Return the device class.
-  // The device class is a 3-byte value.  Look for DEV_CLASS in
-  // stack/include/bt_types.h
-  uint32_t GetDeviceClass() const { return device_class_; }
-
-  // Return the clock offset, which is a defined in the Spec as:
-  // (CLKN_16-2 slave - CLKN_16-2 master ) mod 2**15.
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part C, Section 4.3.2
-  uint16_t GetClockOffset() const { return clock_offset_; }
-
-  // Set the clock offset.
-  void SetClockOffset(uint16_t offset) { clock_offset_ = offset; }
-
-  // Return the page scan repetition mode.
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part B, Section 8.3.1
-  // The values are:
-  // 0 - R0 T_page_scan <= 1.28s and T_page_scan == T_window and
-  // 1 - R1 T_page_scan <= 1.28s
-  // 2 - R2 T_page_scan <= 2.56s
-  uint8_t GetPageScanRepetitionMode() const {
-    return page_scan_repetition_mode_;
-  }
-
-  // Return the extended inquiry data.
-  const std::vector<uint8_t>& GetExtendedInquiryData() const {
-    return extended_inquiry_data_;
-  }
-
-  // Let the device know that time has passed.
-  virtual void TimerTick() {}
-
- protected:
-  BtAddress address_;
-
-  // Address type is defined in the spec:
-  // 0x00 Public Device Address
-  // 0x01 Random Device Address
-  // 0x02 Public Identity Address
-  // 0x03 Random (static) Identity Address
-  // 0x04 – 0xFF Reserved for future use
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.12
-  uint8_t address_type_;
-
-  std::chrono::steady_clock::time_point time_stamp_;
-
-  // Return the device class.
-  // The device class is a 3-byte value.  Look for DEV_CLASS in
-  // stack/include/bt_types.h
-  uint32_t device_class_;
-
-  // Return the page scan repetition mode.
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part B, Section 8.3.1
-  // The values are:
-  // 0 - R0 T_page_scan <= 1.28s and T_page_scan == T_window and
-  // 1 - R1 T_page_scan <= 1.28s
-  // 2 - R2 T_page_scan <= 2.56s
-  uint8_t page_scan_repetition_mode_;
-
-  // The time between page scans.
-  std::chrono::milliseconds page_scan_delay_ms_;
-
-  std::vector<uint8_t> extended_inquiry_data_;
-
-  // Classic Bluetooth CLKN_slave[16..2] - CLKN_master[16..2]
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part C, Section 4.3.2
-  uint16_t clock_offset_;
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.5
-  uint8_t advertising_type_;
-
-  // The spec defines the advertising interval as a 16-bit value, but since it
-  // is never sent in packets, we use std::chrono::milliseconds.
-  std::chrono::milliseconds advertising_interval_ms_;
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.7
-
-  // Bluetooth Core Specification Version 4.2, Volume 3, Part C, Section
-  // 11.1
-  // https://www.bluetooth.com/specifications/assigned-numbers
-  // Supplement to Bluetooth Core Specification | CSSv6, Part A
-  std::vector<uint8_t> adv_data_ = {0x07,  // Length
-                                    BTM_BLE_AD_TYPE_NAME_CMPL,
-                                    'd',
-                                    'e',
-                                    'v',
-                                    'i',
-                                    'c',
-                                    'e'};
-
-  bool scan_response_present_ = true;
-  std::vector<uint8_t> scan_data_ = {0x04,  // Length
-                                     BTM_BLE_AD_TYPE_NAME_SHORT, 'd', 'e', 'v'};
-
- public:
-  static const uint8_t kBtAddressTypePublic = 0x00;
-  static const uint8_t kBtAddressTypeRandom = 0x01;
-  static const uint8_t kBtAddressTypePublicIdentity = 0x02;
-  static const uint8_t kBtAddressTypeRandomIdentity = 0x03;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/device_factory.h b/vendor_libs/test_vendor_lib/include/device_factory.h
deleted file mode 100644
index a66a2e0..0000000
--- a/vendor_libs/test_vendor_lib/include/device_factory.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <string>
-#include <vector>
-
-#include "device.h"
-
-namespace test_vendor_lib {
-
-// Encapsulate the details of supported devices to hide them from the
-// Controller.
-class DeviceFactory {
- public:
-  DeviceFactory();
-  virtual ~DeviceFactory() = default;
-
-  // Call the constructor for the matching device type (arg[0]) and then call
-  // the matching Initialize() function with args.
-  static std::shared_ptr<Device> Create(const std::vector<std::string>& args);
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/device_properties.h b/vendor_libs/test_vendor_lib/include/device_properties.h
deleted file mode 100644
index 98876d5..0000000
--- a/vendor_libs/test_vendor_lib/include/device_properties.h
+++ /dev/null
@@ -1,154 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "acl_packet.h"
-#include "async_manager.h"
-#include "base/json/json_value_converter.h"
-#include "base/time/time.h"
-#include "bt_address.h"
-
-namespace test_vendor_lib {
-
-// Emulates a dual mode BR/EDR + LE controller by maintaining the link layer
-// state machine detailed in the Bluetooth Core Specification Version 4.2,
-// Volume 6, Part B, Section 1.1 (page 30). Provides methods corresponding to
-// commands sent by the HCI. These methods will be registered as callbacks from
-// a controller instance with the HciHandler. To implement a new Bluetooth
-// command, simply add the method declaration below, with return type void and a
-// single const std::vector<uint8_t>& argument. After implementing the
-// method, simply register it with the HciHandler using the SET_HANDLER macro in
-// the controller's default constructor. Be sure to name your method after the
-// corresponding Bluetooth command in the Core Specification with the prefix
-// "Hci" to distinguish it as a controller command.
-class DeviceProperties {
- public:
-  explicit DeviceProperties(const std::string& file_name);
-
-  // Access private configuration data
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.4.1
-  const std::vector<uint8_t>& GetLocalVersionInformation() const;
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.4.2
-  const std::vector<uint8_t>& GetLocalSupportedCommands() const {
-    return local_supported_commands_;
-  }
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.4.3
-  uint64_t GetLocalSupportedFeatures() const {
-    return local_extended_features_[0];
-  };
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.4.4
-  uint8_t GetLocalExtendedFeaturesMaximumPageNumber() const {
-    return local_extended_features_.size() - 1;
-  };
-
-  uint64_t GetLocalExtendedFeatures(uint8_t page_number) const {
-    CHECK(page_number < local_extended_features_.size());
-    return local_extended_features_[page_number];
-  };
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.4.5
-  uint16_t GetAclDataPacketSize() const { return acl_data_packet_size_; }
-
-  uint8_t GetSynchronousDataPacketSize() const { return sco_data_packet_size_; }
-
-  uint16_t GetTotalNumAclDataPackets() const { return num_acl_data_packets_; }
-
-  uint16_t GetTotalNumSynchronousDataPackets() const {
-    return num_sco_data_packets_;
-  }
-
-  const BtAddress& GetAddress() const { return address_; }
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.4.8
-  const std::vector<uint8_t>& GetSupportedCodecs() const {
-    return supported_codecs_;
-  }
-
-  const std::vector<uint32_t>& GetVendorSpecificCodecs() const {
-    return vendor_specific_codecs_;
-  }
-
-  const std::string& GetLocalName() const { return local_name_; }
-
-  uint8_t GetVersion() const { return version_; }
-
-  uint16_t GetRevision() const { return revision_; }
-
-  uint8_t GetLmpPalVersion() const { return lmp_pal_version_; }
-
-  uint16_t GetLmpPalSubversion() const { return lmp_pal_subversion_; }
-
-  uint16_t GetManufacturerName() const { return manufacturer_name_; }
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.8.2
-  uint16_t GetLeDataPacketLength() const { return le_data_packet_length_; }
-
-  uint8_t GetTotalNumLeDataPackets() const { return num_le_data_packets_; }
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.8.3
-  uint64_t GetLeLocalSupportedFeatures() const {
-    return le_supported_features_;
-  }
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.8.14
-  uint8_t GetLeWhiteListSize() const { return le_white_list_size_; }
-
-  // Specification Version 4.2, Volume 2, Part E, Section 7.8.27
-  uint64_t GetLeSupportedStates() const { return le_supported_states_; }
-
-  // Vendor-specific commands (see hcidefs.h)
-  const std::vector<uint8_t>& GetLeVendorCap() const { return le_vendor_cap_; }
-
-  static void RegisterJSONConverter(
-      base::JSONValueConverter<DeviceProperties>* converter);
-
- private:
-  uint16_t acl_data_packet_size_;
-  uint8_t sco_data_packet_size_;
-  uint16_t num_acl_data_packets_;
-  uint16_t num_sco_data_packets_;
-  uint8_t version_;
-  uint16_t revision_;
-  uint8_t lmp_pal_version_;
-  uint16_t manufacturer_name_;
-  uint16_t lmp_pal_subversion_;
-  std::vector<uint8_t> supported_codecs_;
-  std::vector<uint32_t> vendor_specific_codecs_;
-  std::vector<uint8_t> local_supported_commands_;
-  std::string local_name_;
-  std::vector<uint64_t> local_extended_features_;
-  BtAddress address_;
-
-  uint16_t le_data_packet_length_;
-  uint8_t num_le_data_packets_;
-  uint8_t le_white_list_size_;
-  uint64_t le_supported_features_;
-  uint64_t le_supported_states_;
-  std::vector<uint8_t> le_vendor_cap_;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/dual_mode_controller.h b/vendor_libs/test_vendor_lib/include/dual_mode_controller.h
deleted file mode 100644
index 4f7041c..0000000
--- a/vendor_libs/test_vendor_lib/include/dual_mode_controller.h
+++ /dev/null
@@ -1,483 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <unordered_map>
-#include <vector>
-
-#include "acl_packet.h"
-#include "async_manager.h"
-#include "base/time/time.h"
-#include "bt_address.h"
-#include "command_packet.h"
-#include "connection.h"
-#include "device.h"
-#include "device_properties.h"
-#include "event_packet.h"
-#include "sco_packet.h"
-#include "test_channel_transport.h"
-
-namespace test_vendor_lib {
-
-// Emulates a dual mode BR/EDR + LE controller by maintaining the link layer
-// state machine detailed in the Bluetooth Core Specification Version 4.2,
-// Volume 6, Part B, Section 1.1 (page 30). Provides methods corresponding to
-// commands sent by the HCI. These methods will be registered as callbacks from
-// a controller instance with the HciHandler. To implement a new Bluetooth
-// command, simply add the method declaration below, with return type void and a
-// single const std::vector<uint8_t>& argument. After implementing the
-// method, simply register it with the HciHandler using the SET_HANDLER macro in
-// the controller's default constructor. Be sure to name your method after the
-// corresponding Bluetooth command in the Core Specification with the prefix
-// "Hci" to distinguish it as a controller command.
-class DualModeController {
- public:
-  // Sets all of the methods to be used as callbacks in the HciHandler.
-  DualModeController();
-
-  ~DualModeController() = default;
-
-  // Route commands and data from the stack.
-  void HandleAcl(std::unique_ptr<AclPacket> acl_packet);
-  void HandleCommand(std::unique_ptr<CommandPacket> command_packet);
-  void HandleSco(std::unique_ptr<ScoPacket> sco_packet);
-
-  // Dispatches the test channel action corresponding to the command specified
-  // by |name|.
-  void HandleTestChannelCommand(const std::string& name,
-                                const std::vector<std::string>& args);
-
-  // Set the callbacks for scheduling tasks.
-  void RegisterTaskScheduler(
-      std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)>
-          evtScheduler);
-
-  void RegisterPeriodicTaskScheduler(
-      std::function<AsyncTaskId(std::chrono::milliseconds,
-                                std::chrono::milliseconds, const TaskCallback&)>
-          periodicEvtScheduler);
-
-  void RegisterTaskCancel(std::function<void(AsyncTaskId)> cancel);
-
-  // Set the callbacks for sending packets to the HCI.
-  void RegisterEventChannel(
-      const std::function<void(std::unique_ptr<EventPacket>)>& send_event);
-
-  void RegisterAclChannel(
-      const std::function<void(std::unique_ptr<AclPacket>)>& send_acl);
-
-  void RegisterScoChannel(
-      const std::function<void(std::unique_ptr<ScoPacket>)>& send_sco);
-
-  // Controller commands. For error codes, see the Bluetooth Core Specification,
-  // Version 4.2, Volume 2, Part D (page 370).
-
-  // OGF: 0x0003
-  // OCF: 0x0003
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.2
-  void HciReset(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0004
-  // OGF: 0x0005
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4.5
-  void HciReadBufferSize(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0033
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.39
-  void HciHostBufferSize(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0004
-  // OCF: 0x0001
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4.1
-  void HciReadLocalVersionInformation(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0004
-  // OCF: 0x0009
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4.6
-  void HciReadBdAddr(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0004
-  // OCF: 0x0002
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4.2
-  void HciReadLocalSupportedCommands(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0004
-  // OCF: 0x0004
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4.4
-  void HciReadLocalExtendedFeatures(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0004
-  // OCF: 0x000B
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4.8
-  void HciReadLocalSupportedCodecs(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0056
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.59
-  void HciWriteSimplePairingMode(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x006D
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.79
-  void HciWriteLeHostSupport(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0001
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.1
-  void HciSetEventMask(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0045
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.50
-  void HciWriteInquiryMode(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0047
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.52
-  void HciWritePageScanType(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0043
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.48
-  void HciWriteInquiryScanType(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0024
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.26
-  void HciWriteClassOfDevice(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0018
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.16
-  void HciWritePageTimeout(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0002
-  // OCF: 0x000F
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.2.12
-  void HciWriteDefaultLinkPolicySettings(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0014
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.12
-  void HciReadLocalName(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0013
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.11
-  void HciWriteLocalName(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0052
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.56
-  void HciWriteExtendedInquiryResponse(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0026
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.28
-  void HciWriteVoiceSetting(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x003A
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.45
-  void HciWriteCurrentIacLap(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x001E
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.22
-  void HciWriteInquiryScanActivity(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x001A
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.18
-  void HciWriteScanEnable(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0005
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.3
-  void HciSetEventFilter(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0001
-  // OCF: 0x0001
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.1.1
-  void HciInquiry(const std::vector<uint8_t>& args);
-
-  void InquiryTimeout();
-
-  // OGF: 0x0001
-  // OCF: 0x0002
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.1.2
-  void HciInquiryCancel(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0003
-  // OCF: 0x0012
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3.10
-  void HciDeleteStoredLinkKey(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0001
-  // OCF: 0x0019
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.1.19
-  void HciRemoteNameRequest(const std::vector<uint8_t>& args);
-
-  // Test Commands
-
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.7.1
-  void HciReadLoopbackMode(const std::vector<uint8_t>& args);
-
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.7.2
-  void HciWriteLoopbackMode(const std::vector<uint8_t>& args);
-
-  // LE Controller Commands
-
-  // OGF: 0x0008
-  // OCF: 0x0001
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.1
-  void HciLeSetEventMask(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x0002
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.2
-  void HciLeReadBufferSize(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x0003
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.3
-  void HciLeReadLocalSupportedFeatures(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x0005
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.4
-  void HciLeSetRandomAddress(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x0006
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.5
-  void HciLeSetAdvertisingParameters(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x0008
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.7
-  void HciLeSetAdvertisingData(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x000B
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.10
-  void HciLeSetScanParameters(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x000C
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.11
-  void HciLeSetScanEnable(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x000D
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.12
-  void HciLeCreateConnection(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x000E
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.13
-  void HciLeConnectionCancel(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x000F
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.14
-  void HciLeReadWhiteListSize(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x0016
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.21
-  void HciLeReadRemoteUsedFeatures(const std::vector<uint8_t>& args);
-  void HciLeReadRemoteUsedFeaturesB(uint16_t handle);
-
-  // OGF: 0x0008
-  // OCF: 0x0018
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.23
-  void HciLeRand(const std::vector<uint8_t>& args);
-
-  // OGF: 0x0008
-  // OCF: 0x001C
-  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8.27
-  void HciLeReadSupportedStates(const std::vector<uint8_t>& args);
-
-  // Vendor-specific commands (see hcidefs.h)
-
-  // OGF: 0x00FC
-  // OCF: 0x0027
-  void HciBleVendorSleepMode(const std::vector<uint8_t>& args);
-
-  // OGF: 0x00FC
-  // OCF: 0x0153
-  void HciBleVendorCap(const std::vector<uint8_t>& args);
-
-  // OGF: 0x00FC
-  // OCF: 0x0154
-  void HciBleVendorMultiAdv(const std::vector<uint8_t>& args);
-
-  // OGF: 0x00FC
-  // OCF: 0x0155
-  void HciBleVendor155(const std::vector<uint8_t>& args);
-
-  // OGF: 0x00FC
-  // OCF: 0x0157
-  void HciBleVendor157(const std::vector<uint8_t>& args);
-
-  // OGF: 0x00FC
-  // OCF: 0x0159
-  void HciBleEnergyInfo(const std::vector<uint8_t>& args);
-
-  // Test
-  void HciBleAdvertisingFilter(const std::vector<uint8_t>& args);
-
-  // OGF: 0x00FC
-  // OCF: 0x015A
-  void HciBleExtendedScanParams(const std::vector<uint8_t>& args);
-
-  // Test Channel commands:
-
-  // Add devices
-  void TestChannelAdd(const std::vector<std::string>& args);
-
-  // Remove devices by index
-  void TestChannelDel(const std::vector<std::string>& args);
-
-  // List the devices that the controller knows about
-  void TestChannelList(const std::vector<std::string>& args) const;
-
-  void Connections();
-
-  void LeScan();
-
-  void PageScan();
-
-  void HandleTimerTick();
-  void SetTimerPeriod(std::chrono::milliseconds new_period);
-  void StartTimer();
-  void StopTimer();
-
- private:
-  // Current link layer state of the controller.
-  enum State {
-    kStandby,  // Not receiving/transmitting any packets from/to other devices.
-    kInquiry,  // The controller is discovering other nearby devices.
-  };
-
-  // Set a timer for a future action
-  void AddControllerEvent(std::chrono::milliseconds,
-                          const TaskCallback& callback);
-
-  void AddConnectionAction(const TaskCallback& callback, uint16_t handle);
-
-  // Creates a command complete event and sends it back to the HCI.
-  void SendCommandComplete(uint16_t command_opcode,
-                           const std::vector<uint8_t>& return_parameters) const;
-
-  // Sends a command complete event with no return parameters. This event is
-  // typically sent for commands that can be completed immediately.
-  void SendCommandCompleteSuccess(uint16_t command_opcode) const;
-
-  // Sends a command complete event with no return parameters. This event is
-  // typically sent for commands that can be completed immediately.
-  void SendCommandCompleteOnlyStatus(uint16_t command_opcode,
-                                     uint8_t status) const;
-
-  // Creates a command status event and sends it back to the HCI.
-  void SendCommandStatus(uint8_t status, uint16_t command_opcode) const;
-
-  // Sends a command status event with default event parameters.
-  void SendCommandStatusSuccess(uint16_t command_opcode) const;
-
-  void SetEventDelay(int64_t delay);
-
-  // Callbacks to schedule tasks.
-  std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)>
-      schedule_task_;
-  std::function<AsyncTaskId(std::chrono::milliseconds,
-                            std::chrono::milliseconds, const TaskCallback&)>
-      schedule_periodic_task_;
-
-  std::function<void(AsyncTaskId)> cancel_task_;
-
-  // Callbacks to send packets back to the HCI.
-  std::function<void(std::unique_ptr<AclPacket>)> send_acl_;
-  std::function<void(std::unique_ptr<EventPacket>)> send_event_;
-  std::function<void(std::unique_ptr<ScoPacket>)> send_sco_;
-
-  // Maintains the commands to be registered and used in the HciHandler object.
-  // Keys are command opcodes and values are the callbacks to handle each
-  // command.
-  std::unordered_map<uint16_t, std::function<void(const std::vector<uint8_t>&)>>
-      active_hci_commands_;
-
-  std::unordered_map<std::string,
-                     std::function<void(const std::vector<std::string>&)>>
-      active_test_channel_commands_;
-
-  // Specifies the format of Inquiry Result events to be returned during the
-  // Inquiry command.
-  // 0x00: Standard Inquiry Result event format (default).
-  // 0x01: Inquiry Result format with RSSI.
-  // 0x02 Inquiry Result with RSSI format or Extended Inquiry Result format.
-  // 0x03-0xFF: Reserved.
-  uint8_t inquiry_mode_;
-
-  bool inquiry_responses_limited_;
-  uint8_t inquiry_num_responses_;
-  uint8_t inquiry_lap_[3];
-
-  std::vector<uint8_t> le_event_mask_;
-
-  BtAddress le_random_address_;
-
-  uint8_t le_scan_type_;
-  uint16_t le_scan_interval_;
-  uint16_t le_scan_window_;
-  uint8_t own_address_type_;
-  uint8_t scanning_filter_policy_;
-
-  uint8_t le_scan_enable_;
-  uint8_t filter_duplicates_;
-
-  bool le_connect_;
-  uint8_t initiator_filter_policy_;
-
-  BtAddress peer_address_;
-  uint8_t peer_address_type_;
-
-  uint8_t loopback_mode_;
-
-  State state_;
-
-  DeviceProperties properties_;
-
-  std::vector<std::shared_ptr<Device>> devices_;
-
-  std::vector<AsyncTaskId> controller_events_;
-
-  std::vector<std::shared_ptr<Connection>> connections_;
-
-  AsyncTaskId timer_tick_task_;
-  std::chrono::milliseconds timer_period_ = std::chrono::milliseconds(100);
-
-  DualModeController(const DualModeController& cmdPckt) = delete;
-  DualModeController& operator=(const DualModeController& cmdPckt) = delete;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/event_packet.h b/vendor_libs/test_vendor_lib/include/event_packet.h
deleted file mode 100644
index f861c07..0000000
--- a/vendor_libs/test_vendor_lib/include/event_packet.h
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "bt_address.h"
-#include "packet.h"
-
-namespace test_vendor_lib {
-
-// Event Packets are specified in the Bluetooth Core Specification Version 4.2,
-// Volume 2, Part E, Section 5.4.4
-class EventPacket : public Packet {
- public:
-  virtual ~EventPacket() override = default;
-
-  uint8_t GetEventCode() const;
-
-  // Static functions for creating event packets:
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.1
-  static std::unique_ptr<EventPacket> CreateInquiryCompleteEvent(
-      uint8_t status);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.14
-  // This should only be used for testing to send non-standard packets
-  // Most code should use the more specific functions that follow
-  static std::unique_ptr<EventPacket> CreateCommandCompleteEvent(
-      uint16_t command_opcode,
-      const std::vector<uint8_t>& event_return_parameters);
-
-  static std::unique_ptr<EventPacket> CreateCommandCompleteOnlyStatusEvent(
-      uint16_t command_opcode, uint8_t status);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.15
-  static std::unique_ptr<EventPacket> CreateCommandStatusEvent(
-      uint8_t status, uint16_t command_opcode);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.19
-  static std::unique_ptr<EventPacket> CreateNumberOfCompletedPacketsEvent(
-      uint16_t handle, uint16_t num_completed_packets);
-
-  void AddCompletedPackets(uint16_t handle, uint16_t num_completed_packets);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.10
-  static std::unique_ptr<EventPacket> CreateCommandCompleteDeleteStoredLinkKey(
-      uint8_t status, uint16_t num_keys_deleted);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.12
-  static std::unique_ptr<EventPacket> CreateCommandCompleteReadLocalName(
-      uint8_t status, const std::string& local_name);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.1
-  static std::unique_ptr<EventPacket>
-  CreateCommandCompleteReadLocalVersionInformation(uint8_t status,
-                                                   uint8_t hci_version,
-                                                   uint16_t hci_revision,
-                                                   uint8_t lmp_pal_version,
-                                                   uint16_t manufacturer_name,
-                                                   uint16_t lmp_pal_subversion);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.2
-  static std::unique_ptr<EventPacket>
-  CreateCommandCompleteReadLocalSupportedCommands(
-      uint8_t status, const std::vector<uint8_t>& supported_commands);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.4
-  static std::unique_ptr<EventPacket>
-  CreateCommandCompleteReadLocalExtendedFeatures(
-      uint8_t status, uint8_t page_number, uint8_t maximum_page_number,
-      uint64_t extended_lmp_features);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.5
-  static std::unique_ptr<EventPacket> CreateCommandCompleteReadBufferSize(
-      uint8_t status, uint16_t hc_acl_data_packet_length,
-      uint8_t hc_synchronous_data_packet_length,
-      uint16_t hc_total_num_acl_data_packets,
-      uint16_t hc_total_synchronous_data_packets);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.6
-  static std::unique_ptr<EventPacket> CreateCommandCompleteReadBdAddr(
-      uint8_t status, const BtAddress& bt_address);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.8
-  static std::unique_ptr<EventPacket>
-  CreateCommandCompleteReadLocalSupportedCodecs(
-      uint8_t status, const std::vector<uint8_t>& supported_codecs,
-      const std::vector<uint32_t>& vendor_specific_codecs);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.6.1
-  static std::unique_ptr<EventPacket> CreateCommandCompleteReadLoopbackMode(
-      uint8_t status, uint8_t mode);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.2
-  static std::unique_ptr<EventPacket> CreateInquiryResultEvent();
-
-  // Returns true if the result can be added to the event packet.
-  bool AddInquiryResult(const BtAddress& bt_address,
-                        uint8_t page_scan_repetition_mode,
-                        uint32_t class_of_device, uint16_t clock_offset);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.3
-  static std::unique_ptr<EventPacket> CreateConnectionCompleteEvent(
-      uint8_t status, uint16_t handle, const BtAddress& address,
-      uint8_t link_type, bool encryption_enabled);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.25
-  static std::unique_ptr<EventPacket> CreateLoopbackCommandEvent(
-      uint16_t opcode, const std::vector<uint8_t>& payload);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.38
-  static std::unique_ptr<EventPacket> CreateExtendedInquiryResultEvent(
-      const BtAddress& bt_address, uint8_t page_scan_repetition_mode,
-      uint32_t class_of_device, uint16_t clock_offset, uint8_t rssi,
-      const std::vector<uint8_t>& extended_inquiry_response);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
-  // 7.7.65.1
-  static std::unique_ptr<EventPacket> CreateLeConnectionCompleteEvent(
-      uint8_t status, uint16_t handle, uint8_t role, uint8_t peer_address_type,
-      const BtAddress& peer, uint16_t interval, uint16_t latency,
-      uint16_t supervision_timeout);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
-  // 7.7.65.2
-  static std::unique_ptr<EventPacket> CreateLeAdvertisingReportEvent();
-
-  // Returns true if the report can be added to the event packet.
-  bool AddLeAdvertisingReport(uint8_t event_type, uint8_t addr_type,
-                              const BtAddress& addr,
-                              const std::vector<uint8_t>& data, uint8_t rssi);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
-  // 7.7.65.4
-  static std::unique_ptr<EventPacket> CreateLeRemoteUsedFeaturesEvent(
-      uint8_t status, uint16_t handle, uint64_t features);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.2
-  static std::unique_ptr<EventPacket> CreateCommandCompleteLeReadBufferSize(
-      uint8_t status, uint16_t hc_le_data_packet_length,
-      uint8_t hc_total_num_le_data_packets);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.3
-  static std::unique_ptr<EventPacket>
-  CreateCommandCompleteLeReadLocalSupportedFeatures(uint8_t status,
-                                                    uint64_t le_features);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.14
-  static std::unique_ptr<EventPacket> CreateCommandCompleteLeReadWhiteListSize(
-      uint8_t status, uint8_t white_list_size);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.23
-  static std::unique_ptr<EventPacket> CreateCommandCompleteLeRand(
-      uint8_t status, uint64_t random_val);
-
-  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.27
-  static std::unique_ptr<EventPacket>
-  CreateCommandCompleteLeReadSupportedStates(uint8_t status,
-                                             uint64_t le_states);
-
-  // Vendor-specific commands (see hcidefs.h)
-
-  static std::unique_ptr<EventPacket> CreateCommandCompleteLeVendorCap(
-      uint8_t status, const std::vector<uint8_t>& vendor_cap);
-
-  // Size of a data packet header, which consists of a 1 octet event code
-  static const size_t kEventHeaderSize = 1;
-
- private:
-  explicit EventPacket(uint8_t event_code);
-  EventPacket(uint8_t event_code, const std::vector<uint8_t>& payload);
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/hci.h b/vendor_libs/test_vendor_lib/include/hci.h
new file mode 100644
index 0000000..11eb029
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/hci.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+#include <cstdint>
+
+#include "include/hci/event_code.h"
+#include "include/hci/le_sub_event_code.h"
+#include "include/hci/op_code.h"
+#include "include/hci/status.h"
+
+namespace test_vendor_lib {
+namespace hci {
+
+enum class PacketType : uint8_t {
+  UNKNOWN = 0,
+  COMMAND = 1,
+  ACL = 2,
+  SCO = 3,
+  EVENT = 4,
+};
+
+enum class LinkType : uint8_t {
+  SCO = 0x00,
+  ACL = 0x01,
+  ESCO = 0x02,
+};
+
+enum class LoopbackMode : uint8_t {
+  NO = 0x00,
+  LOCAL = 0x01,
+  REMOTE = 0x02,
+};
+
+/* HCI, PAL, and LMP Version numbers are the same */
+enum class Version : uint8_t {
+  V1_0 = 0,
+  V1_1 = 1,
+  V1_2 = 2,
+  V2_0 = 3,
+  V2_1 = 4,
+  V3_0 = 5,
+  V4_0 = 6,
+  V4_1 = 7,
+  V4_2 = 8,
+  V5_0 = 9,
+};
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/hci/event_code.h b/vendor_libs/test_vendor_lib/include/hci/event_code.h
new file mode 100644
index 0000000..c0bdcbc
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/hci/event_code.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+#include <cstdint>
+
+namespace test_vendor_lib {
+namespace hci {
+
+enum class EventCode : uint8_t {
+  INQUIRY_COMPLETE = 0x01,
+  INQUIRY_RESULT = 0x02,
+  CONNECTION_COMPLETE = 0x03,
+  CONNECTION_REQUEST = 0x04,
+  DISCONNECTION_COMPLETE = 0x05,
+  AUTHENTICATION_COMPLETE = 0x06,
+  REMOTE_NAME_REQUEST_COMPLETE = 0x07,
+  ENCRYPTION_CHANGE = 0x08,
+  CHANGE_CONNECTION_LINK_KEY_COMPLETE = 0x09,
+  MASTER_LINK_KEY_COMPLETE = 0x0A,
+  READ_REMOTE_SUPPORTED_FEATURES_COMPLETE = 0x0B,
+  READ_REMOTE_VERSION_INFORMATION_COMPLETE = 0x0C,
+  QOS_SETUP_COMPLETE = 0x0D,
+  COMMAND_COMPLETE = 0x0E,
+  COMMAND_STATUS = 0x0F,
+  HARDWARE_ERROR = 0x10,
+  FLUSH_OCCURED = 0x11,
+  ROLE_CHANGE = 0x12,
+  NUMBER_OF_COMPLETED_PACKETS = 0x13,
+  MODE_CHANGE = 0x14,
+  RETURN_LINK_KEYS = 0x15,
+  PIN_CODE_REQUEST = 0x16,
+  LINK_KEY_REQUEST = 0x17,
+  LINK_KEY_NOTIFICATION = 0x18,
+  LOOPBACK_COMMAND = 0x19,
+  DATA_BUFFER_OVERFLOW = 0x1A,
+  MAX_SLOTS_CHANGE = 0x1B,
+  READ_CLOCK_OFFSET_COMPLETE = 0x1C,
+  CONNECTION_PACKET_TYPE_CHANGE = 0x1D,
+  QOS_VIOLATION = 0x1E,
+  PAGE_SCAN_REPETITION_MODE_CHANGE = 0x20,
+  FLOW_SPECIFICATION_COMPLETE = 0x21,
+  INQUIRY_RESULT_WITH_RSSI = 0x22,
+  READ_REMOTE_EXTENDED_FEATURES_COMPLETE = 0x23,
+  SYNCHRONOUS_CONNECTION_COMPLETE = 0x2C,
+  SYNCHRONOUS_CONNECTION_CHANGED = 0x2D,
+  SNIFF_SUBRATING = 0x2E,
+  EXTENDED_INQUIRY_RESULT = 0x2F,
+  ENCRYPTION_KEY_REFRESH_COMPLETE = 0x30,
+  IO_CAPABILITY_REQUEST = 0x31,
+  IO_CAPABILITY_RESPONSE = 0x32,
+  USER_CONFIRMATION_REQUEST = 0x33,
+  USER_PASSKEY_REQUEST = 0x34,
+  REMOTE_OOB_DATA_REQUEST = 0x35,
+  SIMPLE_PAIRING_COMPLETE = 0x36,
+  LINK_SUPERVISION_TIMEOUT_CHANGED = 0x38,
+  ENHANCED_FLUSH_COMPLETE = 0x39,
+  USER_PASSKEY_NOTIFICATION = 0x3B,
+  KEYPRESS_NOTIFICATION = 0x3C,
+  REMOTE_HOST_SUPPORTED_FEATURES_NOTIFICATION = 0x3D,
+  LE_META_EVENT = 0x3e,
+  PHYSICAL_LINK_COMPLETE = 0x40,
+  CHANNEL_SELECTED = 0x41,
+  DISCONNECTION_PHYSICAL_LINK_COMPLETE = 0x42,
+  PHYSICAL_LINK_LOSS_EARLY_WARNING = 0x43,
+  PHYSICAL_LINK_RECOVERY = 0x44,
+  LOGICAL_LINK_COMPLETE = 0x45,
+  DISCONNECTION_LOGICAL_LINK_COMPLETE = 0x46,
+  FLOW_SPEC_MODIFY_COMPLETE = 0x47,
+  NUMBER_OF_COMPLETED_DATA_BLOCKS = 0x48,
+  SHORT_RANGE_MODE_CHANGE_COMPLETE = 0x4C,
+};
+}
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/hci/le_sub_event_code.h b/vendor_libs/test_vendor_lib/include/hci/le_sub_event_code.h
new file mode 100644
index 0000000..42edecd
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/hci/le_sub_event_code.h
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+#include <cstdint>
+
+namespace test_vendor_lib {
+namespace hci {
+
+enum class LeSubEventCode : uint8_t {
+  CONNECTION_COMPLETE = 0x01,
+  ADVERTISING_REPORT = 0x02,
+  CONNECTION_UPDATE_COMPLETE = 0x03,
+  READ_REMOTE_FEATURES_COMPLETE = 0x04,
+  LONG_TERM_KEY_REQUEST = 0x05,
+  REMOTE_CONNECTION_PARAMETER_REQUEST = 0x06,
+  DATA_LENGTH_CHANGE = 0x07,
+  ENHANCED_CONNECTION_COMPLETE = 0x0a,
+  DIRECTED_ADVERTISING_REPORT = 0x0b,
+  PHY_UPDATE_COMPLETE = 0x0c,
+  EXTENDED_ADVERTISING_REPORT = 0x0D,
+  PERIODIC_ADVERTISING_SYNC_ESTABLISHED = 0x0E,
+  PERIODIC_ADVERTISING_REPORT = 0x0F,
+  PERIODIC_ADVERTISING_SYNC_LOST = 0x10,
+  SCAN_TIMEOUT = 0x11,
+  ADVERTISING_SET_TERMINATED = 0x12,
+  SCAN_REQUEST_RECEIVED = 0x13,
+};
+}
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/hci/op_code.h b/vendor_libs/test_vendor_lib/include/hci/op_code.h
new file mode 100644
index 0000000..931145d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/hci/op_code.h
@@ -0,0 +1,281 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+#include <cstdint>
+
+namespace test_vendor_lib {
+namespace hci {
+
+using CommandGroups = enum {
+  LINK_CONTROL = 0x01 << 10,             /* 0x0400 */
+  LINK_POLICY = 0x02 << 10,              /* 0x0800 */
+  CONTROLLER_AND_BASEBAND = 0x03 << 10,  /* 0x0C00 */
+  INFORMATIONAL_PARAMETERS = 0x04 << 10, /* 0x1000 */
+  STATUS_PARAMETERS = 0x05 << 10,        /* 0x1400 */
+  TESTING = 0x06 << 10,                  /* 0x1800 */
+  LE_CONTROLLER = 0x08 << 10,            /* 0x2000 */
+  VENDOR_SPECIFIC = 0x3F << 10,          /* 0xFC00 */
+};
+
+enum class OpCode : uint16_t {
+  NONE = 0x0000,
+
+  /* LINK_CONTROL */
+  INQUIRY = LINK_CONTROL | 0x0001,
+  INQUIRY_CANCEL = LINK_CONTROL | 0x0002,
+  PERIODIC_INQUIRY_MODE = LINK_CONTROL | 0x0003,
+  EXIT_PERIODIC_INQUIRY_MODE = LINK_CONTROL | 0x0004,
+  CREATE_CONNECTION = LINK_CONTROL | 0x0005,
+  DISCONNECT = LINK_CONTROL | 0x0006,
+  CREATE_CONNECTION_CANCEL = LINK_CONTROL | 0x0008,
+  ACCEPT_CONNECTION_REQUEST = LINK_CONTROL | 0x0009,
+  REJECT_CONNECTION_REQUEST = LINK_CONTROL | 0x000A,
+  LINK_KEY_REQUEST_REPLY = LINK_CONTROL | 0x000B,
+  LINK_KEY_REQUEST_NEGATIVE_REPLY = LINK_CONTROL | 0x000C,
+  PIN_CODE_REQUEST_REPLY = LINK_CONTROL | 0x000D,
+  PIN_CODE_REQUEST_NEGATIVE_REPLY = LINK_CONTROL | 0x000E,
+  CHANGE_CONNECTION_PACKET_TYPE = LINK_CONTROL | 0x000F,
+  AUTHENTICATION_REQUESTED = LINK_CONTROL | 0x0011,
+  SET_CONNECTION_ENCRYPTION = LINK_CONTROL | 0x0013,
+  CHANGE_CONNECTION_LINK_KEY = LINK_CONTROL | 0x0015,
+  MASTER_LINK_KEY = LINK_CONTROL | 0x0017,
+  REMOTE_NAME_REQUEST = LINK_CONTROL | 0x0019,
+  REMOTE_NAME_REQUEST_CANCEL = LINK_CONTROL | 0x001A,
+  READ_REMOTE_SUPPORTED_FEATURES = LINK_CONTROL | 0x001B,
+  READ_REMOTE_EXTENDED_FEATURES = LINK_CONTROL | 0x001C,
+  READ_REMOTE_VERSION_INFORMATION = LINK_CONTROL | 0x001D,
+  READ_CLOCK_OFFSET = LINK_CONTROL | 0x001F,
+  READ_LMP_HANDLE = LINK_CONTROL | 0x0020,
+  SETUP_SYNCHRONOUS_CONNECTION = LINK_CONTROL | 0x0028,
+  ACCEPT_SYNCHRONOUS_CONNECTION = LINK_CONTROL | 0x0029,
+  REJECT_SYNCHRONOUS_CONNECTION = LINK_CONTROL | 0x002A,
+  IO_CAPABILITY_REQUEST_REPLY = LINK_CONTROL | 0x002B,
+  USER_CONFIRMATION_REQUEST_REPLY = LINK_CONTROL | 0x002C,
+  USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY = LINK_CONTROL | 0x002D,
+  USER_PASSKEY_REQUEST_REPLY = LINK_CONTROL | 0x002E,
+  USER_PASSKEY_REQUEST_NEGATIVE_REPLY = LINK_CONTROL | 0x002F,
+  REMOTE_OOB_DATA_REQUEST_REPLY = LINK_CONTROL | 0x0030,
+  REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY = LINK_CONTROL | 0x0033,
+  IO_CAPABILITY_REQUEST_NEGATIVE_REPLY = LINK_CONTROL | 0x0034,
+  ENHANCED_SETUP_SYNCHRONOUS_CONNECTION = LINK_CONTROL | 0x003D,
+  ENHANCED_ACCEPT_SYNCHRONOUS_CONNECTION = LINK_CONTROL | 0x003E,
+
+  /* LINK_POLICY */
+  HOLD_MODE = LINK_POLICY | 0x0001,
+  SNIFF_MODE = LINK_POLICY | 0x0003,
+  EXIT_SNIFF_MODE = LINK_POLICY | 0x0004,
+  QOS_SETUP = LINK_POLICY | 0x0007,
+  ROLE_DISCOVERY = LINK_POLICY | 0x0009,
+  SWITCH_ROLE = LINK_POLICY | 0x000B,
+  READ_LINK_POLICY_SETTINGS = LINK_POLICY | 0x000C,
+  WRITE_LINK_POLICY_SETTINGS = LINK_POLICY | 0x000D,
+  READ_DEFAULT_LINK_POLICY_SETTINGS = LINK_POLICY | 0x000E,
+  WRITE_DEFAULT_LINK_POLICY_SETTINGS = LINK_POLICY | 0x000F,
+  FLOW_SPECIFICATION = LINK_POLICY | 0x0010,
+  SNIFF_SUBRATING = LINK_POLICY | 0x0011,
+
+  /* CONTROLLER_AND_BASEBAND */
+  SET_EVENT_MASK = CONTROLLER_AND_BASEBAND | 0x0001,
+  RESET = CONTROLLER_AND_BASEBAND | 0x0003,
+  SET_EVENT_FILTER = CONTROLLER_AND_BASEBAND | 0x0005,
+  FLUSH = CONTROLLER_AND_BASEBAND | 0x0008,
+  READ_PIN_TYPE = CONTROLLER_AND_BASEBAND | 0x0009,
+  WRITE_PIN_TYPE = CONTROLLER_AND_BASEBAND | 0x000A,
+  CREATE_NEW_UNIT_KEY = CONTROLLER_AND_BASEBAND | 0x000B,
+  READ_STORED_LINK_KEY = CONTROLLER_AND_BASEBAND | 0x000D,
+  WRITE_STORED_LINK_KEY = CONTROLLER_AND_BASEBAND | 0x0011,
+  DELETE_STORED_LINK_KEY = CONTROLLER_AND_BASEBAND | 0x0012,
+  WRITE_LOCAL_NAME = CONTROLLER_AND_BASEBAND | 0x0013,
+  READ_LOCAL_NAME = CONTROLLER_AND_BASEBAND | 0x0014,
+  READ_CONNECTION_ACCEPT_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0015,
+  WRITE_CONNECTION_ACCEPT_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0016,
+  READ_PAGE_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0017,
+  WRITE_PAGE_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0018,
+  READ_SCAN_ENABLE = CONTROLLER_AND_BASEBAND | 0x0019,
+  WRITE_SCAN_ENABLE = CONTROLLER_AND_BASEBAND | 0x001A,
+  READ_PAGE_SCAN_ACTIVITY = CONTROLLER_AND_BASEBAND | 0x001B,
+  WRITE_PAGE_SCAN_ACTIVITY = CONTROLLER_AND_BASEBAND | 0x001C,
+  READ_INQUIRY_SCAN_ACTIVITY = CONTROLLER_AND_BASEBAND | 0x001D,
+  WRITE_INQUIRY_SCAN_ACTIVITY = CONTROLLER_AND_BASEBAND | 0x001E,
+  READ_AUTHENTICATION_ENABLE = CONTROLLER_AND_BASEBAND | 0x001F,
+  WRITE_AUTHENTICATION_ENABLE = CONTROLLER_AND_BASEBAND | 0x0020,
+  READ_CLASS_OF_DEVICE = CONTROLLER_AND_BASEBAND | 0x0023,
+  WRITE_CLASS_OF_DEVICE = CONTROLLER_AND_BASEBAND | 0x0024,
+  READ_VOICE_SETTING = CONTROLLER_AND_BASEBAND | 0x0025,
+  WRITE_VOICE_SETTING = CONTROLLER_AND_BASEBAND | 0x0026,
+  READ_AUTOMATIC_FLUSH_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0027,
+  WRITE_AUTOMATIC_FLUSH_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0028,
+  READ_NUM_BROADCAST_RETRANSMITS = CONTROLLER_AND_BASEBAND | 0x0029,
+  WRITE_NUM_BROADCAST_RETRANSMITS = CONTROLLER_AND_BASEBAND | 0x002A,
+  READ_HOLD_MODE_ACTIVITY = CONTROLLER_AND_BASEBAND | 0x002B,
+  WRITE_HOLD_MODE_ACTIVITY = CONTROLLER_AND_BASEBAND | 0x002C,
+  READ_TRANSMIT_POWER_LEVEL = CONTROLLER_AND_BASEBAND | 0x002D,
+  READ_SYNCHRONOUS_FLOW_CONTROL_ENABLE = CONTROLLER_AND_BASEBAND | 0x002E,
+  WRITE_SYNCHRONOUS_FLOW_CONTROL_ENABLE = CONTROLLER_AND_BASEBAND | 0x002F,
+  SET_CONTROLLER_TO_HOST_FLOW_CONTROL = CONTROLLER_AND_BASEBAND | 0x0031,
+  HOST_BUFFER_SIZE = CONTROLLER_AND_BASEBAND | 0x0033,
+  HOST_NUM_COMPLETED_PACKETS = CONTROLLER_AND_BASEBAND | 0x0035,
+  READ_LINK_SUPERVISION_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0036,
+  WRITE_LINK_SUPERVISION_TIMEOUT = CONTROLLER_AND_BASEBAND | 0x0037,
+  READ_NUMBER_OF_SUPPORTED_IAC = CONTROLLER_AND_BASEBAND | 0x0038,
+  READ_CURRENT_IAC_LAP = CONTROLLER_AND_BASEBAND | 0x0039,
+  WRITE_CURRENT_IAC_LAP = CONTROLLER_AND_BASEBAND | 0x003A,
+  SET_AFH_HOST_CHANNEL_CLASSIFICATION = CONTROLLER_AND_BASEBAND | 0x003F,
+  READ_LE_HOST_SUPPORT = CONTROLLER_AND_BASEBAND | 0x6C,
+  WRITE_LE_HOST_SUPPORT = CONTROLLER_AND_BASEBAND | 0x6D,
+  READ_INQUIRY_SCAN_TYPE = CONTROLLER_AND_BASEBAND | 0x0042,
+  WRITE_INQUIRY_SCAN_TYPE = CONTROLLER_AND_BASEBAND | 0x0043,
+  READ_INQUIRY_MODE = CONTROLLER_AND_BASEBAND | 0x0044,
+  WRITE_INQUIRY_MODE = CONTROLLER_AND_BASEBAND | 0x0045,
+  READ_PAGE_SCAN_TYPE = CONTROLLER_AND_BASEBAND | 0x0046,
+  WRITE_PAGE_SCAN_TYPE = CONTROLLER_AND_BASEBAND | 0x0047,
+  READ_AFH_CHANNEL_ASSESSMENT_MODE = CONTROLLER_AND_BASEBAND | 0x0048,
+  WRITE_AFH_CHANNEL_ASSESSMENT_MODE = CONTROLLER_AND_BASEBAND | 0x0049,
+  READ_EXTENDED_INQUIRY_RESPONSE = CONTROLLER_AND_BASEBAND | 0x0051,
+  WRITE_EXTENDED_INQUIRY_RESPONSE = CONTROLLER_AND_BASEBAND | 0x0052,
+  REFRESH_ENCRYPTION_KEY = CONTROLLER_AND_BASEBAND | 0x0053,
+  READ_SIMPLE_PAIRING_MODE = CONTROLLER_AND_BASEBAND | 0x0055,
+  WRITE_SIMPLE_PAIRING_MODE = CONTROLLER_AND_BASEBAND | 0x0056,
+  READ_LOCAL_OOB_DATA = CONTROLLER_AND_BASEBAND | 0x0057,
+  READ_INQUIRY_RESPONSE_TRANSMIT_POWER_LEVEL = CONTROLLER_AND_BASEBAND | 0x0058,
+  WRITE_INQUIRY_TRANSMIT_POWER_LEVEL = CONTROLLER_AND_BASEBAND | 0x0059,
+  SEND_KEYPRESS_NOTIFICATION = CONTROLLER_AND_BASEBAND | 0x0060,
+
+  READ_SECURE_CONNECTIONS_HOST_SUPPORT = CONTROLLER_AND_BASEBAND | 0x0079,
+  WRITE_SECURE_CONNECTIONS_HOST_SUPPORT = CONTROLLER_AND_BASEBAND | 0x007A,
+
+  /* INFORMATIONAL_PARAMETERS */
+  READ_LOCAL_VERSION_INFORMATION = INFORMATIONAL_PARAMETERS | 0x0001,
+  READ_LOCAL_SUPPORTED_COMMANDS = INFORMATIONAL_PARAMETERS | 0x0002,
+  READ_LOCAL_SUPPORTED_FEATURES = INFORMATIONAL_PARAMETERS | 0x0003,
+  READ_LOCAL_EXTENDED_FEATURES = INFORMATIONAL_PARAMETERS | 0x0004,
+  READ_BUFFER_SIZE = INFORMATIONAL_PARAMETERS | 0x0005,
+  READ_BD_ADDR = INFORMATIONAL_PARAMETERS | 0x0009,
+  READ_DATA_BLOCK_SIZE = INFORMATIONAL_PARAMETERS | 0x000A,
+  READ_LOCAL_SUPPORTED_CODECS = INFORMATIONAL_PARAMETERS | 0x000B,
+
+  /* STATUS_PARAMETERS */
+  READ_FAILED_CONTACT_COUNTER = STATUS_PARAMETERS | 0x0001,
+  RESET_FAILED_CONTACT_COUNTER = STATUS_PARAMETERS | 0x0002,
+  READ_LINK_QUALITY = STATUS_PARAMETERS | 0x0003,
+  READ_RSSI = STATUS_PARAMETERS | 0x0005,
+  READ_AFH_CHANNEL_MAP = STATUS_PARAMETERS | 0x0006,
+  READ_CLOCK = STATUS_PARAMETERS | 0x0007,
+  READ_ENCRYPTION_KEY_SIZE = STATUS_PARAMETERS | 0x0008,
+
+  /* TESTING */
+  READ_LOOPBACK_MODE = TESTING | 0x0001,
+  WRITE_LOOPBACK_MODE = TESTING | 0x0002,
+  ENABLE_DEVICE_UNDER_TEST_MODE = TESTING | 0x0003,
+  WRITE_SIMPLE_PAIRING_DEBUG_MODE = TESTING | 0x0004,
+  WRITE_SECURE_CONNECTIONS_TEST_MODE = TESTING | 0x000A,
+
+  /* LE_CONTROLLER */
+  LE_SET_EVENT_MASK = LE_CONTROLLER | 0x0001,
+  LE_READ_BUFFER_SIZE = LE_CONTROLLER | 0x0002,
+  LE_READ_LOCAL_SUPPORTED_FEATURES = LE_CONTROLLER | 0x0003,
+  LE_WRITE_LOCAL_SUPPORTED_FEATURES = LE_CONTROLLER | 0x0004,
+  LE_SET_RANDOM_ADDRESS = LE_CONTROLLER | 0x0005,
+  LE_SET_ADVERTISING_PARAMETERS = LE_CONTROLLER | 0x0006,
+  LE_READ_ADVERTISING_CHANNEL_TX_POWER = LE_CONTROLLER | 0x0007,
+  LE_SET_ADVERTISING_DATA = LE_CONTROLLER | 0x0008,
+  LE_SET_SCAN_RSPONSE_DATA = LE_CONTROLLER | 0x0009,
+  LE_SET_ADVERTISING_ENABLE = LE_CONTROLLER | 0x000A,
+  LE_SET_SCAN_PARAMETERS = LE_CONTROLLER | 0x000B,
+  LE_SET_SCAN_ENABLE = LE_CONTROLLER | 0x000C,
+  LE_CREATE_CONNECTION = LE_CONTROLLER | 0x000D,
+  LE_CREATE_CONNECTION_CANCEL = LE_CONTROLLER | 0x000E,
+  LE_READ_WHITE_LIST_SIZE = LE_CONTROLLER | 0x000F,
+  LE_CLEAR_WHITE_LIST = LE_CONTROLLER | 0x0010,
+  LE_ADD_DEVICE_TO_WHITE_LIST = LE_CONTROLLER | 0x0011,
+  LE_REMOVE_DEVICE_FROM_WHITE_LIST = LE_CONTROLLER | 0x0012,
+  LE_CONNECTION_UPDATE = LE_CONTROLLER | 0x0013,
+  LE_SET_HOST_CHANNEL_CLASSIFICATION = LE_CONTROLLER | 0x0014,
+  LE_READ_CHANNEL_MAP = LE_CONTROLLER | 0x0015,
+  LE_READ_REMOTE_FEATURES = LE_CONTROLLER | 0x0016,
+  LE_ENCRYPT = LE_CONTROLLER | 0x0017,
+  LE_RAND = LE_CONTROLLER | 0x0018,
+  LE_START_ENCRYPTION = LE_CONTROLLER | 0x0019,
+  LE_LONG_TERM_KEY_REQUEST_REPLY = LE_CONTROLLER | 0x001A,
+  LE_LONG_TERM_KEY_REQUEST_NEGATIVE_REPLY = LE_CONTROLLER | 0x001B,
+  LE_READ_SUPPORTED_STATES = LE_CONTROLLER | 0x001C,
+  LE_RECEIVER_TEST = LE_CONTROLLER | 0x001D,
+  LE_TRANSMITTER_TEST = LE_CONTROLLER | 0x001E,
+  LE_TEST_END = LE_CONTROLLER | 0x001F,
+  LE_REMOTE_CONNECTION_PARAMETER_REQUEST_REPLY = LE_CONTROLLER | 0x0020,
+  LE_REMOTE_CONNECTION_PARAMETER_REQUEST_NEGATIVE_REPLY = LE_CONTROLLER | 0x0021,
+
+  LE_SET_DATA_LENGTH = LE_CONTROLLER | 0x0022,
+  LE_READ_SUGGESTED_DEFAULT_DATA_LENGTH = LE_CONTROLLER | 0x0023,
+  LE_WRITE_SUGGESTED_DEFAULT_DATA_LENGTH = LE_CONTROLLER | 0x0024,
+  LE_READ_LOCAL_P_256_PUBLIC_KEY_COMMAND = LE_CONTROLLER | 0x0025,
+  LE_GENERATE_DHKEY_COMMAND = LE_CONTROLLER | 0x0026,
+  LE_ADD_DEVICE_TO_RESOLVING_LIST = LE_CONTROLLER | 0x0027,
+  LE_REMOVE_DEVICE_FROM_RESOLVING_LIST = LE_CONTROLLER | 0x0028,
+  LE_CLEAR_RESOLVING_LIST = LE_CONTROLLER | 0x0029,
+  LE_READ_RESOLVING_LIST_SIZE = LE_CONTROLLER | 0x002A,
+  LE_READ_PEER_RESOLVABLE_ADDRESS = LE_CONTROLLER | 0x002B,
+  LE_READ_LOCAL_RESOLVABLE_ADDRESS = LE_CONTROLLER | 0x002C,
+  LE_SET_ADDRESS_RESOLUTION_ENABLE = LE_CONTROLLER | 0x002D,
+  LE_SET_RESOLVABLE_PRIVATE_ADDRESS_TIMEOUT = LE_CONTROLLER | 0x002E,
+  LE_READ_MAXIMUM_DATA_LENGTH = LE_CONTROLLER | 0x002F,
+  LE_READ_PHY = LE_CONTROLLER | 0x0030,
+  LE_SET_DEFAULT_PHY = LE_CONTROLLER | 0x0031,
+  LE_SET_PHY = LE_CONTROLLER | 0x0032,
+  LE_ENHANCED_RECEIVER_TEST = LE_CONTROLLER | 0x0033,
+  LE_ENHANCED_TRANSMITTER_TEST = LE_CONTROLLER | 0x0034,
+  LE_SET_EXTENDED_ADVERTISING_RANDOM_ADDRESS = LE_CONTROLLER | 0x35,
+  LE_SET_EXTENDED_ADVERTISING_PARAMETERS = LE_CONTROLLER | 0x36,
+  LE_SET_EXTENDED_ADVERTISING_DATA = LE_CONTROLLER | 0x37,
+  LE_SET_EXTENDED_ADVERTISING_SCAN_RESPONSE = LE_CONTROLLER | 0x38,
+  LE_SET_EXTENDED_ADVERTISING_ENABLE = LE_CONTROLLER | 0x39,
+  LE_READ_MAXIMUM_ADVERTISING_DATA_LENGTH = LE_CONTROLLER | 0x003A,
+  LE_READ_NUMBER_OF_SUPPORTED_ADVERTISING_SETS = LE_CONTROLLER | 0x003B,
+  LE_REMOVE_ADVERTISING_SET = LE_CONTROLLER | 0x003C,
+  LE_CLEAR_ADVERTISING_SETS = LE_CONTROLLER | 0x003D,
+  LE_SET_PERIODIC_ADVERTISING_PARAM = LE_CONTROLLER | 0x003E,
+  LE_SET_PERIODIC_ADVERTISING_DATA = LE_CONTROLLER | 0x003F,
+  LE_SET_PERIODIC_ADVERTISING_ENABLE = LE_CONTROLLER | 0x0040,
+  LE_SET_EXTENDED_SCAN_PARAMETERS = LE_CONTROLLER | 0x0041,
+  LE_SET_EXTENDED_SCAN_ENABLE = LE_CONTROLLER | 0x0042,
+  LE_EXTENDED_CREATE_CONNECTION = LE_CONTROLLER | 0x0043,
+  LE_PERIODIC_ADVERTISING_CREATE_SYNC = LE_CONTROLLER | 0x0044,
+  LE_PERIODIC_ADVERTISING_CREATE_SYNC_CANCEL = LE_CONTROLLER | 0x0045,
+  LE_PERIODIC_ADVERTISING_TERMINATE_SYNC = LE_CONTROLLER | 0x0046,
+  LE_ADD_DEVICE_TO_PERIODIC_ADVERTISING_LIST = LE_CONTROLLER | 0x0047,
+  LE_REMOVE_DEVICE_FROM_PERIODIC_ADVERTISING_LIST = LE_CONTROLLER | 0x0048,
+  LE_CLEAR_PERIODIC_ADVERTISING_LIST = LE_CONTROLLER | 0x0049,
+  LE_READ_PERIODIC_ADVERTISING_LIST_SIZE = LE_CONTROLLER | 0x004A,
+  LE_READ_TRANSMIT_POWER = LE_CONTROLLER | 0x004B,
+  LE_READ_RF_PATH_COMPENSATION_POWER = LE_CONTROLLER | 0x004C,
+  LE_WRITE_RF_PATH_COMPENSATION_POWER = LE_CONTROLLER | 0x004D,
+  LE_SET_PRIVACY_MODE = LE_CONTROLLER | 0x004E,
+
+  /* VENDOR_SPECIFIC */
+  LE_GET_VENDOR_CAPABILITIES = VENDOR_SPECIFIC | 0x0153,
+  LE_MULTI_ADVT = VENDOR_SPECIFIC | 0x0154,
+  LE_BATCH_SCAN = VENDOR_SPECIFIC | 0x0156,
+  LE_ADV_FILTER = VENDOR_SPECIFIC | 0x0157,
+  LE_TRACK_ADV = VENDOR_SPECIFIC | 0x0158,
+  LE_ENERGY_INFO = VENDOR_SPECIFIC | 0x0159,
+  LE_EXTENDED_SCAN_PARAMS = VENDOR_SPECIFIC | 0x015A,
+  CONTROLLER_DEBUG_INFO = VENDOR_SPECIFIC | 0x015B,
+  CONTROLLER_A2DP_OPCODE = VENDOR_SPECIFIC | 0x015D,
+};
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/hci/status.h b/vendor_libs/test_vendor_lib/include/hci/status.h
new file mode 100644
index 0000000..4452cfa
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/hci/status.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+#include <cstdint>
+
+namespace test_vendor_lib {
+namespace hci {
+
+enum class Status : uint8_t {
+  SUCCESS = 0,
+  UNKNOWN_COMMAND = 1,
+  UNKNOWN_CONNECTION = 2,
+  HARDWARE_FAILURE = 3,
+  PAGE_TIMEOUT = 4,
+  AUTHENTICATION_FAILURE = 5,
+  PIN_OR_KEY_MISSING = 6,
+  MEMORY_CAPACITY_EXCEEDED = 7,
+  CONNECTION_TIMEOUT = 8,
+  COMMAND_DISALLOWED = 0x0c,
+  CONNECTION_REJECTED_LIMITED_RESOURCES = 0x0d,
+  CONNECTION_REJECTED_SECURITY = 0x0e,
+  CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR = 0x0f,
+  INVALID_HCI_COMMAND_PARAMETERS = 0x12,
+  REMOTE_USER_TERMINATED_CONNECTION = 0x13,
+  CONNECTION_TERMINATED_BY_LOCAL_HOST = 0x16,
+  UNSPECIFIED_ERROR = 0x1f,
+  ENCRYPTION_MODE_NOT_ACCEPTABLE = 0x25,
+  HOST_BUSY_PAIRING = 0x38,
+  CONTROLLER_BUSY = 0x3a,
+};
+}
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/hci_packet.h b/vendor_libs/test_vendor_lib/include/hci_packet.h
deleted file mode 100644
index f7be08e..0000000
--- a/vendor_libs/test_vendor_lib/include/hci_packet.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#pragma once
-#include <iterator>
-#include <memory>
-#include <type_traits>
-
-#include "base/logging.h"
-
-namespace test_vendor_lib {
-
-// Iterator is a custom iterator class for HciPackets.
-class Iterator
-    : public std::iterator<std::random_access_iterator_tag, uint8_t> {
- public:
-  Iterator(std::shared_ptr<class HciPacket> packet, size_t i);
-  Iterator(const Iterator& itr);
-
-  ~Iterator() {}
-
-  operator bool() const;
-
-  // All addition and subtraction operators are bounded from 0 to the length of
-  // the packet.
-  Iterator operator+(size_t offset);
-  Iterator& operator+=(size_t offset);
-  Iterator operator++(int);
-  Iterator& operator++();
-
-  Iterator operator-(size_t offset);
-  int operator-(Iterator& itr);
-  Iterator& operator-=(size_t offset);
-  Iterator operator--(int);
-  Iterator& operator--();
-
-  Iterator& operator=(const Iterator& itr);
-
-  bool operator!=(Iterator& itr);
-  bool operator==(Iterator& itr);
-
-  bool operator<(Iterator& itr);
-  bool operator>(Iterator& itr);
-
-  bool operator<=(Iterator& itr);
-  bool operator>=(Iterator& itr);
-
-  uint8_t& operator*() const;
-  uint8_t* operator->() const;
-
-  // Get the next sizeof(FixedWidthIntegerType) bytes and return the filled type
-  template <typename FixedWidthIntegerType>
-  FixedWidthIntegerType extract() {
-    static_assert(std::is_integral<FixedWidthIntegerType>::value,
-                  "Iterator::extract requires an integral type.");
-    FixedWidthIntegerType extracted_value = 0;
-
-    for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
-      extracted_value |= static_cast<FixedWidthIntegerType>(**this) << i * 8;
-      (*this)++;
-    }
-
-    return extracted_value;
-  }
-
- private:
-  std::shared_ptr<class HciPacket> hci_packet_;
-  size_t index_;
-
-};  // Iterator
-
-// HciPacket is an abstract class that will serve as the base class for all
-// packet types.
-class HciPacket : public std::enable_shared_from_this<HciPacket> {
- public:
-  virtual ~HciPacket() = default;
-
-  Iterator get_begin();
-  Iterator get_end();
-
-  uint8_t operator[](size_t i);
-
-  virtual size_t get_length() = 0;
-
-  virtual uint8_t& get_at_index(size_t index) = 0;
-
-};  // HciPacket
-
-};  // namespace test_vendor_lib
diff --git a/tools/Android.bp b/vendor_libs/test_vendor_lib/include/inquiry.h
similarity index 61%
copy from tools/Android.bp
copy to vendor_libs/test_vendor_lib/include/inquiry.h
index 9f75ba7..f989af4 100644
--- a/tools/Android.bp
+++ b/vendor_libs/test_vendor_lib/include/inquiry.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,21 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+#pragma once
+
+namespace test_vendor_lib {
+
+class Inquiry {
+ public:
+  enum class InquiryState : uint8_t {
+    STANDBY = 0x00,
+    INQUIRY = 0x01,
+  };
+  enum class InquiryType : uint8_t {
+    STANDARD = 0x00,
+    RSSI = 0x01,
+    EXTENDED = 0x02,
+  };
+};
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/l2cap_packet.h b/vendor_libs/test_vendor_lib/include/l2cap_packet.h
deleted file mode 100644
index 1205ee1..0000000
--- a/vendor_libs/test_vendor_lib/include/l2cap_packet.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cmath>
-#include <cstdint>
-#include <iterator>
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "hci_packet.h"
-#include "l2cap_sdu.h"
-
-namespace test_vendor_lib {
-
-const int kSduHeaderLength = 4;
-
-class L2capPacket : public HciPacket {
- public:
-  // Returns an assembled L2cap object if successful, nullptr if failure.
-  static std::shared_ptr<L2capPacket> assemble(
-      const std::vector<std::shared_ptr<L2capSdu> >& sdu_packet);
-
-  // Returns a fragmented vector of L2capSdu objects if successful
-  // Returns an empty vector of L2capSdu objects if unsuccessful
-  std::vector<std::shared_ptr<L2capSdu> > fragment(uint16_t maximum_sdu_size,
-                                                   uint8_t txseq,
-                                                   uint8_t reqseq);
-
-  uint16_t get_l2cap_cid() const;
-
-  // HciPacket Functions
-  size_t get_length();
-  uint8_t& get_at_index(size_t index);
-
- private:
-  L2capPacket() = default;
-
-  // Entire L2CAP packet: length, CID, and payload in that order.
-  std::vector<uint8_t> l2cap_packet_;
-
-  DISALLOW_COPY_AND_ASSIGN(L2capPacket);
-
-  // Helper functions for fragmenting.
-  static void set_sdu_header_length(std::vector<uint8_t>& sdu, uint16_t length);
-
-  static void set_total_sdu_length(std::vector<uint8_t>& sdu,
-                                   uint16_t total_sdu_length);
-
-  static void set_sdu_cid(std::vector<uint8_t>& sdu, uint16_t cid);
-
-  static void set_sdu_control_bytes(std::vector<uint8_t>& sdu, uint8_t txseq,
-                                    uint8_t reqseq);
-
-  bool check_l2cap_packet() const;
-
-};  // L2capPacket
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/l2cap_sdu.h b/vendor_libs/test_vendor_lib/include/l2cap_sdu.h
deleted file mode 100644
index 489f001..0000000
--- a/vendor_libs/test_vendor_lib/include/l2cap_sdu.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-#include <cstdint>
-#include <iterator>
-#include <vector>
-
-#include "hci_packet.h"
-
-namespace test_vendor_lib {
-
-// Abstract representation of an SDU packet that contains an L2CAP
-// payload. This class is meant to be used in collaboration with
-// the L2cap class defined in l2cap.h. For example, an SDU packet
-// may look as follows:
-//
-// vector<uint8_t> sdu = {0x04, 0x00, 0x48, 0x00, 0x04, 0x00, 0xab,
-//                       0xcd, 0x78, 0x56}
-//
-// The first two bytes (in little endian) should be read as 0x0004
-// and is the length of the payload of the SDU packet.
-//
-// The next two bytes (also in little endian) are the channel ID
-// and should be read as 0x0048. These should remain the same for
-// any number of SDUs that are a part of the same packet stream.
-//
-// Following the CID bytes, are the total length bytes. Since this
-// SDU only requires a single packet, the length here is the same
-// as the length in the first two bytes of the packet. Again stored
-// in little endian.
-//
-// Next comes the two control bytes. These begin the L2CAP payload
-// of the SDU packet; however, they will not be added to the L2CAP
-// packet that is being constructed in the assemble function that
-// will be creating an L2CAP packet from a stream of L2capSdu
-// objects.
-//
-// The final two bytes are the frame check sequence that should be
-// calculated from the start of the vector to the end of the
-// payload.
-//
-// Thus, calling assemble on this example would create a
-// zero-length L2CAP packet because the information payload of the
-// L2CAP packet will not include either of the control or FCS
-// bytes.
-//
-class L2capSdu : public HciPacket {
- public:
-  // Returns a unique_ptr to an L2capSdu object that is constructed with the
-  // assumption that the SDU packet is complete and correct.
-  static std::shared_ptr<L2capSdu> L2capSduConstructor(
-      std::vector<uint8_t> create_from);
-
-  // Adds an FCS to create_from and returns a unique_ptr to an L2capSdu object.
-  static std::shared_ptr<L2capSdu> L2capSduBuilder(
-      std::vector<uint8_t> create_from);
-
-  // Get the FCS bytes from the end of the L2CAP payload of an SDU
-  // packet.
-  uint16_t get_fcs() const;
-
-  uint16_t get_payload_length() const;
-
-  uint16_t calculate_fcs() const;
-
-  // Get the two control bytes that begin the L2CAP payload. These
-  // bytes will contain information such as the Segmentation and
-  // Reassembly bits, and the TxSeq/ReqSeq numbers.
-  uint16_t get_controls() const;
-
-  uint16_t get_total_l2cap_length() const;
-
-  size_t get_vector_size() const;
-
-  uint16_t get_channel_id() const;
-
-  // Returns true if the SDU control sequence for Segmentation and
-  // Reassembly is 00b, false otherwise.
-  static bool is_complete_l2cap(const L2capSdu& sdu);
-
-  // Returns true if the SDU control sequence for Segmentation and
-  // Reassembly is 01b, false otherwise.
-  static bool is_starting_sdu(const L2capSdu& sdu);
-
-  // Returns true if the SDU control sequence for Segmentation and
-  // Reasembly is 10b, false otherwise.
-  static bool is_ending_sdu(const L2capSdu& sdu);
-
-  // HciPacket functions
-  size_t get_length();
-  uint8_t& get_at_index(size_t index);
-
- private:
-  // This is the SDU packet in bytes.
-  std::vector<uint8_t> sdu_data_;
-
-  // Returns a completed L2capSdu object.
-  L2capSdu(std::vector<uint8_t>&& create_from);
-
-  // Table for precalculated lfsr values.
-  static const uint16_t lfsr_table_[256];
-
-  uint16_t convert_from_little_endian(const unsigned int starting_index) const;
-
-};  // L2capSdu
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h b/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h
deleted file mode 100644
index 652ad34..0000000
--- a/vendor_libs/test_vendor_lib/include/l2cap_test_packets.h
+++ /dev/null
@@ -1,1446 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2017 Google, Inc.
- *
- *  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.
- *
- ******************************************************************************/
-#pragma once
-#include <cstdint>
-#include <vector>
-namespace {
-
-// Complete SDUs that should always assemble.
-std::vector<std::vector<uint8_t> > good_sdu = {
-    {0x0c, 0x00, 0x47, 0x00, 0x02, 0x41, 0x12, 0x00, 0x00, 0x01, 0x02, 0x03,
-     0x04, 0x05, 0xeb, 0x0f},
-
-    {0x0a, 0x00, 0x47, 0x00, 0x04, 0xc1, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
-     0x5a, 0x8a},
-
-    {0x0a, 0x00, 0x47, 0x00, 0x06, 0x81, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
-     0x68, 0x1e}};
-
-// The complete L2CAP packet that should be created by calling assemble on the
-// good_sdu vector.
-std::vector<uint8_t> good_l2cap_packet = {
-    0x12, 0x00, 0x47, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
-    0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11};
-
-// SDUs that are missing a payload.
-std::vector<std::vector<uint8_t> > empty_sdu_payload = {
-    {0x06, 0x00, 0x47, 0x00, 0x02, 0x41, 0x00, 0x00, 0xde, 0xf1},
-
-    {0x04, 0x00, 0x47, 0x00, 0x04, 0x81, 0xd7, 0x90}};
-
-// The l2cap packet that should be created by calling assemble on the
-// empty_sdu_payload vector.
-std::vector<uint8_t> empty_l2cap_payload = {0x00, 0x00, 0x47, 0x00};
-
-// SDUs that have all of the control bytes set to be the start of the SDU.
-std::vector<std::vector<uint8_t> > all_first_packet = {
-    {0x0c, 0x00, 0x47, 0x00, 0x02, 0x41, 0x18, 0x00, 0x00, 0x01, 0x02, 0x03,
-     0x04, 0x05, 0x6b, 0x70},
-
-    {0x0c, 0x00, 0x47, 0x00, 0x02, 0x41, 0x18, 0x00, 0x00, 0x01, 0x02, 0x03,
-     0x04, 0x05, 0x6b, 0x70},
-
-    {0x0c, 0x00, 0x47, 0x00, 0x02, 0x41, 0x18, 0x00, 0x00, 0x01, 0x02, 0x03,
-     0x04, 0x05, 0x6b, 0x70}};
-
-// A complete L2CAP packet that has not been segmented.
-std::vector<std::vector<uint8_t> > one_sdu = {{0x0b, 0x00, 0x47, 0x00, 0x02,
-                                               0x00, 0x01, 0x02, 0x03, 0x04,
-                                               0x05, 0x06, 0x07, 0x4a, 0x2f}};
-
-// l2cap_test_packet_[1-9] are SDUs that were extracted from snoop logs.
-std::vector<uint8_t> l2cap_test_packet_1 = {
-    0xf8, 0x03, 0x47, 0x00, 0x02, 0x41, 0x95, 0x1f, 0x02, 0x1f, 0x95, 0xcb,
-    0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x33, 0x00, 0x49, 0x00, 0x4d, 0x00,
-    0x47, 0x00, 0x5f, 0x00, 0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x37, 0x00,
-    0x30, 0x00, 0x36, 0x00, 0x30, 0x00, 0x36, 0x00, 0x5f, 0x00, 0x31, 0x00,
-    0x35, 0x00, 0x34, 0x00, 0x33, 0x00, 0x33, 0x00, 0x38, 0x00, 0x2e, 0x00,
-    0x6a, 0x00, 0x70, 0x00, 0x67, 0x00, 0x00, 0x42, 0x00, 0x0e, 0x69, 0x6d,
-    0x61, 0x67, 0x65, 0x2f, 0x6a, 0x70, 0x65, 0x67, 0x00, 0xc3, 0x00, 0x12,
-    0x30, 0x03, 0x97, 0x01, 0x48, 0x1f, 0x45, 0xff, 0xd8, 0xff, 0xe0, 0x00,
-    0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00,
-    0x01, 0x00, 0x00, 0xff, 0xe1, 0x2b, 0x18, 0x45, 0x78, 0x69, 0x66, 0x00,
-    0x00, 0x4d, 0x4d, 0x00, 0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x01,
-    0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0c, 0xc0, 0x01,
-    0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x90, 0x01,
-    0x0f, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x4c, 0x47, 0x45, 0x00, 0x01,
-    0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9e, 0x01,
-    0x12, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01,
-    0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x01,
-    0x1b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, 0x01,
-    0x28, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01,
-    0x31, 0x00, 0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xb6, 0x01,
-    0x32, 0x00, 0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xbd, 0x02,
-    0x13, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87,
-    0x69, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd2, 0x00,
-    0x00, 0x02, 0x78, 0x4e, 0x65, 0x78, 0x75, 0x73, 0x20, 0x35, 0x00, 0x00,
-    0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00,
-    0x00, 0x00, 0x01, 0x50, 0x69, 0x63, 0x61, 0x73, 0x61, 0x00, 0x32, 0x30,
-    0x31, 0x37, 0x3a, 0x30, 0x36, 0x3a, 0x30, 0x36, 0x20, 0x31, 0x35, 0x3a,
-    0x34, 0x33, 0x3a, 0x33, 0x38, 0x00, 0x00, 0x00, 0x15, 0x82, 0x9a, 0x00,
-    0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xd4, 0x82, 0x9d, 0x00,
-    0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0xdc, 0x88, 0x27, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x01, 0x02, 0x1f, 0x00, 0x00, 0x90, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x04, 0x30, 0x32, 0x32, 0x30, 0x90, 0x03, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0xe4, 0x90, 0x04, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x01, 0xf8, 0x91, 0x01, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x04, 0x01, 0x02, 0x03, 0x00, 0x92, 0x01, 0x00,
-    0x0a, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x0c, 0x92, 0x02, 0x00,
-    0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x14, 0x92, 0x09, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x92, 0x0a, 0x00,
-    0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x1c, 0x92, 0x90, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x24, 0x92, 0x91, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x2b, 0x92, 0x92, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x02, 0x32, 0xa0, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x00, 0x04, 0x30, 0x31, 0x30, 0x30, 0xa0, 0x01, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, 0x00,
-    0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x0a, 0x0a, 0xa0, 0x03, 0x00,
-    0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x07, 0x77, 0xa0, 0x05, 0x00,
-    0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x5a, 0xa4, 0x03, 0x00,
-    0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x20, 0x00,
-    0x02, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x00,
-    0x00, 0x01, 0xfc, 0x8c, 0xb2, 0x3b, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x00,
-    0xf0, 0x00, 0x00, 0x00, 0x64, 0x32, 0x30, 0x31, 0x37, 0x3a, 0x30, 0x36,
-    0x3a, 0x30, 0x36, 0x20, 0x31, 0x35, 0x3a, 0x34, 0x33, 0x3a, 0x33, 0x38,
-    0x00, 0x32, 0x30, 0x31, 0x37, 0x3a, 0x30, 0x36, 0x3a, 0x30, 0x36, 0x20,
-    0x31, 0x35, 0x3a, 0x34, 0x33, 0x3a, 0x33, 0x38, 0x00, 0xff, 0xff, 0xfe,
-    0x16, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
-    0x64, 0x00, 0x00, 0x0f, 0x82, 0x00, 0x00, 0x03, 0xe8, 0x39, 0x39, 0x39,
-    0x37, 0x32, 0x39, 0x00, 0x39, 0x39, 0x39, 0x37, 0x32, 0x39, 0x00, 0x39,
-    0x39, 0x39, 0x37, 0x32, 0x39, 0x00, 0x31, 0x30, 0x61, 0x66, 0x39, 0x37,
-    0x31, 0x37, 0x63, 0x31, 0x30, 0x36, 0x36, 0x33, 0x65, 0x62, 0x30, 0x30,
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x04, 0x52, 0x39, 0x38, 0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x04, 0x30, 0x31, 0x30, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01,
-    0x03, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x01,
-    0x1a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xc6, 0x01,
-    0x1b, 0x00, 0x05, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xce, 0x01,
-    0x28, 0x00, 0x03, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x02,
-    0x01, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xd6, 0x02,
-    0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x28, 0x39, 0x00,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00,
-    0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0xff, 0xd8, 0xff, 0xe0, 0x00,
-    0x10, 0x4a, 0x46, 0x49, 0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00,
-    0x01, 0x00, 0x00, 0xff, 0xdb, 0x00, 0x43, 0x00, 0x05, 0x03, 0x04, 0x04,
-    0x04, 0x03, 0x05, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c,
-    0x08, 0x07, 0x07, 0x07, 0x07, 0x0f, 0x0b, 0x0b, 0x09, 0x0c, 0x11, 0x0f,
-    0x12, 0x12, 0x11, 0x0f, 0x11, 0x11, 0x13, 0x16, 0x1c, 0x17, 0x13, 0x14,
-    0x1a, 0x15, 0x11, 0x11, 0x18, 0x21, 0x18, 0x1a, 0x1d, 0x1d, 0x1f, 0x1f,
-    0x1f, 0x13, 0x17, 0x22, 0x24, 0x22, 0x1e, 0x24, 0x1c, 0x1e, 0x1f, 0x1e,
-    0xff, 0xdb, 0x00, 0x43, 0x01, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e,
-    0x08, 0x08, 0x0e, 0x1e, 0x14, 0x11, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0xff, 0xc0, 0x00,
-    0x11, 0x08, 0x00, 0x78, 0x00, 0xa0, 0x03, 0x01, 0x22, 0x00, 0xaa, 0x72};
-
-std::vector<uint8_t> l2cap_test_packet_2 = {
-    0xf6, 0x03, 0x47, 0x00, 0x04, 0xc1, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
-    0xff, 0xc4, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x01, 0x01,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07,
-    0x00, 0x04, 0x08, 0x03, 0x02, 0x01, 0xff, 0xc4, 0x00, 0x40, 0x10, 0x00,
-    0x01, 0x03, 0x02, 0x05, 0x02, 0x04, 0x04, 0x04, 0x03, 0x06, 0x04, 0x07,
-    0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x00, 0x06, 0x12,
-    0x21, 0x31, 0x07, 0x41, 0x13, 0x22, 0x51, 0x61, 0x14, 0x32, 0x71, 0x81,
-    0x08, 0x42, 0x91, 0xa1, 0x15, 0x16, 0xc1, 0x23, 0x52, 0x62, 0x82, 0xb1,
-    0xe1, 0x24, 0x43, 0x72, 0xf0, 0x17, 0x25, 0x33, 0x92, 0xb2, 0xd1, 0xd2,
-    0xff, 0xc4, 0x00, 0x1c, 0x01, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x01,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07,
-    0x04, 0x03, 0x00, 0x02, 0x08, 0x01, 0xff, 0xc4, 0x00, 0x37, 0x11, 0x00,
-    0x01, 0x02, 0x04, 0x04, 0x03, 0x06, 0x04, 0x05, 0x04, 0x03, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0x11, 0x06, 0x21,
-    0x31, 0x41, 0x12, 0x51, 0x71, 0x13, 0x22, 0x61, 0x81, 0x91, 0xa1, 0x07,
-    0xb1, 0xc1, 0xf0, 0x14, 0x42, 0xd1, 0xe1, 0xf1, 0x15, 0x24, 0x32, 0x82,
-    0x33, 0x52, 0x72, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11,
-    0x03, 0x11, 0x00, 0x3f, 0x00, 0xb1, 0x31, 0x2c, 0x2d, 0xd8, 0xd2, 0xda,
-    0x43, 0x26, 0x4a, 0x99, 0x1e, 0x15, 0x98, 0x2e, 0x2f, 0x51, 0x49, 0x0b,
-    0x03, 0x70, 0x90, 0x6c, 0x9f, 0x4d, 0xb7, 0xf5, 0xc3, 0x0b, 0x4f, 0x09,
-    0x1f, 0x08, 0xa5, 0x95, 0xb6, 0xb7, 0x50, 0x4e, 0x95, 0xab, 0xe4, 0xbf,
-    0x2a, 0xb1, 0x17, 0xb8, 0xb1, 0xde, 0xdd, 0xf1, 0x34, 0xa1, 0x3b, 0x25,
-    0xb6, 0x5d, 0x67, 0xe2, 0xda, 0x5b, 0xeb, 0x49, 0xf0, 0xd2, 0x83, 0xe1,
-    0xa9, 0x37, 0xbe, 0x91, 0x72, 0xab, 0x5f, 0x73, 0x7f, 0xb6, 0x1d, 0x28,
-    0xf0, 0xdf, 0xf1, 0x9b, 0x05, 0x2e, 0x20, 0x32, 0xd8, 0x64, 0x23, 0x52,
-    0x4a, 0x9c, 0xb7, 0x2b, 0x52, 0x8d, 0xd5, 0xe9, 0xe5, 0xdb, 0x83, 0xea,
-    0x30, 0x09, 0x75, 0x86, 0x25, 0xec, 0x1e, 0x58, 0x4d, 0xf9, 0x90, 0x20,
-    0x87, 0x60, 0x4e, 0x91, 0xb2, 0xc3, 0x72, 0x63, 0xcd, 0x40, 0x76, 0x63,
-    0xd2, 0x5b, 0x4a, 0x75, 0x04, 0x20, 0x06, 0xf9, 0xdb, 0xcd, 0xdc, 0x83,
-    0xe9, 0x6b, 0xec, 0x0d, 0xf1, 0xba, 0x5f, 0x76, 0xe9, 0x50, 0x43, 0x65,
-    0xd9, 0x05, 0x21, 0x08, 0xf2, 0x92, 0x94, 0x05, 0x73, 0x72, 0x48, 0x20,
-    0x5c, 0xaa, 0xf8, 0xf8, 0xa9, 0x34, 0x97, 0xe4, 0x3e, 0xc7, 0xc4, 0x80,
-    0x95, 0x90, 0x90, 0x9d, 0x1a, 0x94, 0x8b, 0xd8, 0x6d, 0xb5, 0x80, 0xef,
-    0xf7, 0xc7, 0xeb, 0x14, 0xb7, 0xdb, 0x79, 0x45, 0x2f, 0xb6, 0x50, 0x55,
-    0x7b, 0x96, 0x86, 0xb4, 0xf1, 0xc2, 0xaf, 0x7e, 0xc3, 0x7c, 0x65, 0x77,
-    0x15, 0x52, 0x98, 0x36, 0x53, 0xc3, 0xca, 0xe7, 0xe5, 0x78, 0xf0, 0xb0,
-    0xb3, 0x99, 0x11, 0xae, 0xa6, 0xd8, 0x91, 0x2c, 0x38, 0x3c, 0x37, 0xb4,
-    0x36, 0xa6, 0x99, 0xd2, 0xb2, 0xb0, 0xda, 0x01, 0x04, 0xea, 0x24, 0x8d,
-    0xcd, 0xb6, 0xfa, 0x63, 0x62, 0x92, 0xdb, 0x2c, 0xb8, 0xcb, 0x29, 0x7d,
-    0x97, 0x94, 0x5b, 0x53, 0xa0, 0x22, 0xfa, 0x02, 0x52, 0x52, 0x35, 0x12,
-    0x2f, 0x71, 0x7b, 0x72, 0x77, 0xe0, 0x63, 0xc2, 0xb9, 0x43, 0xa9, 0x39,
-    0x09, 0xc8, 0xd0, 0x1f, 0x6d, 0x95, 0xbb, 0xa5, 0x7f, 0x10, 0xfa, 0x3c,
-    0x5d, 0xf5, 0x58, 0x24, 0x20, 0x5b, 0x51, 0x3c, 0x58, 0x9b, 0x5a, 0xf7,
-    0xbd, 0xf1, 0x2f, 0xcd, 0x94, 0x9c, 0xff, 0x00, 0x4a, 0x94, 0xe4, 0xba,
-    0x8e, 0x60, 0xa8, 0xba, 0xc0, 0x05, 0x1a, 0xe2, 0x47, 0x09, 0x09, 0x4f,
-    0xa6, 0x94, 0x8b, 0xa7, 0xd8, 0x0f, 0xb6, 0x0a, 0xd3, 0xaa, 0x54, 0xe9,
-    0xe5, 0xa1, 0x29, 0x98, 0x4a, 0x4a, 0xb4, 0x0a, 0xba, 0x6f, 0x9d, 0xb7,
-    0x16, 0xbf, 0x21, 0x7b, 0x9d, 0x84, 0x0d, 0xa8, 0x4c, 0xb9, 0x26, 0xd9,
-    0x73, 0xb2, 0x52, 0xc0, 0xff, 0x00, 0xa8, 0x07, 0xda, 0xf7, 0xeb, 0x95,
-    0x84, 0x55, 0xdb, 0x4c, 0x26, 0xa4, 0x3e, 0xdb, 0x0b, 0x2e, 0xcb, 0x91,
-    0x24, 0xbe, 0xa2, 0x2c, 0x08, 0x52, 0x86, 0xca, 0xb7, 0x17, 0x00, 0x58,
-    0xed, 0x72, 0x0e, 0xf8, 0xf8, 0x7e, 0x6c, 0x28, 0xce, 0x3a, 0xc3, 0x25,
-    0x90, 0x88, 0xc9, 0xd4, 0xe9, 0x71, 0xc0, 0x09, 0x52, 0x85, 0xed, 0xa8,
-    0xf7, 0xbd, 0xff, 0x00, 0x4d, 0x86, 0x39, 0x96, 0xa7, 0xd4, 0x6a, 0x63,
-    0x28, 0x5b, 0x1f, 0xce, 0x33, 0xf5, 0x36, 0x0a, 0x5c, 0x49, 0x75, 0x6b,
-    0x70, 0xab, 0x8b, 0x8b, 0x91, 0x63, 0x6b, 0x6d, 0x6e, 0xd8, 0x00, 0xee,
-    0x76, 0xca, 0xce, 0x27, 0xc6, 0x6a, 0x8b, 0x32, 0x78, 0x69, 0x3f, 0xda,
-    0x3a, 0xa6, 0xca, 0x89, 0xb7, 0x2a, 0x3b, 0x9f, 0x7c, 0x37, 0xff, 0x00,
-    0x41, 0x69, 0x1f, 0xf2, 0xbe, 0x07, 0xa7, 0xd4, 0x88, 0x54, 0x18, 0xaa,
-    0x61, 0xcf, 0xf8, 0xa4, 0xd6, 0x7a, 0xe5, 0xf3, 0x1f, 0xac, 0x75, 0x8c,
-    0x0c, 0xc3, 0x02, 0xa3, 0x50, 0x6a, 0x9c, 0xc5, 0x62, 0x92, 0xe4, 0xa7,
-    0x10, 0xb6, 0xbe, 0x1d, 0xb9, 0x2d, 0xad, 0x00, 0x80, 0x3f, 0x2f, 0xcc,
-    0xb5, 0x0b, 0x1e, 0x2c, 0x07, 0xb9, 0xc7, 0xae, 0x68, 0x96, 0xa4, 0xd2,
-    0xcb, 0x31, 0x25, 0x29, 0x72, 0x00, 0x0d, 0x96, 0xda, 0xec, 0x9b, 0xf7,
-    0xb0, 0xd8, 0xf7, 0xda, 0xc7, 0xb6, 0x21, 0x79, 0x22, 0x3d, 0x1e, 0xbf,
-    0x45, 0x8b, 0x3c, 0xd3, 0x95, 0x11, 0xb9, 0x26, 0xf1, 0x5c, 0x69, 0x65,
-    0xa7, 0x10, 0xa0, 0xe6, 0x84, 0x9d, 0xb7, 0x1e, 0x71, 0x89, 0xac, 0x0a,
-    0x9d, 0x56, 0x8f, 0x38, 0x48, 0x8d, 0x52, 0x9d, 0x0d, 0x65, 0xc2, 0x54,
-    0xeb, 0x2e, 0xa9, 0x0a, 0x55, 0x8d, 0x89, 0xe7, 0x7e, 0xfc, 0xe0, 0x0d,
-    0x79, 0xb6, 0xe9, 0x8a, 0x42, 0x50, 0x4a, 0x82, 0xc6, 0xbf, 0xa4, 0x51,
-    0xbe, 0x1b, 0xc8, 0x2b, 0x18, 0x35, 0x32, 0xe3, 0x87, 0xb2, 0x53, 0x2a,
-    0x09, 0xe1, 0xd6, 0xe4, 0x8b, 0xe6, 0x76, 0xf4, 0x31, 0xd6, 0x31, 0x67,
-    0x66, 0x00, 0xda, 0x90, 0x22, 0xc6, 0x79, 0xb4, 0x20, 0xa1, 0x6f, 0xbc,
-    0x0a, 0x41, 0x09, 0xf3, 0x6b, 0x09, 0x37, 0xb0, 0x36, 0xdc, 0x12, 0x4e,
-    0xd8, 0x11, 0x51, 0x7f, 0xf8, 0xed, 0x5a, 0x1c, 0x88, 0x35, 0x04, 0xa5,
-    0xc8, 0x4d, 0x2d, 0x4d, 0xa9, 0xc8, 0xd6, 0x6b, 0x52, 0x87, 0x99, 0x4a,
-    0xb8, 0xdc, 0x93, 0xc0, 0x06, 0xdc, 0xe2, 0x21, 0x13, 0xa9, 0xd9, 0xb0,
-    0xb1, 0xe1, 0x4a, 0xaf, 0x3a, 0xe9, 0x4a, 0xb5, 0x21, 0x6e, 0xb0, 0x85,
-    0x9f, 0x6b, 0xa8, 0x6f, 0x7f, 0xb6, 0x35, 0xe2, 0xf5, 0x37, 0x37, 0xca,
-    0x7c, 0x35, 0x51, 0xaf, 0xae, 0x13, 0x00, 0xfc, 0xed, 0x46, 0xd7, 0x71,
-    0xfe, 0x22, 0x0d, 0xc7, 0xe8, 0x70, 0x10, 0xcf, 0xb0, 0x53, 0x61, 0x73,
-    0xe9, 0xfa, 0xc3, 0xcc, 0xc6, 0x09, 0x7a, 0x50, 0x15, 0x29, 0x1c, 0x5f,
-    0xf9, 0xb9, 0xfa, 0x67, 0xe5, 0x68, 0xe8, 0x7a, 0x34, 0x17, 0x60, 0x34,
-    0xa0, 0x66, 0x53, 0xdb, 0x53, 0x84, 0xea, 0x5b, 0x67, 0x4d, 0xfd, 0xfc,
-    0xbe, 0xfb, 0xf3, 0xbf, 0xd3, 0x6c, 0x7d, 0x66, 0x57, 0x5b};
-
-std::vector<uint8_t> l2cap_test_packet_3 = {
-    0xf6, 0x03, 0x47, 0x00, 0x06, 0xc1, 0x87, 0xeb, 0x74, 0xf8, 0xb1, 0xe1,
-    0xd2, 0xc4, 0x35, 0x49, 0x90, 0xcb, 0xae, 0xc3, 0x73, 0x7d, 0x3a, 0x90,
-    0x9b, 0x90, 0x45, 0xed, 0xbd, 0xf6, 0x3c, 0x0e, 0x6d, 0x89, 0xa6, 0x46,
-    0x89, 0x56, 0xac, 0x4b, 0x81, 0x35, 0xac, 0xdc, 0xfd, 0x56, 0x31, 0x7d,
-    0x2a, 0x29, 0x60, 0x0b, 0x25, 0x49, 0x58, 0xd9, 0xc0, 0x07, 0x96, 0xe3,
-    0xb1, 0xb6, 0xd8, 0xac, 0xe7, 0xb4, 0x45, 0x6a, 0xaf, 0x4b, 0x43, 0x4a,
-    0x6d, 0x25, 0xa9, 0x32, 0x11, 0xa1, 0x24, 0x5d, 0x29, 0x53, 0x5b, 0x6d,
-    0xd8, 0x5c, 0x60, 0xad, 0x29, 0x4d, 0xcc, 0x38, 0x3b, 0xb6, 0x00, 0x8d,
-    0x77, 0x85, 0xb9, 0x96, 0x19, 0x49, 0x52, 0x10, 0x9c, 0xc2, 0x54, 0x73,
-    0x1a, 0x10, 0x92, 0x47, 0xbd, 0xa2, 0x1c, 0x9f, 0xfc, 0x40, 0x7a, 0x32,
-    0x5f, 0x97, 0x99, 0x1d, 0x52, 0xdb, 0x36, 0x11, 0x92, 0xe2, 0x90, 0xd3,
-    0x62, 0xdc, 0x0d, 0x24, 0x11, 0xb1, 0xc2, 0xfd, 0x5a, 0x5e, 0x60, 0x42,
-    0x2c, 0xfc, 0x07, 0x18, 0x75, 0x2a, 0xba, 0x26, 0x21, 0xe5, 0x3f, 0x63,
-    0xfd, 0xe4, 0xa9, 0x47, 0xca, 0x46, 0xe3, 0x71, 0xdf, 0x19, 0xd6, 0x3a,
-    0xd5, 0x5e, 0x91, 0x0d, 0x2f, 0xc1, 0x21, 0x94, 0x29, 0xd7, 0x2e, 0x15,
-    0x65, 0x05, 0x5b, 0x4e, 0xe4, 0x7d, 0xf8, 0x38, 0x0b, 0x42, 0xea, 0x69,
-    0x30, 0x9b, 0x6a, 0xb9, 0x4b, 0x43, 0xe1, 0xb0, 0x12, 0x1d, 0x8e, 0x7c,
-    0x32, 0x8f, 0xb7, 0x6f, 0xb6, 0x28, 0xcb, 0x99, 0x92, 0x95, 0x74, 0x36,
-    0xa0, 0x94, 0xa8, 0x8b, 0x8c, 0xac, 0x39, 0x74, 0x88, 0xa6, 0x1f, 0xc4,
-    0x18, 0xbd, 0x12, 0x9f, 0x8e, 0x67, 0x85, 0xe6, 0xd4, 0x4d, 0xd2, 0x6d,
-    0x71, 0x6d, 0x6d, 0x98, 0x3e, 0x40, 0xf9, 0x40, 0xf9, 0x19, 0x9a, 0xad,
-    0xe3, 0x3b, 0x11, 0x6e, 0xca, 0xa9, 0x6b, 0x56, 0x8d, 0x72, 0x5c, 0x4a,
-    0xad, 0x7b, 0x0b, 0x24, 0xe9, 0x3a, 0x71, 0xf7, 0x97, 0xaa, 0x19, 0x86,
-    0x65, 0x52, 0x24, 0x66, 0xe9, 0x0d, 0xb7, 0xe3, 0x38, 0x1b, 0x49, 0x44,
-    0x50, 0xab, 0x82, 0xab, 0x5e, 0xc4, 0x6f, 0x6c, 0x35, 0xb3, 0x4b, 0xcb,
-    0x79, 0x89, 0xe4, 0xce, 0xa6, 0x26, 0x6c, 0x69, 0x5a, 0x82, 0x95, 0x29,
-    0x2b, 0x52, 0x1d, 0x41, 0x3b, 0x8b, 0x91, 0xda, 0xc3, 0x6d, 0x88, 0xd8,
-    0xe1, 0x93, 0x2f, 0xcf, 0xab, 0xe5, 0x7c, 0xc7, 0x4d, 0x46, 0x60, 0x97,
-    0x0e, 0x75, 0x31, 0xe9, 0x08, 0x69, 0x12, 0x8c, 0x60, 0x87, 0xda, 0xf4,
-    0xbe, 0x8b, 0x05, 0x0f, 0xb0, 0x3d, 0xf1, 0x8a, 0x64, 0xd5, 0x5a, 0x1c,
-    0x52, 0xae, 0x24, 0xa0, 0x67, 0x6b, 0x01, 0xfc, 0xfa, 0xc3, 0x75, 0x33,
-    0xe2, 0x63, 0x4f, 0xbc, 0x99, 0x57, 0xd2, 0x59, 0x73, 0x4e, 0x12, 0x32,
-    0xbf, 0xcf, 0xd6, 0x06, 0xf5, 0x01, 0xd9, 0x74, 0xac, 0xba, 0xdb, 0x2f,
-    0x33, 0x1d, 0xba, 0x85, 0x36, 0xae, 0xe4, 0x77, 0x5d, 0x61, 0xad, 0x96,
-    0x0b, 0x63, 0x70, 0x07, 0xfd, 0x37, 0xb6, 0x1f, 0xba, 0x4b, 0x5b, 0x95,
-    0x3f, 0x2b, 0xc1, 0x44, 0xc7, 0x1e, 0x96, 0x02, 0x8d, 0xca, 0x9b, 0xb2,
-    0x94, 0x41, 0x24, 0x12, 0x2f, 0xcd, 0xec, 0x37, 0xe7, 0xdf, 0x13, 0xbe,
-    0xb2, 0x54, 0x4c, 0xba, 0xce, 0x60, 0x5c, 0x25, 0x87, 0xe9, 0xee, 0x4a,
-    0x6e, 0x49, 0xf0, 0xd3, 0x72, 0x95, 0x29, 0x24, 0x03, 0xa8, 0x1d, 0xb9,
-    0x3b, 0x7b, 0x7b, 0x60, 0xef, 0x43, 0x5d, 0x29, 0x88, 0xdb, 0x8b, 0x72,
-    0x33, 0x65, 0x5e, 0x25, 0xee, 0x17, 0x7b, 0x10, 0x05, 0xac, 0x0d, 0x89,
-    0xdb, 0x83, 0x85, 0x8c, 0x5a, 0x78, 0x66, 0x9a, 0x58, 0xdd, 0x20, 0x9f,
-    0x3b, 0x9f, 0xac, 0x3b, 0xd5, 0xdb, 0xb9, 0x4a, 0xd5, 0xa9, 0x00, 0xfb,
-    0x40, 0xac, 0xbf, 0x98, 0xbe, 0x31, 0x9a, 0xab, 0x73, 0x42, 0xde, 0x80,
-    0xc7, 0x87, 0xa9, 0x2b, 0x6c, 0x10, 0xe0, 0x28, 0xbe, 0xe0, 0xec, 0x47,
-    0xa7, 0xfb, 0x62, 0x9b, 0x94, 0x9a, 0xa9, 0xd6, 0x72, 0xa8, 0x95, 0x90,
-    0x33, 0x73, 0x72, 0xd6, 0x86, 0x2e, 0x69, 0x92, 0xbc, 0xcb, 0x61, 0x76,
-    0xf9, 0x52, 0x54, 0x6f, 0xa7, 0xd8, 0x92, 0x3d, 0x14, 0x31, 0x03, 0x76,
-    0x3b, 0x4d, 0xe4, 0xcc, 0xcd, 0x23, 0x58, 0xbb, 0x8d, 0xa2, 0xe9, 0x04,
-    0xd9, 0x20, 0x04, 0x8d, 0xbd, 0x76, 0xc4, 0xf3, 0x2a, 0x55, 0x33, 0x44,
-    0x4c, 0xf6, 0x22, 0xe5, 0x27, 0xa6, 0xae, 0xa2, 0xe4, 0xa0, 0x96, 0x44,
-    0x72, 0x6e, 0x0d, 0x85, 0xcd, 0x87, 0x6b, 0x5e, 0xff, 0x00, 0xbe, 0x3d,
-    0xa6, 0x9a, 0x94, 0x98, 0xa7, 0xcb, 0x4a, 0x4c, 0xb4, 0x16, 0x14, 0x9b,
-    0xe6, 0x01, 0xcf, 0x2d, 0xb5, 0xdf, 0x50, 0x41, 0x89, 0x54, 0x8c, 0xa3,
-    0xc2, 0xa1, 0x3d, 0x50, 0x65, 0xee, 0x12, 0x85, 0x81, 0x62, 0x6c, 0x2d,
-    0x62, 0x49, 0xdc, 0x65, 0x6d, 0xd2, 0x44, 0x5c, 0x1e, 0xcf, 0x3d, 0x5a,
-    0x62, 0xa4, 0xe5, 0x3e, 0xa5, 0x50, 0xa7, 0xd2, 0xdd, 0x49, 0xd2, 0x84,
-    0xbc, 0xd6, 0x95, 0x39, 0xcd, 0x82, 0x6f, 0x7b, 0xf1, 0xce, 0xe0, 0x7a,
-    0xe1, 0x83, 0x20, 0xbf, 0xd4, 0x0a, 0xad, 0x42, 0x4b, 0xd5, 0x6c, 0xe0,
-    0xf1, 0x66, 0x24, 0xe6, 0xee, 0xcb, 0x6d, 0x20, 0x02, 0x9b, 0x82, 0x52,
-    0xab, 0x0f, 0x4d, 0x88, 0xf7, 0xc1, 0x8c, 0xd5, 0x2e, 0x8a, 0x7a, 0x5d,
-    0x4e, 0x8b, 0x5b, 0x8e, 0xd2, 0xab, 0x06, 0xea, 0x50, 0x6d, 0x3b, 0xa1,
-    0xb2, 0xa3, 0xa0, 0x58, 0x7f, 0xcc, 0x50, 0xb5, 0x80, 0xdc, 0x83, 0xbe,
-    0x24, 0xbd, 0x36, 0xcc, 0x33, 0xb2, 0xcd, 0x54, 0x25, 0x42, 0x4a, 0x5a,
-    0x2e, 0x02, 0x96, 0xdc, 0x90, 0x4a, 0x55, 0x7d, 0x89, 0xb7, 0x04, 0x81,
-    0xff, 0x00, 0xd6, 0xf8, 0x54, 0xad, 0xe1, 0x4a, 0x6d, 0x38, 0x07, 0x19,
-    0x69, 0x20, 0x1b, 0xe4, 0x52, 0x2f, 0x96, 0xe0, 0xf2, 0x3b, 0x7d, 0x61,
-    0xaf, 0x0d, 0x62, 0x79, 0x8a, 0xb0, 0x52, 0x1c, 0x02, 0xe9, 0x09, 0xcc,
-    0x68, 0x4a, 0x85, 0xed, 0xa7, 0xf9, 0x0d, 0xc7, 0x8e, 0xd1, 0xd8, 0x64,
-    0xff, 0x00, 0xc5, 0xb4, 0xd3, 0x68, 0x05, 0x28, 0x0a, 0x5a, 0x92, 0x4f,
-    0xe5, 0x4b, 0x97, 0xb7, 0xe8, 0x71, 0x1a, 0xab, 0xfe, 0x21, 0x29, 0xd4,
-    0x7e, 0xa5, 0xce, 0xca, 0x35, 0xea, 0x64, 0x91, 0x09, 0x01, 0x05, 0x12,
-    0xda, 0x40, 0x50, 0x4e, 0xa1, 0xdd, 0x3c, 0xd8, 0x7a, 0xef, 0x8a, 0xc5,
-    0x36, 0xa9, 0x0e, 0x44, 0x84, 0xe8, 0x73, 0xfb, 0x59, 0x2c, 0x29, 0x4d,
-    0xa7, 0xbf, 0x65, 0x7f, 0xa1, 0xc7, 0x13, 0xf5, 0x06, 0x9b, 0x52, 0xac,
-    0xfe, 0x20, 0x6a, 0x90, 0x20, 0x45, 0x91, 0x2a, 0x5b, 0x8b, 0x6d, 0xb6,
-    0x19, 0x6c, 0x5d, 0x4b, 0xb2, 0x78, 0x1f, 0xbe, 0xfc, 0x0c, 0x21, 0x61,
-    0xb9, 0x66, 0xa7, 0xdb, 0xb3, 0xa7, 0x44, 0x2b, 0x43, 0x6b, 0x10, 0xb4,
-    0x81, 0xec, 0x77, 0xb8, 0xcc, 0xc1, 0xa7, 0xf8, 0x99, 0x48, 0x36, 0xce,
-    0xe0, 0x67, 0xc8, 0x85, 0x1f, 0xa6, 0xa2, 0x3a, 0x3b, 0x33, 0xe4, 0x8c,
-    0x85, 0xd4, 0x46, 0xda, 0xae, 0x52, 0xc4, 0x07, 0x64, 0x2e, 0xc0, 0x49,
-    0x61, 0x00, 0x2b, 0xe8, 0xbb, 0x6f, 0xbe, 0x14, 0xab, 0xb9, 0x30, 0x50,
-    0x22, 0xff, 0x00, 0x0f, 0xfe, 0x13, 0x18, 0x7c, 0x72, 0x96, 0xc0, 0x90,
-    0x41, 0x29, 0x41, 0x50, 0xb0, 0xbf, 0x1e, 0x5e, 0x76, 0xdb, 0xdc, 0xfa,
-    0xb5, 0xf4, 0xeb, 0x24, 0x53, 0x7a, 0x71, 0x45, 0x44, 0xe6};
-
-std::vector<uint8_t> l2cap_test_packet_4 = {
-    0xf6, 0x03, 0x47, 0x00, 0x08, 0xc1, 0x7a, 0xa1, 0x5b, 0xa8, 0x32, 0x89,
-    0xd3, 0x96, 0xda, 0xa5, 0x25, 0xb5, 0xf9, 0x1b, 0x08, 0x3a, 0x92, 0x80,
-    0x7f, 0x32, 0xb5, 0x5a, 0xea, 0xf6, 0xb0, 0xbe, 0x06, 0x75, 0x3e, 0xa9,
-    0x5a, 0xce, 0x51, 0xa1, 0xc3, 0xa7, 0xb0, 0x61, 0xc5, 0x5c, 0x80, 0x59,
-    0x52, 0x8d, 0x9c, 0x58, 0x48, 0x24, 0x1b, 0x7e, 0x54, 0xef, 0xdf, 0x72,
-    0x71, 0xda, 0x98, 0xf4, 0xe8, 0x9f, 0xec, 0xa5, 0x9d, 0x2e, 0x32, 0x35,
-    0xb8, 0xc8, 0x78, 0x03, 0xe9, 0xa6, 0xa7, 0x6b, 0x46, 0x87, 0xc3, 0x45,
-    0xae, 0x35, 0xa4, 0x5f, 0x9e, 0xff, 0x00, 0xbf, 0xa6, 0x9b, 0xc2, 0xfc,
-    0xa9, 0xf1, 0x13, 0x97, 0xbc, 0x4a, 0x32, 0x2e, 0xd4, 0x0b, 0xb4, 0xa0,
-    0x11, 0xa7, 0xcc, 0xd3, 0x89, 0x52, 0x94, 0x94, 0x8b, 0x00, 0x2f, 0x72,
-    0x3d, 0xb1, 0x36, 0xeb, 0x1c, 0x07, 0x28, 0xd3, 0x6b, 0xb4, 0xc9, 0x4e,
-    0x15, 0x25, 0x82, 0xb5, 0x31, 0xa4, 0xdd, 0x29, 0x4a, 0x9c, 0x43, 0xa9,
-    0x23, 0xfc, 0xaa, 0xfd, 0xf1, 0xbb, 0x2e, 0x55, 0x6a, 0x87, 0x1a, 0xbc,
-    0x89, 0x20, 0x29, 0x69, 0x63, 0x5a, 0x52, 0xb0, 0x6c, 0x51, 0xa1, 0x40,
-    0xf1, 0xea, 0x06, 0x06, 0x67, 0xc9, 0x92, 0x33, 0x14, 0x36, 0xe4, 0xcb,
-    0x5f, 0x8a, 0xec, 0x9a, 0x6c, 0x7b, 0xab, 0x48, 0x04, 0xff, 0x00, 0x62,
-    0x11, 0xfb, 0x14, 0xe2, 0xb3, 0x88, 0x78, 0x7f, 0x01, 0x26, 0xb3, 0xa8,
-    0x03, 0xe9, 0xfa, 0x46, 0x4f, 0x85, 0x0c, 0x3c, 0xa9, 0xba, 0xd4, 0xba,
-    0x45, 0xc2, 0xc5, 0xc5, 0xb5, 0xe2, 0xb1, 0xb7, 0xce, 0xde, 0x71, 0x36,
-    0xa6, 0x4b, 0xaa, 0xbf, 0x20, 0x98, 0xaf, 0x68, 0x69, 0xb4, 0xdf, 0x4d,
-    0xb6, 0xb0, 0xf6, 0xe4, 0x93, 0x87, 0x95, 0xaa, 0x38, 0xa5, 0x44, 0x4a,
-    0x81, 0xf8, 0xd4, 0xeb, 0x32, 0x1d, 0x1b, 0x21, 0x49, 0x36, 0x29, 0xb0,
-    0xf5, 0x1b, 0xdc, 0xfd, 0x30, 0x0f, 0x2d, 0xd1, 0xd3, 0x0d, 0xa6, 0xde,
-    0xa8, 0xb8, 0x12, 0xb0, 0x2f, 0x60, 0x0a, 0x83, 0x7b, 0x6f, 0x6b, 0x72,
-    0xac, 0x36, 0xd2, 0xa8, 0x46, 0xbb, 0x1e, 0x4c, 0xa8, 0x92, 0x22, 0xa0,
-    0x34, 0xc9, 0x71, 0xa6, 0x0b, 0xa1, 0x4a, 0x3d, 0xbc, 0xd6, 0x3b, 0x2b,
-    0x93, 0x7e, 0x01, 0xdb, 0x9c, 0x28, 0x4c, 0xad, 0x2e, 0x2a, 0xc8, 0x02,
-    0xdc, 0xe2, 0xc1, 0x46, 0x2f, 0x50, 0x25, 0x7f, 0x11, 0x50, 0x75, 0x5c,
-    0x4a, 0xff, 0x00, 0x16, 0xef, 0xa7, 0x5b, 0xe9, 0xd3, 0x6d, 0xf3, 0xc8,
-    0x6e, 0xf4, 0xff, 0x00, 0x3d, 0x4c, 0xca, 0xf9, 0x88, 0x7c, 0x2c, 0x1d,
-    0x46, 0x63, 0x29, 0x6c, 0xa4, 0x27, 0x40, 0xb2, 0x38, 0x59, 0xf5, 0x27,
-    0x7f, 0xd7, 0x1d, 0x08, 0xce, 0x65, 0x6e, 0xa7, 0x54, 0xa7, 0x4f, 0xac,
-    0xa6, 0x3c, 0x79, 0x29, 0x7e, 0x13, 0xc8, 0x49, 0x50, 0x05, 0x45, 0xd0,
-    0xa4, 0xad, 0x36, 0xfc, 0xdc, 0x03, 0x8e, 0x7d, 0x32, 0xa0, 0x57, 0xa9,
-    0x52, 0x6a, 0xeb, 0x52, 0x19, 0xaa, 0x46, 0x8a, 0x52, 0x96, 0xb4, 0x24,
-    0x2d, 0xc2, 0x15, 0xdf, 0xe8, 0x07, 0x1c, 0x91, 0xfa, 0x63, 0xa0, 0xf3,
-    0x25, 0x39, 0x0e, 0x51, 0x29, 0x12, 0xc2, 0x59, 0xb3, 0x52, 0x60, 0x91,
-    0x74, 0x0b, 0xdb, 0xc3, 0x3d, 0xff, 0x00, 0x4c, 0x14, 0xa5, 0x29, 0x69,
-    0x70, 0x24, 0x69, 0xcb, 0xce, 0x13, 0xa6, 0xa7, 0x45, 0x49, 0xf7, 0x5d,
-    0x75, 0x20, 0x29, 0x79, 0x65, 0xb0, 0xd2, 0xde, 0x62, 0x21, 0xff, 0x00,
-    0x88, 0xf6, 0x9b, 0xa9, 0x52, 0x2a, 0xb2, 0xa1, 0x21, 0x6d, 0x21, 0x55,
-    0x37, 0x96, 0xce, 0xa1, 0xa4, 0xe8, 0x52, 0xc1, 0xbe, 0x9e, 0xc2, 0xd7,
-    0xdb, 0x12, 0x9e, 0x9c, 0xd2, 0xe6, 0xd5, 0x5f, 0x31, 0xe1, 0x34, 0xeb,
-    0xce, 0xa9, 0x77, 0x5a, 0x95, 0xe6, 0x48, 0x48, 0x16, 0x25, 0x46, 0xf6,
-    0x03, 0x91, 0x8b, 0xa6, 0x64, 0xa0, 0x53, 0xb3, 0x35, 0x3e, 0x43, 0x55,
-    0x17, 0x8b, 0x4d, 0x25, 0xe2, 0xe2, 0x8a, 0x57, 0xa7, 0x6b, 0x9b, 0x8b,
-    0x8c, 0x20, 0x55, 0xf3, 0xad, 0x03, 0x2c, 0x43, 0x5e, 0x5a, 0xca, 0x8c,
-    0xc6, 0x6e, 0xc7, 0x77, 0xd1, 0x65, 0x24, 0x2b, 0xde, 0xff, 0x00, 0x3e,
-    0x29, 0x53, 0xb4, 0xa6, 0x9e, 0x71, 0x2f, 0xbc, 0xab, 0x21, 0x09, 0x00,
-    0xff, 0x00, 0x3f, 0x66, 0x3e, 0x6d, 0xa0, 0xe2, 0x09, 0xa6, 0xd8, 0x5c,
-    0x8c, 0x8b, 0x65, 0x4f, 0x95, 0xa8, 0xdf, 0xf2, 0xa4, 0x13, 0xaf, 0xcf,
-    0x28, 0x6c, 0x8e, 0xec, 0x2c, 0xa7, 0x0d, 0x98, 0xad, 0x3d, 0xfc, 0x46,
-    0xa5, 0x21, 0x21, 0xa4, 0x45, 0x8e, 0x92, 0x55, 0xb7, 0x01, 0x29, 0xf4,
-    0xdc, 0xf9, 0x8f, 0xfa, 0x63, 0xe2, 0xa1, 0x42, 0xcc, 0xf5, 0x67, 0x04,
-    0xfa, 0xac, 0x96, 0xd8, 0x75, 0x2b, 0x40, 0x6a, 0x1b, 0x67, 0x59, 0x66,
-    0xff, 0x00, 0x4f, 0x99, 0x7f, 0xb0, 0xf7, 0xc0, 0x8c, 0x9b, 0x51, 0xa7,
-    0x46, 0xa6, 0xaa, 0x5c, 0xe9, 0xaf, 0x3d, 0x52, 0x99, 0xaf, 0xc5, 0x74,
-    0x2e, 0xca, 0x52, 0x38, 0xb1, 0x3f, 0x30, 0x16, 0xbe, 0xc2, 0xc3, 0x7c,
-    0x51, 0x1e, 0xcd, 0xd4, 0xc5, 0x25, 0xa8, 0xca, 0x9d, 0x09, 0x98, 0xcd,
-    0xa5, 0xb6, 0x8a, 0x84, 0x93, 0xad, 0x56, 0x1c, 0x9b, 0x26, 0xfe, 0xbb,
-    0x8e, 0x6f, 0x85, 0xaa, 0x96, 0x21, 0x2a, 0x4f, 0xe1, 0xa4, 0xc7, 0x0a,
-    0x34, 0xbe, 0xe7, 0xa7, 0x21, 0xef, 0x0e, 0x94, 0x6c, 0x22, 0xdc, 0xab,
-    0x9f, 0x8d, 0x9d, 0x3d, 0xac, 0xc1, 0xcc, 0x93, 0x98, 0x1d, 0x07, 0x84,
-    0x44, 0x73, 0x33, 0xd3, 0xe9, 0x30, 0x26, 0x95, 0xbb, 0xe3, 0x04, 0xb6,
-    0x94, 0x3e, 0x82, 0x2d, 0x72, 0x97, 0x08, 0xbe, 0xde, 0x84, 0x1c, 0x51,
-    0xba, 0x0d, 0x3d, 0x72, 0x29, 0x25, 0x6c, 0x48, 0x5b, 0x5a, 0x96, 0x97,
-    0x2e, 0xa2, 0x12, 0x1b, 0x00, 0x8b, 0xf3, 0x7b, 0xdf, 0xb6, 0x17, 0xb3,
-    0x4c, 0x5a, 0x6d, 0x43, 0x2d, 0x66, 0x37, 0x20, 0xba, 0x99, 0x29, 0x44,
-    0x67, 0x9c, 0x2e, 0x24, 0x6c, 0x56, 0x97, 0x8a, 0xbf, 0xf8, 0xd8, 0xfd,
-    0xf1, 0xf5, 0xf8, 0x7d, 0x6c, 0x38, 0x66, 0x43, 0x4a, 0x1d, 0xf0, 0x8b,
-    0xc1, 0xd0, 0x7c, 0x3b, 0xa5, 0x28, 0xd3, 0x7b, 0x0b, 0x5f, 0xbe, 0xd6,
-    0x27, 0x1e, 0x63, 0x04, 0x36, 0x4b, 0x2e, 0xb7, 0xba, 0x47, 0xb4, 0x3e,
-    0xcf, 0xa5, 0x60, 0xa0, 0xab, 0x74, 0x88, 0x1f, 0x4d, 0x6a, 0x75, 0x5a,
-    0x85, 0x98, 0xe0, 0xb0, 0x94, 0x95, 0x49, 0x75, 0xb6, 0xc0, 0xe6, 0xc0,
-    0x5a, 0xdb, 0xfa, 0x5b, 0x9c, 0x13, 0xc9, 0xf5, 0xea, 0x5f, 0x4b, 0xa2,
-    0x4c, 0xa8, 0xc4, 0x9e, 0xc2, 0x6b, 0x13, 0x9b, 0x51, 0x54, 0x94, 0xb4,
-    0x16, 0xea, 0x49, 0x04, 0x14, 0xb6, 0x54, 0x3c, 0xa9, 0x17, 0xed, 0xb9,
-    0x3e, 0x98, 0x0f, 0x42, 0x62, 0xa9, 0x22, 0x74, 0xb8, 0x14, 0xe9, 0x11,
-    0x23, 0xc7, 0x92, 0xe0, 0x52, 0xca, 0x95, 0xa0, 0x71, 0x62, 0x9d, 0x86,
-    0xff, 0x00, 0x41, 0x6b, 0xf0, 0x4e, 0x08, 0x37, 0xd1, 0x25, 0x57, 0x67,
-    0x99, 0x55, 0x4c, 0xd8, 0xb5, 0xb8, 0xad, 0x92, 0x94, 0x37, 0xa7, 0x48,
-    0xec, 0x07, 0x60, 0x31, 0x96, 0x6b, 0x15, 0x52, 0x29, 0xf2, 0xad, 0x05,
-    0xaa, 0xee, 0x84, 0x81, 0xa1, 0x36, 0xc8, 0x5e, 0xff, 0x00, 0x7e, 0xd1,
-    0x3c, 0x6b, 0x0b, 0x55, 0xa7, 0x66, 0x5e, 0xba, 0xb8, 0x18, 0x52, 0xf8,
-    0xb2, 0x20, 0x15, 0x1d, 0xb3, 0xfb, 0xf3, 0x3a, 0xb0, 0x21};
-
-std::vector<uint8_t> l2cap_test_packet_5 = {
-    0xf6, 0x03, 0x47, 0x00, 0x0a, 0xc1, 0x0a, 0x8d, 0x2e, 0xa1, 0x99, 0xd9,
-    0x12, 0x98, 0xab, 0x13, 0x50, 0x64, 0x87, 0x9b, 0xf1, 0x1c, 0xb0, 0x48,
-    0xd4, 0x76, 0x1f, 0xdd, 0x1e, 0xa7, 0xe8, 0x37, 0xbe, 0x1b, 0xe9, 0x35,
-    0x68, 0x53, 0x99, 0x55, 0x32, 0x7c, 0x66, 0x51, 0x53, 0x41, 0x0e, 0x3c,
-    0xeb, 0x29, 0x1e, 0x1b, 0x8d, 0x95, 0x69, 0x0b, 0xd8, 0xec, 0x49, 0x3f,
-    0x4d, 0xb0, 0x73, 0x2e, 0xf4, 0x5f, 0x24, 0xd0, 0x90, 0xbf, 0x8e, 0xcd,
-    0x32, 0x8b, 0x65, 0x43, 0xc4, 0x02, 0x62, 0x12, 0x92, 0x47, 0xaf, 0x9a,
-    0xe7, 0xe9, 0x86, 0x58, 0x39, 0x6b, 0xa3, 0x14, 0x79, 0xc9, 0x9a, 0xe5,
-    0x4a, 0x13, 0xb2, 0xda, 0x01, 0x21, 0xc7, 0x65, 0xeb, 0xb0, 0x1c, 0x6c,
-    0x4e, 0x9b, 0x62, 0x73, 0x52, 0xc5, 0xcd, 0x4d, 0x3a, 0x57, 0xc2, 0xb5,
-    0x93, 0xc9, 0x3f, 0xc6, 0x50, 0xf7, 0x23, 0x4e, 0x44, 0xab, 0x61, 0xb6,
-    0x80, 0x00, 0x6c, 0x9f, 0xd8, 0x6b, 0xce, 0x1b, 0x24, 0x43, 0x99, 0x1a,
-    0x65, 0x00, 0x38, 0xb5, 0x29, 0x25, 0xa5, 0xb4, 0xbb, 0x7a, 0xea, 0x40,
-    0xfe, 0x98, 0xf0, 0xae, 0xcd, 0xc9, 0x3d, 0x32, 0x7a, 0xa7, 0x99, 0x24,
-    0x31, 0x09, 0x35, 0x49, 0x48, 0x4a, 0x65, 0xc9, 0x2b, 0x25, 0xd2, 0x81,
-    0xc2, 0x4a, 0xbf, 0x28, 0x3f, 0xdc, 0x4e, 0xe4, 0xf3, 0x7c, 0x22, 0x75,
-    0xaf, 0xad, 0x59, 0x7e, 0x9b, 0x0e, 0x9f, 0x13, 0x2c, 0x4c, 0x6e, 0x6c,
-    0xf2, 0xfa, 0x34, 0xe8, 0x21, 0xd0, 0x11, 0xbe, 0xa2, 0x42, 0x4d, 0xf7,
-    0xd8, 0x0e, 0x09, 0x3c, 0x71, 0x88, 0xd6, 0x70, 0xcd, 0x31, 0xf3, 0x25,
-    0x41, 0x2e, 0xd5, 0x68, 0x95, 0x29, 0xe9, 0x4a, 0x8a, 0xc3, 0x0b, 0x49,
-    0x4a, 0x50, 0xa3, 0xed, 0xdc, 0xf6, 0xb9, 0xdf, 0x18, 0xf0, 0xa6, 0x0d,
-    0xa8, 0x55, 0x07, 0x6a, 0xb5, 0x76, 0x4d, 0xd8, 0x85, 0x0c, 0xee, 0x41,
-    0x37, 0xb5, 0xad, 0xa1, 0xf1, 0xcb, 0x2d, 0xe3, 0xde, 0xa9, 0x5b, 0x6a,
-    0x59, 0x09, 0x41, 0x69, 0x4e, 0x2f, 0x50, 0x00, 0x16, 0xbe, 0xd7, 0x37,
-    0xca, 0xc3, 0x61, 0x99, 0xbe, 0xd0, 0xe3, 0x37, 0xac, 0xc9, 0xcd, 0xb9,
-    0x8d, 0x72, 0x65, 0xca, 0x8d, 0x1a, 0x9f, 0x1d, 0xc0, 0x98, 0xa8, 0x20,
-    0x0d, 0x42, 0xe4, 0x03, 0x63, 0xb8, 0x16, 0x37, 0xb7, 0x3f, 0xd0, 0x3d,
-    0x2b, 0xa9, 0x52, 0xa8, 0xb5, 0x1b, 0xc2, 0x9e, 0xa9, 0x3e, 0x0a, 0xac,
-    0xea, 0x96, 0x92, 0xef, 0x8e, 0x02, 0x48, 0xb6, 0xc3, 0x6d, 0xcf, 0x3e,
-    0xc3, 0x1e, 0x39, 0x2a, 0x3c, 0x19, 0xad, 0x95, 0x46, 0xc8, 0xae, 0xb0,
-    0x11, 0x75, 0x17, 0x9d, 0x6d, 0x94, 0x22, 0xd7, 0xb5, 0xb5, 0x38, 0x40,
-    0xf6, 0xe4, 0x9f, 0x6c, 0x13, 0x55, 0x4e, 0xbe, 0x89, 0x0e, 0xb1, 0x0b,
-    0x25, 0x25, 0xf0, 0xcb, 0xab, 0x6c, 0x3a, 0xd8, 0x6d, 0x68, 0x5d, 0xb7,
-    0xd8, 0xa4, 0xd8, 0xd8, 0x11, 0x72, 0x0d, 0xb1, 0x5d, 0x63, 0x05, 0xca,
-    0xa1, 0x29, 0x42, 0x5c, 0xb0, 0x1a, 0x00, 0x3f, 0x7b, 0xf9, 0x98, 0x4a,
-    0xfe, 0xb9, 0x5b, 0x71, 0xc2, 0x96, 0xa4, 0x14, 0xa2, 0x79, 0xe5, 0x97,
-    0x90, 0xb5, 0xba, 0x46, 0xf3, 0x75, 0x37, 0x73, 0x65, 0x1e, 0xb1, 0x53,
-    0x96, 0xd2, 0x51, 0x25, 0xe8, 0x2a, 0x43, 0x89, 0x4b, 0x6a, 0x4e, 0xe1,
-    0xb2, 0x01, 0x37, 0xee, 0x7f, 0x7b, 0x13, 0x8d, 0x2a, 0xad, 0x06, 0xac,
-    0xed, 0x0f, 0x2f, 0xcd, 0x85, 0x49, 0x95, 0x22, 0x3b, 0xb4, 0xb6, 0x42,
-    0x5c, 0x61, 0xa5, 0x2c, 0x13, 0xa4, 0x13, 0x7b, 0x0d, 0x8d, 0xcf, 0x7c,
-    0x7d, 0x48, 0x77, 0xa8, 0xd2, 0xe9, 0xef, 0xf8, 0x39, 0x6d, 0x2c, 0xc7,
-    0x28, 0x50, 0x71, 0x20, 0x04, 0xdd, 0x36, 0xdc, 0x12, 0x2e, 0x78, 0xf4,
-    0xdf, 0x1e, 0x1d, 0x31, 0xce, 0x99, 0xaa, 0x9b, 0x96, 0xc5, 0x39, 0xfa,
-    0xb5, 0x3a, 0x0e, 0x95, 0xa9, 0xa6, 0x93, 0xf1, 0x0a, 0x42, 0x96, 0x80,
-    0x4d, 0xb5, 0x24, 0x0b, 0x0b, 0x5e, 0xc0, 0x92, 0x36, 0x03, 0x1a, 0xeb,
-    0xf4, 0xd0, 0xe4, 0xa3, 0x52, 0xa8, 0x24, 0xf0, 0xee, 0x6c, 0x32, 0x1c,
-    0xc9, 0xb0, 0x83, 0x38, 0x0e, 0x7a, 0xa5, 0x86, 0x2a, 0x53, 0x35, 0x2a,
-    0x8b, 0x25, 0x01, 0xdd, 0x12, 0x02, 0x95, 0x9f, 0x44, 0x82, 0x72, 0x19,
-    0xe9, 0x68, 0x13, 0x23, 0x20, 0x67, 0x9a, 0xa2, 0xd2, 0x5a, 0xa5, 0xaa,
-    0x24, 0x72, 0x6c, 0x16, 0xf1, 0xd3, 0x72, 0x76, 0x16, 0xc3, 0x36, 0x42,
-    0xe9, 0x8e, 0x68, 0xa5, 0x3a, 0xec, 0x31, 0x5e, 0xa2, 0x35, 0x2a, 0x45,
-    0x99, 0x0d, 0xf8, 0xda, 0x9c, 0x4a, 0xb7, 0x16, 0x00, 0x7e, 0x6d, 0xef,
-    0xf5, 0x03, 0x04, 0x17, 0x54, 0xcc, 0x09, 0x74, 0x3e, 0xac, 0xcd, 0x1d,
-    0x85, 0x83, 0xa8, 0x29, 0x0b, 0x2a, 0x50, 0xf7, 0x1e, 0x71, 0x8d, 0x79,
-    0xf9, 0x8e, 0xb7, 0xf0, 0x4e, 0xd3, 0x0e, 0x64, 0x68, 0xb6, 0xe5, 0xd0,
-    0xa9, 0xa1, 0xd8, 0xed, 0xad, 0x77, 0x37, 0x2a, 0xb6, 0x92, 0xb2, 0x77,
-    0x3c, 0xaa, 0xfe, 0xf8, 0x0a, 0xde, 0x16, 0x9c, 0x29, 0xe0, 0x20, 0x01,
-    0xd4, 0x7d, 0x2f, 0x05, 0x2a, 0xbf, 0x13, 0xe8, 0x73, 0x93, 0x05, 0xd2,
-    0x54, 0xe2, 0x8f, 0x81, 0x00, 0x0f, 0x00, 0x48, 0x19, 0x72, 0xd4, 0xc1,
-    0x8c, 0xbf, 0xd0, 0xc9, 0x10, 0xa5, 0x2e, 0x54, 0x9c, 0xe1, 0x19, 0x84,
-    0xa9, 0x65, 0x4a, 0x07, 0x65, 0x13, 0xde, 0xfa, 0xad, 0x7d, 0xfd, 0x71,
-    0x4a, 0xcf, 0x79, 0x96, 0x83, 0x46, 0xca, 0xb1, 0x62, 0xbb, 0x5c, 0x8b,
-    0x29, 0xf8, 0xcf, 0x32, 0xe2, 0xfc, 0x35, 0x02, 0x43, 0x6d, 0x24, 0xdd,
-    0x4a, 0xb6, 0xc3, 0xf2, 0x8d, 0xf9, 0x27, 0x10, 0x77, 0x17, 0x45, 0xf1,
-    0x94, 0x26, 0x66, 0xb9, 0x4f, 0xac, 0x9e, 0x4a, 0x91, 0x73, 0xf7, 0xb1,
-    0xc7, 0xb5, 0x7b, 0x2a, 0x51, 0x6a, 0x79, 0x3e, 0x5c, 0xc8, 0x95, 0x19,
-    0xcf, 0xa9, 0xa4, 0xeb, 0xb2, 0x9f, 0x51, 0x06, 0xde, 0xa3, 0x83, 0x82,
-    0xac, 0xe1, 0xa9, 0x86, 0x7b, 0xe9, 0x29, 0xe2, 0xea, 0x4f, 0xd2, 0x03,
-    0x2f, 0xe2, 0x75, 0x19, 0xa7, 0x12, 0x7b, 0x27, 0x2d, 0x71, 0x6e, 0xe8,
-    0x02, 0xfb, 0x5c, 0xdc, 0x9b, 0x40, 0x2c, 0xcf, 0x57, 0xa5, 0xc9, 0x6e,
-    0x75, 0x35, 0x55, 0xa5, 0xb1, 0x19, 0xc7, 0x54, 0x7c, 0x26, 0x93, 0x7b,
-    0x79, 0x89, 0xb0, 0x3b, 0x6d, 0x85, 0x08, 0xd4, 0x6c, 0xa4, 0xf4, 0x84,
-    0x80, 0x9a, 0x9c, 0x85, 0x13, 0x62, 0xb2, 0xda, 0x95, 0xfa, 0x01, 0x8e,
-    0x87, 0x43, 0xf1, 0x29, 0x61, 0x8a, 0x76, 0x5c, 0xc9, 0xf4, 0x09, 0x50,
-    0x62, 0x46, 0x6c, 0x27, 0xc6, 0x6c, 0xba, 0xe3, 0xde, 0x51, 0xa9, 0x45,
-    0x77, 0xe4, 0x9b, 0xf0, 0x0f, 0xdf, 0x18, 0xff, 0x00, 0x54, 0x59, 0xa4,
-    0x7f, 0x66, 0x3a, 0x74, 0xc4, 0x37, 0x00, 0xf9, 0xda, 0x4a, 0x54, 0x01,
-    0xf6, 0xf2, 0x7f, 0xa8, 0x18, 0x2d, 0x3f, 0x3d, 0x34, 0x5b, 0x4a, 0x9e,
-    0x65, 0x27, 0xc8, 0x9b, 0x75, 0x17, 0xfa, 0x43, 0xf4, 0xae, 0x1a, 0x69,
-    0x94, 0x87, 0x99, 0x96, 0x48, 0x0b, 0xef, 0x1b, 0x01, 0xbe, 0xe7, 0x33,
-    0x6f, 0x41, 0x12, 0x68, 0xb9, 0x4d, 0x86, 0x23, 0x7c, 0x44, 0x6a, 0x0d,
-    0x5a, 0x53, 0x62, 0xca, 0xf2, 0xc5, 0x74, 0x5c, 0x7d, 0x54, 0x9b, 0x71,
-    0xef, 0x82, 0xf0, 0x32, 0x95, 0x69, 0x6f, 0x29, 0x11, 0xb2, 0x24, 0x97,
-    0xd2, 0x4d, 0xd2, 0x5f, 0x6c, 0xa4, 0xe9, 0x3c, 0x96, 0xae};
-
-std::vector<uint8_t> l2cap_test_packet_6 = {
-    0xf6, 0x03, 0x47, 0x00, 0x0c, 0xc1, 0x5c, 0x0b, 0x8c, 0x33, 0x2b, 0xac,
-    0x14, 0x79, 0x95, 0x37, 0x6a, 0x2b, 0xca, 0x2e, 0xbb, 0x31, 0x0b, 0x4b,
-    0x8a, 0x2a, 0x71, 0xd2, 0x02, 0xbb, 0x10, 0x92, 0x42, 0x47, 0x1c, 0x01,
-    0x82, 0x8b, 0xeb, 0x4e, 0x66, 0x76, 0x58, 0x71, 0x14, 0xe9, 0x11, 0x12,
-    0xf0, 0xd4, 0x35, 0x35, 0x74, 0xda, 0xc3, 0x72, 0x49, 0x36, 0xda, 0xdc,
-    0xe1, 0x69, 0x58, 0x8d, 0x6d, 0x9e, 0xe8, 0x48, 0xe8, 0x91, 0x1d, 0x84,
-    0xc2, 0x19, 0x3c, 0x29, 0x09, 0x1e, 0x9f, 0x40, 0x60, 0x2b, 0x99, 0x1f,
-    0xa9, 0x12, 0x68, 0x52, 0xa0, 0xc4, 0xa0, 0xc3, 0xa7, 0x46, 0x76, 0x3a,
-    0xdb, 0x5a, 0x02, 0x14, 0x14, 0xa4, 0x11, 0xba, 0x45, 0xc5, 0x85, 0xfd,
-    0x70, 0x13, 0xa5, 0xd9, 0x39, 0xd8, 0xcb, 0xf0, 0x5a, 0x9d, 0x32, 0x9a,
-    0xea, 0xd6, 0x59, 0x90, 0x1a, 0x59, 0x2a, 0x4a, 0xfd, 0x2c, 0x38, 0xb5,
-    0xb1, 0xd1, 0x7d, 0x1c, 0xcd, 0x33, 0xb3, 0x35, 0x0d, 0xea, 0x9c, 0x97,
-    0x94, 0xb2, 0xd4, 0xa2, 0xc3, 0x8d, 0xad, 0x20, 0x8b, 0x69, 0x06, 0xe0,
-    0x81, 0xf5, 0x18, 0x8b, 0xe7, 0x5f, 0x8a, 0xa4, 0x75, 0x36, 0xac, 0x23,
-    0xad, 0x49, 0x40, 0x9e, 0x56, 0x50, 0xa2, 0x40, 0x20, 0x80, 0x47, 0x18,
-    0x15, 0x58, 0x9f, 0x76, 0x71, 0xa4, 0xba, 0xb5, 0x5c, 0x79, 0x0f, 0xbd,
-    0x20, 0x7c, 0xea, 0xbf, 0x11, 0x72, 0x75, 0x1f, 0x28, 0x97, 0x3a, 0xc5,
-    0x52, 0xb5, 0x29, 0x70, 0x68, 0xb2, 0xdc, 0x8f, 0x31, 0x0d, 0x97, 0x95,
-    0xe1, 0x91, 0x7d, 0xd4, 0x76, 0xbd, 0xf6, 0xb5, 0xb9, 0xde, 0xfb, 0x61,
-    0x36, 0xb9, 0xfc, 0xcf, 0x47, 0x7c, 0xb5, 0x57, 0x7e, 0xb3, 0xc6, 0xea,
-    0x4c, 0x85, 0x14, 0x1f, 0xdf, 0x0d, 0x9d, 0x3b, 0x8f, 0x36, 0x99, 0x9b,
-    0xeb, 0x4b, 0x1a, 0x89, 0x6a, 0x31, 0xb1, 0x4f, 0x3a, 0x49, 0x2b, 0xb8,
-    0x27, 0xd8, 0x7e, 0xa7, 0x1e, 0x39, 0x6b, 0xa9, 0x5f, 0x1c, 0xfb, 0xb1,
-    0x6b, 0xd1, 0x14, 0xe2, 0x5c, 0x73, 0x50, 0x79, 0xb4, 0xa5, 0x6a, 0x48,
-    0x1c, 0x02, 0x95, 0x6c, 0xa0, 0x2f, 0xc6, 0x1b, 0xa9, 0x32, 0xf2, 0x32,
-    0xf2, 0x4d, 0xad, 0x49, 0x4f, 0x12, 0xaf, 0x9a, 0x80, 0x39, 0xf9, 0xe9,
-    0x12, 0x49, 0xfa, 0xa5, 0x4c, 0x4f, 0xbc, 0x86, 0x87, 0x1b, 0x68, 0xb6,
-    0x40, 0xd8, 0x8b, 0xf2, 0x84, 0x96, 0xaa, 0xce, 0xc8, 0x64, 0xc4, 0x65,
-    0x87, 0x54, 0xca, 0xc5, 0x94, 0x84, 0xb2, 0x92, 0x55, 0xbd, 0xcf, 0x98,
-    0xdc, 0xfe, 0xf8, 0xd9, 0x4b, 0xae, 0x34, 0x14, 0xf2, 0xe8, 0x0c, 0x21,
-    0x29, 0xdc, 0xf8, 0x82, 0xc7, 0xf4, 0xbe, 0x2a, 0xa7, 0x28, 0xb1, 0x2d,
-    0x46, 0xab, 0x95, 0xaa, 0x10, 0x52, 0xf2, 0x95, 0xe2, 0xa5, 0xa4, 0x37,
-    0x76, 0xaf, 0x6e, 0x34, 0x9d, 0xc7, 0xaf, 0xd7, 0x08, 0x35, 0x18, 0xf2,
-    0x20, 0xd4, 0x16, 0xc5, 0x5d, 0x2a, 0x65, 0xf0, 0x8b, 0x8f, 0x35, 0xc1,
-    0xed, 0xa8, 0x11, 0xee, 0x38, 0xc7, 0x5a, 0x85, 0x4e, 0xa9, 0x4f, 0x1c,
-    0x69, 0x42, 0x78, 0x79, 0x81, 0xf7, 0x6f, 0x94, 0x68, 0xa3, 0xcc, 0x53,
-    0x6a, 0xaa, 0x2d, 0xa5, 0x44, 0x2f, 0x74, 0x9b, 0x83, 0xe3, 0xd6, 0x19,
-    0xfa, 0x3f, 0x06, 0x8b, 0x5b, 0xcf, 0xf4, 0x09, 0x4f, 0xc0, 0x43, 0x5e,
-    0x12, 0x1d, 0x79, 0x2d, 0xa1, 0x45, 0x20, 0xba, 0x84, 0x9d, 0x17, 0x23,
-    0x7b, 0x03, 0x63, 0xf6, 0xb6, 0x3a, 0x0e, 0xbb, 0xd3, 0xa6, 0x44, 0x24,
-    0x0c, 0xbd, 0x3d, 0xba, 0x6c, 0xb2, 0xd8, 0x21, 0xb5, 0x30, 0x85, 0xa1,
-    0x47, 0xd4, 0x02, 0x2e, 0x2f, 0xed, 0x8e, 0x7e, 0xfc, 0x3c, 0x32, 0xb7,
-    0xb3, 0xe5, 0x27, 0x72, 0xa4, 0x21, 0x52, 0x75, 0x90, 0x3e, 0x54, 0xe8,
-    0x51, 0xfe, 0x98, 0x6c, 0xfc, 0x47, 0xe7, 0xdc, 0xd7, 0x94, 0xb3, 0xed,
-    0x1d, 0xda, 0x05, 0x5d, 0x71, 0xdb, 0x11, 0x0a, 0x8b, 0x7a, 0x02, 0x9b,
-    0x76, 0xe4, 0x6c, 0xb4, 0x91, 0xb8, 0xed, 0x89, 0xee, 0x39, 0x99, 0xaa,
-    0xb9, 0x88, 0xd8, 0x44, 0x8b, 0xe5, 0xb2, 0x5a, 0x0a, 0xf0, 0xdf, 0x23,
-    0xcf, 0x6d, 0x61, 0xef, 0x0d, 0x38, 0xdc, 0x9d, 0x35, 0xc5, 0x9f, 0xca,
-    0xb2, 0x0e, 0xe6, 0xd7, 0x00, 0x7c, 0xe0, 0x1f, 0x50, 0x8f, 0x55, 0xf2,
-    0xa3, 0xaa, 0x45, 0x4a, 0x04, 0x79, 0xb0, 0x55, 0xb8, 0x91, 0x19, 0x8d,
-    0x4d, 0xaa, 0xde, 0xa3, 0x80, 0x47, 0xd3, 0x09, 0xea, 0xae, 0xf5, 0x11,
-    0x6d, 0xa5, 0xc7, 0x1c, 0x99, 0x15, 0xbd, 0x65, 0x01, 0x49, 0x8b, 0xa0,
-    0x6a, 0xb5, 0xf4, 0x8b, 0x27, 0x9d, 0x8f, 0xe9, 0x8b, 0x87, 0x4c, 0xba,
-    0xd9, 0x4b, 0xce, 0x4d, 0xff, 0x00, 0x07, 0xcc, 0x94, 0x71, 0x16, 0x72,
-    0x80, 0x05, 0x6d, 0x5d, 0x71, 0xdd, 0x27, 0x61, 0x71, 0xc8, 0x37, 0x3d,
-    0xef, 0xcf, 0x38, 0x79, 0x9f, 0x93, 0x8c, 0x58, 0x4e, 0xd4, 0x68, 0xf2,
-    0x4b, 0x4c, 0xdb, 0x53, 0x8c, 0x2c, 0x6a, 0x09, 0x23, 0x6f, 0x29, 0x3b,
-    0x8f, 0x4f, 0xbe, 0x04, 0x9c, 0x77, 0x52, 0x92, 0x58, 0x97, 0xa9, 0xdd,
-    0x2a, 0xe6, 0x0e, 0x47, 0xd2, 0x0e, 0x25, 0x2e, 0x4c, 0x27, 0x8d, 0xa7,
-    0x8d, 0x8e, 0xd7, 0xb7, 0x95, 0xf5, 0xf5, 0xf5, 0x89, 0x1f, 0x47, 0xa4,
-    0x67, 0x06, 0x27, 0x4a, 0x35, 0xc7, 0x25, 0x86, 0xd4, 0xd1, 0x08, 0xf1,
-    0x52, 0x52, 0x1c, 0xba, 0x55, 0x71, 0xbf, 0xd0, 0x1f, 0xbe, 0x00, 0xaf,
-    0x5c, 0xa8, 0x5a, 0x94, 0x10, 0x5a, 0x84, 0xcb, 0x81, 0x5c, 0x27, 0x48,
-    0xf1, 0xd4, 0x3e, 0xe4, 0x95, 0x7b, 0x9f, 0xd3, 0x14, 0x2f, 0xe6, 0xaa,
-    0x6d, 0x4d, 0x6c, 0xd3, 0xdb, 0x42, 0x5a, 0x79, 0x32, 0x1d, 0x2a, 0x4a,
-    0x2e, 0x92, 0x2c, 0x40, 0xb6, 0xae, 0x49, 0xb0, 0xb9, 0x3e, 0xf8, 0x47,
-    0xcc, 0xb4, 0xc3, 0x4a, 0x6d, 0x6b, 0x2e, 0x25, 0xc2, 0xe4, 0xa7, 0xc1,
-    0x08, 0xb8, 0x03, 0x4b, 0xa4, 0xff, 0x00, 0xa1, 0x18, 0x6f, 0xa9, 0xce,
-    0x2e, 0x6a, 0x8a, 0xda, 0x9c, 0x37, 0x25, 0x47, 0xdb, 0xf9, 0x87, 0x1c,
-    0x20, 0xa3, 0xda, 0x25, 0xc3, 0x9a, 0x80, 0x56, 0xb9, 0x9d, 0xb7, 0x85,
-    0x77, 0xe9, 0xb4, 0xfa, 0xab, 0x28, 0x11, 0xe7, 0x2e, 0x39, 0x24, 0x85,
-    0xad, 0x06, 0xc1, 0x06, 0xfe, 0xd7, 0xfb, 0xed, 0x82, 0x39, 0x17, 0x2c,
-    0xd0, 0xd9, 0x9e, 0xf4, 0x3c, 0xcf, 0x54, 0x5f, 0x88, 0xbb, 0x18, 0x8b,
-    0x5b, 0xc4, 0xb6, 0xbd, 0xf9, 0x0a, 0x1d, 0xfd, 0xb6, 0xf4, 0xb6, 0x25,
-    0x94, 0xb9, 0x92, 0x62, 0x49, 0x75, 0xd8, 0xce, 0xa9, 0xb5, 0x29, 0xc5,
-    0x6d, 0x7d, 0xb9, 0x3b, 0x1c, 0x51, 0x28, 0x4e, 0x48, 0xaa, 0xd2, 0x5e,
-    0x79, 0xf8, 0xbe, 0x46, 0x52, 0x95, 0x2c, 0x84, 0xdd, 0x04, 0x15, 0x69,
-    0xe7, 0xd6, 0xfd, 0xb0, 0x15, 0xd3, 0x31, 0x2c, 0x9b, 0x71, 0x92, 0x9e,
-    0xb0, 0x2a, 0x5d, 0x9a, 0x26, 0x2b, 0x50, 0x2a, 0x68, 0x31, 0x30, 0xad,
-    0xc0, 0x04, 0x28, 0xfb, 0x67, 0xd7, 0x3f, 0x13, 0x15, 0xe8, 0x99, 0x07,
-    0x2d, 0x48, 0x6d, 0x0d, 0xc5, 0x61, 0x12, 0xdc, 0x5b, 0x6e, 0x5d, 0xa5,
-    0x2f, 0xec, 0x13, 0xb8, 0x3c, 0x1b, 0x0d, 0xf7, 0xbd, 0xce, 0x05, 0xc1,
-    0xa4, 0x39, 0x43, 0xca, 0x15, 0x0a, 0x3b, 0xad, 0x84, 0x2e, 0x3b, 0x6f,
-    0xb4, 0x42, 0x56, 0x5c, 0x06, 0xc5, 0x44, 0x79, 0xac, 0x2e, 0x34, 0xdb,
-    0x7b, 0x0c, 0x2b, 0x65, 0x9a, 0xcd, 0x47, 0x2d, 0x54, 0x92};
-
-std::vector<uint8_t> l2cap_test_packet_7 = {
-    0xf6, 0x03, 0x47, 0x00, 0x0e, 0xc1, 0xa0, 0xaa, 0x33, 0xea, 0x72, 0x1b,
-    0xab, 0xb2, 0xa3, 0xea, 0x1a, 0xae, 0x3c, 0xd7, 0x07, 0xe6, 0xb5, 0xff,
-    0x00, 0xec, 0x61, 0xd2, 0x7e, 0x67, 0x6b, 0x30, 0x49, 0x9a, 0xb0, 0x9f,
-    0x04, 0x2c, 0x36, 0x1f, 0xb6, 0xc0, 0x21, 0x68, 0x20, 0x8d, 0xb8, 0xb5,
-    0xb0, 0xc7, 0x84, 0x66, 0x82, 0xa7, 0x14, 0x39, 0xa4, 0xfd, 0x22, 0x3f,
-    0xf1, 0x5f, 0x0e, 0xcc, 0x52, 0x24, 0xd0, 0xdb, 0x80, 0x1b, 0x2d, 0x26,
-    0xe3, 0x96, 0x63, 0xe7, 0x1a, 0xf4, 0xf9, 0xb2, 0xe3, 0xe5, 0xb9, 0x2f,
-    0xb6, 0x99, 0x09, 0x53, 0x71, 0xf4, 0x25, 0xc4, 0x70, 0x8b, 0x2b, 0x7b,
-    0xff, 0x00, 0x97, 0xd3, 0x08, 0x59, 0x5f, 0xab, 0x71, 0xd2, 0xa5, 0xc5,
-    0xae, 0x53, 0x64, 0x25, 0xbd, 0x56, 0xf8, 0x86, 0x5e, 0x2a, 0x5a, 0x2c,
-    0x6f, 0x7b, 0x1e, 0x37, 0xdf, 0x6c, 0x58, 0xd2, 0xdd, 0x2e, 0xa5, 0xd2,
-    0x9a, 0x1f, 0xf0, 0xc2, 0xcf, 0xc5, 0xae, 0x0b, 0xc2, 0x62, 0x19, 0xf9,
-    0x8d, 0xd3, 0xb2, 0x96, 0x3e, 0xa9, 0xef, 0x8e, 0x46, 0x7d, 0x6b, 0x8b,
-    0x52, 0x93, 0x09, 0xc4, 0x95, 0xa1, 0x0f, 0xad, 0x36, 0x1c, 0xde, 0xe4,
-    0x6d, 0x83, 0x75, 0x4a, 0x93, 0xe8, 0x29, 0x71, 0xbc, 0xb6, 0x3e, 0x36,
-    0x8a, 0x83, 0xd5, 0xe9, 0x96, 0x29, 0xb2, 0x4e, 0xb2, 0x78, 0x41, 0x4d,
-    0x88, 0x23, 0x5b, 0x00, 0x05, 0xf7, 0xd8, 0xe9, 0x1d, 0x04, 0xec, 0xac,
-    0xbb, 0x9a, 0xa0, 0xae, 0x45, 0x3a, 0xb4, 0x15, 0x2d, 0xb2, 0x16, 0xd1,
-    0x69, 0x94, 0xb6, 0xf2, 0x8d, 0xff, 0x00, 0x38, 0xb5, 0x96, 0x07, 0x3c,
-    0x5f, 0x1f, 0x12, 0x8e, 0x69, 0x0d, 0x33, 0x26, 0xa0, 0x83, 0x52, 0x84,
-    0x96, 0xf4, 0x78, 0x91, 0xd0, 0x94, 0x92, 0x9b, 0x8f, 0x99, 0x36, 0xb1,
-    0xe3, 0x8d, 0xb0, 0x1f, 0xa4, 0x19, 0x3e, 0x7c, 0x69, 0x10, 0xf3, 0x0b,
-    0x8c, 0x7c, 0x38, 0x68, 0x97, 0x63, 0xb0, 0xf1, 0xf3, 0xba, 0x46, 0xe0,
-    0x1e, 0x39, 0xf4, 0xed, 0x83, 0x15, 0xac, 0xf6, 0xed, 0x26, 0x24, 0x88,
-    0x34, 0x94, 0xaf, 0xc6, 0xd4, 0x4b, 0xcb, 0x6d, 0x37, 0xd1, 0x7d, 0xac,
-    0x3d, 0xf9, 0xdb, 0x9c, 0x63, 0x5c, 0x8c, 0xac, 0xcc, 0xa9, 0x76, 0x75,
-    0x01, 0xbe, 0x56, 0xca, 0xfe, 0x50, 0xc0, 0xd2, 0x18, 0x9a, 0x94, 0x33,
-    0x33, 0xcd, 0x04, 0x11, 0xbd, 0xed, 0x97, 0x80, 0xd7, 0xa0, 0xb1, 0x31,
-    0x7b, 0xe9, 0x12, 0xe8, 0xec, 0xe5, 0x1b, 0xd3, 0x65, 0x25, 0x2b, 0x7e,
-    0x38, 0x94, 0xb2, 0xa5, 0x15, 0x0b, 0x8d, 0x8d, 0xc6, 0xd6, 0x20, 0x1d,
-    0xc0, 0xe0, 0x8c, 0x47, 0xfa, 0xd7, 0x35, 0x11, 0x33, 0xed, 0x55, 0xe7,
-    0x8b, 0x6a, 0xd4, 0x84, 0xb8, 0x46, 0xab, 0x0b, 0x80, 0x47, 0xef, 0x6c,
-    0x6c, 0xf4, 0x0a, 0x53, 0xf3, 0xe4, 0xd4, 0x59, 0xbc, 0x86, 0x5b, 0x4c,
-    0x72, 0xd8, 0x4b, 0xbb, 0x06, 0xf5, 0x21, 0x57, 0x1f, 0x5b, 0x81, 0x7c,
-    0x2a, 0x7e, 0x26, 0x9b, 0x7e, 0x36, 0x64, 0x8b, 0xe6, 0x4b, 0xa8, 0x98,
-    0xd2, 0x3c, 0xac, 0x82, 0xa2, 0xa0, 0x9b, 0x77, 0x23, 0x6d, 0xf7, 0xc2,
-    0x83, 0xbc, 0x0b, 0x68, 0x34, 0x9d, 0x02, 0xb2, 0xe9, 0x09, 0xce, 0x80,
-    0x86, 0x94, 0xb4, 0x1b, 0x8b, 0x9d, 0x75, 0xb5, 0xf2, 0x8d, 0x18, 0x68,
-    0x47, 0xf3, 0x58, 0x60, 0x04, 0x24, 0x96, 0x46, 0xab, 0xaa, 0xdb, 0x59,
-    0x69, 0x23, 0x7e, 0xe4, 0xf6, 0x18, 0x8c, 0x65, 0x88, 0x92, 0xe5, 0xd7,
-    0xfe, 0x12, 0x23, 0x0b, 0x79, 0xd5, 0x28, 0xa7, 0x4a, 0x47, 0xbf, 0xed,
-    0x8b, 0x58, 0x8b, 0x1d, 0x59, 0xe9, 0xb6, 0xd6, 0xa0, 0xd2, 0x1c, 0x80,
-    0x95, 0x6c, 0x6c, 0x51, 0xe6, 0x26, 0xff, 0x00, 0x6e, 0x70, 0x0e, 0xa7,
-    0x99, 0x72, 0xbe, 0x49, 0x79, 0xf6, 0x29, 0x30, 0x99, 0x9c, 0xe3, 0xaa,
-    0xd6, 0xe0, 0x4a, 0x8a, 0x75, 0x2b, 0x7b, 0x82, 0x46, 0xf6, 0x3d, 0xc6,
-    0x1e, 0xa4, 0xe4, 0x91, 0x35, 0x4c, 0x61, 0x4e, 0x2a, 0xc9, 0x48, 0x37,
-    0xf5, 0x88, 0xd4, 0xe4, 0xeb, 0xb2, 0xb5, 0x59, 0x86, 0xd8, 0x41, 0x5a,
-    0xd4, 0x13, 0x6e, 0x43, 0x5c, 0xc9, 0xf3, 0x86, 0x4c, 0xb5, 0x16, 0x9f,
-    0x93, 0x61, 0x8a, 0x85, 0x46, 0xa4, 0xc7, 0x8e, 0xa4, 0xa8, 0x2d, 0x09,
-    0x57, 0x97, 0x56, 0xdb, 0x7b, 0x9d, 0xb0, 0xbd, 0x9d, 0x69, 0xd5, 0x4c,
-    0xc7, 0x25, 0xea, 0xab, 0x2c, 0x06, 0xda, 0x6e, 0x3a, 0xec, 0x93, 0xf3,
-    0x2a, 0xf6, 0x55, 0xcd, 0xb8, 0xe0, 0x58, 0x5c, 0xfb, 0xde, 0xf8, 0x9b,
-    0xe6, 0x0c, 0xd3, 0x2b, 0x30, 0xd5, 0x05, 0x4a, 0xa4, 0xab, 0xbf, 0xa9,
-    0x21, 0x0d, 0x36, 0x90, 0x96, 0x9a, 0x48, 0xb5, 0x92, 0x00, 0x1e, 0x82,
-    0xd8, 0x7d, 0x9d, 0xd4, 0x5a, 0x62, 0xe8, 0x72, 0x22, 0xc7, 0x6d, 0xe5,
-    0x3a, 0xe4, 0x52, 0xd0, 0x48, 0x05, 0x37, 0x51, 0xb0, 0xd4, 0x3d, 0x3b,
-    0xfe, 0xd8, 0xc7, 0x51, 0x9f, 0x79, 0xf6, 0x44, 0xac, 0x93, 0x47, 0x83,
-    0xa1, 0x37, 0xb7, 0xdf, 0x58, 0xdf, 0x45, 0xa1, 0xa1, 0x89, 0x83, 0x3f,
-    0x38, 0xbe, 0x27, 0x8f, 0x90, 0x17, 0xe5, 0x19, 0xf8, 0x7e, 0xa9, 0x7f,
-    0x0c, 0xcf, 0x74, 0xe6, 0x41, 0x4a, 0xd2, 0xeb, 0xce, 0xb3, 0xa8, 0xde,
-    0xe0, 0x68, 0x5e, 0xff, 0x00, 0xed, 0x86, 0xef, 0xc4, 0xae, 0x57, 0xad,
-    0x66, 0x9c, 0xf5, 0x96, 0xa9, 0x99, 0x7a, 0x9d, 0x22, 0xa3, 0x2d, 0xe8,
-    0xaa, 0x40, 0x08, 0x48, 0x09, 0x16, 0x37, 0x25, 0x44, 0xec, 0x91, 0x6d,
-    0xee, 0x48, 0x18, 0x40, 0xe9, 0x72, 0x97, 0x1f, 0x38, 0xd0, 0xe4, 0x4c,
-    0x01, 0x82, 0xed, 0x49, 0xc4, 0x5d, 0xc5, 0x00, 0x2e, 0xa4, 0xe9, 0x1b,
-    0xf1, 0xc9, 0xb6, 0x3a, 0x7f, 0x38, 0x67, 0x5a, 0x2e, 0x59, 0xa6, 0xa5,
-    0xe0, 0x17, 0x2e, 0xa6, 0xb8, 0xfa, 0x52, 0xdb, 0x00, 0xd8, 0x26, 0xfb,
-    0x6b, 0x20, 0x5c, 0xef, 0xc2, 0x45, 0xf0, 0x93, 0x8e, 0x17, 0x35, 0x2b,
-    0x5d, 0x93, 0x71, 0x96, 0x8a, 0xd6, 0x59, 0x02, 0xde, 0x3d, 0xe1, 0xed,
-    0xbc, 0x50, 0xb0, 0xeb, 0x0d, 0xcd, 0x53, 0xdf, 0x6c, 0x1d, 0x56, 0x6f,
-    0xe5, 0x63, 0xf4, 0x85, 0xbe, 0x94, 0xf4, 0x72, 0x85, 0xd3, 0xd8, 0x08,
-    0xcc, 0xb9, 0x96, 0x4b, 0x33, 0xab, 0x2c, 0xd8, 0x87, 0x41, 0xbc, 0x68,
-    0x8b, 0xec, 0x1b, 0x07, 0xff, 0x00, 0x51, 0x63, 0xfb, 0xdd, 0xbb, 0x0e,
-    0xf8, 0xdb, 0xcc, 0xd9, 0xc6, 0x7d, 0x6e, 0x97, 0x22, 0x99, 0x97, 0xdc,
-    0x30, 0xd2, 0xa6, 0xd4, 0x18, 0x23, 0xe7, 0x70, 0xff, 0x00, 0x7d, 0x44,
-    0xf0, 0x2f, 0xe9, 0xbd, 0xed, 0xef, 0x88, 0x96, 0x6e, 0xcd, 0xdd, 0x45,
-    0xce, 0x15, 0x44, 0x29, 0xea, 0x7c, 0xe4, 0x42, 0x6a, 0xe1, 0xa6, 0x49,
-    0x08, 0xda, 0xe7, 0x7b, 0x5f, 0xcb, 0x7f, 0x41, 0xe9, 0xdf, 0x07, 0xa9,
-    0xaf, 0xe7, 0x01, 0x14, 0xb6, 0xb8, 0x4d, 0x0f, 0x11, 0x21, 0x09, 0x40,
-    0x76, 0xe5, 0x24, 0xef, 0x60, 0x07, 0xdf, 0x6c, 0x0f, 0x6b, 0x07, 0xd4,
-    0xa6, 0xdd, 0x13, 0x53, 0xa8, 0x2b, 0x5e, 0xc2, 0xdd, 0xd4, 0xf4, 0x82,
-    0xcd, 0x87, 0x52, 0x9e, 0xce, 0x55, 0xb2, 0x40, 0xde, 0xc7, 0xda, 0xff,
-    0x00, 0x3f, 0xe6, 0x14, 0xb2, 0x2c, 0x09, 0x51, 0x33, 0x8c, 0x66, 0x96,
-    0xe1, 0x7d, 0xc5, 0x2d, 0xc4, 0x94, 0x29, 0xcb, 0xf9, 0x86, 0xc6, 0xe4,
-    0x5e, 0xdd, 0xf0, 0x56, 0x6c, 0xc9, 0x93, 0x95, 0xfa, 0xf6};
-
-std::vector<uint8_t> l2cap_test_packet_8 = {
-    0xf6, 0x03, 0x47, 0x00, 0x10, 0xc1, 0x53, 0x69, 0x65, 0xc7, 0x52, 0xcc,
-    0xa7, 0x94, 0x02, 0xd5, 0xa8, 0xa0, 0x6b, 0xde, 0xde, 0xbd, 0xbf, 0x4c,
-    0x39, 0xe4, 0xec, 0x9f, 0x57, 0x77, 0x33, 0x35, 0x50, 0x9f, 0x4e, 0x44,
-    0x25, 0x34, 0xab, 0xa5, 0xd0, 0x8d, 0x3a, 0x81, 0xd8, 0x85, 0x71, 0xc7,
-    0x37, 0xe4, 0x93, 0x84, 0x99, 0x2f, 0xb0, 0xd5, 0x72, 0xae, 0x88, 0xe8,
-    0x7a, 0x4a, 0xdb, 0x98, 0xf0, 0x75, 0x09, 0x68, 0x9d, 0x0a, 0xd5, 0xb0,
-    0xbf, 0x1b, 0xdb, 0x0e, 0x75, 0x19, 0x29, 0x84, 0x51, 0xd0, 0x85, 0xa0,
-    0xf1, 0xf1, 0xde, 0xdb, 0xd8, 0x8f, 0xda, 0x1b, 0xb0, 0xc3, 0x8c, 0xc8,
-    0x9f, 0xee, 0x94, 0x1b, 0x04, 0x2b, 0xfc, 0x8d, 0xb6, 0x1b, 0x9e, 0x86,
-    0x13, 0x32, 0xee, 0x51, 0x95, 0x26, 0x62, 0x97, 0x2b, 0xca, 0x85, 0x38,
-    0x74, 0x36, 0x8d, 0xd4, 0xab, 0x9d, 0xbe, 0x98, 0x69, 0xa8, 0xfc, 0x0d,
-    0x1c, 0x22, 0x1c, 0x55, 0x32, 0x08, 0x1b, 0xa5, 0x0e, 0x6a, 0x08, 0xf5,
-    0x04, 0x8e, 0x4f, 0x7d, 0xb1, 0xf9, 0x3a, 0x8f, 0x99, 0xea, 0x68, 0x4a,
-    0x63, 0xc8, 0x85, 0x01, 0xbe, 0x74, 0x97, 0x81, 0xd3, 0x7f, 0x5b, 0x72,
-    0x71, 0xa3, 0x1b, 0xa7, 0x33, 0x18, 0x92, 0xdb, 0x95, 0x3a, 0xd3, 0x84,
-    0xba, 0x82, 0xa1, 0xe0, 0x46, 0x71, 0x6a, 0x29, 0xe3, 0xb0, 0x36, 0xc6,
-    0x54, 0xe1, 0xea, 0x8c, 0xd0, 0x0b, 0x75, 0x36, 0x1c, 0xb2, 0x10, 0xa0,
-    0xf7, 0xc4, 0x6c, 0x37, 0x86, 0xc1, 0x96, 0xa4, 0x1e, 0x35, 0x0c, 0x8a,
-    0xc8, 0xb9, 0x3d, 0x32, 0xf6, 0xc8, 0x43, 0x2e, 0x4d, 0x99, 0x97, 0xd4,
-    0x5c, 0x4d, 0x69, 0x97, 0x3c, 0x55, 0x0b, 0xa6, 0x42, 0xaf, 0x66, 0xc6,
-    0x92, 0x6c, 0x12, 0x0d, 0xbe, 0xfe, 0xbd, 0xf0, 0xcf, 0x05, 0xa8, 0x4e,
-    0xd6, 0x27, 0x1a, 0x5b, 0xc8, 0x2c, 0x08, 0x8d, 0x82, 0xb6, 0x55, 0x70,
-    0xa5, 0x00, 0xaf, 0x5e, 0xdb, 0xe1, 0x61, 0x8e, 0x9b, 0x44, 0x0a, 0x68,
-    0xbd, 0x5a, 0x7d, 0x69, 0x28, 0x05, 0x2a, 0x5a, 0xc8, 0xf2, 0xfa, 0x7b,
-    0x7d, 0x30, 0xdd, 0x95, 0xa9, 0x54, 0xbc, 0xb6, 0xc4, 0x8b, 0xcf, 0x69,
-    0x48, 0x5f, 0x9c, 0xf9, 0x49, 0x3b, 0x0b, 0x6e, 0x7b, 0xe1, 0x86, 0x83,
-    0x40, 0x98, 0x91, 0x9b, 0x0f, 0x39, 0x60, 0x90, 0x0e, 0xf1, 0x1b, 0xc6,
-    0xf8, 0xe6, 0x56, 0xbb, 0x28, 0xa4, 0xa5, 0x4a, 0x53, 0x84, 0x8d, 0x41,
-    0xd8, 0xc6, 0x8e, 0x49, 0x2b, 0xfe, 0x58, 0xa4, 0x2c, 0x3a, 0xb4, 0x07,
-    0x1a, 0x2d, 0x2e, 0xcb, 0x29, 0xbe, 0x95, 0x91, 0xcf, 0xf9, 0x86, 0x34,
-    0x1b, 0xc8, 0xf4, 0x8c, 0xaf, 0x5e, 0x7b, 0x30, 0xd7, 0x5a, 0x69, 0xe4,
-    0x15, 0xf8, 0x89, 0x2e, 0x3a, 0x34, 0x81, 0xea, 0x07, 0xae, 0x0e, 0xf4,
-    0xc1, 0xba, 0x5d, 0x63, 0xa7, 0xae, 0xc4, 0x55, 0x72, 0x1c, 0x19, 0xf0,
-    0x66, 0x38, 0x02, 0x5f, 0x41, 0xf9, 0x54, 0x41, 0x1c, 0x6f, 0x6f, 0x70,
-    0x0e, 0xe2, 0xc7, 0x1e, 0x95, 0x1c, 0xa7, 0x95, 0x6a, 0x8f, 0x78, 0x99,
-    0xa7, 0x38, 0xbb, 0x31, 0x60, 0xec, 0xdc, 0x55, 0x04, 0xb2, 0x91, 0xed,
-    0xab, 0x73, 0xf5, 0x23, 0x1e, 0xf3, 0x75, 0x49, 0x44, 0x23, 0x3e, 0xf2,
-    0x92, 0x4d, 0x87, 0x99, 0xce, 0x3e, 0x82, 0xa0, 0x54, 0x25, 0x95, 0x47,
-    0x96, 0xed, 0x52, 0x14, 0xb4, 0x0c, 0xae, 0x0e, 0x47, 0x63, 0x7d, 0xad,
-    0x7f, 0x13, 0xf3, 0x08, 0x59, 0xa7, 0xa9, 0x90, 0xe7, 0xd4, 0x3f, 0x87,
-    0xd3, 0xd6, 0x44, 0x73, 0xb1, 0x7d, 0x46, 0xca, 0xb7, 0x64, 0x8b, 0x7c,
-    0xa3, 0x8d, 0x86, 0xe7, 0xb9, 0xed, 0x80, 0xd4, 0x1a, 0xac, 0x04, 0xb8,
-    0xe1, 0x71, 0x0b, 0xd2, 0xb7, 0x09, 0xdc, 0xdf, 0x49, 0xdf, 0x6b, 0x1f,
-    0xad, 0xcf, 0xed, 0x8a, 0xe2, 0x32, 0x5e, 0x40, 0x85, 0x1d, 0x89, 0x14,
-    0xa8, 0x54, 0xea, 0xb8, 0x52, 0x94, 0x1c, 0x0f, 0x4f, 0x53, 0x3e, 0x1f,
-    0xf7, 0x46, 0xc8, 0x37, 0x36, 0xbd, 0xed, 0xc6, 0x18, 0xa9, 0xf4, 0xfe,
-    0x9a, 0xa6, 0x12, 0x14, 0xfd, 0x0c, 0x31, 0x25, 0x0a, 0x21, 0xe6, 0x58,
-    0x43, 0xce, 0x83, 0xb6, 0xc5, 0x2e, 0x5b, 0x71, 0xfa, 0x61, 0x36, 0xa1,
-    0x3e, 0x26, 0x94, 0x4b, 0xae, 0x0f, 0x33, 0x18, 0x26, 0x3b, 0x79, 0xb7,
-    0x4a, 0x9e, 0x70, 0x78, 0x00, 0x32, 0x1e, 0xa7, 0xde, 0x37, 0x7a, 0x17,
-    0xe0, 0x3b, 0x48, 0x42, 0x53, 0xe0, 0x3a, 0xfb, 0xa9, 0x5b, 0xee, 0x29,
-    0xa1, 0xc9, 0x06, 0xc7, 0x9e, 0xc0, 0x5b, 0x02, 0x7f, 0x12, 0x50, 0xd2,
-    0xdd, 0x7e, 0x93, 0x25, 0x20, 0x05, 0x29, 0x82, 0x90, 0x37, 0xb1, 0xb1,
-    0x1e, 0x9f, 0x43, 0x86, 0xaa, 0x5d, 0x7f, 0x25, 0x51, 0x5d, 0x0b, 0xa7,
-    0x50, 0xaa, 0x37, 0x00, 0x68, 0x09, 0x69, 0x66, 0xc3, 0xef, 0x84, 0xbe,
-    0xa7, 0xe6, 0x98, 0xb9, 0xb2, 0xbf, 0x16, 0x33, 0x50, 0x64, 0xc2, 0xf8,
-    0x26, 0xff, 0x00, 0xe7, 0x24, 0xa5, 0x4a, 0x4f, 0xae, 0xe3, 0x8d, 0xf9,
-    0xe3, 0x6c, 0x60, 0x4b, 0x8c, 0xf6, 0x25, 0x01, 0x60, 0xaa, 0xf7, 0xc8,
-    0xc6, 0x57, 0x18, 0xec, 0x90, 0x45, 0xf2, 0xf1, 0xb7, 0xca, 0xe6, 0x24,
-    0x3d, 0x41, 0x97, 0x21, 0x1f, 0x0d, 0xf0, 0x4e, 0xa2, 0x3c, 0xc7, 0x96,
-    0x4e, 0xa5, 0x10, 0x0f, 0x86, 0x05, 0x92, 0x8b, 0x9f, 0xca, 0x76, 0xfd,
-    0x31, 0x3c, 0x10, 0xaa, 0xae, 0xbe, 0xaf, 0xfc, 0xad, 0x97, 0x97, 0x7d,
-    0xce, 0x92, 0xa3, 0xfa, 0xe2, 0xae, 0x8a, 0x4c, 0x1a, 0xef, 0x50, 0x69,
-    0x54, 0x9a, 0x83, 0xc9, 0x62, 0x3f, 0xc0, 0xba, 0xf1, 0x71, 0x36, 0x3a,
-    0x52, 0x3e, 0x5d, 0xcf, 0xa0, 0x37, 0xbe, 0x07, 0xe6, 0x8c, 0x85, 0x9a,
-    0xe3, 0xcf, 0x28, 0xc9, 0xd5, 0x29, 0xb5, 0x66, 0x42, 0x43, 0x88, 0x44,
-    0x72, 0xa2, 0xbd, 0x2a, 0xbd, 0xb9, 0xdd, 0x5c, 0x1b, 0x73, 0xf5, 0xc5,
-    0x33, 0x0d, 0xb6, 0xf3, 0x34, 0xd0, 0xe7, 0x19, 0xb1, 0xb9, 0x00, 0x01,
-    0x90, 0xb9, 0x1a, 0xab, 0x2f, 0x28, 0x57, 0x55, 0x29, 0xb7, 0xc2, 0xa6,
-    0x0a, 0x49, 0xd8, 0xdb, 0x5c, 0xa0, 0x05, 0x1f, 0x29, 0x54, 0xdd, 0xa7,
-    0xa9, 0xe7, 0xe3, 0x53, 0xa2, 0x10, 0x9b, 0xb7, 0xe2, 0x4f, 0x09, 0x2e,
-    0x0b, 0x5e, 0xe0, 0x04, 0x2a, 0xff, 0x00, 0xb6, 0x3c, 0x19, 0xcb, 0xd9,
-    0xd9, 0x45, 0x3f, 0x0d, 0x47, 0x8e, 0x9d, 0x48, 0x4a, 0xbc, 0xa5, 0x2a,
-    0xb5, 0xc6, 0xd7, 0xb9, 0x36, 0x3e, 0xd8, 0x0e, 0x89, 0x59, 0xb5, 0x89,
-    0x4b, 0x82, 0xa9, 0x72, 0xe3, 0xb8, 0x83, 0x65, 0x24, 0xf9, 0x74, 0x9f,
-    0x43, 0xb6, 0xc7, 0xeb, 0x82, 0xb4, 0xea, 0x6e, 0x75, 0x9e, 0xca, 0xa5,
-    0x36, 0xed, 0x49, 0xc4, 0xa1, 0x5a, 0x54, 0x52, 0x6f, 0xc7, 0x3c, 0x63,
-    0x43, 0xb8, 0xa9, 0xa6, 0xcf, 0x0a, 0x8a, 0xc5, 0xbf, 0xf3, 0xf7, 0xe8,
-    0x04, 0x71, 0x6e, 0x9f, 0x4a, 0x51, 0xcd, 0x0b, 0x3d, 0x48, 0xfa, 0xde,
-    0x33, 0x30, 0xe5, 0xec, 0xe9, 0x12, 0x9a, 0x89, 0xd5, 0x86, 0x99, 0x6a,
-    0x34, 0x75, 0x78, 0x88, 0xd4, 0x05, 0x8a, 0x86, 0xe1, 0x36, 0xb7, 0x7b,
-    0x7d, 0x31, 0xeb, 0x53, 0xa8, 0x67, 0xc8, 0x49, 0x65, 0x6e, 0x39, 0x22,
-    0x13, 0x2a, 0x17, 0x65, 0x41, 0xb5, 0xb4, 0x9b, 0x13, 0xdb, 0x55, 0x88,
-    0x1b, 0xf7, 0xc3, 0xfd, 0x0e, 0x44, 0xc7, 0xa8, 0x2c, 0xc1, 0xac, 0x34,
-    0x92, 0xb6, 0x27, 0xc7, 0x6d, 0x68, 0x51, 0xb8, 0xa4, 0x1d};
-
-std::vector<uint8_t> l2cap_test_packet_9 = {0x09, 0x00, 0x47, 0x00, 0x12,
-                                            0x81, 0x3c, 0x1d, 0xc7, 0x62,
-                                            0x45, 0x1a, 0x78};
-
-// complete_l2cap_packet is the l2cap packet that should be created when
-// assemble is called on a vector<L2capSdu*> that contains the previous 9 test
-// packets.
-std::vector<uint8_t> complete_l2cap_packet = {
-    0x95, 0x1f, 0x47, 0x00, 0x02, 0x1f, 0x95, 0xcb, 0x00, 0x00, 0x00, 0x01,
-    0x01, 0x00, 0x33, 0x00, 0x49, 0x00, 0x4d, 0x00, 0x47, 0x00, 0x5f, 0x00,
-    0x32, 0x00, 0x30, 0x00, 0x31, 0x00, 0x37, 0x00, 0x30, 0x00, 0x36, 0x00,
-    0x30, 0x00, 0x36, 0x00, 0x5f, 0x00, 0x31, 0x00, 0x35, 0x00, 0x34, 0x00,
-    0x33, 0x00, 0x33, 0x00, 0x38, 0x00, 0x2e, 0x00, 0x6a, 0x00, 0x70, 0x00,
-    0x67, 0x00, 0x00, 0x42, 0x00, 0x0e, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x2f,
-    0x6a, 0x70, 0x65, 0x67, 0x00, 0xc3, 0x00, 0x12, 0x30, 0x03, 0x97, 0x01,
-    0x48, 0x1f, 0x45, 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49,
-    0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff,
-    0xe1, 0x2b, 0x18, 0x45, 0x78, 0x69, 0x66, 0x00, 0x00, 0x4d, 0x4d, 0x00,
-    0x2a, 0x00, 0x00, 0x00, 0x08, 0x00, 0x0c, 0x01, 0x00, 0x00, 0x04, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x0c, 0xc0, 0x01, 0x01, 0x00, 0x04, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x09, 0x90, 0x01, 0x0f, 0x00, 0x02, 0x00,
-    0x00, 0x00, 0x04, 0x4c, 0x47, 0x45, 0x00, 0x01, 0x10, 0x00, 0x02, 0x00,
-    0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x9e, 0x01, 0x12, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x05, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xa6, 0x01, 0x1b, 0x00, 0x05, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xae, 0x01, 0x28, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x31, 0x00, 0x02, 0x00,
-    0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0xb6, 0x01, 0x32, 0x00, 0x02, 0x00,
-    0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0xbd, 0x02, 0x13, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x87, 0x69, 0x00, 0x04, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xd2, 0x00, 0x00, 0x02, 0x78, 0x4e,
-    0x65, 0x78, 0x75, 0x73, 0x20, 0x35, 0x00, 0x00, 0x00, 0x00, 0x48, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x50,
-    0x69, 0x63, 0x61, 0x73, 0x61, 0x00, 0x32, 0x30, 0x31, 0x37, 0x3a, 0x30,
-    0x36, 0x3a, 0x30, 0x36, 0x20, 0x31, 0x35, 0x3a, 0x34, 0x33, 0x3a, 0x33,
-    0x38, 0x00, 0x00, 0x00, 0x15, 0x82, 0x9a, 0x00, 0x05, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x01, 0xd4, 0x82, 0x9d, 0x00, 0x05, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x01, 0xdc, 0x88, 0x27, 0x00, 0x03, 0x00, 0x00, 0x00,
-    0x01, 0x02, 0x1f, 0x00, 0x00, 0x90, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x04, 0x30, 0x32, 0x32, 0x30, 0x90, 0x03, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x14, 0x00, 0x00, 0x01, 0xe4, 0x90, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x14, 0x00, 0x00, 0x01, 0xf8, 0x91, 0x01, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x04, 0x01, 0x02, 0x03, 0x00, 0x92, 0x01, 0x00, 0x0a, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x02, 0x0c, 0x92, 0x02, 0x00, 0x05, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x02, 0x14, 0x92, 0x09, 0x00, 0x03, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0x92, 0x0a, 0x00, 0x05, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x02, 0x1c, 0x92, 0x90, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x02, 0x24, 0x92, 0x91, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x02, 0x2b, 0x92, 0x92, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x07, 0x00, 0x00, 0x02, 0x32, 0xa0, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-    0x04, 0x30, 0x31, 0x30, 0x30, 0xa0, 0x01, 0x00, 0x03, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x01, 0x00, 0x00, 0xa0, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x0a, 0x0a, 0xa0, 0x03, 0x00, 0x04, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x07, 0x77, 0xa0, 0x05, 0x00, 0x04, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x02, 0x5a, 0xa4, 0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
-    0x01, 0x00, 0x00, 0x00, 0x00, 0xa4, 0x20, 0x00, 0x02, 0x00, 0x00, 0x00,
-    0x21, 0x00, 0x00, 0x02, 0x39, 0x00, 0x00, 0x00, 0x00, 0x01, 0xfc, 0x8c,
-    0xb2, 0x3b, 0x9a, 0xca, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x00,
-    0x64, 0x32, 0x30, 0x31, 0x37, 0x3a, 0x30, 0x36, 0x3a, 0x30, 0x36, 0x20,
-    0x31, 0x35, 0x3a, 0x34, 0x33, 0x3a, 0x33, 0x38, 0x00, 0x32, 0x30, 0x31,
-    0x37, 0x3a, 0x30, 0x36, 0x3a, 0x30, 0x36, 0x20, 0x31, 0x35, 0x3a, 0x34,
-    0x33, 0x3a, 0x33, 0x38, 0x00, 0xff, 0xff, 0xfe, 0x16, 0x00, 0x00, 0x00,
-    0x64, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x64, 0x00, 0x00, 0x0f,
-    0x82, 0x00, 0x00, 0x03, 0xe8, 0x39, 0x39, 0x39, 0x37, 0x32, 0x39, 0x00,
-    0x39, 0x39, 0x39, 0x37, 0x32, 0x39, 0x00, 0x39, 0x39, 0x39, 0x37, 0x32,
-    0x39, 0x00, 0x31, 0x30, 0x61, 0x66, 0x39, 0x37, 0x31, 0x37, 0x63, 0x31,
-    0x30, 0x36, 0x36, 0x33, 0x65, 0x62, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
-    0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x00, 0x00,
-    0x02, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x04, 0x52, 0x39, 0x38,
-    0x00, 0x00, 0x02, 0x00, 0x07, 0x00, 0x00, 0x00, 0x04, 0x30, 0x31, 0x30,
-    0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00, 0x01, 0x1a, 0x00, 0x05, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xc6, 0x01, 0x1b, 0x00, 0x05, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xce, 0x01, 0x28, 0x00, 0x03, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x00, 0x04, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0xd6, 0x02, 0x02, 0x00, 0x04, 0x00,
-    0x00, 0x00, 0x01, 0x00, 0x00, 0x28, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00,
-    0x00, 0x00, 0x48, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x48, 0x00,
-    0x00, 0x00, 0x01, 0xff, 0xd8, 0xff, 0xe0, 0x00, 0x10, 0x4a, 0x46, 0x49,
-    0x46, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0xff,
-    0xdb, 0x00, 0x43, 0x00, 0x05, 0x03, 0x04, 0x04, 0x04, 0x03, 0x05, 0x04,
-    0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x07, 0x0c, 0x08, 0x07, 0x07, 0x07,
-    0x07, 0x0f, 0x0b, 0x0b, 0x09, 0x0c, 0x11, 0x0f, 0x12, 0x12, 0x11, 0x0f,
-    0x11, 0x11, 0x13, 0x16, 0x1c, 0x17, 0x13, 0x14, 0x1a, 0x15, 0x11, 0x11,
-    0x18, 0x21, 0x18, 0x1a, 0x1d, 0x1d, 0x1f, 0x1f, 0x1f, 0x13, 0x17, 0x22,
-    0x24, 0x22, 0x1e, 0x24, 0x1c, 0x1e, 0x1f, 0x1e, 0xff, 0xdb, 0x00, 0x43,
-    0x01, 0x05, 0x05, 0x05, 0x07, 0x06, 0x07, 0x0e, 0x08, 0x08, 0x0e, 0x1e,
-    0x14, 0x11, 0x14, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0x1e,
-    0x1e, 0x1e, 0x1e, 0x1e, 0x1e, 0xff, 0xc0, 0x00, 0x11, 0x08, 0x00, 0x78,
-    0x00, 0xa0, 0x03, 0x01, 0x22, 0x00, 0x02, 0x11, 0x01, 0x03, 0x11, 0x01,
-    0xff, 0xc4, 0x00, 0x1c, 0x00, 0x00, 0x03, 0x00, 0x03, 0x01, 0x01, 0x01,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07,
-    0x00, 0x04, 0x08, 0x03, 0x02, 0x01, 0xff, 0xc4, 0x00, 0x40, 0x10, 0x00,
-    0x01, 0x03, 0x02, 0x05, 0x02, 0x04, 0x04, 0x04, 0x03, 0x06, 0x04, 0x07,
-    0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x11, 0x00, 0x06, 0x12,
-    0x21, 0x31, 0x07, 0x41, 0x13, 0x22, 0x51, 0x61, 0x14, 0x32, 0x71, 0x81,
-    0x08, 0x42, 0x91, 0xa1, 0x15, 0x16, 0xc1, 0x23, 0x52, 0x62, 0x82, 0xb1,
-    0xe1, 0x24, 0x43, 0x72, 0xf0, 0x17, 0x25, 0x33, 0x92, 0xb2, 0xd1, 0xd2,
-    0xff, 0xc4, 0x00, 0x1c, 0x01, 0x00, 0x03, 0x01, 0x01, 0x00, 0x03, 0x01,
-    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07,
-    0x04, 0x03, 0x00, 0x02, 0x08, 0x01, 0xff, 0xc4, 0x00, 0x37, 0x11, 0x00,
-    0x01, 0x02, 0x04, 0x04, 0x03, 0x06, 0x04, 0x05, 0x04, 0x03, 0x00, 0x00,
-    0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x04, 0x05, 0x11, 0x06, 0x21,
-    0x31, 0x41, 0x12, 0x51, 0x71, 0x13, 0x22, 0x61, 0x81, 0x91, 0xa1, 0x07,
-    0xb1, 0xc1, 0xf0, 0x14, 0x42, 0xd1, 0xe1, 0xf1, 0x15, 0x24, 0x32, 0x82,
-    0x33, 0x52, 0x72, 0xff, 0xda, 0x00, 0x0c, 0x03, 0x01, 0x00, 0x02, 0x11,
-    0x03, 0x11, 0x00, 0x3f, 0x00, 0xb1, 0x31, 0x2c, 0x2d, 0xd8, 0xd2, 0xda,
-    0x43, 0x26, 0x4a, 0x99, 0x1e, 0x15, 0x98, 0x2e, 0x2f, 0x51, 0x49, 0x0b,
-    0x03, 0x70, 0x90, 0x6c, 0x9f, 0x4d, 0xb7, 0xf5, 0xc3, 0x0b, 0x4f, 0x09,
-    0x1f, 0x08, 0xa5, 0x95, 0xb6, 0xb7, 0x50, 0x4e, 0x95, 0xab, 0xe4, 0xbf,
-    0x2a, 0xb1, 0x17, 0xb8, 0xb1, 0xde, 0xdd, 0xf1, 0x34, 0xa1, 0x3b, 0x25,
-    0xb6, 0x5d, 0x67, 0xe2, 0xda, 0x5b, 0xeb, 0x49, 0xf0, 0xd2, 0x83, 0xe1,
-    0xa9, 0x37, 0xbe, 0x91, 0x72, 0xab, 0x5f, 0x73, 0x7f, 0xb6, 0x1d, 0x28,
-    0xf0, 0xdf, 0xf1, 0x9b, 0x05, 0x2e, 0x20, 0x32, 0xd8, 0x64, 0x23, 0x52,
-    0x4a, 0x9c, 0xb7, 0x2b, 0x52, 0x8d, 0xd5, 0xe9, 0xe5, 0xdb, 0x83, 0xea,
-    0x30, 0x09, 0x75, 0x86, 0x25, 0xec, 0x1e, 0x58, 0x4d, 0xf9, 0x90, 0x20,
-    0x87, 0x60, 0x4e, 0x91, 0xb2, 0xc3, 0x72, 0x63, 0xcd, 0x40, 0x76, 0x63,
-    0xd2, 0x5b, 0x4a, 0x75, 0x04, 0x20, 0x06, 0xf9, 0xdb, 0xcd, 0xdc, 0x83,
-    0xe9, 0x6b, 0xec, 0x0d, 0xf1, 0xba, 0x5f, 0x76, 0xe9, 0x50, 0x43, 0x65,
-    0xd9, 0x05, 0x21, 0x08, 0xf2, 0x92, 0x94, 0x05, 0x73, 0x72, 0x48, 0x20,
-    0x5c, 0xaa, 0xf8, 0xf8, 0xa9, 0x34, 0x97, 0xe4, 0x3e, 0xc7, 0xc4, 0x80,
-    0x95, 0x90, 0x90, 0x9d, 0x1a, 0x94, 0x8b, 0xd8, 0x6d, 0xb5, 0x80, 0xef,
-    0xf7, 0xc7, 0xeb, 0x14, 0xb7, 0xdb, 0x79, 0x45, 0x2f, 0xb6, 0x50, 0x55,
-    0x7b, 0x96, 0x86, 0xb4, 0xf1, 0xc2, 0xaf, 0x7e, 0xc3, 0x7c, 0x65, 0x77,
-    0x15, 0x52, 0x98, 0x36, 0x53, 0xc3, 0xca, 0xe7, 0xe5, 0x78, 0xf0, 0xb0,
-    0xb3, 0x99, 0x11, 0xae, 0xa6, 0xd8, 0x91, 0x2c, 0x38, 0x3c, 0x37, 0xb4,
-    0x36, 0xa6, 0x99, 0xd2, 0xb2, 0xb0, 0xda, 0x01, 0x04, 0xea, 0x24, 0x8d,
-    0xcd, 0xb6, 0xfa, 0x63, 0x62, 0x92, 0xdb, 0x2c, 0xb8, 0xcb, 0x29, 0x7d,
-    0x97, 0x94, 0x5b, 0x53, 0xa0, 0x22, 0xfa, 0x02, 0x52, 0x52, 0x35, 0x12,
-    0x2f, 0x71, 0x7b, 0x72, 0x77, 0xe0, 0x63, 0xc2, 0xb9, 0x43, 0xa9, 0x39,
-    0x09, 0xc8, 0xd0, 0x1f, 0x6d, 0x95, 0xbb, 0xa5, 0x7f, 0x10, 0xfa, 0x3c,
-    0x5d, 0xf5, 0x58, 0x24, 0x20, 0x5b, 0x51, 0x3c, 0x58, 0x9b, 0x5a, 0xf7,
-    0xbd, 0xf1, 0x2f, 0xcd, 0x94, 0x9c, 0xff, 0x00, 0x4a, 0x94, 0xe4, 0xba,
-    0x8e, 0x60, 0xa8, 0xba, 0xc0, 0x05, 0x1a, 0xe2, 0x47, 0x09, 0x09, 0x4f,
-    0xa6, 0x94, 0x8b, 0xa7, 0xd8, 0x0f, 0xb6, 0x0a, 0xd3, 0xaa, 0x54, 0xe9,
-    0xe5, 0xa1, 0x29, 0x98, 0x4a, 0x4a, 0xb4, 0x0a, 0xba, 0x6f, 0x9d, 0xb7,
-    0x16, 0xbf, 0x21, 0x7b, 0x9d, 0x84, 0x0d, 0xa8, 0x4c, 0xb9, 0x26, 0xd9,
-    0x73, 0xb2, 0x52, 0xc0, 0xff, 0x00, 0xa8, 0x07, 0xda, 0xf7, 0xeb, 0x95,
-    0x84, 0x55, 0xdb, 0x4c, 0x26, 0xa4, 0x3e, 0xdb, 0x0b, 0x2e, 0xcb, 0x91,
-    0x24, 0xbe, 0xa2, 0x2c, 0x08, 0x52, 0x86, 0xca, 0xb7, 0x17, 0x00, 0x58,
-    0xed, 0x72, 0x0e, 0xf8, 0xf8, 0x7e, 0x6c, 0x28, 0xce, 0x3a, 0xc3, 0x25,
-    0x90, 0x88, 0xc9, 0xd4, 0xe9, 0x71, 0xc0, 0x09, 0x52, 0x85, 0xed, 0xa8,
-    0xf7, 0xbd, 0xff, 0x00, 0x4d, 0x86, 0x39, 0x96, 0xa7, 0xd4, 0x6a, 0x63,
-    0x28, 0x5b, 0x1f, 0xce, 0x33, 0xf5, 0x36, 0x0a, 0x5c, 0x49, 0x75, 0x6b,
-    0x70, 0xab, 0x8b, 0x8b, 0x91, 0x63, 0x6b, 0x6d, 0x6e, 0xd8, 0x00, 0xee,
-    0x76, 0xca, 0xce, 0x27, 0xc6, 0x6a, 0x8b, 0x32, 0x78, 0x69, 0x3f, 0xda,
-    0x3a, 0xa6, 0xca, 0x89, 0xb7, 0x2a, 0x3b, 0x9f, 0x7c, 0x37, 0xff, 0x00,
-    0x41, 0x69, 0x1f, 0xf2, 0xbe, 0x07, 0xa7, 0xd4, 0x88, 0x54, 0x18, 0xaa,
-    0x61, 0xcf, 0xf8, 0xa4, 0xd6, 0x7a, 0xe5, 0xf3, 0x1f, 0xac, 0x75, 0x8c,
-    0x0c, 0xc3, 0x02, 0xa3, 0x50, 0x6a, 0x9c, 0xc5, 0x62, 0x92, 0xe4, 0xa7,
-    0x10, 0xb6, 0xbe, 0x1d, 0xb9, 0x2d, 0xad, 0x00, 0x80, 0x3f, 0x2f, 0xcc,
-    0xb5, 0x0b, 0x1e, 0x2c, 0x07, 0xb9, 0xc7, 0xae, 0x68, 0x96, 0xa4, 0xd2,
-    0xcb, 0x31, 0x25, 0x29, 0x72, 0x00, 0x0d, 0x96, 0xda, 0xec, 0x9b, 0xf7,
-    0xb0, 0xd8, 0xf7, 0xda, 0xc7, 0xb6, 0x21, 0x79, 0x22, 0x3d, 0x1e, 0xbf,
-    0x45, 0x8b, 0x3c, 0xd3, 0x95, 0x11, 0xb9, 0x26, 0xf1, 0x5c, 0x69, 0x65,
-    0xa7, 0x10, 0xa0, 0xe6, 0x84, 0x9d, 0xb7, 0x1e, 0x71, 0x89, 0xac, 0x0a,
-    0x9d, 0x56, 0x8f, 0x38, 0x48, 0x8d, 0x52, 0x9d, 0x0d, 0x65, 0xc2, 0x54,
-    0xeb, 0x2e, 0xa9, 0x0a, 0x55, 0x8d, 0x89, 0xe7, 0x7e, 0xfc, 0xe0, 0x0d,
-    0x79, 0xb6, 0xe9, 0x8a, 0x42, 0x50, 0x4a, 0x82, 0xc6, 0xbf, 0xa4, 0x51,
-    0xbe, 0x1b, 0xc8, 0x2b, 0x18, 0x35, 0x32, 0xe3, 0x87, 0xb2, 0x53, 0x2a,
-    0x09, 0xe1, 0xd6, 0xe4, 0x8b, 0xe6, 0x76, 0xf4, 0x31, 0xd6, 0x31, 0x67,
-    0x66, 0x00, 0xda, 0x90, 0x22, 0xc6, 0x79, 0xb4, 0x20, 0xa1, 0x6f, 0xbc,
-    0x0a, 0x41, 0x09, 0xf3, 0x6b, 0x09, 0x37, 0xb0, 0x36, 0xdc, 0x12, 0x4e,
-    0xd8, 0x11, 0x51, 0x7f, 0xf8, 0xed, 0x5a, 0x1c, 0x88, 0x35, 0x04, 0xa5,
-    0xc8, 0x4d, 0x2d, 0x4d, 0xa9, 0xc8, 0xd6, 0x6b, 0x52, 0x87, 0x99, 0x4a,
-    0xb8, 0xdc, 0x93, 0xc0, 0x06, 0xdc, 0xe2, 0x21, 0x13, 0xa9, 0xd9, 0xb0,
-    0xb1, 0xe1, 0x4a, 0xaf, 0x3a, 0xe9, 0x4a, 0xb5, 0x21, 0x6e, 0xb0, 0x85,
-    0x9f, 0x6b, 0xa8, 0x6f, 0x7f, 0xb6, 0x35, 0xe2, 0xf5, 0x37, 0x37, 0xca,
-    0x7c, 0x35, 0x51, 0xaf, 0xae, 0x13, 0x00, 0xfc, 0xed, 0x46, 0xd7, 0x71,
-    0xfe, 0x22, 0x0d, 0xc7, 0xe8, 0x70, 0x10, 0xcf, 0xb0, 0x53, 0x61, 0x73,
-    0xe9, 0xfa, 0xc3, 0xcc, 0xc6, 0x09, 0x7a, 0x50, 0x15, 0x29, 0x1c, 0x5f,
-    0xf9, 0xb9, 0xfa, 0x67, 0xe5, 0x68, 0xe8, 0x7a, 0x34, 0x17, 0x60, 0x34,
-    0xa0, 0x66, 0x53, 0xdb, 0x53, 0x84, 0xea, 0x5b, 0x67, 0x4d, 0xfd, 0xfc,
-    0xbe, 0xfb, 0xf3, 0xbf, 0xd3, 0x6c, 0x7d, 0x66, 0x87, 0xeb, 0x74, 0xf8,
-    0xb1, 0xe1, 0xd2, 0xc4, 0x35, 0x49, 0x90, 0xcb, 0xae, 0xc3, 0x73, 0x7d,
-    0x3a, 0x90, 0x9b, 0x90, 0x45, 0xed, 0xbd, 0xf6, 0x3c, 0x0e, 0x6d, 0x89,
-    0xa6, 0x46, 0x89, 0x56, 0xac, 0x4b, 0x81, 0x35, 0xac, 0xdc, 0xfd, 0x56,
-    0x31, 0x7d, 0x2a, 0x29, 0x60, 0x0b, 0x25, 0x49, 0x58, 0xd9, 0xc0, 0x07,
-    0x96, 0xe3, 0xb1, 0xb6, 0xd8, 0xac, 0xe7, 0xb4, 0x45, 0x6a, 0xaf, 0x4b,
-    0x43, 0x4a, 0x6d, 0x25, 0xa9, 0x32, 0x11, 0xa1, 0x24, 0x5d, 0x29, 0x53,
-    0x5b, 0x6d, 0xd8, 0x5c, 0x60, 0xad, 0x29, 0x4d, 0xcc, 0x38, 0x3b, 0xb6,
-    0x00, 0x8d, 0x77, 0x85, 0xb9, 0x96, 0x19, 0x49, 0x52, 0x10, 0x9c, 0xc2,
-    0x54, 0x73, 0x1a, 0x10, 0x92, 0x47, 0xbd, 0xa2, 0x1c, 0x9f, 0xfc, 0x40,
-    0x7a, 0x32, 0x5f, 0x97, 0x99, 0x1d, 0x52, 0xdb, 0x36, 0x11, 0x92, 0xe2,
-    0x90, 0xd3, 0x62, 0xdc, 0x0d, 0x24, 0x11, 0xb1, 0xc2, 0xfd, 0x5a, 0x5e,
-    0x60, 0x42, 0x2c, 0xfc, 0x07, 0x18, 0x75, 0x2a, 0xba, 0x26, 0x21, 0xe5,
-    0x3f, 0x63, 0xfd, 0xe4, 0xa9, 0x47, 0xca, 0x46, 0xe3, 0x71, 0xdf, 0x19,
-    0xd6, 0x3a, 0xd5, 0x5e, 0x91, 0x0d, 0x2f, 0xc1, 0x21, 0x94, 0x29, 0xd7,
-    0x2e, 0x15, 0x65, 0x05, 0x5b, 0x4e, 0xe4, 0x7d, 0xf8, 0x38, 0x0b, 0x42,
-    0xea, 0x69, 0x30, 0x9b, 0x6a, 0xb9, 0x4b, 0x43, 0xe1, 0xb0, 0x12, 0x1d,
-    0x8e, 0x7c, 0x32, 0x8f, 0xb7, 0x6f, 0xb6, 0x28, 0xcb, 0x99, 0x92, 0x95,
-    0x74, 0x36, 0xa0, 0x94, 0xa8, 0x8b, 0x8c, 0xac, 0x39, 0x74, 0x88, 0xa6,
-    0x1f, 0xc4, 0x18, 0xbd, 0x12, 0x9f, 0x8e, 0x67, 0x85, 0xe6, 0xd4, 0x4d,
-    0xd2, 0x6d, 0x71, 0x6d, 0x6d, 0x98, 0x3e, 0x40, 0xf9, 0x40, 0xf9, 0x19,
-    0x9a, 0xad, 0xe3, 0x3b, 0x11, 0x6e, 0xca, 0xa9, 0x6b, 0x56, 0x8d, 0x72,
-    0x5c, 0x4a, 0xad, 0x7b, 0x0b, 0x24, 0xe9, 0x3a, 0x71, 0xf7, 0x97, 0xaa,
-    0x19, 0x86, 0x65, 0x52, 0x24, 0x66, 0xe9, 0x0d, 0xb7, 0xe3, 0x38, 0x1b,
-    0x49, 0x44, 0x50, 0xab, 0x82, 0xab, 0x5e, 0xc4, 0x6f, 0x6c, 0x35, 0xb3,
-    0x4b, 0xcb, 0x79, 0x89, 0xe4, 0xce, 0xa6, 0x26, 0x6c, 0x69, 0x5a, 0x82,
-    0x95, 0x29, 0x2b, 0x52, 0x1d, 0x41, 0x3b, 0x8b, 0x91, 0xda, 0xc3, 0x6d,
-    0x88, 0xd8, 0xe1, 0x93, 0x2f, 0xcf, 0xab, 0xe5, 0x7c, 0xc7, 0x4d, 0x46,
-    0x60, 0x97, 0x0e, 0x75, 0x31, 0xe9, 0x08, 0x69, 0x12, 0x8c, 0x60, 0x87,
-    0xda, 0xf4, 0xbe, 0x8b, 0x05, 0x0f, 0xb0, 0x3d, 0xf1, 0x8a, 0x64, 0xd5,
-    0x5a, 0x1c, 0x52, 0xae, 0x24, 0xa0, 0x67, 0x6b, 0x01, 0xfc, 0xfa, 0xc3,
-    0x75, 0x33, 0xe2, 0x63, 0x4f, 0xbc, 0x99, 0x57, 0xd2, 0x59, 0x73, 0x4e,
-    0x12, 0x32, 0xbf, 0xcf, 0xd6, 0x06, 0xf5, 0x01, 0xd9, 0x74, 0xac, 0xba,
-    0xdb, 0x2f, 0x33, 0x1d, 0xba, 0x85, 0x36, 0xae, 0xe4, 0x77, 0x5d, 0x61,
-    0xad, 0x96, 0x0b, 0x63, 0x70, 0x07, 0xfd, 0x37, 0xb6, 0x1f, 0xba, 0x4b,
-    0x5b, 0x95, 0x3f, 0x2b, 0xc1, 0x44, 0xc7, 0x1e, 0x96, 0x02, 0x8d, 0xca,
-    0x9b, 0xb2, 0x94, 0x41, 0x24, 0x12, 0x2f, 0xcd, 0xec, 0x37, 0xe7, 0xdf,
-    0x13, 0xbe, 0xb2, 0x54, 0x4c, 0xba, 0xce, 0x60, 0x5c, 0x25, 0x87, 0xe9,
-    0xee, 0x4a, 0x6e, 0x49, 0xf0, 0xd3, 0x72, 0x95, 0x29, 0x24, 0x03, 0xa8,
-    0x1d, 0xb9, 0x3b, 0x7b, 0x7b, 0x60, 0xef, 0x43, 0x5d, 0x29, 0x88, 0xdb,
-    0x8b, 0x72, 0x33, 0x65, 0x5e, 0x25, 0xee, 0x17, 0x7b, 0x10, 0x05, 0xac,
-    0x0d, 0x89, 0xdb, 0x83, 0x85, 0x8c, 0x5a, 0x78, 0x66, 0x9a, 0x58, 0xdd,
-    0x20, 0x9f, 0x3b, 0x9f, 0xac, 0x3b, 0xd5, 0xdb, 0xb9, 0x4a, 0xd5, 0xa9,
-    0x00, 0xfb, 0x40, 0xac, 0xbf, 0x98, 0xbe, 0x31, 0x9a, 0xab, 0x73, 0x42,
-    0xde, 0x80, 0xc7, 0x87, 0xa9, 0x2b, 0x6c, 0x10, 0xe0, 0x28, 0xbe, 0xe0,
-    0xec, 0x47, 0xa7, 0xfb, 0x62, 0x9b, 0x94, 0x9a, 0xa9, 0xd6, 0x72, 0xa8,
-    0x95, 0x90, 0x33, 0x73, 0x72, 0xd6, 0x86, 0x2e, 0x69, 0x92, 0xbc, 0xcb,
-    0x61, 0x76, 0xf9, 0x52, 0x54, 0x6f, 0xa7, 0xd8, 0x92, 0x3d, 0x14, 0x31,
-    0x03, 0x76, 0x3b, 0x4d, 0xe4, 0xcc, 0xcd, 0x23, 0x58, 0xbb, 0x8d, 0xa2,
-    0xe9, 0x04, 0xd9, 0x20, 0x04, 0x8d, 0xbd, 0x76, 0xc4, 0xf3, 0x2a, 0x55,
-    0x33, 0x44, 0x4c, 0xf6, 0x22, 0xe5, 0x27, 0xa6, 0xae, 0xa2, 0xe4, 0xa0,
-    0x96, 0x44, 0x72, 0x6e, 0x0d, 0x85, 0xcd, 0x87, 0x6b, 0x5e, 0xff, 0x00,
-    0xbe, 0x3d, 0xa6, 0x9a, 0x94, 0x98, 0xa7, 0xcb, 0x4a, 0x4c, 0xb4, 0x16,
-    0x14, 0x9b, 0xe6, 0x01, 0xcf, 0x2d, 0xb5, 0xdf, 0x50, 0x41, 0x89, 0x54,
-    0x8c, 0xa3, 0xc2, 0xa1, 0x3d, 0x50, 0x65, 0xee, 0x12, 0x85, 0x81, 0x62,
-    0x6c, 0x2d, 0x62, 0x49, 0xdc, 0x65, 0x6d, 0xd2, 0x44, 0x5c, 0x1e, 0xcf,
-    0x3d, 0x5a, 0x62, 0xa4, 0xe5, 0x3e, 0xa5, 0x50, 0xa7, 0xd2, 0xdd, 0x49,
-    0xd2, 0x84, 0xbc, 0xd6, 0x95, 0x39, 0xcd, 0x82, 0x6f, 0x7b, 0xf1, 0xce,
-    0xe0, 0x7a, 0xe1, 0x83, 0x20, 0xbf, 0xd4, 0x0a, 0xad, 0x42, 0x4b, 0xd5,
-    0x6c, 0xe0, 0xf1, 0x66, 0x24, 0xe6, 0xee, 0xcb, 0x6d, 0x20, 0x02, 0x9b,
-    0x82, 0x52, 0xab, 0x0f, 0x4d, 0x88, 0xf7, 0xc1, 0x8c, 0xd5, 0x2e, 0x8a,
-    0x7a, 0x5d, 0x4e, 0x8b, 0x5b, 0x8e, 0xd2, 0xab, 0x06, 0xea, 0x50, 0x6d,
-    0x3b, 0xa1, 0xb2, 0xa3, 0xa0, 0x58, 0x7f, 0xcc, 0x50, 0xb5, 0x80, 0xdc,
-    0x83, 0xbe, 0x24, 0xbd, 0x36, 0xcc, 0x33, 0xb2, 0xcd, 0x54, 0x25, 0x42,
-    0x4a, 0x5a, 0x2e, 0x02, 0x96, 0xdc, 0x90, 0x4a, 0x55, 0x7d, 0x89, 0xb7,
-    0x04, 0x81, 0xff, 0x00, 0xd6, 0xf8, 0x54, 0xad, 0xe1, 0x4a, 0x6d, 0x38,
-    0x07, 0x19, 0x69, 0x20, 0x1b, 0xe4, 0x52, 0x2f, 0x96, 0xe0, 0xf2, 0x3b,
-    0x7d, 0x61, 0xaf, 0x0d, 0x62, 0x79, 0x8a, 0xb0, 0x52, 0x1c, 0x02, 0xe9,
-    0x09, 0xcc, 0x68, 0x4a, 0x85, 0xed, 0xa7, 0xf9, 0x0d, 0xc7, 0x8e, 0xd1,
-    0xd8, 0x64, 0xff, 0x00, 0xc5, 0xb4, 0xd3, 0x68, 0x05, 0x28, 0x0a, 0x5a,
-    0x92, 0x4f, 0xe5, 0x4b, 0x97, 0xb7, 0xe8, 0x71, 0x1a, 0xab, 0xfe, 0x21,
-    0x29, 0xd4, 0x7e, 0xa5, 0xce, 0xca, 0x35, 0xea, 0x64, 0x91, 0x09, 0x01,
-    0x05, 0x12, 0xda, 0x40, 0x50, 0x4e, 0xa1, 0xdd, 0x3c, 0xd8, 0x7a, 0xef,
-    0x8a, 0xc5, 0x36, 0xa9, 0x0e, 0x44, 0x84, 0xe8, 0x73, 0xfb, 0x59, 0x2c,
-    0x29, 0x4d, 0xa7, 0xbf, 0x65, 0x7f, 0xa1, 0xc7, 0x13, 0xf5, 0x06, 0x9b,
-    0x52, 0xac, 0xfe, 0x20, 0x6a, 0x90, 0x20, 0x45, 0x91, 0x2a, 0x5b, 0x8b,
-    0x6d, 0xb6, 0x19, 0x6c, 0x5d, 0x4b, 0xb2, 0x78, 0x1f, 0xbe, 0xfc, 0x0c,
-    0x21, 0x61, 0xb9, 0x66, 0xa7, 0xdb, 0xb3, 0xa7, 0x44, 0x2b, 0x43, 0x6b,
-    0x10, 0xb4, 0x81, 0xec, 0x77, 0xb8, 0xcc, 0xc1, 0xa7, 0xf8, 0x99, 0x48,
-    0x36, 0xce, 0xe0, 0x67, 0xc8, 0x85, 0x1f, 0xa6, 0xa2, 0x3a, 0x3b, 0x33,
-    0xe4, 0x8c, 0x85, 0xd4, 0x46, 0xda, 0xae, 0x52, 0xc4, 0x07, 0x64, 0x2e,
-    0xc0, 0x49, 0x61, 0x00, 0x2b, 0xe8, 0xbb, 0x6f, 0xbe, 0x14, 0xab, 0xb9,
-    0x30, 0x50, 0x22, 0xff, 0x00, 0x0f, 0xfe, 0x13, 0x18, 0x7c, 0x72, 0x96,
-    0xc0, 0x90, 0x41, 0x29, 0x41, 0x50, 0xb0, 0xbf, 0x1e, 0x5e, 0x76, 0xdb,
-    0xdc, 0xfa, 0xb5, 0xf4, 0xeb, 0x24, 0x53, 0x7a, 0x71, 0x45, 0x7a, 0xa1,
-    0x5b, 0xa8, 0x32, 0x89, 0xd3, 0x96, 0xda, 0xa5, 0x25, 0xb5, 0xf9, 0x1b,
-    0x08, 0x3a, 0x92, 0x80, 0x7f, 0x32, 0xb5, 0x5a, 0xea, 0xf6, 0xb0, 0xbe,
-    0x06, 0x75, 0x3e, 0xa9, 0x5a, 0xce, 0x51, 0xa1, 0xc3, 0xa7, 0xb0, 0x61,
-    0xc5, 0x5c, 0x80, 0x59, 0x52, 0x8d, 0x9c, 0x58, 0x48, 0x24, 0x1b, 0x7e,
-    0x54, 0xef, 0xdf, 0x72, 0x71, 0xda, 0x98, 0xf4, 0xe8, 0x9f, 0xec, 0xa5,
-    0x9d, 0x2e, 0x32, 0x35, 0xb8, 0xc8, 0x78, 0x03, 0xe9, 0xa6, 0xa7, 0x6b,
-    0x46, 0x87, 0xc3, 0x45, 0xae, 0x35, 0xa4, 0x5f, 0x9e, 0xff, 0x00, 0xbf,
-    0xa6, 0x9b, 0xc2, 0xfc, 0xa9, 0xf1, 0x13, 0x97, 0xbc, 0x4a, 0x32, 0x2e,
-    0xd4, 0x0b, 0xb4, 0xa0, 0x11, 0xa7, 0xcc, 0xd3, 0x89, 0x52, 0x94, 0x94,
-    0x8b, 0x00, 0x2f, 0x72, 0x3d, 0xb1, 0x36, 0xeb, 0x1c, 0x07, 0x28, 0xd3,
-    0x6b, 0xb4, 0xc9, 0x4e, 0x15, 0x25, 0x82, 0xb5, 0x31, 0xa4, 0xdd, 0x29,
-    0x4a, 0x9c, 0x43, 0xa9, 0x23, 0xfc, 0xaa, 0xfd, 0xf1, 0xbb, 0x2e, 0x55,
-    0x6a, 0x87, 0x1a, 0xbc, 0x89, 0x20, 0x29, 0x69, 0x63, 0x5a, 0x52, 0xb0,
-    0x6c, 0x51, 0xa1, 0x40, 0xf1, 0xea, 0x06, 0x06, 0x67, 0xc9, 0x92, 0x33,
-    0x14, 0x36, 0xe4, 0xcb, 0x5f, 0x8a, 0xec, 0x9a, 0x6c, 0x7b, 0xab, 0x48,
-    0x04, 0xff, 0x00, 0x62, 0x11, 0xfb, 0x14, 0xe2, 0xb3, 0x88, 0x78, 0x7f,
-    0x01, 0x26, 0xb3, 0xa8, 0x03, 0xe9, 0xfa, 0x46, 0x4f, 0x85, 0x0c, 0x3c,
-    0xa9, 0xba, 0xd4, 0xba, 0x45, 0xc2, 0xc5, 0xc5, 0xb5, 0xe2, 0xb1, 0xb7,
-    0xce, 0xde, 0x71, 0x36, 0xa6, 0x4b, 0xaa, 0xbf, 0x20, 0x98, 0xaf, 0x68,
-    0x69, 0xb4, 0xdf, 0x4d, 0xb6, 0xb0, 0xf6, 0xe4, 0x93, 0x87, 0x95, 0xaa,
-    0x38, 0xa5, 0x44, 0x4a, 0x81, 0xf8, 0xd4, 0xeb, 0x32, 0x1d, 0x1b, 0x21,
-    0x49, 0x36, 0x29, 0xb0, 0xf5, 0x1b, 0xdc, 0xfd, 0x30, 0x0f, 0x2d, 0xd1,
-    0xd3, 0x0d, 0xa6, 0xde, 0xa8, 0xb8, 0x12, 0xb0, 0x2f, 0x60, 0x0a, 0x83,
-    0x7b, 0x6f, 0x6b, 0x72, 0xac, 0x36, 0xd2, 0xa8, 0x46, 0xbb, 0x1e, 0x4c,
-    0xa8, 0x92, 0x22, 0xa0, 0x34, 0xc9, 0x71, 0xa6, 0x0b, 0xa1, 0x4a, 0x3d,
-    0xbc, 0xd6, 0x3b, 0x2b, 0x93, 0x7e, 0x01, 0xdb, 0x9c, 0x28, 0x4c, 0xad,
-    0x2e, 0x2a, 0xc8, 0x02, 0xdc, 0xe2, 0xc1, 0x46, 0x2f, 0x50, 0x25, 0x7f,
-    0x11, 0x50, 0x75, 0x5c, 0x4a, 0xff, 0x00, 0x16, 0xef, 0xa7, 0x5b, 0xe9,
-    0xd3, 0x6d, 0xf3, 0xc8, 0x6e, 0xf4, 0xff, 0x00, 0x3d, 0x4c, 0xca, 0xf9,
-    0x88, 0x7c, 0x2c, 0x1d, 0x46, 0x63, 0x29, 0x6c, 0xa4, 0x27, 0x40, 0xb2,
-    0x38, 0x59, 0xf5, 0x27, 0x7f, 0xd7, 0x1d, 0x08, 0xce, 0x65, 0x6e, 0xa7,
-    0x54, 0xa7, 0x4f, 0xac, 0xa6, 0x3c, 0x79, 0x29, 0x7e, 0x13, 0xc8, 0x49,
-    0x50, 0x05, 0x45, 0xd0, 0xa4, 0xad, 0x36, 0xfc, 0xdc, 0x03, 0x8e, 0x7d,
-    0x32, 0xa0, 0x57, 0xa9, 0x52, 0x6a, 0xeb, 0x52, 0x19, 0xaa, 0x46, 0x8a,
-    0x52, 0x96, 0xb4, 0x24, 0x2d, 0xc2, 0x15, 0xdf, 0xe8, 0x07, 0x1c, 0x91,
-    0xfa, 0x63, 0xa0, 0xf3, 0x25, 0x39, 0x0e, 0x51, 0x29, 0x12, 0xc2, 0x59,
-    0xb3, 0x52, 0x60, 0x91, 0x74, 0x0b, 0xdb, 0xc3, 0x3d, 0xff, 0x00, 0x4c,
-    0x14, 0xa5, 0x29, 0x69, 0x70, 0x24, 0x69, 0xcb, 0xce, 0x13, 0xa6, 0xa7,
-    0x45, 0x49, 0xf7, 0x5d, 0x75, 0x20, 0x29, 0x79, 0x65, 0xb0, 0xd2, 0xde,
-    0x62, 0x21, 0xff, 0x00, 0x88, 0xf6, 0x9b, 0xa9, 0x52, 0x2a, 0xb2, 0xa1,
-    0x21, 0x6d, 0x21, 0x55, 0x37, 0x96, 0xce, 0xa1, 0xa4, 0xe8, 0x52, 0xc1,
-    0xbe, 0x9e, 0xc2, 0xd7, 0xdb, 0x12, 0x9e, 0x9c, 0xd2, 0xe6, 0xd5, 0x5f,
-    0x31, 0xe1, 0x34, 0xeb, 0xce, 0xa9, 0x77, 0x5a, 0x95, 0xe6, 0x48, 0x48,
-    0x16, 0x25, 0x46, 0xf6, 0x03, 0x91, 0x8b, 0xa6, 0x64, 0xa0, 0x53, 0xb3,
-    0x35, 0x3e, 0x43, 0x55, 0x17, 0x8b, 0x4d, 0x25, 0xe2, 0xe2, 0x8a, 0x57,
-    0xa7, 0x6b, 0x9b, 0x8b, 0x8c, 0x20, 0x55, 0xf3, 0xad, 0x03, 0x2c, 0x43,
-    0x5e, 0x5a, 0xca, 0x8c, 0xc6, 0x6e, 0xc7, 0x77, 0xd1, 0x65, 0x24, 0x2b,
-    0xde, 0xff, 0x00, 0x3e, 0x29, 0x53, 0xb4, 0xa6, 0x9e, 0x71, 0x2f, 0xbc,
-    0xab, 0x21, 0x09, 0x00, 0xff, 0x00, 0x3f, 0x66, 0x3e, 0x6d, 0xa0, 0xe2,
-    0x09, 0xa6, 0xd8, 0x5c, 0x8c, 0x8b, 0x65, 0x4f, 0x95, 0xa8, 0xdf, 0xf2,
-    0xa4, 0x13, 0xaf, 0xcf, 0x28, 0x6c, 0x8e, 0xec, 0x2c, 0xa7, 0x0d, 0x98,
-    0xad, 0x3d, 0xfc, 0x46, 0xa5, 0x21, 0x21, 0xa4, 0x45, 0x8e, 0x92, 0x55,
-    0xb7, 0x01, 0x29, 0xf4, 0xdc, 0xf9, 0x8f, 0xfa, 0x63, 0xe2, 0xa1, 0x42,
-    0xcc, 0xf5, 0x67, 0x04, 0xfa, 0xac, 0x96, 0xd8, 0x75, 0x2b, 0x40, 0x6a,
-    0x1b, 0x67, 0x59, 0x66, 0xff, 0x00, 0x4f, 0x99, 0x7f, 0xb0, 0xf7, 0xc0,
-    0x8c, 0x9b, 0x51, 0xa7, 0x46, 0xa6, 0xaa, 0x5c, 0xe9, 0xaf, 0x3d, 0x52,
-    0x99, 0xaf, 0xc5, 0x74, 0x2e, 0xca, 0x52, 0x38, 0xb1, 0x3f, 0x30, 0x16,
-    0xbe, 0xc2, 0xc3, 0x7c, 0x51, 0x1e, 0xcd, 0xd4, 0xc5, 0x25, 0xa8, 0xca,
-    0x9d, 0x09, 0x98, 0xcd, 0xa5, 0xb6, 0x8a, 0x84, 0x93, 0xad, 0x56, 0x1c,
-    0x9b, 0x26, 0xfe, 0xbb, 0x8e, 0x6f, 0x85, 0xaa, 0x96, 0x21, 0x2a, 0x4f,
-    0xe1, 0xa4, 0xc7, 0x0a, 0x34, 0xbe, 0xe7, 0xa7, 0x21, 0xef, 0x0e, 0x94,
-    0x6c, 0x22, 0xdc, 0xab, 0x9f, 0x8d, 0x9d, 0x3d, 0xac, 0xc1, 0xcc, 0x93,
-    0x98, 0x1d, 0x07, 0x84, 0x44, 0x73, 0x33, 0xd3, 0xe9, 0x30, 0x26, 0x95,
-    0xbb, 0xe3, 0x04, 0xb6, 0x94, 0x3e, 0x82, 0x2d, 0x72, 0x97, 0x08, 0xbe,
-    0xde, 0x84, 0x1c, 0x51, 0xba, 0x0d, 0x3d, 0x72, 0x29, 0x25, 0x6c, 0x48,
-    0x5b, 0x5a, 0x96, 0x97, 0x2e, 0xa2, 0x12, 0x1b, 0x00, 0x8b, 0xf3, 0x7b,
-    0xdf, 0xb6, 0x17, 0xb3, 0x4c, 0x5a, 0x6d, 0x43, 0x2d, 0x66, 0x37, 0x20,
-    0xba, 0x99, 0x29, 0x44, 0x67, 0x9c, 0x2e, 0x24, 0x6c, 0x56, 0x97, 0x8a,
-    0xbf, 0xf8, 0xd8, 0xfd, 0xf1, 0xf5, 0xf8, 0x7d, 0x6c, 0x38, 0x66, 0x43,
-    0x4a, 0x1d, 0xf0, 0x8b, 0xc1, 0xd0, 0x7c, 0x3b, 0xa5, 0x28, 0xd3, 0x7b,
-    0x0b, 0x5f, 0xbe, 0xd6, 0x27, 0x1e, 0x63, 0x04, 0x36, 0x4b, 0x2e, 0xb7,
-    0xba, 0x47, 0xb4, 0x3e, 0xcf, 0xa5, 0x60, 0xa0, 0xab, 0x74, 0x88, 0x1f,
-    0x4d, 0x6a, 0x75, 0x5a, 0x85, 0x98, 0xe0, 0xb0, 0x94, 0x95, 0x49, 0x75,
-    0xb6, 0xc0, 0xe6, 0xc0, 0x5a, 0xdb, 0xfa, 0x5b, 0x9c, 0x13, 0xc9, 0xf5,
-    0xea, 0x5f, 0x4b, 0xa2, 0x4c, 0xa8, 0xc4, 0x9e, 0xc2, 0x6b, 0x13, 0x9b,
-    0x51, 0x54, 0x94, 0xb4, 0x16, 0xea, 0x49, 0x04, 0x14, 0xb6, 0x54, 0x3c,
-    0xa9, 0x17, 0xed, 0xb9, 0x3e, 0x98, 0x0f, 0x42, 0x62, 0xa9, 0x22, 0x74,
-    0xb8, 0x14, 0xe9, 0x11, 0x23, 0xc7, 0x92, 0xe0, 0x52, 0xca, 0x95, 0xa0,
-    0x71, 0x62, 0x9d, 0x86, 0xff, 0x00, 0x41, 0x6b, 0xf0, 0x4e, 0x08, 0x37,
-    0xd1, 0x25, 0x57, 0x67, 0x99, 0x55, 0x4c, 0xd8, 0xb5, 0xb8, 0xad, 0x92,
-    0x94, 0x37, 0xa7, 0x48, 0xec, 0x07, 0x60, 0x31, 0x96, 0x6b, 0x15, 0x52,
-    0x29, 0xf2, 0xad, 0x05, 0xaa, 0xee, 0x84, 0x81, 0xa1, 0x36, 0xc8, 0x5e,
-    0xff, 0x00, 0x7e, 0xd1, 0x3c, 0x6b, 0x0b, 0x55, 0xa7, 0x66, 0x5e, 0xba,
-    0xb8, 0x18, 0x52, 0xf8, 0xb2, 0x20, 0x15, 0x1d, 0xb3, 0xfb, 0xf3, 0x3a,
-    0x0a, 0x8d, 0x2e, 0xa1, 0x99, 0xd9, 0x12, 0x98, 0xab, 0x13, 0x50, 0x64,
-    0x87, 0x9b, 0xf1, 0x1c, 0xb0, 0x48, 0xd4, 0x76, 0x1f, 0xdd, 0x1e, 0xa7,
-    0xe8, 0x37, 0xbe, 0x1b, 0xe9, 0x35, 0x68, 0x53, 0x99, 0x55, 0x32, 0x7c,
-    0x66, 0x51, 0x53, 0x41, 0x0e, 0x3c, 0xeb, 0x29, 0x1e, 0x1b, 0x8d, 0x95,
-    0x69, 0x0b, 0xd8, 0xec, 0x49, 0x3f, 0x4d, 0xb0, 0x73, 0x2e, 0xf4, 0x5f,
-    0x24, 0xd0, 0x90, 0xbf, 0x8e, 0xcd, 0x32, 0x8b, 0x65, 0x43, 0xc4, 0x02,
-    0x62, 0x12, 0x92, 0x47, 0xaf, 0x9a, 0xe7, 0xe9, 0x86, 0x58, 0x39, 0x6b,
-    0xa3, 0x14, 0x79, 0xc9, 0x9a, 0xe5, 0x4a, 0x13, 0xb2, 0xda, 0x01, 0x21,
-    0xc7, 0x65, 0xeb, 0xb0, 0x1c, 0x6c, 0x4e, 0x9b, 0x62, 0x73, 0x52, 0xc5,
-    0xcd, 0x4d, 0x3a, 0x57, 0xc2, 0xb5, 0x93, 0xc9, 0x3f, 0xc6, 0x50, 0xf7,
-    0x23, 0x4e, 0x44, 0xab, 0x61, 0xb6, 0x80, 0x00, 0x6c, 0x9f, 0xd8, 0x6b,
-    0xce, 0x1b, 0x24, 0x43, 0x99, 0x1a, 0x65, 0x00, 0x38, 0xb5, 0x29, 0x25,
-    0xa5, 0xb4, 0xbb, 0x7a, 0xea, 0x40, 0xfe, 0x98, 0xf0, 0xae, 0xcd, 0xc9,
-    0x3d, 0x32, 0x7a, 0xa7, 0x99, 0x24, 0x31, 0x09, 0x35, 0x49, 0x48, 0x4a,
-    0x65, 0xc9, 0x2b, 0x25, 0xd2, 0x81, 0xc2, 0x4a, 0xbf, 0x28, 0x3f, 0xdc,
-    0x4e, 0xe4, 0xf3, 0x7c, 0x22, 0x75, 0xaf, 0xad, 0x59, 0x7e, 0x9b, 0x0e,
-    0x9f, 0x13, 0x2c, 0x4c, 0x6e, 0x6c, 0xf2, 0xfa, 0x34, 0xe8, 0x21, 0xd0,
-    0x11, 0xbe, 0xa2, 0x42, 0x4d, 0xf7, 0xd8, 0x0e, 0x09, 0x3c, 0x71, 0x88,
-    0xd6, 0x70, 0xcd, 0x31, 0xf3, 0x25, 0x41, 0x2e, 0xd5, 0x68, 0x95, 0x29,
-    0xe9, 0x4a, 0x8a, 0xc3, 0x0b, 0x49, 0x4a, 0x50, 0xa3, 0xed, 0xdc, 0xf6,
-    0xb9, 0xdf, 0x18, 0xf0, 0xa6, 0x0d, 0xa8, 0x55, 0x07, 0x6a, 0xb5, 0x76,
-    0x4d, 0xd8, 0x85, 0x0c, 0xee, 0x41, 0x37, 0xb5, 0xad, 0xa1, 0xf1, 0xcb,
-    0x2d, 0xe3, 0xde, 0xa9, 0x5b, 0x6a, 0x59, 0x09, 0x41, 0x69, 0x4e, 0x2f,
-    0x50, 0x00, 0x16, 0xbe, 0xd7, 0x37, 0xca, 0xc3, 0x61, 0x99, 0xbe, 0xd0,
-    0xe3, 0x37, 0xac, 0xc9, 0xcd, 0xb9, 0x8d, 0x72, 0x65, 0xca, 0x8d, 0x1a,
-    0x9f, 0x1d, 0xc0, 0x98, 0xa8, 0x20, 0x0d, 0x42, 0xe4, 0x03, 0x63, 0xb8,
-    0x16, 0x37, 0xb7, 0x3f, 0xd0, 0x3d, 0x2b, 0xa9, 0x52, 0xa8, 0xb5, 0x1b,
-    0xc2, 0x9e, 0xa9, 0x3e, 0x0a, 0xac, 0xea, 0x96, 0x92, 0xef, 0x8e, 0x02,
-    0x48, 0xb6, 0xc3, 0x6d, 0xcf, 0x3e, 0xc3, 0x1e, 0x39, 0x2a, 0x3c, 0x19,
-    0xad, 0x95, 0x46, 0xc8, 0xae, 0xb0, 0x11, 0x75, 0x17, 0x9d, 0x6d, 0x94,
-    0x22, 0xd7, 0xb5, 0xb5, 0x38, 0x40, 0xf6, 0xe4, 0x9f, 0x6c, 0x13, 0x55,
-    0x4e, 0xbe, 0x89, 0x0e, 0xb1, 0x0b, 0x25, 0x25, 0xf0, 0xcb, 0xab, 0x6c,
-    0x3a, 0xd8, 0x6d, 0x68, 0x5d, 0xb7, 0xd8, 0xa4, 0xd8, 0xd8, 0x11, 0x72,
-    0x0d, 0xb1, 0x5d, 0x63, 0x05, 0xca, 0xa1, 0x29, 0x42, 0x5c, 0xb0, 0x1a,
-    0x00, 0x3f, 0x7b, 0xf9, 0x98, 0x4a, 0xfe, 0xb9, 0x5b, 0x71, 0xc2, 0x96,
-    0xa4, 0x14, 0xa2, 0x79, 0xe5, 0x97, 0x90, 0xb5, 0xba, 0x46, 0xf3, 0x75,
-    0x37, 0x73, 0x65, 0x1e, 0xb1, 0x53, 0x96, 0xd2, 0x51, 0x25, 0xe8, 0x2a,
-    0x43, 0x89, 0x4b, 0x6a, 0x4e, 0xe1, 0xb2, 0x01, 0x37, 0xee, 0x7f, 0x7b,
-    0x13, 0x8d, 0x2a, 0xad, 0x06, 0xac, 0xed, 0x0f, 0x2f, 0xcd, 0x85, 0x49,
-    0x95, 0x22, 0x3b, 0xb4, 0xb6, 0x42, 0x5c, 0x61, 0xa5, 0x2c, 0x13, 0xa4,
-    0x13, 0x7b, 0x0d, 0x8d, 0xcf, 0x7c, 0x7d, 0x48, 0x77, 0xa8, 0xd2, 0xe9,
-    0xef, 0xf8, 0x39, 0x6d, 0x2c, 0xc7, 0x28, 0x50, 0x71, 0x20, 0x04, 0xdd,
-    0x36, 0xdc, 0x12, 0x2e, 0x78, 0xf4, 0xdf, 0x1e, 0x1d, 0x31, 0xce, 0x99,
-    0xaa, 0x9b, 0x96, 0xc5, 0x39, 0xfa, 0xb5, 0x3a, 0x0e, 0x95, 0xa9, 0xa6,
-    0x93, 0xf1, 0x0a, 0x42, 0x96, 0x80, 0x4d, 0xb5, 0x24, 0x0b, 0x0b, 0x5e,
-    0xc0, 0x92, 0x36, 0x03, 0x1a, 0xeb, 0xf4, 0xd0, 0xe4, 0xa3, 0x52, 0xa8,
-    0x24, 0xf0, 0xee, 0x6c, 0x32, 0x1c, 0xc9, 0xb0, 0x83, 0x38, 0x0e, 0x7a,
-    0xa5, 0x86, 0x2a, 0x53, 0x35, 0x2a, 0x8b, 0x25, 0x01, 0xdd, 0x12, 0x02,
-    0x95, 0x9f, 0x44, 0x82, 0x72, 0x19, 0xe9, 0x68, 0x13, 0x23, 0x20, 0x67,
-    0x9a, 0xa2, 0xd2, 0x5a, 0xa5, 0xaa, 0x24, 0x72, 0x6c, 0x16, 0xf1, 0xd3,
-    0x72, 0x76, 0x16, 0xc3, 0x36, 0x42, 0xe9, 0x8e, 0x68, 0xa5, 0x3a, 0xec,
-    0x31, 0x5e, 0xa2, 0x35, 0x2a, 0x45, 0x99, 0x0d, 0xf8, 0xda, 0x9c, 0x4a,
-    0xb7, 0x16, 0x00, 0x7e, 0x6d, 0xef, 0xf5, 0x03, 0x04, 0x17, 0x54, 0xcc,
-    0x09, 0x74, 0x3e, 0xac, 0xcd, 0x1d, 0x85, 0x83, 0xa8, 0x29, 0x0b, 0x2a,
-    0x50, 0xf7, 0x1e, 0x71, 0x8d, 0x79, 0xf9, 0x8e, 0xb7, 0xf0, 0x4e, 0xd3,
-    0x0e, 0x64, 0x68, 0xb6, 0xe5, 0xd0, 0xa9, 0xa1, 0xd8, 0xed, 0xad, 0x77,
-    0x37, 0x2a, 0xb6, 0x92, 0xb2, 0x77, 0x3c, 0xaa, 0xfe, 0xf8, 0x0a, 0xde,
-    0x16, 0x9c, 0x29, 0xe0, 0x20, 0x01, 0xd4, 0x7d, 0x2f, 0x05, 0x2a, 0xbf,
-    0x13, 0xe8, 0x73, 0x93, 0x05, 0xd2, 0x54, 0xe2, 0x8f, 0x81, 0x00, 0x0f,
-    0x00, 0x48, 0x19, 0x72, 0xd4, 0xc1, 0x8c, 0xbf, 0xd0, 0xc9, 0x10, 0xa5,
-    0x2e, 0x54, 0x9c, 0xe1, 0x19, 0x84, 0xa9, 0x65, 0x4a, 0x07, 0x65, 0x13,
-    0xde, 0xfa, 0xad, 0x7d, 0xfd, 0x71, 0x4a, 0xcf, 0x79, 0x96, 0x83, 0x46,
-    0xca, 0xb1, 0x62, 0xbb, 0x5c, 0x8b, 0x29, 0xf8, 0xcf, 0x32, 0xe2, 0xfc,
-    0x35, 0x02, 0x43, 0x6d, 0x24, 0xdd, 0x4a, 0xb6, 0xc3, 0xf2, 0x8d, 0xf9,
-    0x27, 0x10, 0x77, 0x17, 0x45, 0xf1, 0x94, 0x26, 0x66, 0xb9, 0x4f, 0xac,
-    0x9e, 0x4a, 0x91, 0x73, 0xf7, 0xb1, 0xc7, 0xb5, 0x7b, 0x2a, 0x51, 0x6a,
-    0x79, 0x3e, 0x5c, 0xc8, 0x95, 0x19, 0xcf, 0xa9, 0xa4, 0xeb, 0xb2, 0x9f,
-    0x51, 0x06, 0xde, 0xa3, 0x83, 0x82, 0xac, 0xe1, 0xa9, 0x86, 0x7b, 0xe9,
-    0x29, 0xe2, 0xea, 0x4f, 0xd2, 0x03, 0x2f, 0xe2, 0x75, 0x19, 0xa7, 0x12,
-    0x7b, 0x27, 0x2d, 0x71, 0x6e, 0xe8, 0x02, 0xfb, 0x5c, 0xdc, 0x9b, 0x40,
-    0x2c, 0xcf, 0x57, 0xa5, 0xc9, 0x6e, 0x75, 0x35, 0x55, 0xa5, 0xb1, 0x19,
-    0xc7, 0x54, 0x7c, 0x26, 0x93, 0x7b, 0x79, 0x89, 0xb0, 0x3b, 0x6d, 0x85,
-    0x08, 0xd4, 0x6c, 0xa4, 0xf4, 0x84, 0x80, 0x9a, 0x9c, 0x85, 0x13, 0x62,
-    0xb2, 0xda, 0x95, 0xfa, 0x01, 0x8e, 0x87, 0x43, 0xf1, 0x29, 0x61, 0x8a,
-    0x76, 0x5c, 0xc9, 0xf4, 0x09, 0x50, 0x62, 0x46, 0x6c, 0x27, 0xc6, 0x6c,
-    0xba, 0xe3, 0xde, 0x51, 0xa9, 0x45, 0x77, 0xe4, 0x9b, 0xf0, 0x0f, 0xdf,
-    0x18, 0xff, 0x00, 0x54, 0x59, 0xa4, 0x7f, 0x66, 0x3a, 0x74, 0xc4, 0x37,
-    0x00, 0xf9, 0xda, 0x4a, 0x54, 0x01, 0xf6, 0xf2, 0x7f, 0xa8, 0x18, 0x2d,
-    0x3f, 0x3d, 0x34, 0x5b, 0x4a, 0x9e, 0x65, 0x27, 0xc8, 0x9b, 0x75, 0x17,
-    0xfa, 0x43, 0xf4, 0xae, 0x1a, 0x69, 0x94, 0x87, 0x99, 0x96, 0x48, 0x0b,
-    0xef, 0x1b, 0x01, 0xbe, 0xe7, 0x33, 0x6f, 0x41, 0x12, 0x68, 0xb9, 0x4d,
-    0x86, 0x23, 0x7c, 0x44, 0x6a, 0x0d, 0x5a, 0x53, 0x62, 0xca, 0xf2, 0xc5,
-    0x74, 0x5c, 0x7d, 0x54, 0x9b, 0x71, 0xef, 0x82, 0xf0, 0x32, 0x95, 0x69,
-    0x6f, 0x29, 0x11, 0xb2, 0x24, 0x97, 0xd2, 0x4d, 0xd2, 0x5f, 0x6c, 0xa4,
-    0xe9, 0x3c, 0x5c, 0x0b, 0x8c, 0x33, 0x2b, 0xac, 0x14, 0x79, 0x95, 0x37,
-    0x6a, 0x2b, 0xca, 0x2e, 0xbb, 0x31, 0x0b, 0x4b, 0x8a, 0x2a, 0x71, 0xd2,
-    0x02, 0xbb, 0x10, 0x92, 0x42, 0x47, 0x1c, 0x01, 0x82, 0x8b, 0xeb, 0x4e,
-    0x66, 0x76, 0x58, 0x71, 0x14, 0xe9, 0x11, 0x12, 0xf0, 0xd4, 0x35, 0x35,
-    0x74, 0xda, 0xc3, 0x72, 0x49, 0x36, 0xda, 0xdc, 0xe1, 0x69, 0x58, 0x8d,
-    0x6d, 0x9e, 0xe8, 0x48, 0xe8, 0x91, 0x1d, 0x84, 0xc2, 0x19, 0x3c, 0x29,
-    0x09, 0x1e, 0x9f, 0x40, 0x60, 0x2b, 0x99, 0x1f, 0xa9, 0x12, 0x68, 0x52,
-    0xa0, 0xc4, 0xa0, 0xc3, 0xa7, 0x46, 0x76, 0x3a, 0xdb, 0x5a, 0x02, 0x14,
-    0x14, 0xa4, 0x11, 0xba, 0x45, 0xc5, 0x85, 0xfd, 0x70, 0x13, 0xa5, 0xd9,
-    0x39, 0xd8, 0xcb, 0xf0, 0x5a, 0x9d, 0x32, 0x9a, 0xea, 0xd6, 0x59, 0x90,
-    0x1a, 0x59, 0x2a, 0x4a, 0xfd, 0x2c, 0x38, 0xb5, 0xb1, 0xd1, 0x7d, 0x1c,
-    0xcd, 0x33, 0xb3, 0x35, 0x0d, 0xea, 0x9c, 0x97, 0x94, 0xb2, 0xd4, 0xa2,
-    0xc3, 0x8d, 0xad, 0x20, 0x8b, 0x69, 0x06, 0xe0, 0x81, 0xf5, 0x18, 0x8b,
-    0xe7, 0x5f, 0x8a, 0xa4, 0x75, 0x36, 0xac, 0x23, 0xad, 0x49, 0x40, 0x9e,
-    0x56, 0x50, 0xa2, 0x40, 0x20, 0x80, 0x47, 0x18, 0x15, 0x58, 0x9f, 0x76,
-    0x71, 0xa4, 0xba, 0xb5, 0x5c, 0x79, 0x0f, 0xbd, 0x20, 0x7c, 0xea, 0xbf,
-    0x11, 0x72, 0x75, 0x1f, 0x28, 0x97, 0x3a, 0xc5, 0x52, 0xb5, 0x29, 0x70,
-    0x68, 0xb2, 0xdc, 0x8f, 0x31, 0x0d, 0x97, 0x95, 0xe1, 0x91, 0x7d, 0xd4,
-    0x76, 0xbd, 0xf6, 0xb5, 0xb9, 0xde, 0xfb, 0x61, 0x36, 0xb9, 0xfc, 0xcf,
-    0x47, 0x7c, 0xb5, 0x57, 0x7e, 0xb3, 0xc6, 0xea, 0x4c, 0x85, 0x14, 0x1f,
-    0xdf, 0x0d, 0x9d, 0x3b, 0x8f, 0x36, 0x99, 0x9b, 0xeb, 0x4b, 0x1a, 0x89,
-    0x6a, 0x31, 0xb1, 0x4f, 0x3a, 0x49, 0x2b, 0xb8, 0x27, 0xd8, 0x7e, 0xa7,
-    0x1e, 0x39, 0x6b, 0xa9, 0x5f, 0x1c, 0xfb, 0xb1, 0x6b, 0xd1, 0x14, 0xe2,
-    0x5c, 0x73, 0x50, 0x79, 0xb4, 0xa5, 0x6a, 0x48, 0x1c, 0x02, 0x95, 0x6c,
-    0xa0, 0x2f, 0xc6, 0x1b, 0xa9, 0x32, 0xf2, 0x32, 0xf2, 0x4d, 0xad, 0x49,
-    0x4f, 0x12, 0xaf, 0x9a, 0x80, 0x39, 0xf9, 0xe9, 0x12, 0x49, 0xfa, 0xa5,
-    0x4c, 0x4f, 0xbc, 0x86, 0x87, 0x1b, 0x68, 0xb6, 0x40, 0xd8, 0x8b, 0xf2,
-    0x84, 0x96, 0xaa, 0xce, 0xc8, 0x64, 0xc4, 0x65, 0x87, 0x54, 0xca, 0xc5,
-    0x94, 0x84, 0xb2, 0x92, 0x55, 0xbd, 0xcf, 0x98, 0xdc, 0xfe, 0xf8, 0xd9,
-    0x4b, 0xae, 0x34, 0x14, 0xf2, 0xe8, 0x0c, 0x21, 0x29, 0xdc, 0xf8, 0x82,
-    0xc7, 0xf4, 0xbe, 0x2a, 0xa7, 0x28, 0xb1, 0x2d, 0x46, 0xab, 0x95, 0xaa,
-    0x10, 0x52, 0xf2, 0x95, 0xe2, 0xa5, 0xa4, 0x37, 0x76, 0xaf, 0x6e, 0x34,
-    0x9d, 0xc7, 0xaf, 0xd7, 0x08, 0x35, 0x18, 0xf2, 0x20, 0xd4, 0x16, 0xc5,
-    0x5d, 0x2a, 0x65, 0xf0, 0x8b, 0x8f, 0x35, 0xc1, 0xed, 0xa8, 0x11, 0xee,
-    0x38, 0xc7, 0x5a, 0x85, 0x4e, 0xa9, 0x4f, 0x1c, 0x69, 0x42, 0x78, 0x79,
-    0x81, 0xf7, 0x6f, 0x94, 0x68, 0xa3, 0xcc, 0x53, 0x6a, 0xaa, 0x2d, 0xa5,
-    0x44, 0x2f, 0x74, 0x9b, 0x83, 0xe3, 0xd6, 0x19, 0xfa, 0x3f, 0x06, 0x8b,
-    0x5b, 0xcf, 0xf4, 0x09, 0x4f, 0xc0, 0x43, 0x5e, 0x12, 0x1d, 0x79, 0x2d,
-    0xa1, 0x45, 0x20, 0xba, 0x84, 0x9d, 0x17, 0x23, 0x7b, 0x03, 0x63, 0xf6,
-    0xb6, 0x3a, 0x0e, 0xbb, 0xd3, 0xa6, 0x44, 0x24, 0x0c, 0xbd, 0x3d, 0xba,
-    0x6c, 0xb2, 0xd8, 0x21, 0xb5, 0x30, 0x85, 0xa1, 0x47, 0xd4, 0x02, 0x2e,
-    0x2f, 0xed, 0x8e, 0x7e, 0xfc, 0x3c, 0x32, 0xb7, 0xb3, 0xe5, 0x27, 0x72,
-    0xa4, 0x21, 0x52, 0x75, 0x90, 0x3e, 0x54, 0xe8, 0x51, 0xfe, 0x98, 0x6c,
-    0xfc, 0x47, 0xe7, 0xdc, 0xd7, 0x94, 0xb3, 0xed, 0x1d, 0xda, 0x05, 0x5d,
-    0x71, 0xdb, 0x11, 0x0a, 0x8b, 0x7a, 0x02, 0x9b, 0x76, 0xe4, 0x6c, 0xb4,
-    0x91, 0xb8, 0xed, 0x89, 0xee, 0x39, 0x99, 0xaa, 0xb9, 0x88, 0xd8, 0x44,
-    0x8b, 0xe5, 0xb2, 0x5a, 0x0a, 0xf0, 0xdf, 0x23, 0xcf, 0x6d, 0x61, 0xef,
-    0x0d, 0x38, 0xdc, 0x9d, 0x35, 0xc5, 0x9f, 0xca, 0xb2, 0x0e, 0xe6, 0xd7,
-    0x00, 0x7c, 0xe0, 0x1f, 0x50, 0x8f, 0x55, 0xf2, 0xa3, 0xaa, 0x45, 0x4a,
-    0x04, 0x79, 0xb0, 0x55, 0xb8, 0x91, 0x19, 0x8d, 0x4d, 0xaa, 0xde, 0xa3,
-    0x80, 0x47, 0xd3, 0x09, 0xea, 0xae, 0xf5, 0x11, 0x6d, 0xa5, 0xc7, 0x1c,
-    0x99, 0x15, 0xbd, 0x65, 0x01, 0x49, 0x8b, 0xa0, 0x6a, 0xb5, 0xf4, 0x8b,
-    0x27, 0x9d, 0x8f, 0xe9, 0x8b, 0x87, 0x4c, 0xba, 0xd9, 0x4b, 0xce, 0x4d,
-    0xff, 0x00, 0x07, 0xcc, 0x94, 0x71, 0x16, 0x72, 0x80, 0x05, 0x6d, 0x5d,
-    0x71, 0xdd, 0x27, 0x61, 0x71, 0xc8, 0x37, 0x3d, 0xef, 0xcf, 0x38, 0x79,
-    0x9f, 0x93, 0x8c, 0x58, 0x4e, 0xd4, 0x68, 0xf2, 0x4b, 0x4c, 0xdb, 0x53,
-    0x8c, 0x2c, 0x6a, 0x09, 0x23, 0x6f, 0x29, 0x3b, 0x8f, 0x4f, 0xbe, 0x04,
-    0x9c, 0x77, 0x52, 0x92, 0x58, 0x97, 0xa9, 0xdd, 0x2a, 0xe6, 0x0e, 0x47,
-    0xd2, 0x0e, 0x25, 0x2e, 0x4c, 0x27, 0x8d, 0xa7, 0x8d, 0x8e, 0xd7, 0xb7,
-    0x95, 0xf5, 0xf5, 0xf5, 0x89, 0x1f, 0x47, 0xa4, 0x67, 0x06, 0x27, 0x4a,
-    0x35, 0xc7, 0x25, 0x86, 0xd4, 0xd1, 0x08, 0xf1, 0x52, 0x52, 0x1c, 0xba,
-    0x55, 0x71, 0xbf, 0xd0, 0x1f, 0xbe, 0x00, 0xaf, 0x5c, 0xa8, 0x5a, 0x94,
-    0x10, 0x5a, 0x84, 0xcb, 0x81, 0x5c, 0x27, 0x48, 0xf1, 0xd4, 0x3e, 0xe4,
-    0x95, 0x7b, 0x9f, 0xd3, 0x14, 0x2f, 0xe6, 0xaa, 0x6d, 0x4d, 0x6c, 0xd3,
-    0xdb, 0x42, 0x5a, 0x79, 0x32, 0x1d, 0x2a, 0x4a, 0x2e, 0x92, 0x2c, 0x40,
-    0xb6, 0xae, 0x49, 0xb0, 0xb9, 0x3e, 0xf8, 0x47, 0xcc, 0xb4, 0xc3, 0x4a,
-    0x6d, 0x6b, 0x2e, 0x25, 0xc2, 0xe4, 0xa7, 0xc1, 0x08, 0xb8, 0x03, 0x4b,
-    0xa4, 0xff, 0x00, 0xa1, 0x18, 0x6f, 0xa9, 0xce, 0x2e, 0x6a, 0x8a, 0xda,
-    0x9c, 0x37, 0x25, 0x47, 0xdb, 0xf9, 0x87, 0x1c, 0x20, 0xa3, 0xda, 0x25,
-    0xc3, 0x9a, 0x80, 0x56, 0xb9, 0x9d, 0xb7, 0x85, 0x77, 0xe9, 0xb4, 0xfa,
-    0xab, 0x28, 0x11, 0xe7, 0x2e, 0x39, 0x24, 0x85, 0xad, 0x06, 0xc1, 0x06,
-    0xfe, 0xd7, 0xfb, 0xed, 0x82, 0x39, 0x17, 0x2c, 0xd0, 0xd9, 0x9e, 0xf4,
-    0x3c, 0xcf, 0x54, 0x5f, 0x88, 0xbb, 0x18, 0x8b, 0x5b, 0xc4, 0xb6, 0xbd,
-    0xf9, 0x0a, 0x1d, 0xfd, 0xb6, 0xf4, 0xb6, 0x25, 0x94, 0xb9, 0x92, 0x62,
-    0x49, 0x75, 0xd8, 0xce, 0xa9, 0xb5, 0x29, 0xc5, 0x6d, 0x7d, 0xb9, 0x3b,
-    0x1c, 0x51, 0x28, 0x4e, 0x48, 0xaa, 0xd2, 0x5e, 0x79, 0xf8, 0xbe, 0x46,
-    0x52, 0x95, 0x2c, 0x84, 0xdd, 0x04, 0x15, 0x69, 0xe7, 0xd6, 0xfd, 0xb0,
-    0x15, 0xd3, 0x31, 0x2c, 0x9b, 0x71, 0x92, 0x9e, 0xb0, 0x2a, 0x5d, 0x9a,
-    0x26, 0x2b, 0x50, 0x2a, 0x68, 0x31, 0x30, 0xad, 0xc0, 0x04, 0x28, 0xfb,
-    0x67, 0xd7, 0x3f, 0x13, 0x15, 0xe8, 0x99, 0x07, 0x2d, 0x48, 0x6d, 0x0d,
-    0xc5, 0x61, 0x12, 0xdc, 0x5b, 0x6e, 0x5d, 0xa5, 0x2f, 0xec, 0x13, 0xb8,
-    0x3c, 0x1b, 0x0d, 0xf7, 0xbd, 0xce, 0x05, 0xc1, 0xa4, 0x39, 0x43, 0xca,
-    0x15, 0x0a, 0x3b, 0xad, 0x84, 0x2e, 0x3b, 0x6f, 0xb4, 0x42, 0x56, 0x5c,
-    0x06, 0xc5, 0x44, 0x79, 0xac, 0x2e, 0x34, 0xdb, 0x7b, 0x0c, 0x2b, 0x65,
-    0x9a, 0xcd, 0x47, 0x2d, 0xa0, 0xaa, 0x33, 0xea, 0x72, 0x1b, 0xab, 0xb2,
-    0xa3, 0xea, 0x1a, 0xae, 0x3c, 0xd7, 0x07, 0xe6, 0xb5, 0xff, 0x00, 0xec,
-    0x61, 0xd2, 0x7e, 0x67, 0x6b, 0x30, 0x49, 0x9a, 0xb0, 0x9f, 0x04, 0x2c,
-    0x36, 0x1f, 0xb6, 0xc0, 0x21, 0x68, 0x20, 0x8d, 0xb8, 0xb5, 0xb0, 0xc7,
-    0x84, 0x66, 0x82, 0xa7, 0x14, 0x39, 0xa4, 0xfd, 0x22, 0x3f, 0xf1, 0x5f,
-    0x0e, 0xcc, 0x52, 0x24, 0xd0, 0xdb, 0x80, 0x1b, 0x2d, 0x26, 0xe3, 0x96,
-    0x63, 0xe7, 0x1a, 0xf4, 0xf9, 0xb2, 0xe3, 0xe5, 0xb9, 0x2f, 0xb6, 0x99,
-    0x09, 0x53, 0x71, 0xf4, 0x25, 0xc4, 0x70, 0x8b, 0x2b, 0x7b, 0xff, 0x00,
-    0x97, 0xd3, 0x08, 0x59, 0x5f, 0xab, 0x71, 0xd2, 0xa5, 0xc5, 0xae, 0x53,
-    0x64, 0x25, 0xbd, 0x56, 0xf8, 0x86, 0x5e, 0x2a, 0x5a, 0x2c, 0x6f, 0x7b,
-    0x1e, 0x37, 0xdf, 0x6c, 0x58, 0xd2, 0xdd, 0x2e, 0xa5, 0xd2, 0x9a, 0x1f,
-    0xf0, 0xc2, 0xcf, 0xc5, 0xae, 0x0b, 0xc2, 0x62, 0x19, 0xf9, 0x8d, 0xd3,
-    0xb2, 0x96, 0x3e, 0xa9, 0xef, 0x8e, 0x46, 0x7d, 0x6b, 0x8b, 0x52, 0x93,
-    0x09, 0xc4, 0x95, 0xa1, 0x0f, 0xad, 0x36, 0x1c, 0xde, 0xe4, 0x6d, 0x83,
-    0x75, 0x4a, 0x93, 0xe8, 0x29, 0x71, 0xbc, 0xb6, 0x3e, 0x36, 0x8a, 0x83,
-    0xd5, 0xe9, 0x96, 0x29, 0xb2, 0x4e, 0xb2, 0x78, 0x41, 0x4d, 0x88, 0x23,
-    0x5b, 0x00, 0x05, 0xf7, 0xd8, 0xe9, 0x1d, 0x04, 0xec, 0xac, 0xbb, 0x9a,
-    0xa0, 0xae, 0x45, 0x3a, 0xb4, 0x15, 0x2d, 0xb2, 0x16, 0xd1, 0x69, 0x94,
-    0xb6, 0xf2, 0x8d, 0xff, 0x00, 0x38, 0xb5, 0x96, 0x07, 0x3c, 0x5f, 0x1f,
-    0x12, 0x8e, 0x69, 0x0d, 0x33, 0x26, 0xa0, 0x83, 0x52, 0x84, 0x96, 0xf4,
-    0x78, 0x91, 0xd0, 0x94, 0x92, 0x9b, 0x8f, 0x99, 0x36, 0xb1, 0xe3, 0x8d,
-    0xb0, 0x1f, 0xa4, 0x19, 0x3e, 0x7c, 0x69, 0x10, 0xf3, 0x0b, 0x8c, 0x7c,
-    0x38, 0x68, 0x97, 0x63, 0xb0, 0xf1, 0xf3, 0xba, 0x46, 0xe0, 0x1e, 0x39,
-    0xf4, 0xed, 0x83, 0x15, 0xac, 0xf6, 0xed, 0x26, 0x24, 0x88, 0x34, 0x94,
-    0xaf, 0xc6, 0xd4, 0x4b, 0xcb, 0x6d, 0x37, 0xd1, 0x7d, 0xac, 0x3d, 0xf9,
-    0xdb, 0x9c, 0x63, 0x5c, 0x8c, 0xac, 0xcc, 0xa9, 0x76, 0x75, 0x01, 0xbe,
-    0x56, 0xca, 0xfe, 0x50, 0xc0, 0xd2, 0x18, 0x9a, 0x94, 0x33, 0x33, 0xcd,
-    0x04, 0x11, 0xbd, 0xed, 0x97, 0x80, 0xd7, 0xa0, 0xb1, 0x31, 0x7b, 0xe9,
-    0x12, 0xe8, 0xec, 0xe5, 0x1b, 0xd3, 0x65, 0x25, 0x2b, 0x7e, 0x38, 0x94,
-    0xb2, 0xa5, 0x15, 0x0b, 0x8d, 0x8d, 0xc6, 0xd6, 0x20, 0x1d, 0xc0, 0xe0,
-    0x8c, 0x47, 0xfa, 0xd7, 0x35, 0x11, 0x33, 0xed, 0x55, 0xe7, 0x8b, 0x6a,
-    0xd4, 0x84, 0xb8, 0x46, 0xab, 0x0b, 0x80, 0x47, 0xef, 0x6c, 0x6c, 0xf4,
-    0x0a, 0x53, 0xf3, 0xe4, 0xd4, 0x59, 0xbc, 0x86, 0x5b, 0x4c, 0x72, 0xd8,
-    0x4b, 0xbb, 0x06, 0xf5, 0x21, 0x57, 0x1f, 0x5b, 0x81, 0x7c, 0x2a, 0x7e,
-    0x26, 0x9b, 0x7e, 0x36, 0x64, 0x8b, 0xe6, 0x4b, 0xa8, 0x98, 0xd2, 0x3c,
-    0xac, 0x82, 0xa2, 0xa0, 0x9b, 0x77, 0x23, 0x6d, 0xf7, 0xc2, 0x83, 0xbc,
-    0x0b, 0x68, 0x34, 0x9d, 0x02, 0xb2, 0xe9, 0x09, 0xce, 0x80, 0x86, 0x94,
-    0xb4, 0x1b, 0x8b, 0x9d, 0x75, 0xb5, 0xf2, 0x8d, 0x18, 0x68, 0x47, 0xf3,
-    0x58, 0x60, 0x04, 0x24, 0x96, 0x46, 0xab, 0xaa, 0xdb, 0x59, 0x69, 0x23,
-    0x7e, 0xe4, 0xf6, 0x18, 0x8c, 0x65, 0x88, 0x92, 0xe5, 0xd7, 0xfe, 0x12,
-    0x23, 0x0b, 0x79, 0xd5, 0x28, 0xa7, 0x4a, 0x47, 0xbf, 0xed, 0x8b, 0x58,
-    0x8b, 0x1d, 0x59, 0xe9, 0xb6, 0xd6, 0xa0, 0xd2, 0x1c, 0x80, 0x95, 0x6c,
-    0x6c, 0x51, 0xe6, 0x26, 0xff, 0x00, 0x6e, 0x70, 0x0e, 0xa7, 0x99, 0x72,
-    0xbe, 0x49, 0x79, 0xf6, 0x29, 0x30, 0x99, 0x9c, 0xe3, 0xaa, 0xd6, 0xe0,
-    0x4a, 0x8a, 0x75, 0x2b, 0x7b, 0x82, 0x46, 0xf6, 0x3d, 0xc6, 0x1e, 0xa4,
-    0xe4, 0x91, 0x35, 0x4c, 0x61, 0x4e, 0x2a, 0xc9, 0x48, 0x37, 0xf5, 0x88,
-    0xd4, 0xe4, 0xeb, 0xb2, 0xb5, 0x59, 0x86, 0xd8, 0x41, 0x5a, 0xd4, 0x13,
-    0x6e, 0x43, 0x5c, 0xc9, 0xf3, 0x86, 0x4c, 0xb5, 0x16, 0x9f, 0x93, 0x61,
-    0x8a, 0x85, 0x46, 0xa4, 0xc7, 0x8e, 0xa4, 0xa8, 0x2d, 0x09, 0x57, 0x97,
-    0x56, 0xdb, 0x7b, 0x9d, 0xb0, 0xbd, 0x9d, 0x69, 0xd5, 0x4c, 0xc7, 0x25,
-    0xea, 0xab, 0x2c, 0x06, 0xda, 0x6e, 0x3a, 0xec, 0x93, 0xf3, 0x2a, 0xf6,
-    0x55, 0xcd, 0xb8, 0xe0, 0x58, 0x5c, 0xfb, 0xde, 0xf8, 0x9b, 0xe6, 0x0c,
-    0xd3, 0x2b, 0x30, 0xd5, 0x05, 0x4a, 0xa4, 0xab, 0xbf, 0xa9, 0x21, 0x0d,
-    0x36, 0x90, 0x96, 0x9a, 0x48, 0xb5, 0x92, 0x00, 0x1e, 0x82, 0xd8, 0x7d,
-    0x9d, 0xd4, 0x5a, 0x62, 0xe8, 0x72, 0x22, 0xc7, 0x6d, 0xe5, 0x3a, 0xe4,
-    0x52, 0xd0, 0x48, 0x05, 0x37, 0x51, 0xb0, 0xd4, 0x3d, 0x3b, 0xfe, 0xd8,
-    0xc7, 0x51, 0x9f, 0x79, 0xf6, 0x44, 0xac, 0x93, 0x47, 0x83, 0xa1, 0x37,
-    0xb7, 0xdf, 0x58, 0xdf, 0x45, 0xa1, 0xa1, 0x89, 0x83, 0x3f, 0x38, 0xbe,
-    0x27, 0x8f, 0x90, 0x17, 0xe5, 0x19, 0xf8, 0x7e, 0xa9, 0x7f, 0x0c, 0xcf,
-    0x74, 0xe6, 0x41, 0x4a, 0xd2, 0xeb, 0xce, 0xb3, 0xa8, 0xde, 0xe0, 0x68,
-    0x5e, 0xff, 0x00, 0xed, 0x86, 0xef, 0xc4, 0xae, 0x57, 0xad, 0x66, 0x9c,
-    0xf5, 0x96, 0xa9, 0x99, 0x7a, 0x9d, 0x22, 0xa3, 0x2d, 0xe8, 0xaa, 0x40,
-    0x08, 0x48, 0x09, 0x16, 0x37, 0x25, 0x44, 0xec, 0x91, 0x6d, 0xee, 0x48,
-    0x18, 0x40, 0xe9, 0x72, 0x97, 0x1f, 0x38, 0xd0, 0xe4, 0x4c, 0x01, 0x82,
-    0xed, 0x49, 0xc4, 0x5d, 0xc5, 0x00, 0x2e, 0xa4, 0xe9, 0x1b, 0xf1, 0xc9,
-    0xb6, 0x3a, 0x7f, 0x38, 0x67, 0x5a, 0x2e, 0x59, 0xa6, 0xa5, 0xe0, 0x17,
-    0x2e, 0xa6, 0xb8, 0xfa, 0x52, 0xdb, 0x00, 0xd8, 0x26, 0xfb, 0x6b, 0x20,
-    0x5c, 0xef, 0xc2, 0x45, 0xf0, 0x93, 0x8e, 0x17, 0x35, 0x2b, 0x5d, 0x93,
-    0x71, 0x96, 0x8a, 0xd6, 0x59, 0x02, 0xde, 0x3d, 0xe1, 0xed, 0xbc, 0x50,
-    0xb0, 0xeb, 0x0d, 0xcd, 0x53, 0xdf, 0x6c, 0x1d, 0x56, 0x6f, 0xe5, 0x63,
-    0xf4, 0x85, 0xbe, 0x94, 0xf4, 0x72, 0x85, 0xd3, 0xd8, 0x08, 0xcc, 0xb9,
-    0x96, 0x4b, 0x33, 0xab, 0x2c, 0xd8, 0x87, 0x41, 0xbc, 0x68, 0x8b, 0xec,
-    0x1b, 0x07, 0xff, 0x00, 0x51, 0x63, 0xfb, 0xdd, 0xbb, 0x0e, 0xf8, 0xdb,
-    0xcc, 0xd9, 0xc6, 0x7d, 0x6e, 0x97, 0x22, 0x99, 0x97, 0xdc, 0x30, 0xd2,
-    0xa6, 0xd4, 0x18, 0x23, 0xe7, 0x70, 0xff, 0x00, 0x7d, 0x44, 0xf0, 0x2f,
-    0xe9, 0xbd, 0xed, 0xef, 0x88, 0x96, 0x6e, 0xcd, 0xdd, 0x45, 0xce, 0x15,
-    0x44, 0x29, 0xea, 0x7c, 0xe4, 0x42, 0x6a, 0xe1, 0xa6, 0x49, 0x08, 0xda,
-    0xe7, 0x7b, 0x5f, 0xcb, 0x7f, 0x41, 0xe9, 0xdf, 0x07, 0xa9, 0xaf, 0xe7,
-    0x01, 0x14, 0xb6, 0xb8, 0x4d, 0x0f, 0x11, 0x21, 0x09, 0x40, 0x76, 0xe5,
-    0x24, 0xef, 0x60, 0x07, 0xdf, 0x6c, 0x0f, 0x6b, 0x07, 0xd4, 0xa6, 0xdd,
-    0x13, 0x53, 0xa8, 0x2b, 0x5e, 0xc2, 0xdd, 0xd4, 0xf4, 0x82, 0xcd, 0x87,
-    0x52, 0x9e, 0xce, 0x55, 0xb2, 0x40, 0xde, 0xc7, 0xda, 0xff, 0x00, 0x3f,
-    0xe6, 0x14, 0xb2, 0x2c, 0x09, 0x51, 0x33, 0x8c, 0x66, 0x96, 0xe1, 0x7d,
-    0xc5, 0x2d, 0xc4, 0x94, 0x29, 0xcb, 0xf9, 0x86, 0xc6, 0xe4, 0x5e, 0xdd,
-    0xf0, 0x56, 0x6c, 0xc9, 0x93, 0x95, 0x53, 0x69, 0x65, 0xc7, 0x52, 0xcc,
-    0xa7, 0x94, 0x02, 0xd5, 0xa8, 0xa0, 0x6b, 0xde, 0xde, 0xbd, 0xbf, 0x4c,
-    0x39, 0xe4, 0xec, 0x9f, 0x57, 0x77, 0x33, 0x35, 0x50, 0x9f, 0x4e, 0x44,
-    0x25, 0x34, 0xab, 0xa5, 0xd0, 0x8d, 0x3a, 0x81, 0xd8, 0x85, 0x71, 0xc7,
-    0x37, 0xe4, 0x93, 0x84, 0x99, 0x2f, 0xb0, 0xd5, 0x72, 0xae, 0x88, 0xe8,
-    0x7a, 0x4a, 0xdb, 0x98, 0xf0, 0x75, 0x09, 0x68, 0x9d, 0x0a, 0xd5, 0xb0,
-    0xbf, 0x1b, 0xdb, 0x0e, 0x75, 0x19, 0x29, 0x84, 0x51, 0xd0, 0x85, 0xa0,
-    0xf1, 0xf1, 0xde, 0xdb, 0xd8, 0x8f, 0xda, 0x1b, 0xb0, 0xc3, 0x8c, 0xc8,
-    0x9f, 0xee, 0x94, 0x1b, 0x04, 0x2b, 0xfc, 0x8d, 0xb6, 0x1b, 0x9e, 0x86,
-    0x13, 0x32, 0xee, 0x51, 0x95, 0x26, 0x62, 0x97, 0x2b, 0xca, 0x85, 0x38,
-    0x74, 0x36, 0x8d, 0xd4, 0xab, 0x9d, 0xbe, 0x98, 0x69, 0xa8, 0xfc, 0x0d,
-    0x1c, 0x22, 0x1c, 0x55, 0x32, 0x08, 0x1b, 0xa5, 0x0e, 0x6a, 0x08, 0xf5,
-    0x04, 0x8e, 0x4f, 0x7d, 0xb1, 0xf9, 0x3a, 0x8f, 0x99, 0xea, 0x68, 0x4a,
-    0x63, 0xc8, 0x85, 0x01, 0xbe, 0x74, 0x97, 0x81, 0xd3, 0x7f, 0x5b, 0x72,
-    0x71, 0xa3, 0x1b, 0xa7, 0x33, 0x18, 0x92, 0xdb, 0x95, 0x3a, 0xd3, 0x84,
-    0xba, 0x82, 0xa1, 0xe0, 0x46, 0x71, 0x6a, 0x29, 0xe3, 0xb0, 0x36, 0xc6,
-    0x54, 0xe1, 0xea, 0x8c, 0xd0, 0x0b, 0x75, 0x36, 0x1c, 0xb2, 0x10, 0xa0,
-    0xf7, 0xc4, 0x6c, 0x37, 0x86, 0xc1, 0x96, 0xa4, 0x1e, 0x35, 0x0c, 0x8a,
-    0xc8, 0xb9, 0x3d, 0x32, 0xf6, 0xc8, 0x43, 0x2e, 0x4d, 0x99, 0x97, 0xd4,
-    0x5c, 0x4d, 0x69, 0x97, 0x3c, 0x55, 0x0b, 0xa6, 0x42, 0xaf, 0x66, 0xc6,
-    0x92, 0x6c, 0x12, 0x0d, 0xbe, 0xfe, 0xbd, 0xf0, 0xcf, 0x05, 0xa8, 0x4e,
-    0xd6, 0x27, 0x1a, 0x5b, 0xc8, 0x2c, 0x08, 0x8d, 0x82, 0xb6, 0x55, 0x70,
-    0xa5, 0x00, 0xaf, 0x5e, 0xdb, 0xe1, 0x61, 0x8e, 0x9b, 0x44, 0x0a, 0x68,
-    0xbd, 0x5a, 0x7d, 0x69, 0x28, 0x05, 0x2a, 0x5a, 0xc8, 0xf2, 0xfa, 0x7b,
-    0x7d, 0x30, 0xdd, 0x95, 0xa9, 0x54, 0xbc, 0xb6, 0xc4, 0x8b, 0xcf, 0x69,
-    0x48, 0x5f, 0x9c, 0xf9, 0x49, 0x3b, 0x0b, 0x6e, 0x7b, 0xe1, 0x86, 0x83,
-    0x40, 0x98, 0x91, 0x9b, 0x0f, 0x39, 0x60, 0x90, 0x0e, 0xf1, 0x1b, 0xc6,
-    0xf8, 0xe6, 0x56, 0xbb, 0x28, 0xa4, 0xa5, 0x4a, 0x53, 0x84, 0x8d, 0x41,
-    0xd8, 0xc6, 0x8e, 0x49, 0x2b, 0xfe, 0x58, 0xa4, 0x2c, 0x3a, 0xb4, 0x07,
-    0x1a, 0x2d, 0x2e, 0xcb, 0x29, 0xbe, 0x95, 0x91, 0xcf, 0xf9, 0x86, 0x34,
-    0x1b, 0xc8, 0xf4, 0x8c, 0xaf, 0x5e, 0x7b, 0x30, 0xd7, 0x5a, 0x69, 0xe4,
-    0x15, 0xf8, 0x89, 0x2e, 0x3a, 0x34, 0x81, 0xea, 0x07, 0xae, 0x0e, 0xf4,
-    0xc1, 0xba, 0x5d, 0x63, 0xa7, 0xae, 0xc4, 0x55, 0x72, 0x1c, 0x19, 0xf0,
-    0x66, 0x38, 0x02, 0x5f, 0x41, 0xf9, 0x54, 0x41, 0x1c, 0x6f, 0x6f, 0x70,
-    0x0e, 0xe2, 0xc7, 0x1e, 0x95, 0x1c, 0xa7, 0x95, 0x6a, 0x8f, 0x78, 0x99,
-    0xa7, 0x38, 0xbb, 0x31, 0x60, 0xec, 0xdc, 0x55, 0x04, 0xb2, 0x91, 0xed,
-    0xab, 0x73, 0xf5, 0x23, 0x1e, 0xf3, 0x75, 0x49, 0x44, 0x23, 0x3e, 0xf2,
-    0x92, 0x4d, 0x87, 0x99, 0xce, 0x3e, 0x82, 0xa0, 0x54, 0x25, 0x95, 0x47,
-    0x96, 0xed, 0x52, 0x14, 0xb4, 0x0c, 0xae, 0x0e, 0x47, 0x63, 0x7d, 0xad,
-    0x7f, 0x13, 0xf3, 0x08, 0x59, 0xa7, 0xa9, 0x90, 0xe7, 0xd4, 0x3f, 0x87,
-    0xd3, 0xd6, 0x44, 0x73, 0xb1, 0x7d, 0x46, 0xca, 0xb7, 0x64, 0x8b, 0x7c,
-    0xa3, 0x8d, 0x86, 0xe7, 0xb9, 0xed, 0x80, 0xd4, 0x1a, 0xac, 0x04, 0xb8,
-    0xe1, 0x71, 0x0b, 0xd2, 0xb7, 0x09, 0xdc, 0xdf, 0x49, 0xdf, 0x6b, 0x1f,
-    0xad, 0xcf, 0xed, 0x8a, 0xe2, 0x32, 0x5e, 0x40, 0x85, 0x1d, 0x89, 0x14,
-    0xa8, 0x54, 0xea, 0xb8, 0x52, 0x94, 0x1c, 0x0f, 0x4f, 0x53, 0x3e, 0x1f,
-    0xf7, 0x46, 0xc8, 0x37, 0x36, 0xbd, 0xed, 0xc6, 0x18, 0xa9, 0xf4, 0xfe,
-    0x9a, 0xa6, 0x12, 0x14, 0xfd, 0x0c, 0x31, 0x25, 0x0a, 0x21, 0xe6, 0x58,
-    0x43, 0xce, 0x83, 0xb6, 0xc5, 0x2e, 0x5b, 0x71, 0xfa, 0x61, 0x36, 0xa1,
-    0x3e, 0x26, 0x94, 0x4b, 0xae, 0x0f, 0x33, 0x18, 0x26, 0x3b, 0x79, 0xb7,
-    0x4a, 0x9e, 0x70, 0x78, 0x00, 0x32, 0x1e, 0xa7, 0xde, 0x37, 0x7a, 0x17,
-    0xe0, 0x3b, 0x48, 0x42, 0x53, 0xe0, 0x3a, 0xfb, 0xa9, 0x5b, 0xee, 0x29,
-    0xa1, 0xc9, 0x06, 0xc7, 0x9e, 0xc0, 0x5b, 0x02, 0x7f, 0x12, 0x50, 0xd2,
-    0xdd, 0x7e, 0x93, 0x25, 0x20, 0x05, 0x29, 0x82, 0x90, 0x37, 0xb1, 0xb1,
-    0x1e, 0x9f, 0x43, 0x86, 0xaa, 0x5d, 0x7f, 0x25, 0x51, 0x5d, 0x0b, 0xa7,
-    0x50, 0xaa, 0x37, 0x00, 0x68, 0x09, 0x69, 0x66, 0xc3, 0xef, 0x84, 0xbe,
-    0xa7, 0xe6, 0x98, 0xb9, 0xb2, 0xbf, 0x16, 0x33, 0x50, 0x64, 0xc2, 0xf8,
-    0x26, 0xff, 0x00, 0xe7, 0x24, 0xa5, 0x4a, 0x4f, 0xae, 0xe3, 0x8d, 0xf9,
-    0xe3, 0x6c, 0x60, 0x4b, 0x8c, 0xf6, 0x25, 0x01, 0x60, 0xaa, 0xf7, 0xc8,
-    0xc6, 0x57, 0x18, 0xec, 0x90, 0x45, 0xf2, 0xf1, 0xb7, 0xca, 0xe6, 0x24,
-    0x3d, 0x41, 0x97, 0x21, 0x1f, 0x0d, 0xf0, 0x4e, 0xa2, 0x3c, 0xc7, 0x96,
-    0x4e, 0xa5, 0x10, 0x0f, 0x86, 0x05, 0x92, 0x8b, 0x9f, 0xca, 0x76, 0xfd,
-    0x31, 0x3c, 0x10, 0xaa, 0xae, 0xbe, 0xaf, 0xfc, 0xad, 0x97, 0x97, 0x7d,
-    0xce, 0x92, 0xa3, 0xfa, 0xe2, 0xae, 0x8a, 0x4c, 0x1a, 0xef, 0x50, 0x69,
-    0x54, 0x9a, 0x83, 0xc9, 0x62, 0x3f, 0xc0, 0xba, 0xf1, 0x71, 0x36, 0x3a,
-    0x52, 0x3e, 0x5d, 0xcf, 0xa0, 0x37, 0xbe, 0x07, 0xe6, 0x8c, 0x85, 0x9a,
-    0xe3, 0xcf, 0x28, 0xc9, 0xd5, 0x29, 0xb5, 0x66, 0x42, 0x43, 0x88, 0x44,
-    0x72, 0xa2, 0xbd, 0x2a, 0xbd, 0xb9, 0xdd, 0x5c, 0x1b, 0x73, 0xf5, 0xc5,
-    0x33, 0x0d, 0xb6, 0xf3, 0x34, 0xd0, 0xe7, 0x19, 0xb1, 0xb9, 0x00, 0x01,
-    0x90, 0xb9, 0x1a, 0xab, 0x2f, 0x28, 0x57, 0x55, 0x29, 0xb7, 0xc2, 0xa6,
-    0x0a, 0x49, 0xd8, 0xdb, 0x5c, 0xa0, 0x05, 0x1f, 0x29, 0x54, 0xdd, 0xa7,
-    0xa9, 0xe7, 0xe3, 0x53, 0xa2, 0x10, 0x9b, 0xb7, 0xe2, 0x4f, 0x09, 0x2e,
-    0x0b, 0x5e, 0xe0, 0x04, 0x2a, 0xff, 0x00, 0xb6, 0x3c, 0x19, 0xcb, 0xd9,
-    0xd9, 0x45, 0x3f, 0x0d, 0x47, 0x8e, 0x9d, 0x48, 0x4a, 0xbc, 0xa5, 0x2a,
-    0xb5, 0xc6, 0xd7, 0xb9, 0x36, 0x3e, 0xd8, 0x0e, 0x89, 0x59, 0xb5, 0x89,
-    0x4b, 0x82, 0xa9, 0x72, 0xe3, 0xb8, 0x83, 0x65, 0x24, 0xf9, 0x74, 0x9f,
-    0x43, 0xb6, 0xc7, 0xeb, 0x82, 0xb4, 0xea, 0x6e, 0x75, 0x9e, 0xca, 0xa5,
-    0x36, 0xed, 0x49, 0xc4, 0xa1, 0x5a, 0x54, 0x52, 0x6f, 0xc7, 0x3c, 0x63,
-    0x43, 0xb8, 0xa9, 0xa6, 0xcf, 0x0a, 0x8a, 0xc5, 0xbf, 0xf3, 0xf7, 0xe8,
-    0x04, 0x71, 0x6e, 0x9f, 0x4a, 0x51, 0xcd, 0x0b, 0x3d, 0x48, 0xfa, 0xde,
-    0x33, 0x30, 0xe5, 0xec, 0xe9, 0x12, 0x9a, 0x89, 0xd5, 0x86, 0x99, 0x6a,
-    0x34, 0x75, 0x78, 0x88, 0xd4, 0x05, 0x8a, 0x86, 0xe1, 0x36, 0xb7, 0x7b,
-    0x7d, 0x31, 0xeb, 0x53, 0xa8, 0x67, 0xc8, 0x49, 0x65, 0x6e, 0x39, 0x22,
-    0x13, 0x2a, 0x17, 0x65, 0x41, 0xb5, 0xb4, 0x9b, 0x13, 0xdb, 0x55, 0x88,
-    0x1b, 0xf7, 0xc3, 0xfd, 0x0e, 0x44, 0xc7, 0xa8, 0x2c, 0xc1, 0xac, 0x34,
-    0x92, 0xb6, 0x27, 0xc7, 0x6d, 0x68, 0x51, 0xb8, 0x3c, 0x1d, 0xc7, 0x62,
-    0x45};
-}  // namespace
diff --git a/vendor_libs/test_vendor_lib/include/le_advertisement.h b/vendor_libs/test_vendor_lib/include/le_advertisement.h
new file mode 100644
index 0000000..a5c1396
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/le_advertisement.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+namespace test_vendor_lib {
+
+class LeAdvertisement {
+ public:
+  enum class AdvertisementType : uint8_t {
+    ADV_IND = 0,          // Connectable and scannable
+    ADV_DIRECT_IND = 1,   // Connectable directed
+    ADV_SCAN_IND = 2,     // Scannable undirected
+    ADV_NONCONN_IND = 3,  // Non connectable undirected
+    SCAN_RESPONSE = 4,
+  };
+  enum class AddressType : uint8_t {
+    PUBLIC = 0,
+    RANDOM = 1,
+    PUBLIC_IDENTITY = 2,
+    RANDOM_IDENTITY = 3,
+  };
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/link.h b/vendor_libs/test_vendor_lib/include/link.h
new file mode 100644
index 0000000..1c60e3d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/include/link.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+namespace test_vendor_lib {
+class Link {
+ public:
+  static constexpr size_t kSizeBytes = sizeof(uint32_t);
+  static constexpr size_t kTypeBytes = sizeof(uint8_t);
+
+  enum class PacketType : uint8_t {
+    UNKNOWN,
+    ACL,
+    COMMAND,
+    DISCONNECT,
+    ENCRYPT_CONNECTION,
+    ENCRYPT_CONNECTION_RESPONSE,
+    EVENT,
+    INQUIRY,
+    INQUIRY_RESPONSE,
+    IO_CAPABILITY_REQUEST,
+    IO_CAPABILITY_RESPONSE,
+    IO_CAPABILITY_NEGATIVE_RESPONSE,
+    LE_ADVERTISEMENT,
+    LE_SCAN,
+    LE_SCAN_RESPONSE,
+    PAGE,
+    PAGE_RESPONSE,
+    RESPONSE,
+    SCO,
+  };
+};
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/packet.h b/vendor_libs/test_vendor_lib/include/packet.h
deleted file mode 100644
index 8bad493..0000000
--- a/vendor_libs/test_vendor_lib/include/packet.h
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#pragma once
-
-#include <cstdint>
-#include <vector>
-
-#include "bt_address.h"
-#include "hci/include/hci_hal.h"
-
-namespace test_vendor_lib {
-
-const size_t kReservedZero = 0;
-
-// Abstract base class that is subclassed to provide type-specifc accessors on
-// data. Manages said data's memory and guarantees the data's persistence for IO
-// operations.
-class Packet {
- public:
-  virtual ~Packet() = default;
-
-  // Returns the size in octets of the entire packet, which consists of the type
-  // octet, the header, and the payload.
-  size_t GetPacketSize() const;
-
-  const std::vector<uint8_t>& GetPayload() const;
-
-  size_t GetPayloadSize() const;
-
-  const std::vector<uint8_t>& GetHeader() const;
-
-  uint8_t GetHeaderSize() const;
-
-  serial_data_type_t GetType() const;
-
-  // Add |octets| bytes to the payload.  Return true if:
-  // - the size of |bytes| is equal to |octets| and
-  // - the new size of the payload is still < |kMaxPayloadOctets|
-  bool AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes);
-
- private:
-  // Add |octets| bytes to the payload.  Return true if:
-  // - the value of |value| fits in |octets| bytes and
-  // - the new size of the payload is still < |kMaxPayloadOctets|
-  bool AddPayloadOctets(size_t octets, uint64_t value);
-
- public:
-  // Add type-checking versions
-  bool AddPayloadOctets1(uint8_t value) { return AddPayloadOctets(1, value); }
-  bool AddPayloadOctets2(uint16_t value) { return AddPayloadOctets(2, value); }
-  bool AddPayloadOctets3(uint32_t value) { return AddPayloadOctets(3, value); }
-  bool AddPayloadOctets4(uint32_t value) { return AddPayloadOctets(4, value); }
-  bool AddPayloadOctets6(uint64_t value) { return AddPayloadOctets(6, value); }
-  bool AddPayloadOctets8(uint64_t value) { return AddPayloadOctets(8, value); }
-
-  // Add |address| to the payload.  Return true if:
-  // - the new size of the payload is still < |kMaxPayloadOctets|
-  bool AddPayloadBtAddress(const BtAddress& address);
-
-  // Return true if |num_bytes| can be added to the payload.
-  bool CanAddPayloadOctets(size_t num_bytes) const {
-    return GetPayloadSize() + num_bytes <= kMaxPayloadOctets;
-  }
-
- protected:
-  // Constructs an empty packet of type |type| and header |header|
-  Packet(serial_data_type_t type, std::vector<uint8_t> header);
-
-  bool IncrementPayloadCounter(size_t index);
-  bool IncrementPayloadCounter(size_t index, uint8_t max_val);
-
- private:
-  const size_t kMaxPayloadOctets = 256;  // Includes the size byte.
-
-  // Underlying containers for storing the actual packet
-
-  // The packet type is one of DATA_TYPE_ACL, DATA_TYPE_COMMAND,
-  // DATA_TYPE_EVENT, or DATA_TYPE_SCO.
-  serial_data_type_t type_;
-
-  std::vector<uint8_t> header_;
-
-  std::vector<uint8_t> payload_;
-};
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/packet_stream.h b/vendor_libs/test_vendor_lib/include/packet_stream.h
deleted file mode 100644
index e2cec7d..0000000
--- a/vendor_libs/test_vendor_lib/include/packet_stream.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// 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.
-//
-
-#pragma once
-
-#include <cstdint>
-#include <memory>
-#include <vector>
-
-#include "command_packet.h"
-#include "event_packet.h"
-#include "packet.h"
-
-namespace test_vendor_lib {
-
-// Provides abstractions for IO with Packet objects. Used to receive commands
-// and data from the HCI and to send controller events back to the host.
-class PacketStream {
- public:
-  PacketStream() = default;
-
-  virtual ~PacketStream() = default;
-
-  // Reads a command packet from the file descriptor at |fd| and returns the
-  // packet back to the caller, along with the responsibility of managing the
-  // packet.
-  std::unique_ptr<CommandPacket> ReceiveCommand(int fd) const;
-
-  // Reads a single octet from |fd| and interprets it as a packet type octet.
-  // Validates the type octet for correctness.
-  serial_data_type_t ReceivePacketType(int fd) const;
-
-  // Sends an event to file descriptor |fd|. The ownership of the event is left
-  // with the caller.
-  bool SendEvent(std::unique_ptr<EventPacket> event, int fd) const;
-
- private:
-  // Checks if |type| is in the valid range from DATA_TYPE_COMMAND to
-  // DATA_TYPE_SCO.
-  bool ValidateTypeOctet(serial_data_type_t type) const;
-
-  // Attempts to receive |num_octets_to_receive| into |destination| from |fd|,
-  // returning false if an error occurs.
-  bool ReceiveAll(std::vector<uint8_t>& destination,
-                  size_t num_octets_to_receive, int fd) const;
-
-  // Attempts to send |num_octets_to_send| from |source| to |fd|, returning
-  // false if an error occurs.
-  bool SendAll(const std::vector<uint8_t>& source, size_t num_octets_to_send,
-               int fd) const;
-};
-
-}  // namespace test_vendor_lib
diff --git a/tools/Android.bp b/vendor_libs/test_vendor_lib/include/phy.h
similarity index 72%
copy from tools/Android.bp
copy to vendor_libs/test_vendor_lib/include/phy.h
index 9f75ba7..da3673c 100644
--- a/tools/Android.bp
+++ b/vendor_libs/test_vendor_lib/include/phy.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,16 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+#pragma once
+
+namespace test_vendor_lib {
+
+class Phy {
+ public:
+  enum class Type {
+    LOW_ENERGY,
+    BR_EDR,
+  };
+};
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/sco_packet.h b/vendor_libs/test_vendor_lib/include/sco.h
similarity index 62%
rename from vendor_libs/test_vendor_lib/include/sco_packet.h
rename to vendor_libs/test_vendor_lib/include/sco.h
index 7b95063..b3691cf 100644
--- a/vendor_libs/test_vendor_lib/include/sco_packet.h
+++ b/vendor_libs/test_vendor_lib/include/sco.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,30 +17,17 @@
 #pragma once
 
 #include <cstdint>
-#include <string>
-#include <vector>
-
-#include "packet.h"
 
 namespace test_vendor_lib {
+namespace sco {
 
 // SCO data packets are specified in the Bluetooth Core Specification Version
 // 4.2, Volume 2, Part E, Section 5.4.3
-class ScoPacket : public Packet {
- public:
-  virtual ~ScoPacket() override = default;
-  typedef enum {
-    CorrectlyReceived,
-    PossiblyIncomplete,
-    NoData,
-    PartiallyLost
-  } PacketStatusFlags;
-
-  uint16_t GetChannel() const;
-
-  PacketStatusFlags GetPacketStatusFlags() const;
-
-  explicit ScoPacket(uint16_t channel, PacketStatusFlags status_flags);
+enum class PacketStatusFlagsType : uint8_t {
+  CORRECTLY_RECEIVED = 0,
+  POSSIBLY_INCOMPLETE = 1,
+  NO_DATA = 2,
+  PARTIALLY_LOST = 3
 };
-
+}  // namespace sco
 }  // namespace test_vendor_lib
diff --git a/tools/Android.bp b/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
similarity index 68%
copy from tools/Android.bp
copy to vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
index 9f75ba7..460f550 100644
--- a/tools/Android.bp
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection.cc
@@ -1,5 +1,5 @@
 /*
- * Copyright 2017 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -13,6 +13,15 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-subdirs = [
-    "mcap_tool",
-]
+
+#define LOG_TAG "acl_connection"
+
+#include "acl_connection.h"
+
+#include "base/logging.h"
+
+#include "osi/include/log.h"
+
+using std::shared_ptr;
+
+namespace test_vendor_lib {}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection.h b/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
new file mode 100644
index 0000000..796d04e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "types/address.h"
+
+namespace test_vendor_lib {
+
+// Model the connection of a device to the controller.
+class AclConnection {
+ public:
+  AclConnection(const Address& addr) : address_(addr), connected_(false), encrypted_(false) {}
+
+  virtual ~AclConnection() = default;
+
+  void SetConnected(bool connected) {
+    connected_ = connected;
+  };
+  bool IsConnected() const {
+    return connected_;
+  };
+
+  void Encrypt() {
+    encrypted_ = true;
+  };
+  bool IsEncrypted() const {
+    return encrypted_;
+  };
+
+  const Address& GetAddress() const {
+    return address_;
+  }
+  void SetAddress(const Address& address) {
+    address_ = address;
+  }
+
+ private:
+  Address address_;
+
+  // State variables
+  bool connected_;
+  bool encrypted_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
new file mode 100644
index 0000000..2d5ff97
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.cc
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "acl_connection_handler"
+
+#include "acl_connection_handler.h"
+
+#include "base/logging.h"
+
+#include "osi/include/log.h"
+#include "types/address.h"
+
+using std::shared_ptr;
+
+namespace test_vendor_lib {
+
+bool AclConnectionHandler::HasHandle(uint16_t handle) const {
+  if (acl_connections_.count(handle) == 0) {
+    return false;
+  }
+  return true;
+}
+
+uint16_t AclConnectionHandler::GetUnusedHandle() {
+  static uint16_t sNextHandle = acl::kReservedHandle - 2;
+  while (acl_connections_.count(sNextHandle) == 1) {
+    sNextHandle = (sNextHandle + 1) % acl::kReservedHandle;
+  }
+  uint16_t unused_handle = sNextHandle;
+  sNextHandle = (sNextHandle + 1) % acl::kReservedHandle;
+  return unused_handle;
+}
+
+bool AclConnectionHandler::CreatePendingConnection(const Address& addr) {
+  if ((pending_connections_.size() + 1 > max_pending_connections_) || HasPendingConnection(addr)) {
+    return false;
+  }
+  pending_connections_.insert(addr);
+  return true;
+}
+
+bool AclConnectionHandler::HasPendingConnection(const Address& addr) {
+  return pending_connections_.count(addr) == 1;
+}
+
+bool AclConnectionHandler::CancelPendingConnection(const Address& addr) {
+  if (!HasPendingConnection(addr)) {
+    return false;
+  }
+  pending_connections_.erase(addr);
+  return true;
+}
+
+uint16_t AclConnectionHandler::CreateConnection(const Address& addr) {
+  if (CancelPendingConnection(addr)) {
+    uint16_t handle = GetUnusedHandle();
+    acl_connections_.emplace(handle, addr);
+    SetConnected(handle, true);
+    return handle;
+  }
+  return acl::kReservedHandle;
+}
+
+bool AclConnectionHandler::Disconnect(uint16_t handle) {
+  return acl_connections_.erase(handle) > 0;
+}
+
+uint16_t AclConnectionHandler::GetHandle(const Address& addr) const {
+  for (auto pair : acl_connections_) {
+    if (std::get<AclConnection>(pair).GetAddress() == addr) {
+      return std::get<0>(pair);
+    }
+  }
+  return acl::kReservedHandle;
+}
+
+const Address& AclConnectionHandler::GetAddress(uint16_t handle) const {
+  CHECK(HasHandle(handle)) << "Handle unknown " << handle;
+  return acl_connections_.at(handle).GetAddress();
+}
+
+void AclConnectionHandler::SetConnected(uint16_t handle, bool connected) {
+  if (!HasHandle(handle)) {
+    return;
+  }
+  acl_connections_.at(handle).SetConnected(connected);
+}
+
+bool AclConnectionHandler::IsConnected(uint16_t handle) const {
+  if (!HasHandle(handle)) {
+    return false;
+  }
+  return acl_connections_.at(handle).IsConnected();
+}
+
+void AclConnectionHandler::Encrypt(uint16_t handle) {
+  if (!HasHandle(handle)) {
+    return;
+  }
+  acl_connections_.at(handle).Encrypt();
+}
+
+bool AclConnectionHandler::IsEncrypted(uint16_t handle) const {
+  if (!HasHandle(handle)) {
+    return false;
+  }
+  return acl_connections_.at(handle).IsEncrypted();
+}
+
+void AclConnectionHandler::SetAddress(uint16_t handle, const Address& address) {
+  if (!HasHandle(handle)) {
+    return;
+  }
+  acl_connections_.at(handle).SetAddress(address);
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
new file mode 100644
index 0000000..fda1d3d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/acl_connection_handler.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <set>
+#include <unordered_map>
+
+#include "acl_connection.h"
+#include "include/acl.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+
+class AclConnectionHandler {
+ public:
+  AclConnectionHandler(size_t max_pending_connections = 1) : max_pending_connections_(max_pending_connections) {}
+
+  virtual ~AclConnectionHandler() = default;
+
+  bool CreatePendingConnection(const Address& addr);
+  bool HasPendingConnection(const Address& addr);
+  bool CancelPendingConnection(const Address& addr);
+
+  uint16_t CreateConnection(const Address& addr);
+  bool Disconnect(uint16_t handle);
+  bool HasHandle(uint16_t handle) const;
+
+  uint16_t GetHandle(const Address& addr) const;
+  const Address& GetAddress(uint16_t handle) const;
+
+  void SetConnected(uint16_t handle, bool connected);
+  bool IsConnected(uint16_t handle) const;
+
+  void Encrypt(uint16_t handle);
+  bool IsEncrypted(uint16_t handle) const;
+
+  void SetAddress(uint16_t handle, const Address& address);
+
+ private:
+  std::unordered_map<uint16_t, AclConnection> acl_connections_;
+  size_t max_pending_connections_;
+  std::set<Address> pending_connections_;
+  uint16_t GetUnusedHandle();
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
new file mode 100644
index 0000000..273dd09
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.cc
@@ -0,0 +1,1093 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "dual_mode_controller"
+
+#include "dual_mode_controller.h"
+
+#include <memory>
+
+#include <base/files/file_util.h>
+#include <base/json/json_reader.h>
+#include <base/logging.h>
+#include <base/values.h>
+
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+
+#include "hci.h"
+#include "packets/hci/acl_packet_view.h"
+#include "packets/hci/command_packet_view.h"
+#include "packets/hci/event_packet_builder.h"
+#include "packets/hci/sco_packet_view.h"
+
+using std::vector;
+using test_vendor_lib::hci::EventCode;
+using test_vendor_lib::hci::OpCode;
+
+namespace {
+
+size_t LastNonZero(test_vendor_lib::packets::PacketView<true> view) {
+  for (size_t i = view.size() - 1; i > 0; i--) {
+    if (view[i] != 0) {
+      return i;
+    }
+  }
+  return 0;
+}
+
+}  // namespace
+
+namespace test_vendor_lib {
+constexpr char DualModeController::kControllerPropertiesFile[];
+constexpr uint16_t DualModeController::kSecurityManagerNumKeys;
+
+// Device methods.
+void DualModeController::Initialize(const std::vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
+};
+
+std::string DualModeController::GetTypeString() const {
+  return "Simulated Bluetooth Controller";
+}
+
+void DualModeController::IncomingPacket(packets::LinkLayerPacketView incoming) {
+  link_layer_controller_.IncomingPacket(incoming);
+}
+
+void DualModeController::TimerTick() {
+  link_layer_controller_.TimerTick();
+}
+
+void DualModeController::SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> to_send,
+                                             Phy::Type phy_type) {
+  for (auto phy_pair : phy_layers_) {
+    auto phy_list = std::get<1>(phy_pair);
+    if (phy_type != std::get<0>(phy_pair)) {
+      continue;
+    }
+    for (auto phy : phy_list) {
+      phy->Send(to_send);
+    }
+  }
+}
+
+/*
+void DualModeController::AddConnectionAction(const TaskCallback& task,
+                                             uint16_t handle) {
+  for (size_t i = 0; i < connections_.size(); i++)
+    if (connections_[i]->GetHandle() == handle)
+connections_[i]->AddAction(task);
+}
+*/
+
+void DualModeController::SendCommandCompleteSuccess(OpCode command_opcode) const {
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(command_opcode, hci::Status::SUCCESS)
+                  ->ToVector());
+}
+
+void DualModeController::SendCommandCompleteUnknownOpCodeEvent(uint16_t command_opcode) const {
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteUnknownOpCodeEvent(command_opcode)->ToVector());
+}
+
+void DualModeController::SendCommandCompleteOnlyStatus(OpCode command_opcode, hci::Status status) const {
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(command_opcode, status)->ToVector());
+}
+
+void DualModeController::SendCommandCompleteStatusAndAddress(OpCode command_opcode, hci::Status status,
+                                                             const Address& address) const {
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteStatusAndAddressEvent(command_opcode, status, address)
+                  ->ToVector());
+}
+
+void DualModeController::SendCommandStatus(hci::Status status, OpCode command_opcode) const {
+  send_event_(packets::EventPacketBuilder::CreateCommandStatusEvent(status, command_opcode)->ToVector());
+}
+
+void DualModeController::SendCommandStatusSuccess(OpCode command_opcode) const {
+  SendCommandStatus(hci::Status::SUCCESS, command_opcode);
+}
+
+DualModeController::DualModeController(const std::string& properties_filename, uint16_t num_keys)
+    : Device(properties_filename), security_manager_(num_keys) {
+  loopback_mode_ = hci::LoopbackMode::NO;
+
+  Address public_address;
+  CHECK(Address::FromString("3C:5A:B4:04:05:06", public_address));
+  properties_.SetAddress(public_address);
+
+  link_layer_controller_.RegisterRemoteChannel(
+      [this](std::shared_ptr<packets::LinkLayerPacketBuilder> packet, Phy::Type phy_type) {
+        DualModeController::SendLinkLayerPacket(packet, phy_type);
+      });
+
+#define SET_HANDLER(opcode, method) \
+  active_hci_commands_[static_cast<uint16_t>(opcode)] = [this](packets::PacketView<true> param) { method(param); };
+  SET_HANDLER(OpCode::RESET, HciReset);
+  SET_HANDLER(OpCode::READ_BUFFER_SIZE, HciReadBufferSize);
+  SET_HANDLER(OpCode::HOST_BUFFER_SIZE, HciHostBufferSize);
+  SET_HANDLER(OpCode::SNIFF_SUBRATING, HciSniffSubrating);
+  SET_HANDLER(OpCode::READ_LOCAL_VERSION_INFORMATION, HciReadLocalVersionInformation);
+  SET_HANDLER(OpCode::READ_BD_ADDR, HciReadBdAddr);
+  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_COMMANDS, HciReadLocalSupportedCommands);
+  SET_HANDLER(OpCode::READ_LOCAL_SUPPORTED_CODECS, HciReadLocalSupportedCodecs);
+  SET_HANDLER(OpCode::READ_LOCAL_EXTENDED_FEATURES, HciReadLocalExtendedFeatures);
+  SET_HANDLER(OpCode::READ_REMOTE_EXTENDED_FEATURES, HciReadRemoteExtendedFeatures);
+  SET_HANDLER(OpCode::READ_REMOTE_SUPPORTED_FEATURES, HciReadRemoteSupportedFeatures);
+  SET_HANDLER(OpCode::READ_CLOCK_OFFSET, HciReadClockOffset);
+  SET_HANDLER(OpCode::IO_CAPABILITY_REQUEST_REPLY, HciIoCapabilityRequestReply);
+  SET_HANDLER(OpCode::USER_CONFIRMATION_REQUEST_REPLY, HciUserConfirmationRequestReply);
+  SET_HANDLER(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, HciUserConfirmationRequestNegativeReply);
+  SET_HANDLER(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, HciIoCapabilityRequestNegativeReply);
+  SET_HANDLER(OpCode::WRITE_SIMPLE_PAIRING_MODE, HciWriteSimplePairingMode);
+  SET_HANDLER(OpCode::WRITE_LE_HOST_SUPPORT, HciWriteLeHostSupport);
+  SET_HANDLER(OpCode::SET_EVENT_MASK, HciSetEventMask);
+  SET_HANDLER(OpCode::WRITE_INQUIRY_MODE, HciWriteInquiryMode);
+  SET_HANDLER(OpCode::WRITE_PAGE_SCAN_TYPE, HciWritePageScanType);
+  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_TYPE, HciWriteInquiryScanType);
+  SET_HANDLER(OpCode::AUTHENTICATION_REQUESTED, HciAuthenticationRequested);
+  SET_HANDLER(OpCode::SET_CONNECTION_ENCRYPTION, HciSetConnectionEncryption);
+  SET_HANDLER(OpCode::WRITE_AUTHENTICATION_ENABLE, HciWriteAuthenticationEnable);
+  SET_HANDLER(OpCode::READ_AUTHENTICATION_ENABLE, HciReadAuthenticationEnable);
+  SET_HANDLER(OpCode::WRITE_CLASS_OF_DEVICE, HciWriteClassOfDevice);
+  SET_HANDLER(OpCode::WRITE_PAGE_TIMEOUT, HciWritePageTimeout);
+  SET_HANDLER(OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, HciWriteLinkSupervisionTimeout);
+  SET_HANDLER(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS, HciWriteDefaultLinkPolicySettings);
+  SET_HANDLER(OpCode::WRITE_LINK_POLICY_SETTINGS, HciWriteLinkPolicySettings);
+  SET_HANDLER(OpCode::CHANGE_CONNECTION_PACKET_TYPE, HciChangeConnectionPacketType);
+  SET_HANDLER(OpCode::WRITE_LOCAL_NAME, HciWriteLocalName);
+  SET_HANDLER(OpCode::READ_LOCAL_NAME, HciReadLocalName);
+  SET_HANDLER(OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE, HciWriteExtendedInquiryResponse);
+  SET_HANDLER(OpCode::WRITE_VOICE_SETTING, HciWriteVoiceSetting);
+  SET_HANDLER(OpCode::WRITE_CURRENT_IAC_LAP, HciWriteCurrentIacLap);
+  SET_HANDLER(OpCode::WRITE_INQUIRY_SCAN_ACTIVITY, HciWriteInquiryScanActivity);
+  SET_HANDLER(OpCode::WRITE_SCAN_ENABLE, HciWriteScanEnable);
+  SET_HANDLER(OpCode::SET_EVENT_FILTER, HciSetEventFilter);
+  SET_HANDLER(OpCode::INQUIRY, HciInquiry);
+  SET_HANDLER(OpCode::INQUIRY_CANCEL, HciInquiryCancel);
+  SET_HANDLER(OpCode::ACCEPT_CONNECTION_REQUEST, HciAcceptConnectionRequest);
+  SET_HANDLER(OpCode::REJECT_CONNECTION_REQUEST, HciRejectConnectionRequest);
+  SET_HANDLER(OpCode::LINK_KEY_REQUEST_REPLY, HciLinkKeyRequestReply);
+  SET_HANDLER(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, HciLinkKeyRequestNegativeReply);
+  SET_HANDLER(OpCode::DELETE_STORED_LINK_KEY, HciDeleteStoredLinkKey);
+  SET_HANDLER(OpCode::REMOTE_NAME_REQUEST, HciRemoteNameRequest);
+  SET_HANDLER(OpCode::LE_SET_EVENT_MASK, HciLeSetEventMask);
+  SET_HANDLER(OpCode::LE_READ_BUFFER_SIZE, HciLeReadBufferSize);
+  SET_HANDLER(OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES, HciLeReadLocalSupportedFeatures);
+  SET_HANDLER(OpCode::LE_SET_RANDOM_ADDRESS, HciLeSetRandomAddress);
+  SET_HANDLER(OpCode::LE_SET_ADVERTISING_DATA, HciLeSetAdvertisingData);
+  SET_HANDLER(OpCode::LE_SET_ADVERTISING_PARAMETERS, HciLeSetAdvertisingParameters);
+  SET_HANDLER(OpCode::LE_SET_SCAN_PARAMETERS, HciLeSetScanParameters);
+  SET_HANDLER(OpCode::LE_SET_SCAN_ENABLE, HciLeSetScanEnable);
+  SET_HANDLER(OpCode::LE_CREATE_CONNECTION, HciLeCreateConnection);
+  SET_HANDLER(OpCode::CREATE_CONNECTION, HciCreateConnection);
+  SET_HANDLER(OpCode::DISCONNECT, HciDisconnect);
+  SET_HANDLER(OpCode::LE_CREATE_CONNECTION_CANCEL, HciLeConnectionCancel);
+  SET_HANDLER(OpCode::LE_READ_WHITE_LIST_SIZE, HciLeReadWhiteListSize);
+  SET_HANDLER(OpCode::LE_CLEAR_WHITE_LIST, HciLeClearWhiteList);
+  SET_HANDLER(OpCode::LE_ADD_DEVICE_TO_WHITE_LIST, HciLeAddDeviceToWhiteList);
+  SET_HANDLER(OpCode::LE_REMOVE_DEVICE_FROM_WHITE_LIST, HciLeRemoveDeviceFromWhiteList);
+  SET_HANDLER(OpCode::LE_RAND, HciLeRand);
+  SET_HANDLER(OpCode::LE_READ_SUPPORTED_STATES, HciLeReadSupportedStates);
+  SET_HANDLER(OpCode::LE_GET_VENDOR_CAPABILITIES, HciLeVendorCap);
+  SET_HANDLER(OpCode::LE_MULTI_ADVT, HciLeVendorMultiAdv);
+  SET_HANDLER(OpCode::LE_ADV_FILTER, HciLeAdvertisingFilter);
+  SET_HANDLER(OpCode::LE_ENERGY_INFO, HciLeEnergyInfo);
+  SET_HANDLER(OpCode::LE_EXTENDED_SCAN_PARAMS, HciLeExtendedScanParams);
+  SET_HANDLER(OpCode::LE_READ_REMOTE_FEATURES, HciLeReadRemoteFeatures);
+  SET_HANDLER(OpCode::READ_REMOTE_VERSION_INFORMATION, HciReadRemoteVersionInformation);
+  SET_HANDLER(OpCode::LE_CONNECTION_UPDATE, HciLeConnectionUpdate);
+  SET_HANDLER(OpCode::LE_START_ENCRYPTION, HciLeStartEncryption);
+  // Testing Commands
+  SET_HANDLER(OpCode::READ_LOOPBACK_MODE, HciReadLoopbackMode);
+  SET_HANDLER(OpCode::WRITE_LOOPBACK_MODE, HciWriteLoopbackMode);
+#undef SET_HANDLER
+}
+
+void DualModeController::HciSniffSubrating(packets::PacketView<true> args) {
+  CHECK(args.size() == 8) << __func__ << " size=" << args.size();
+
+  uint16_t handle = args.begin().extract<uint16_t>();
+
+  send_event_(packets::EventPacketBuilder::CreateSniffSubratingEvent(hci::Status::SUCCESS, handle)->ToVector());
+}
+
+void DualModeController::RegisterTaskScheduler(
+    std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> oneshot_scheduler) {
+  link_layer_controller_.RegisterTaskScheduler(oneshot_scheduler);
+}
+
+void DualModeController::RegisterPeriodicTaskScheduler(
+    std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+        periodic_scheduler) {
+  link_layer_controller_.RegisterPeriodicTaskScheduler(periodic_scheduler);
+}
+
+void DualModeController::RegisterTaskCancel(std::function<void(AsyncTaskId)> task_cancel) {
+  link_layer_controller_.RegisterTaskCancel(task_cancel);
+}
+
+void DualModeController::HandleAcl(std::shared_ptr<std::vector<uint8_t>> packet) {
+  auto acl_packet = packets::AclPacketView::Create(packet);
+  if (loopback_mode_ == hci::LoopbackMode::LOCAL) {
+    uint16_t handle = acl_packet.GetHandle();
+    send_acl_(packet);
+    send_event_(packets::EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(handle, 1)->ToVector());
+    return;
+  }
+
+  link_layer_controller_.SendAclToRemote(acl_packet);
+}
+
+void DualModeController::HandleSco(std::shared_ptr<std::vector<uint8_t>> packet) {
+  auto sco_packet = packets::ScoPacketView::Create(packet);
+  if (loopback_mode_ == hci::LoopbackMode::LOCAL) {
+    uint16_t handle = sco_packet.GetHandle();
+    send_sco_(packet);
+    send_event_(packets::EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(handle, 1)->ToVector());
+    return;
+  }
+}
+
+void DualModeController::HandleCommand(std::shared_ptr<std::vector<uint8_t>> packet) {
+  auto command_packet = packets::CommandPacketView::Create(packet);
+  uint16_t opcode = command_packet.GetOpcode();
+  hci::OpCode op = static_cast<hci::OpCode>(opcode);
+
+  if (loopback_mode_ == hci::LoopbackMode::LOCAL &&
+      // Loopback exceptions.
+      op != OpCode::RESET && op != OpCode::SET_CONTROLLER_TO_HOST_FLOW_CONTROL && op != OpCode::HOST_BUFFER_SIZE &&
+      op != OpCode::HOST_NUM_COMPLETED_PACKETS && op != OpCode::READ_BUFFER_SIZE && op != OpCode::READ_LOOPBACK_MODE &&
+      op != OpCode::WRITE_LOOPBACK_MODE) {
+    send_event_(packets::EventPacketBuilder::CreateLoopbackCommandEvent(op, command_packet.GetPayload())->ToVector());
+  } else if (active_hci_commands_.count(opcode) > 0) {
+    active_hci_commands_[opcode](command_packet.GetPayload());
+  } else {
+    SendCommandCompleteUnknownOpCodeEvent(opcode);
+    LOG_INFO(LOG_TAG, "Command opcode: 0x%04X, OGF: 0x%04X, OCF: 0x%04X", opcode, opcode & 0xFC00, opcode & 0x03FF);
+  }
+}
+
+void DualModeController::RegisterEventChannel(
+    const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+  link_layer_controller_.RegisterEventChannel(callback);
+  send_event_ = callback;
+}
+
+void DualModeController::RegisterAclChannel(
+    const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+  link_layer_controller_.RegisterAclChannel(callback);
+  send_acl_ = callback;
+}
+
+void DualModeController::RegisterScoChannel(
+    const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+  link_layer_controller_.RegisterScoChannel(callback);
+  send_sco_ = callback;
+}
+
+void DualModeController::HciReset(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  link_layer_controller_.Reset();
+
+  SendCommandCompleteSuccess(OpCode::RESET);
+}
+
+void DualModeController::HciReadBufferSize(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadBufferSize(
+          hci::Status::SUCCESS, properties_.GetAclDataPacketSize(), properties_.GetSynchronousDataPacketSize(),
+          properties_.GetTotalNumAclDataPackets(), properties_.GetTotalNumSynchronousDataPackets());
+
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciHostBufferSize(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::HOST_BUFFER_SIZE);
+}
+
+void DualModeController::HciReadLocalVersionInformation(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadLocalVersionInformation(
+          hci::Status::SUCCESS, properties_.GetVersion(), properties_.GetRevision(), properties_.GetLmpPalVersion(),
+          properties_.GetManufacturerName(), properties_.GetLmpPalSubversion());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciReadRemoteVersionInformation(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+
+  uint16_t handle = args.begin().extract<uint16_t>();
+
+  hci::Status status =
+      link_layer_controller_.SendCommandToRemoteByHandle(OpCode::READ_REMOTE_VERSION_INFORMATION, args, handle);
+
+  SendCommandStatus(status, OpCode::READ_REMOTE_VERSION_INFORMATION);
+}
+
+void DualModeController::HciReadBdAddr(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadBdAddr(hci::Status::SUCCESS, properties_.GetAddress());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciReadLocalSupportedCommands(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadLocalSupportedCommands(hci::Status::SUCCESS,
+                                                                                   properties_.GetSupportedCommands());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciReadLocalSupportedCodecs(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadLocalSupportedCodecs(
+          hci::Status::SUCCESS, properties_.GetSupportedCodecs(), properties_.GetVendorSpecificCodecs());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciReadLocalExtendedFeatures(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  uint8_t page_number = args.begin().extract<uint8_t>();
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteReadLocalExtendedFeatures(
+                  hci::Status::SUCCESS, page_number, properties_.GetExtendedFeaturesMaximumPageNumber(),
+                  properties_.GetExtendedFeatures(page_number))
+                  ->ToVector());
+}
+
+void DualModeController::HciReadRemoteExtendedFeatures(packets::PacketView<true> args) {
+  CHECK(args.size() == 3) << __func__ << " size=" << args.size();
+
+  uint16_t handle = args.begin().extract<uint16_t>();
+
+  hci::Status status =
+      link_layer_controller_.SendCommandToRemoteByHandle(OpCode::READ_REMOTE_EXTENDED_FEATURES, args, handle);
+
+  SendCommandStatus(status, OpCode::READ_REMOTE_EXTENDED_FEATURES);
+}
+
+void DualModeController::HciReadRemoteSupportedFeatures(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+
+  uint16_t handle = args.begin().extract<uint16_t>();
+
+  hci::Status status =
+      link_layer_controller_.SendCommandToRemoteByHandle(OpCode::READ_REMOTE_SUPPORTED_FEATURES, args, handle);
+
+  SendCommandStatus(status, OpCode::READ_REMOTE_SUPPORTED_FEATURES);
+}
+
+void DualModeController::HciReadClockOffset(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+
+  uint16_t handle = args.begin().extract<uint16_t>();
+
+  hci::Status status = link_layer_controller_.SendCommandToRemoteByHandle(OpCode::READ_CLOCK_OFFSET, args, handle);
+
+  SendCommandStatus(status, OpCode::READ_CLOCK_OFFSET);
+}
+
+void DualModeController::HciIoCapabilityRequestReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 9) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  Address peer = args_itr.extract<Address>();
+  uint8_t io_capability = args_itr.extract<uint8_t>();
+  uint8_t oob_data_present_flag = args_itr.extract<uint8_t>();
+  uint8_t authentication_requirements = args_itr.extract<uint8_t>();
+
+  hci::Status status = link_layer_controller_.IoCapabilityRequestReply(peer, io_capability, oob_data_present_flag,
+                                                                       authentication_requirements);
+
+  SendCommandCompleteStatusAndAddress(OpCode::IO_CAPABILITY_REQUEST_REPLY, status, peer);
+}
+
+void DualModeController::HciUserConfirmationRequestReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
+
+  Address peer = args.begin().extract<Address>();
+
+  hci::Status status = link_layer_controller_.UserConfirmationRequestReply(peer);
+
+  SendCommandCompleteStatusAndAddress(OpCode::USER_CONFIRMATION_REQUEST_REPLY, status, peer);
+}
+
+void DualModeController::HciUserConfirmationRequestNegativeReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
+
+  Address peer = args.begin().extract<Address>();
+
+  hci::Status status = link_layer_controller_.UserConfirmationRequestNegativeReply(peer);
+
+  SendCommandCompleteStatusAndAddress(OpCode::USER_CONFIRMATION_REQUEST_NEGATIVE_REPLY, status, peer);
+}
+
+void DualModeController::HciUserPasskeyRequestReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 10) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  Address peer = args_itr.extract<Address>();
+  uint32_t numeric_value = args_itr.extract<uint32_t>();
+
+  hci::Status status = link_layer_controller_.UserPasskeyRequestReply(peer, numeric_value);
+
+  SendCommandCompleteStatusAndAddress(OpCode::USER_PASSKEY_REQUEST_REPLY, status, peer);
+}
+
+void DualModeController::HciUserPasskeyRequestNegativeReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
+
+  Address peer = args.begin().extract<Address>();
+
+  hci::Status status = link_layer_controller_.UserPasskeyRequestNegativeReply(peer);
+
+  SendCommandCompleteStatusAndAddress(OpCode::USER_PASSKEY_REQUEST_NEGATIVE_REPLY, status, peer);
+}
+
+void DualModeController::HciRemoteOobDataRequestReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 38) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  Address peer = args_itr.extract<Address>();
+  std::vector<uint8_t> c;
+  std::vector<uint8_t> r;
+  for (size_t i = 0; i < 16; i++) {
+    c.push_back(args_itr.extract<uint8_t>());
+  }
+  for (size_t i = 0; i < 16; i++) {
+    r.push_back(args_itr.extract<uint8_t>());
+  }
+  hci::Status status = link_layer_controller_.RemoteOobDataRequestReply(peer, c, r);
+
+  SendCommandCompleteStatusAndAddress(OpCode::REMOTE_OOB_DATA_REQUEST_REPLY, status, peer);
+}
+
+void DualModeController::HciRemoteOobDataRequestNegativeReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
+
+  Address peer = args.begin().extract<Address>();
+
+  hci::Status status = link_layer_controller_.RemoteOobDataRequestNegativeReply(peer);
+
+  SendCommandCompleteStatusAndAddress(OpCode::REMOTE_OOB_DATA_REQUEST_NEGATIVE_REPLY, status, peer);
+}
+
+void DualModeController::HciIoCapabilityRequestNegativeReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  Address peer = args_itr.extract<Address>();
+  hci::Status reason = args_itr.extract<hci::Status>();
+
+  hci::Status status = link_layer_controller_.IoCapabilityRequestNegativeReply(peer, reason);
+
+  SendCommandCompleteStatusAndAddress(OpCode::IO_CAPABILITY_REQUEST_NEGATIVE_REPLY, status, peer);
+}
+
+void DualModeController::HciWriteSimplePairingMode(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  CHECK(args[0] == 1 || args[0] == 0);
+  link_layer_controller_.WriteSimplePairingMode(args[0] == 1);
+  SendCommandCompleteSuccess(OpCode::WRITE_SIMPLE_PAIRING_MODE);
+}
+
+void DualModeController::HciChangeConnectionPacketType(packets::PacketView<true> args) {
+  CHECK(args.size() == 4) << __func__ << " size=" << args.size();
+  auto args_itr = args.begin();
+  uint16_t handle = args_itr.extract<uint16_t>();
+  uint16_t packet_type = args_itr.extract<uint16_t>();
+
+  hci::Status status = link_layer_controller_.ChangeConnectionPacketType(handle, packet_type);
+
+  SendCommandStatus(status, OpCode::CHANGE_CONNECTION_PACKET_TYPE);
+}
+
+void DualModeController::HciWriteLeHostSupport(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_LE_HOST_SUPPORT);
+}
+
+void DualModeController::HciSetEventMask(packets::PacketView<true> args) {
+  CHECK(args.size() == 8) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::SET_EVENT_MASK);
+}
+
+void DualModeController::HciWriteInquiryMode(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  link_layer_controller_.SetInquiryMode(args[0]);
+  SendCommandCompleteSuccess(OpCode::WRITE_INQUIRY_MODE);
+}
+
+void DualModeController::HciWritePageScanType(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_PAGE_SCAN_TYPE);
+}
+
+void DualModeController::HciWriteInquiryScanType(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_INQUIRY_SCAN_TYPE);
+}
+
+void DualModeController::HciAuthenticationRequested(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+  uint16_t handle = args.begin().extract<uint16_t>();
+  hci::Status status = link_layer_controller_.AuthenticationRequested(handle);
+
+  SendCommandStatus(status, OpCode::AUTHENTICATION_REQUESTED);
+}
+
+void DualModeController::HciSetConnectionEncryption(packets::PacketView<true> args) {
+  CHECK(args.size() == 3) << __func__ << " size=" << args.size();
+  auto args_itr = args.begin();
+  uint16_t handle = args_itr.extract<uint16_t>();
+  uint8_t encryption_enable = args_itr.extract<uint8_t>();
+  hci::Status status = link_layer_controller_.SetConnectionEncryption(handle, encryption_enable);
+
+  SendCommandStatus(status, OpCode::SET_CONNECTION_ENCRYPTION);
+}
+
+void DualModeController::HciWriteAuthenticationEnable(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  properties_.SetAuthenticationEnable(args[0]);
+  SendCommandCompleteSuccess(OpCode::WRITE_AUTHENTICATION_ENABLE);
+}
+
+void DualModeController::HciReadAuthenticationEnable(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadAuthenticationEnable(hci::Status::SUCCESS,
+                                                                                 properties_.GetAuthenticationEnable());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciWriteClassOfDevice(packets::PacketView<true> args) {
+  CHECK(args.size() == 3) << __func__ << " size=" << args.size();
+  properties_.SetClassOfDevice(args[0], args[1], args[2]);
+  SendCommandCompleteSuccess(OpCode::WRITE_CLASS_OF_DEVICE);
+}
+
+void DualModeController::HciWritePageTimeout(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_PAGE_TIMEOUT);
+}
+
+void DualModeController::HciWriteDefaultLinkPolicySettings(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_DEFAULT_LINK_POLICY_SETTINGS);
+}
+
+void DualModeController::HciWriteLinkPolicySettings(packets::PacketView<true> args) {
+  CHECK(args.size() == 4) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  uint16_t handle = args_itr.extract<uint16_t>();
+  uint16_t settings = args_itr.extract<uint16_t>();
+
+  hci::Status status = link_layer_controller_.WriteLinkPolicySettings(handle, settings);
+
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteWriteLinkPolicySettings(status, handle)->ToVector());
+}
+
+void DualModeController::HciWriteLinkSupervisionTimeout(packets::PacketView<true> args) {
+  CHECK(args.size() == 4) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  uint16_t handle = args_itr.extract<uint16_t>();
+  uint16_t timeout = args_itr.extract<uint16_t>();
+
+  hci::Status status = link_layer_controller_.WriteLinkSupervisionTimeout(handle, timeout);
+
+  send_event_(
+      packets::EventPacketBuilder::CreateCommandCompleteWriteLinkSupervisionTimeout(status, handle)->ToVector());
+}
+
+void DualModeController::HciReadLocalName(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteReadLocalName(hci::Status::SUCCESS, properties_.GetName());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciWriteLocalName(packets::PacketView<true> args) {
+  CHECK(args.size() == 248) << __func__ << " size=" << args.size();
+  std::vector<uint8_t> clipped(args.begin(), args.begin() + LastNonZero(args) + 1);
+  properties_.SetName(clipped);
+  SendCommandCompleteSuccess(OpCode::WRITE_LOCAL_NAME);
+}
+
+void DualModeController::HciWriteExtendedInquiryResponse(packets::PacketView<true> args) {
+  CHECK(args.size() == 241) << __func__ << " size=" << args.size();
+  // Strip FEC byte and trailing zeros
+  std::vector<uint8_t> clipped(args.begin() + 1, args.begin() + LastNonZero(args) + 1);
+  properties_.SetExtendedInquiryData(clipped);
+  LOG_WARN(LOG_TAG, "Write EIR Inquiry - Size = %d (%d)", static_cast<int>(properties_.GetExtendedInquiryData().size()),
+           static_cast<int>(clipped.size()));
+  SendCommandCompleteSuccess(OpCode::WRITE_EXTENDED_INQUIRY_RESPONSE);
+}
+
+void DualModeController::HciWriteVoiceSetting(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_VOICE_SETTING);
+}
+
+void DualModeController::HciWriteCurrentIacLap(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  CHECK(args.size() == 1 + (3 * args[0]));  // count + 3-byte IACs
+
+  SendCommandCompleteSuccess(OpCode::WRITE_CURRENT_IAC_LAP);
+}
+
+void DualModeController::HciWriteInquiryScanActivity(packets::PacketView<true> args) {
+  CHECK(args.size() == 4) << __func__ << " size=" << args.size();
+  SendCommandCompleteSuccess(OpCode::WRITE_INQUIRY_SCAN_ACTIVITY);
+}
+
+void DualModeController::HciWriteScanEnable(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  link_layer_controller_.SetInquiryScanEnable(args[0] & 0x1);
+  link_layer_controller_.SetPageScanEnable(args[0] & 0x2);
+  SendCommandCompleteSuccess(OpCode::WRITE_SCAN_ENABLE);
+}
+
+void DualModeController::HciSetEventFilter(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  SendCommandCompleteSuccess(OpCode::SET_EVENT_FILTER);
+}
+
+void DualModeController::HciInquiry(packets::PacketView<true> args) {
+  CHECK(args.size() == 5) << __func__ << " size=" << args.size();
+  link_layer_controller_.SetInquiryLAP(args[0] | (args[1] << 8) | (args[2] << 16));
+  link_layer_controller_.SetInquiryMaxResponses(args[4]);
+  link_layer_controller_.StartInquiry(std::chrono::milliseconds(args[3] * 1280));
+
+  SendCommandStatusSuccess(OpCode::INQUIRY);
+}
+
+void DualModeController::HciInquiryCancel(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  link_layer_controller_.InquiryCancel();
+  SendCommandCompleteSuccess(OpCode::INQUIRY_CANCEL);
+}
+
+void DualModeController::HciAcceptConnectionRequest(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+  Address addr = args.begin().extract<Address>();
+  bool try_role_switch = args[6] == 0;
+  hci::Status status = link_layer_controller_.AcceptConnectionRequest(addr, try_role_switch);
+  SendCommandStatus(status, OpCode::ACCEPT_CONNECTION_REQUEST);
+}
+
+void DualModeController::HciRejectConnectionRequest(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+  auto args_itr = args.begin();
+  Address addr = args_itr.extract<Address>();
+  uint8_t reason = args_itr.extract<uint8_t>();
+  hci::Status status = link_layer_controller_.RejectConnectionRequest(addr, reason);
+  SendCommandStatus(status, OpCode::REJECT_CONNECTION_REQUEST);
+}
+
+void DualModeController::HciLinkKeyRequestReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 22) << __func__ << " size=" << args.size();
+  Address addr = args.begin().extract<Address>();
+  packets::PacketView<true> key = args.SubViewLittleEndian(6, 22);
+  hci::Status status = link_layer_controller_.LinkKeyRequestReply(addr, key);
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteLinkKeyRequestReply(status, addr)->ToVector());
+}
+
+void DualModeController::HciLinkKeyRequestNegativeReply(packets::PacketView<true> args) {
+  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
+  Address addr = args.begin().extract<Address>();
+  hci::Status status = link_layer_controller_.LinkKeyRequestNegativeReply(addr);
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteLinkKeyRequestNegativeReply(status, addr)->ToVector());
+}
+
+void DualModeController::HciDeleteStoredLinkKey(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+
+  uint16_t deleted_keys = 0;
+
+  if (args[6] == 0) {
+    Address addr = args.begin().extract<Address>();
+    deleted_keys = security_manager_.DeleteKey(addr);
+  }
+
+  if (args[6] == 1) {
+    security_manager_.DeleteAllKeys();
+  }
+
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteDeleteStoredLinkKey(hci::Status::SUCCESS, deleted_keys)
+                  ->ToVector());
+}
+
+void DualModeController::HciRemoteNameRequest(packets::PacketView<true> args) {
+  CHECK(args.size() == 10) << __func__ << " size=" << args.size();
+
+  Address remote_addr = args.begin().extract<Address>();
+
+  hci::Status status =
+      link_layer_controller_.SendCommandToRemoteByAddress(OpCode::REMOTE_NAME_REQUEST, args, remote_addr, false);
+
+  SendCommandStatus(status, OpCode::REMOTE_NAME_REQUEST);
+}
+
+void DualModeController::HciLeSetEventMask(packets::PacketView<true> args) {
+  CHECK(args.size() == 8) << __func__ << " size=" << args.size();
+  /*
+    uint64_t mask = args.begin().extract<uint64_t>();
+    link_layer_controller_.SetLeEventMask(mask);
+  */
+  SendCommandCompleteSuccess(OpCode::LE_SET_EVENT_MASK);
+}
+
+void DualModeController::HciLeReadBufferSize(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteLeReadBufferSize(
+          hci::Status::SUCCESS, properties_.GetLeDataPacketLength(), properties_.GetTotalNumLeDataPackets());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciLeReadLocalSupportedFeatures(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteLeReadLocalSupportedFeatures(
+          hci::Status::SUCCESS, properties_.GetLeSupportedFeatures());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciLeSetRandomAddress(packets::PacketView<true> args) {
+  CHECK(args.size() == 6) << __func__ << " size=" << args.size();
+  properties_.SetLeAddress(args.begin().extract<Address>());
+  SendCommandCompleteSuccess(OpCode::LE_SET_RANDOM_ADDRESS);
+}
+
+void DualModeController::HciLeSetAdvertisingParameters(packets::PacketView<true> args) {
+  CHECK(args.size() == 15) << __func__ << " size=" << args.size();
+
+  SendCommandCompleteSuccess(OpCode::LE_SET_ADVERTISING_PARAMETERS);
+}
+
+void DualModeController::HciLeSetAdvertisingData(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  SendCommandCompleteSuccess(OpCode::LE_SET_ADVERTISING_DATA);
+}
+
+void DualModeController::HciLeSetScanParameters(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+  link_layer_controller_.SetLeScanType(args[0]);
+  link_layer_controller_.SetLeScanInterval(args[1] | (args[2] << 8));
+  link_layer_controller_.SetLeScanWindow(args[3] | (args[4] << 8));
+  link_layer_controller_.SetLeAddressType(args[5]);
+  link_layer_controller_.SetLeScanFilterPolicy(args[6]);
+  SendCommandCompleteSuccess(OpCode::LE_SET_SCAN_PARAMETERS);
+}
+
+void DualModeController::HciLeSetScanEnable(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+  LOG_INFO(LOG_TAG, "SetScanEnable: %d %d", args[0], args[1]);
+  link_layer_controller_.SetLeScanEnable(args[0]);
+  link_layer_controller_.SetLeFilterDuplicates(args[1]);
+  SendCommandCompleteSuccess(OpCode::LE_SET_SCAN_ENABLE);
+}
+
+void DualModeController::HciLeCreateConnection(packets::PacketView<true> args) {
+  CHECK(args.size() == 25) << __func__ << " size=" << args.size();
+  auto args_itr = args.begin();
+  link_layer_controller_.SetLeScanInterval(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeScanWindow(args_itr.extract<uint16_t>());
+  uint8_t initiator_filter_policy = args_itr.extract<uint8_t>();
+  link_layer_controller_.SetLeInitiatorFilterPolicy(initiator_filter_policy);
+
+  if (initiator_filter_policy == 0) {  // White list not used
+    uint8_t peer_address_type = args_itr.extract<uint8_t>();
+    Address peer_address = args_itr.extract<Address>();
+    link_layer_controller_.SetLePeerAddressType(peer_address_type);
+    link_layer_controller_.SetLePeerAddress(peer_address);
+  }
+  link_layer_controller_.SetLeAddressType(args_itr.extract<uint8_t>());
+  link_layer_controller_.SetLeConnectionIntervalMin(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeConnectionIntervalMax(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeConnectionLatency(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeSupervisionTimeout(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeMinimumCeLength(args_itr.extract<uint16_t>());
+  link_layer_controller_.SetLeMaximumCeLength(args_itr.extract<uint16_t>());
+
+  hci::Status status = link_layer_controller_.SetLeConnect(true);
+
+  SendCommandStatus(status, OpCode::LE_CREATE_CONNECTION);
+}
+
+void DualModeController::HciLeConnectionUpdate(packets::PacketView<true> args) {
+  CHECK(args.size() == 14) << __func__ << " size=" << args.size();
+
+  SendCommandStatus(hci::Status::CONNECTION_REJECTED_UNACCEPTABLE_BD_ADDR, OpCode::LE_CONNECTION_UPDATE);
+
+  send_event_(packets::EventPacketBuilder::CreateLeConnectionUpdateCompleteEvent(hci::Status::SUCCESS, 0x0002, 0x0006,
+                                                                                 0x0000, 0x01f4)
+                  ->ToVector());
+}
+
+void DualModeController::HciCreateConnection(packets::PacketView<true> args) {
+  CHECK(args.size() == 13) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  Address address = args_itr.extract<Address>();
+  uint16_t packet_type = args_itr.extract<uint16_t>();
+  uint8_t page_scan_mode = args_itr.extract<uint8_t>();
+  uint16_t clock_offset = args_itr.extract<uint16_t>();
+  uint8_t allow_role_switch = args_itr.extract<uint8_t>();
+
+  hci::Status status =
+      link_layer_controller_.CreateConnection(address, packet_type, page_scan_mode, clock_offset, allow_role_switch);
+
+  SendCommandStatus(status, OpCode::CREATE_CONNECTION);
+}
+
+void DualModeController::HciDisconnect(packets::PacketView<true> args) {
+  CHECK(args.size() == 3) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  uint16_t handle = args_itr.extract<uint16_t>();
+  uint8_t reason = args_itr.extract<uint8_t>();
+
+  hci::Status status = link_layer_controller_.Disconnect(handle, reason);
+
+  SendCommandStatus(status, OpCode::DISCONNECT);
+}
+
+void DualModeController::HciLeConnectionCancel(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  link_layer_controller_.SetLeConnect(false);
+  SendCommandStatusSuccess(OpCode::LE_CREATE_CONNECTION_CANCEL);
+  /* For testing Jakub's patch:  Figure out a neat way to call this without
+     recompiling.  I'm thinking about a bad device. */
+  /*
+  SendCommandCompleteOnlyStatus(OpCode::LE_CREATE_CONNECTION_CANCEL,
+                                Status::ERR_COMMAND_DISALLOWED);
+  */
+}
+
+void DualModeController::HciLeReadWhiteListSize(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteLeReadWhiteListSize(hci::Status::SUCCESS,
+                                                                            properties_.GetLeWhiteListSize());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciLeClearWhiteList(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  link_layer_controller_.LeWhiteListClear();
+  SendCommandCompleteSuccess(OpCode::LE_CLEAR_WHITE_LIST);
+}
+
+void DualModeController::HciLeAddDeviceToWhiteList(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+
+  if (link_layer_controller_.LeWhiteListFull()) {
+    SendCommandCompleteOnlyStatus(OpCode::LE_ADD_DEVICE_TO_WHITE_LIST, hci::Status::MEMORY_CAPACITY_EXCEEDED);
+    return;
+  }
+  auto args_itr = args.begin();
+  uint8_t addr_type = args_itr.extract<uint8_t>();
+  Address address = args_itr.extract<Address>();
+  link_layer_controller_.LeWhiteListAddDevice(address, addr_type);
+  SendCommandCompleteSuccess(OpCode::LE_ADD_DEVICE_TO_WHITE_LIST);
+}
+
+void DualModeController::HciLeRemoveDeviceFromWhiteList(packets::PacketView<true> args) {
+  CHECK(args.size() == 7) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  uint8_t addr_type = args_itr.extract<uint8_t>();
+  Address address = args_itr.extract<Address>();
+  link_layer_controller_.LeWhiteListRemoveDevice(address, addr_type);
+  SendCommandCompleteSuccess(OpCode::LE_REMOVE_DEVICE_FROM_WHITE_LIST);
+}
+
+/*
+void DualModeController::HciLeReadRemoteUsedFeaturesRsp(uint16_t handle,
+                                                        uint64_t features) {
+  std::shared_ptr<packets::EventPacketBuilder> event =
+      packets::EventPacketBuilder::CreateLeRemoteUsedFeaturesEvent(
+          hci::Status::SUCCESS, handle, features);
+  send_event_(event->ToVector());
+}
+*/
+
+void DualModeController::HciLeReadRemoteFeatures(packets::PacketView<true> args) {
+  CHECK(args.size() == 2) << __func__ << " size=" << args.size();
+
+  uint16_t handle = args.begin().extract<uint16_t>();
+
+  hci::Status status =
+      link_layer_controller_.SendCommandToRemoteByHandle(OpCode::LE_READ_REMOTE_FEATURES, args, handle);
+
+  SendCommandStatus(status, OpCode::LE_READ_REMOTE_FEATURES);
+}
+
+void DualModeController::HciLeRand(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  uint64_t random_val = 0;
+  for (size_t rand_bytes = 0; rand_bytes < sizeof(uint64_t); rand_bytes += sizeof(RAND_MAX)) {
+    random_val = (random_val << (8 * sizeof(RAND_MAX))) | random();
+  }
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteLeRand(hci::Status::SUCCESS, random_val);
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciLeReadSupportedStates(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteLeReadSupportedStates(hci::Status::SUCCESS,
+                                                                              properties_.GetLeSupportedStates());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciLeVendorCap(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  vector<uint8_t> caps = properties_.GetLeVendorCap();
+  if (caps.size() == 0) {
+    SendCommandCompleteOnlyStatus(OpCode::LE_GET_VENDOR_CAPABILITIES, hci::Status::UNKNOWN_COMMAND);
+    return;
+  }
+
+  std::shared_ptr<packets::EventPacketBuilder> command_complete =
+      packets::EventPacketBuilder::CreateCommandCompleteLeGetVendorCapabilities(hci::Status::SUCCESS,
+                                                                                properties_.GetLeVendorCap());
+  send_event_(command_complete->ToVector());
+}
+
+void DualModeController::HciLeVendorMultiAdv(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  SendCommandCompleteOnlyStatus(OpCode::LE_MULTI_ADVT, hci::Status::UNKNOWN_COMMAND);
+}
+
+void DualModeController::HciLeAdvertisingFilter(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  SendCommandCompleteOnlyStatus(OpCode::LE_ADV_FILTER, hci::Status::UNKNOWN_COMMAND);
+}
+
+void DualModeController::HciLeEnergyInfo(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  SendCommandCompleteOnlyStatus(OpCode::LE_ENERGY_INFO, hci::Status::UNKNOWN_COMMAND);
+}
+
+void DualModeController::HciLeExtendedScanParams(packets::PacketView<true> args) {
+  CHECK(args.size() > 0);
+  SendCommandCompleteOnlyStatus(OpCode::LE_EXTENDED_SCAN_PARAMS, hci::Status::UNKNOWN_COMMAND);
+}
+
+void DualModeController::HciLeStartEncryption(packets::PacketView<true> args) {
+  CHECK(args.size() == 28) << __func__ << " size=" << args.size();
+
+  auto args_itr = args.begin();
+  uint16_t handle = args_itr.extract<uint16_t>();
+  // uint64_t random_number = args_itr.extract<uint64_t>();
+  // uint16_t encrypted_diversifier = args_itr.extract<uint16_t>();
+  // std::vector<uint8_t> long_term_key;
+  // for (size_t i = 0; i < 16; i++) {
+  //   long_term_key.push_back(args_itr.extract<uint18_t>();
+  // }
+  SendCommandStatus(hci::Status::SUCCESS, OpCode::LE_START_ENCRYPTION);
+
+  send_event_(packets::EventPacketBuilder::CreateEncryptionChange(hci::Status::SUCCESS, handle, 0x01)->ToVector());
+#if 0
+
+  std::shared_ptr<packets::AclPacketBuilder> encryption_information =
+      std::make_shared<packets::AclPacketBuilder>(
+          0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
+          std::vector<uint8_t>({}));
+
+  encryption_information->AddPayloadOctets2(0x0011);
+  encryption_information->AddPayloadOctets2(0x0006);
+  encryption_information->AddPayloadOctets1(0x06);
+  encryption_information->AddPayloadOctets8(0x0706050403020100);
+  encryption_information->AddPayloadOctets8(0x0F0E0D0C0B0A0908);
+
+  send_acl_(encryption_information);
+
+  encryption_information = std::make_shared<packets::AclPacketBuilder>(
+      0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
+      std::vector<uint8_t>({}));
+
+  encryption_information->AddPayloadOctets2(0x000B);
+  encryption_information->AddPayloadOctets2(0x0006);
+  encryption_information->AddPayloadOctets1(0x07);
+  encryption_information->AddPayloadOctets2(0xBEEF);
+  encryption_information->AddPayloadOctets8(0x0706050403020100);
+
+  send_acl_(encryption_information);
+
+  encryption_information = std::make_shared<packets::AclPacketBuilder>(
+      0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
+      std::vector<uint8_t>({}));
+
+  encryption_information->AddPayloadOctets2(0x0011);
+  encryption_information->AddPayloadOctets2(0x0006);
+  encryption_information->AddPayloadOctets1(0x08);
+  encryption_information->AddPayloadOctets8(0x0F0E0D0C0B0A0908);
+  encryption_information->AddPayloadOctets8(0x0706050403020100);
+
+  send_acl_(encryption_information);
+
+  encryption_information = std::make_shared<packets::AclPacketBuilder>(
+      0x0002, Acl::FIRST_AUTOMATICALLY_FLUSHABLE, Acl::POINT_TO_POINT,
+      std::vector<uint8_t>({}));
+
+  encryption_information->AddPayloadOctets2(0x0008);
+  encryption_information->AddPayloadOctets2(0x0006);
+  encryption_information->AddPayloadOctets1(0x09);
+  encryption_information->AddPayloadOctets1(0x01);
+  encryption_information->AddPayloadOctets6(0xDEADBEEFF00D);
+  send_acl_(encryption_information);
+  // send_event_(packets::EventPacketBuilder::CreateLeStartEncryption()->ToVector());
+
+#endif
+}
+
+void DualModeController::HciReadLoopbackMode(packets::PacketView<true> args) {
+  CHECK(args.size() == 0) << __func__ << " size=" << args.size();
+  send_event_(packets::EventPacketBuilder::CreateCommandCompleteReadLoopbackMode(hci::Status::SUCCESS, loopback_mode_)
+                  ->ToVector());
+}
+
+void DualModeController::HciWriteLoopbackMode(packets::PacketView<true> args) {
+  CHECK(args.size() == 1) << __func__ << " size=" << args.size();
+  loopback_mode_ = static_cast<hci::LoopbackMode>(args[0]);
+  // ACL channel
+  uint16_t acl_handle = 0x123;
+  send_event_(packets::EventPacketBuilder::CreateConnectionCompleteEvent(
+                  hci::Status::SUCCESS, acl_handle, properties_.GetAddress(), hci::LinkType::ACL, false)
+                  ->ToVector());
+  // SCO channel
+  uint16_t sco_handle = 0x345;
+  send_event_(packets::EventPacketBuilder::CreateConnectionCompleteEvent(
+                  hci::Status::SUCCESS, sco_handle, properties_.GetAddress(), hci::LinkType::SCO, false)
+                  ->ToVector());
+  SendCommandCompleteSuccess(OpCode::WRITE_LOOPBACK_MODE);
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
new file mode 100644
index 0000000..f33bbb8
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/dual_mode_controller.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "base/time/time.h"
+#include "link_layer_controller.h"
+#include "model/devices/device.h"
+#include "model/setup/async_manager.h"
+#include "security_manager.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+
+// Emulates a dual mode BR/EDR + LE controller by maintaining the link layer
+// state machine detailed in the Bluetooth Core Specification Version 4.2,
+// Volume 6, Part B, Section 1.1 (page 30). Provides methods corresponding to
+// commands sent by the HCI. These methods will be registered as callbacks from
+// a controller instance with the HciHandler. To implement a new Bluetooth
+// command, simply add the method declaration below, with return type void and a
+// single const std::vector<uint8_t>& argument. After implementing the
+// method, simply register it with the HciHandler using the SET_HANDLER macro in
+// the controller's default constructor. Be sure to name your method after the
+// corresponding Bluetooth command in the Core Specification with the prefix
+// "Hci" to distinguish it as a controller command.
+class DualModeController : public Device {
+  // The location of the config file loaded to populate controller attributes.
+  static constexpr char kControllerPropertiesFile[] = "/etc/bluetooth/controller_properties.json";
+  static constexpr uint16_t kSecurityManagerNumKeys = 15;
+
+ public:
+  // Sets all of the methods to be used as callbacks in the HciHandler.
+  DualModeController(const std::string& properties_filename = std::string(kControllerPropertiesFile),
+                     uint16_t num_keys = kSecurityManagerNumKeys);
+
+  ~DualModeController() = default;
+
+  // Device methods.
+  virtual void Initialize(const std::vector<std::string>& args) override;
+
+  virtual std::string GetTypeString() const override;
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView incoming) override;
+
+  virtual void TimerTick() override;
+
+  // Send packets to remote devices
+  void SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> to_send, Phy::Type phy_type);
+
+  // Route commands and data from the stack.
+  void HandleAcl(std::shared_ptr<std::vector<uint8_t>> acl_packet);
+  void HandleCommand(std::shared_ptr<std::vector<uint8_t>> command_packet);
+  void HandleSco(std::shared_ptr<std::vector<uint8_t>> sco_packet);
+
+  // Set the callbacks for scheduling tasks.
+  void RegisterTaskScheduler(std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> evtScheduler);
+
+  void RegisterPeriodicTaskScheduler(
+      std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+          periodicEvtScheduler);
+
+  void RegisterTaskCancel(std::function<void(AsyncTaskId)> cancel);
+
+  // Set the callbacks for sending packets to the HCI.
+  void RegisterEventChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_event);
+
+  void RegisterAclChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_acl);
+
+  void RegisterScoChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_sco);
+
+  // Controller commands. For error codes, see the Bluetooth Core Specification,
+  // Version 4.2, Volume 2, Part D (page 370).
+
+  // Link Control Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.1
+
+  // 7.1.1
+  void HciInquiry(packets::PacketView<true> args);
+
+  // 7.1.2
+  void HciInquiryCancel(packets::PacketView<true> args);
+
+  // 7.1.5
+  void HciCreateConnection(packets::PacketView<true> args);
+
+  // 7.1.6
+  void HciDisconnect(packets::PacketView<true> args);
+
+  // 7.1.8
+  void HciAcceptConnectionRequest(packets::PacketView<true> args);
+
+  // 7.1.9
+  void HciRejectConnectionRequest(packets::PacketView<true> args);
+
+  // 7.1.10
+  void HciLinkKeyRequestReply(packets::PacketView<true> args);
+
+  // 7.1.11
+  void HciLinkKeyRequestNegativeReply(packets::PacketView<true> args);
+
+  // 7.1.14
+  void HciChangeConnectionPacketType(packets::PacketView<true> args);
+
+  // 7.1.15
+  void HciAuthenticationRequested(packets::PacketView<true> args);
+
+  // 7.1.16
+  void HciSetConnectionEncryption(packets::PacketView<true> args);
+
+  // 7.1.19
+  void HciRemoteNameRequest(packets::PacketView<true> args);
+
+  // 7.1.21
+  void HciReadRemoteSupportedFeatures(packets::PacketView<true> args);
+
+  // 7.1.22
+  void HciReadRemoteExtendedFeatures(packets::PacketView<true> args);
+
+  // 7.1.23
+  void HciReadRemoteVersionInformation(packets::PacketView<true> args);
+
+  // 7.1.24
+  void HciReadClockOffset(packets::PacketView<true> args);
+
+  // 7.1.29
+  void HciIoCapabilityRequestReply(packets::PacketView<true> args);
+
+  // 7.1.30
+  void HciUserConfirmationRequestReply(packets::PacketView<true> args);
+
+  // 7.1.31
+  void HciUserConfirmationRequestNegativeReply(packets::PacketView<true> args);
+
+  // 7.1.32
+  void HciUserPasskeyRequestReply(packets::PacketView<true> args);
+
+  // 7.1.33
+  void HciUserPasskeyRequestNegativeReply(packets::PacketView<true> args);
+
+  // 7.1.34
+  void HciRemoteOobDataRequestReply(packets::PacketView<true> args);
+
+  // 7.1.35
+  void HciRemoteOobDataRequestNegativeReply(packets::PacketView<true> args);
+
+  // 7.1.36
+  void HciIoCapabilityRequestNegativeReply(packets::PacketView<true> args);
+
+  // Link Policy Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.2
+
+  // 7.2.10
+  void HciWriteLinkPolicySettings(packets::PacketView<true> args);
+
+  // 7.2.12
+  void HciWriteDefaultLinkPolicySettings(packets::PacketView<true> args);
+
+  // 7.2.14
+  void HciSniffSubrating(packets::PacketView<true> args);
+
+  // Link Controller Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.3
+
+  // 7.3.1
+  void HciSetEventMask(packets::PacketView<true> args);
+
+  // 7.3.2
+  void HciReset(packets::PacketView<true> args);
+
+  // 7.3.3
+  void HciSetEventFilter(packets::PacketView<true> args);
+
+  // 7.3.10
+  void HciDeleteStoredLinkKey(packets::PacketView<true> args);
+
+  // 7.3.11
+  void HciWriteLocalName(packets::PacketView<true> args);
+
+  // 7.3.12
+  void HciReadLocalName(packets::PacketView<true> args);
+
+  // 7.3.16
+  void HciWritePageTimeout(packets::PacketView<true> args);
+
+  // 7.3.18
+  void HciWriteScanEnable(packets::PacketView<true> args);
+
+  // 7.3.22
+  void HciWriteInquiryScanActivity(packets::PacketView<true> args);
+
+  // 7.3.23
+  void HciReadAuthenticationEnable(packets::PacketView<true> args);
+
+  // 7.3.24
+  void HciWriteAuthenticationEnable(packets::PacketView<true> args);
+
+  // 7.3.26
+  void HciWriteClassOfDevice(packets::PacketView<true> args);
+
+  // 7.3.28
+  void HciWriteVoiceSetting(packets::PacketView<true> args);
+
+  // 7.3.39
+  void HciHostBufferSize(packets::PacketView<true> args);
+
+  // 7.3.42
+  void HciWriteLinkSupervisionTimeout(packets::PacketView<true> args);
+
+  // 7.3.45
+  void HciWriteCurrentIacLap(packets::PacketView<true> args);
+
+  // 7.3.48
+  void HciWriteInquiryScanType(packets::PacketView<true> args);
+
+  // 7.3.50
+  void HciWriteInquiryMode(packets::PacketView<true> args);
+
+  // 7.3.52
+  void HciWritePageScanType(packets::PacketView<true> args);
+
+  // 7.3.56
+  void HciWriteExtendedInquiryResponse(packets::PacketView<true> args);
+
+  // 7.3.59
+  void HciWriteSimplePairingMode(packets::PacketView<true> args);
+
+  // 7.3.79
+  void HciWriteLeHostSupport(packets::PacketView<true> args);
+
+  // Informational Parameters Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.4
+
+  // 7.4.5
+  void HciReadBufferSize(packets::PacketView<true> args);
+
+  // 7.4.1
+  void HciReadLocalVersionInformation(packets::PacketView<true> args);
+
+  // 7.4.6
+  void HciReadBdAddr(packets::PacketView<true> args);
+
+  // 7.4.2
+  void HciReadLocalSupportedCommands(packets::PacketView<true> args);
+
+  // 7.4.4
+  void HciReadLocalExtendedFeatures(packets::PacketView<true> args);
+
+  // 7.4.8
+  void HciReadLocalSupportedCodecs(packets::PacketView<true> args);
+
+  // Status Parameters Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.5
+
+  // Test Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.7
+
+  // 7.7.1
+  void HciReadLoopbackMode(packets::PacketView<true> args);
+
+  // 7.7.2
+  void HciWriteLoopbackMode(packets::PacketView<true> args);
+
+  // LE Controller Commands
+  // Bluetooth Core Specification Version 4.2 Volume 2 Part E 7.8
+
+  // 7.8.1
+  void HciLeSetEventMask(packets::PacketView<true> args);
+
+  // 7.8.2
+  void HciLeReadBufferSize(packets::PacketView<true> args);
+
+  // 7.8.3
+  void HciLeReadLocalSupportedFeatures(packets::PacketView<true> args);
+
+  // 7.8.4
+  void HciLeSetRandomAddress(packets::PacketView<true> args);
+
+  // 7.8.5
+  void HciLeSetAdvertisingParameters(packets::PacketView<true> args);
+
+  // 7.8.7
+  void HciLeSetAdvertisingData(packets::PacketView<true> args);
+
+  // 7.8.10
+  void HciLeSetScanParameters(packets::PacketView<true> args);
+
+  // 7.8.11
+  void HciLeSetScanEnable(packets::PacketView<true> args);
+
+  // 7.8.12
+  void HciLeCreateConnection(packets::PacketView<true> args);
+
+  // 7.8.18
+  void HciLeConnectionUpdate(packets::PacketView<true> args);
+
+  // 7.8.13
+  void HciLeConnectionCancel(packets::PacketView<true> args);
+
+  // 7.8.14
+  void HciLeReadWhiteListSize(packets::PacketView<true> args);
+
+  // 7.8.15
+  void HciLeClearWhiteList(packets::PacketView<true> args);
+
+  // 7.8.16
+  void HciLeAddDeviceToWhiteList(packets::PacketView<true> args);
+
+  // 7.8.17
+  void HciLeRemoveDeviceFromWhiteList(packets::PacketView<true> args);
+
+  // 7.8.21
+  void HciLeReadRemoteFeatures(packets::PacketView<true> args);
+
+  // 7.8.23
+  void HciLeRand(packets::PacketView<true> args);
+
+  // 7.8.24
+  void HciLeStartEncryption(packets::PacketView<true> args);
+
+  // 7.8.27
+  void HciLeReadSupportedStates(packets::PacketView<true> args);
+
+  // Vendor-specific Commands
+
+  void HciLeVendorSleepMode(packets::PacketView<true> args);
+  void HciLeVendorCap(packets::PacketView<true> args);
+  void HciLeVendorMultiAdv(packets::PacketView<true> args);
+  void HciLeVendor155(packets::PacketView<true> args);
+  void HciLeVendor157(packets::PacketView<true> args);
+  void HciLeEnergyInfo(packets::PacketView<true> args);
+  void HciLeAdvertisingFilter(packets::PacketView<true> args);
+  void HciLeExtendedScanParams(packets::PacketView<true> args);
+
+  void SetTimerPeriod(std::chrono::milliseconds new_period);
+  void StartTimer();
+  void StopTimer();
+
+ protected:
+  LinkLayerController link_layer_controller_{properties_};
+
+ private:
+  // Set a timer for a future action
+  void AddControllerEvent(std::chrono::milliseconds, const TaskCallback& callback);
+
+  void AddConnectionAction(const TaskCallback& callback, uint16_t handle);
+
+  // Creates a command complete event and sends it back to the HCI.
+  void SendCommandComplete(hci::OpCode command_opcode, const std::vector<uint8_t>& return_parameters) const;
+
+  // Sends a command complete event with no return parameters.
+  void SendCommandCompleteSuccess(hci::OpCode command_opcode) const;
+
+  void SendCommandCompleteUnknownOpCodeEvent(uint16_t command_opcode) const;
+
+  // Sends a command complete event with no return parameters.
+  void SendCommandCompleteOnlyStatus(hci::OpCode command_opcode, hci::Status status) const;
+
+  void SendCommandCompleteStatusAndAddress(hci::OpCode command_opcode, hci::Status status,
+                                           const Address& address) const;
+
+  // Creates a command status event and sends it back to the HCI.
+  void SendCommandStatus(hci::Status status, hci::OpCode command_opcode) const;
+
+  // Sends a command status event with default event parameters.
+  void SendCommandStatusSuccess(hci::OpCode command_opcode) const;
+
+  // Callbacks to send packets back to the HCI.
+  std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_acl_;
+  std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_event_;
+  std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_sco_;
+
+  // Maintains the commands to be registered and used in the HciHandler object.
+  // Keys are command opcodes and values are the callbacks to handle each
+  // command.
+  std::unordered_map<uint16_t, std::function<void(packets::PacketView<true>)>> active_hci_commands_;
+
+  hci::LoopbackMode loopback_mode_;
+
+  SecurityManager security_manager_;
+
+  DualModeController(const DualModeController& cmdPckt) = delete;
+  DualModeController& operator=(const DualModeController& cmdPckt) = delete;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
new file mode 100644
index 0000000..ba11436
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.cc
@@ -0,0 +1,1142 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "link_layer_controller"
+
+#include "link_layer_controller.h"
+
+#include <base/logging.h>
+
+#include "hci.h"
+#include "osi/include/log.h"
+#include "packets/hci/acl_packet_builder.h"
+#include "packets/hci/command_packet_view.h"
+#include "packets/hci/event_packet_builder.h"
+#include "packets/hci/sco_packet_builder.h"
+#include "packets/link_layer/command_builder.h"
+#include "packets/link_layer/command_view.h"
+#include "packets/link_layer/disconnect_view.h"
+#include "packets/link_layer/encrypt_connection_view.h"
+#include "packets/link_layer/inquiry_response_view.h"
+#include "packets/link_layer/inquiry_view.h"
+#include "packets/link_layer/io_capability_view.h"
+#include "packets/link_layer/le_advertisement_view.h"
+#include "packets/link_layer/page_response_view.h"
+#include "packets/link_layer/page_view.h"
+#include "packets/link_layer/response_view.h"
+
+using std::vector;
+using namespace std::chrono;
+using namespace test_vendor_lib::packets;
+
+namespace test_vendor_lib {
+
+// TODO: Model Rssi?
+static uint8_t GetRssi() {
+  static uint8_t rssi = 0;
+  rssi += 5;
+  if (rssi > 128) {
+    rssi = rssi % 7;
+  }
+  return -(rssi);
+}
+
+void LinkLayerController::SendLELinkLayerPacket(std::shared_ptr<LinkLayerPacketBuilder> packet) {
+  if (schedule_task_) {
+    schedule_task_(milliseconds(50), [this, packet]() { send_to_remote_(packet, Phy::Type::LOW_ENERGY); });
+  } else {
+    send_to_remote_(packet, Phy::Type::LOW_ENERGY);
+  }
+}
+
+void LinkLayerController::SendLinkLayerPacket(std::shared_ptr<LinkLayerPacketBuilder> packet) {
+  if (schedule_task_) {
+    schedule_task_(milliseconds(50), [this, packet]() { send_to_remote_(packet, Phy::Type::BR_EDR); });
+  } else {
+    send_to_remote_(packet, Phy::Type::BR_EDR);
+  }
+}
+
+hci::Status LinkLayerController::SendCommandToRemoteByAddress(hci::OpCode opcode, PacketView<true> args,
+                                                              const Address& remote, bool use_public_address) {
+  std::shared_ptr<LinkLayerPacketBuilder> command;
+  Address local_address;
+  if (use_public_address) {
+    local_address = properties_.GetAddress();
+  } else {
+    local_address = properties_.GetLeAddress();
+  }
+  command = LinkLayerPacketBuilder::WrapCommand(CommandBuilder::Create(static_cast<uint16_t>(opcode), args),
+                                                local_address, remote);
+  SendLinkLayerPacket(std::move(command));
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::SendCommandToRemoteByHandle(hci::OpCode opcode, PacketView<true> args,
+                                                             uint16_t handle) {
+  // TODO: Handle LE connections
+  bool use_public_address = true;
+  if (!classic_connections_.HasHandle(handle)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+  return SendCommandToRemoteByAddress(opcode, args, classic_connections_.GetAddress(handle), use_public_address);
+}
+
+hci::Status LinkLayerController::SendAclToRemote(AclPacketView acl_packet) {
+  // TODO: Handle LE connections
+  uint16_t handle = acl_packet.GetHandle();
+  if (!classic_connections_.HasHandle(handle)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  std::unique_ptr<ViewForwarderBuilder> acl_builder = ViewForwarderBuilder::Create(acl_packet);
+
+  std::shared_ptr<LinkLayerPacketBuilder> acl = LinkLayerPacketBuilder::WrapAcl(
+      std::move(acl_builder), properties_.GetAddress(), classic_connections_.GetAddress(handle));
+
+  LOG_INFO(LOG_TAG, "%s(%s): handle 0x%x size %d", __func__, properties_.GetAddress().ToString().c_str(), handle,
+           static_cast<int>(acl_packet.size()));
+
+  schedule_task_(milliseconds(5), [this, handle]() {
+    send_event_(EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(handle, 1)->ToVector());
+  });
+  SendLinkLayerPacket(acl);
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::IncomingPacket(LinkLayerPacketView incoming) {
+  // TODO: Resolvable private addresses?
+  if (incoming.GetDestinationAddress() != properties_.GetAddress() &&
+      incoming.GetDestinationAddress() != properties_.GetLeAddress() &&
+      incoming.GetDestinationAddress() != Address::kEmpty) {
+    // Drop packets not addressed to me
+    return;
+  }
+
+  switch (incoming.GetType()) {
+    case Link::PacketType::ACL:
+      IncomingAclPacket(incoming);
+      break;
+    case Link::PacketType::COMMAND:
+      IncomingCommandPacket(incoming);
+      break;
+    case Link::PacketType::DISCONNECT:
+      IncomingDisconnectPacket(incoming);
+      break;
+    case Link::PacketType::ENCRYPT_CONNECTION:
+      IncomingEncryptConnection(incoming);
+      break;
+    case Link::PacketType::ENCRYPT_CONNECTION_RESPONSE:
+      IncomingEncryptConnectionResponse(incoming);
+      break;
+    case Link::PacketType::INQUIRY:
+      if (inquiry_scans_enabled_) {
+        IncomingInquiryPacket(incoming);
+      }
+      break;
+    case Link::PacketType::INQUIRY_RESPONSE:
+      IncomingInquiryResponsePacket(incoming);
+      break;
+    case Link::PacketType::IO_CAPABILITY_REQUEST:
+      IncomingIoCapabilityRequestPacket(incoming);
+      break;
+    case Link::PacketType::IO_CAPABILITY_RESPONSE:
+      IncomingIoCapabilityResponsePacket(incoming);
+      break;
+    case Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE:
+      IncomingIoCapabilityNegativeResponsePacket(incoming);
+      break;
+    case Link::PacketType::LE_ADVERTISEMENT:
+      if (le_scan_enable_ || le_connect_) {
+        IncomingLeAdvertisementPacket(incoming);
+      }
+      break;
+    case Link::PacketType::LE_SCAN:
+      // TODO: Check Advertising flags and see if we are scannable.
+      IncomingLeScanPacket(incoming);
+      break;
+    case Link::PacketType::LE_SCAN_RESPONSE:
+      if (le_scan_enable_ && le_scan_type_ == 1) {
+        IncomingLeScanResponsePacket(incoming);
+      }
+      break;
+    case Link::PacketType::PAGE:
+      if (page_scans_enabled_) {
+        IncomingPagePacket(incoming);
+      }
+      break;
+    case Link::PacketType::PAGE_RESPONSE:
+      IncomingPageResponsePacket(incoming);
+      break;
+    case Link::PacketType::RESPONSE:
+      IncomingResponsePacket(incoming);
+      break;
+    default:
+      LOG_WARN(LOG_TAG, "Dropping unhandled packet of type %d", static_cast<int32_t>(incoming.GetType()));
+  }
+}
+
+void LinkLayerController::IncomingAclPacket(LinkLayerPacketView incoming) {
+  LOG_INFO(LOG_TAG, "Acl Packet %s -> %s", incoming.GetSourceAddress().ToString().c_str(),
+           incoming.GetDestinationAddress().ToString().c_str());
+  AclPacketView acl_view = AclPacketView::Create(incoming.GetPayload());
+  LOG_INFO(LOG_TAG, "%s: remote handle 0x%x size %d", __func__, acl_view.GetHandle(),
+           static_cast<int>(acl_view.size()));
+  uint16_t local_handle = classic_connections_.GetHandle(incoming.GetSourceAddress());
+  LOG_INFO(LOG_TAG, "%s: local handle 0x%x", __func__, local_handle);
+
+  acl::PacketBoundaryFlagsType boundary_flags = acl_view.GetPacketBoundaryFlags();
+  acl::BroadcastFlagsType broadcast_flags = acl_view.GetBroadcastFlags();
+  std::unique_ptr<ViewForwarderBuilder> builder = ViewForwarderBuilder::Create(acl_view.GetPayload());
+  std::unique_ptr<AclPacketBuilder> local_acl =
+      AclPacketBuilder::Create(local_handle, boundary_flags, broadcast_flags, std::move(builder));
+  send_acl_(local_acl->ToVector());
+}
+
+void LinkLayerController::IncomingCommandPacket(LinkLayerPacketView incoming) {
+  // TODO: Check the destination address to see if this packet is for me.
+  CommandView command = CommandView::GetCommand(incoming);
+  hci::OpCode opcode = static_cast<hci::OpCode>(command.GetOpcode());
+  auto args = command.GetData();
+  std::vector<uint64_t> response_data;
+
+  switch (opcode) {
+    case (hci::OpCode::REMOTE_NAME_REQUEST): {
+      std::vector<uint8_t> name = properties_.GetName();
+      LOG_INFO(LOG_TAG, "Remote Name (Local Name) %d", static_cast<int>(name.size()));
+      response_data.push_back(static_cast<uint8_t>(hci::Status::SUCCESS));
+      response_data.push_back(name.size());
+      uint64_t word = 0;
+      for (size_t i = 0; i < name.size(); i++) {
+        if (i > 0 && (i % 8 == 0)) {
+          response_data.push_back(word);
+          word = 0;
+        }
+        word |= static_cast<uint64_t>(name[i]) << (8 * (i % 8));
+      }
+      response_data.push_back(word);
+    } break;
+    case (hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES):
+      LOG_INFO(LOG_TAG, "(%s) Remote Supported Features Requested by: %s %x",
+               incoming.GetDestinationAddress().ToString().c_str(), incoming.GetSourceAddress().ToString().c_str(),
+               static_cast<int>(properties_.GetSupportedFeatures()));
+      response_data.push_back(static_cast<uint8_t>(hci::Status::SUCCESS));
+      response_data.push_back(properties_.GetSupportedFeatures());
+      break;
+    case (hci::OpCode::READ_REMOTE_EXTENDED_FEATURES): {
+      uint8_t page_number = (args + 2).extract<uint8_t>();  // skip the handle
+      LOG_INFO(LOG_TAG, "(%s) Remote Extended Features %d Requested by: %s",
+               incoming.GetDestinationAddress().ToString().c_str(), page_number,
+               incoming.GetSourceAddress().ToString().c_str());
+      uint8_t max_page_number = properties_.GetExtendedFeaturesMaximumPageNumber();
+      if (page_number > max_page_number) {
+        response_data.push_back(static_cast<uint8_t>(hci::Status::INVALID_HCI_COMMAND_PARAMETERS));
+        response_data.push_back(page_number);
+        response_data.push_back(max_page_number);
+        response_data.push_back(0);
+      } else {
+        response_data.push_back(static_cast<uint8_t>(hci::Status::SUCCESS));
+        response_data.push_back(page_number);
+        response_data.push_back(max_page_number);
+        response_data.push_back(properties_.GetExtendedFeatures(page_number));
+      }
+    } break;
+    case (hci::OpCode::READ_REMOTE_VERSION_INFORMATION):
+      response_data.push_back(static_cast<uint8_t>(hci::Status::SUCCESS));
+      response_data.push_back(properties_.GetLmpPalVersion());
+      response_data.push_back(properties_.GetManufacturerName());
+      response_data.push_back(properties_.GetLmpPalSubversion());
+      break;
+    case (hci::OpCode::READ_CLOCK_OFFSET):
+      response_data.push_back(static_cast<uint8_t>(hci::Status::SUCCESS));
+      response_data.push_back(properties_.GetClockOffset());
+      break;
+    default:
+      LOG_INFO(LOG_TAG, "Dropping unhandled command 0x%04x", static_cast<uint16_t>(opcode));
+      return;
+  }
+  SendLinkLayerPacket(
+      LinkLayerPacketBuilder::WrapResponse(ResponseBuilder::Create(static_cast<uint16_t>(opcode), response_data),
+                                           properties_.GetAddress(), incoming.GetSourceAddress()));
+}
+
+void LinkLayerController::IncomingDisconnectPacket(LinkLayerPacketView incoming) {
+  LOG_INFO(LOG_TAG, "Disconnect Packet");
+  DisconnectView disconnect = DisconnectView::GetDisconnect(incoming);
+  Address peer = incoming.GetSourceAddress();
+  uint16_t handle = classic_connections_.GetHandle(peer);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO(LOG_TAG, "%s: Unknown connection @%s", __func__, peer.ToString().c_str());
+    return;
+  }
+  CHECK(classic_connections_.Disconnect(handle)) << "GetHandle() returned invalid handle " << handle;
+
+  uint8_t reason = disconnect.GetReason();
+  schedule_task_(milliseconds(20), [this, handle, reason]() { DisconnectCleanup(handle, reason); });
+}
+
+void LinkLayerController::IncomingEncryptConnection(LinkLayerPacketView incoming) {
+  LOG_INFO(LOG_TAG, "%s", __func__);
+  // TODO: Check keys
+  Address peer = incoming.GetSourceAddress();
+  uint16_t handle = classic_connections_.GetHandle(peer);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO(LOG_TAG, "%s: Unknown connection @%s", __func__, peer.ToString().c_str());
+    return;
+  }
+  send_event_(EventPacketBuilder::CreateEncryptionChange(hci::Status::SUCCESS, handle, 1)->ToVector());
+  SendLinkLayerPacket(LinkLayerPacketBuilder::WrapEncryptConnectionResponse(
+      EncryptConnectionBuilder::Create(security_manager_.GetKey(peer)), properties_.GetAddress(), peer));
+}
+
+void LinkLayerController::IncomingEncryptConnectionResponse(LinkLayerPacketView incoming) {
+  LOG_INFO(LOG_TAG, "%s", __func__);
+  // TODO: Check keys
+  uint16_t handle = classic_connections_.GetHandle(incoming.GetSourceAddress());
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO(LOG_TAG, "%s: Unknown connection @%s", __func__, incoming.GetSourceAddress().ToString().c_str());
+    return;
+  }
+  send_event_(EventPacketBuilder::CreateEncryptionChange(hci::Status::SUCCESS, handle, 1)->ToVector());
+}
+
+void LinkLayerController::IncomingInquiryPacket(LinkLayerPacketView incoming) {
+  InquiryView inquiry = InquiryView::GetInquiry(incoming);
+  std::unique_ptr<InquiryResponseBuilder> inquiry_response;
+  switch (inquiry.GetType()) {
+    case (Inquiry::InquiryType::STANDARD):
+      inquiry_response = InquiryResponseBuilder::CreateStandard(
+          properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(), properties_.GetClockOffset());
+      break;
+
+    case (Inquiry::InquiryType::RSSI):
+      inquiry_response =
+          InquiryResponseBuilder::CreateRssi(properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(),
+                                             properties_.GetClockOffset(), GetRssi());
+      break;
+
+    case (Inquiry::InquiryType::EXTENDED):
+      inquiry_response = InquiryResponseBuilder::CreateExtended(
+          properties_.GetPageScanRepetitionMode(), properties_.GetClassOfDevice(), properties_.GetClockOffset(),
+          GetRssi(), properties_.GetExtendedInquiryData());
+      break;
+    default:
+      LOG_WARN(LOG_TAG, "Unhandled Incoming Inquiry of type %d", static_cast<int>(inquiry.GetType()));
+      return;
+  }
+  SendLinkLayerPacket(LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response), properties_.GetAddress(),
+                                                                  incoming.GetSourceAddress()));
+  // TODO: Send an Inquriy Response Notification Event 7.7.74
+}
+
+void LinkLayerController::IncomingInquiryResponsePacket(LinkLayerPacketView incoming) {
+  InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(incoming);
+  std::vector<uint8_t> eir;
+
+  switch (inquiry_response.GetType()) {
+    case (Inquiry::InquiryType::STANDARD): {
+      LOG_WARN(LOG_TAG, "Incoming Standard Inquiry Response");
+      // TODO: Support multiple inquiries in the same packet.
+      std::unique_ptr<EventPacketBuilder> inquiry_result = EventPacketBuilder::CreateInquiryResultEvent();
+      bool result_added =
+          inquiry_result->AddInquiryResult(incoming.GetSourceAddress(), inquiry_response.GetPageScanRepetitionMode(),
+                                           inquiry_response.GetClassOfDevice(), inquiry_response.GetClockOffset());
+      CHECK(result_added);
+      send_event_(inquiry_result->ToVector());
+    } break;
+
+    case (Inquiry::InquiryType::RSSI):
+      LOG_WARN(LOG_TAG, "Incoming RSSI Inquiry Response");
+      send_event_(EventPacketBuilder::CreateExtendedInquiryResultEvent(
+                      incoming.GetSourceAddress(), inquiry_response.GetPageScanRepetitionMode(),
+                      inquiry_response.GetClassOfDevice(), inquiry_response.GetClockOffset(), GetRssi(), eir)
+                      ->ToVector());
+      break;
+
+    case (Inquiry::InquiryType::EXTENDED): {
+      LOG_WARN(LOG_TAG, "Incoming Extended Inquiry Response");
+      auto eir_itr = inquiry_response.GetExtendedData();
+      size_t eir_bytes = eir_itr.NumBytesRemaining();
+      LOG_WARN(LOG_TAG, "Payload size = %d", static_cast<int>(eir_bytes));
+      for (size_t i = 0; i < eir_bytes; i++) {
+        eir.push_back(eir_itr.extract<uint8_t>());
+      }
+      send_event_(EventPacketBuilder::CreateExtendedInquiryResultEvent(
+                      incoming.GetSourceAddress(), inquiry_response.GetPageScanRepetitionMode(),
+                      inquiry_response.GetClassOfDevice(), inquiry_response.GetClockOffset(), GetRssi(), eir)
+                      ->ToVector());
+    } break;
+    default:
+      LOG_WARN(LOG_TAG, "Unhandled Incoming Inquiry Response of type %d", static_cast<int>(inquiry_response.GetType()));
+  }
+}
+
+void LinkLayerController::IncomingIoCapabilityRequestPacket(LinkLayerPacketView incoming) {
+  LOG_DEBUG(LOG_TAG, "%s", __func__);
+  if (!simple_pairing_mode_enabled_) {
+    LOG_WARN(LOG_TAG, "%s: Only simple pairing mode is implemented", __func__);
+    return;
+  }
+  auto request = IoCapabilityView::GetIoCapability(incoming);
+  Address peer = incoming.GetSourceAddress();
+
+  uint8_t io_capability = request.GetIoCapability();
+  uint8_t oob_data_present = request.GetOobDataPresent();
+  uint8_t authentication_requirements = request.GetAuthenticationRequirements();
+
+  uint16_t handle = classic_connections_.GetHandle(peer);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO(LOG_TAG, "%s: Device not connected %s", __func__, peer.ToString().c_str());
+    return;
+  }
+
+  security_manager_.AuthenticationRequest(peer, handle);
+
+  security_manager_.SetPeerIoCapability(peer, io_capability, oob_data_present, authentication_requirements);
+
+  send_event_(EventPacketBuilder::CreateIoCapabilityResponseEvent(peer, io_capability, oob_data_present,
+                                                                  authentication_requirements)
+                  ->ToVector());
+
+  StartSimplePairing(peer);
+}
+
+void LinkLayerController::IncomingIoCapabilityResponsePacket(LinkLayerPacketView incoming) {
+  LOG_DEBUG(LOG_TAG, "%s", __func__);
+  auto response = IoCapabilityView::GetIoCapability(incoming);
+  Address peer = incoming.GetSourceAddress();
+  uint8_t io_capability = response.GetIoCapability();
+  uint8_t oob_data_present = response.GetOobDataPresent();
+  uint8_t authentication_requirements = response.GetAuthenticationRequirements();
+
+  security_manager_.SetPeerIoCapability(peer, io_capability, oob_data_present, authentication_requirements);
+
+  send_event_(EventPacketBuilder::CreateIoCapabilityResponseEvent(peer, io_capability, oob_data_present,
+                                                                  authentication_requirements)
+                  ->ToVector());
+
+  PairingType pairing_type = security_manager_.GetSimplePairingType();
+  if (pairing_type != PairingType::INVALID) {
+    schedule_task_(milliseconds(5), [this, peer, pairing_type]() { AuthenticateRemoteStage1(peer, pairing_type); });
+  } else {
+    LOG_INFO(LOG_TAG, "%s: Security Manager returned INVALID", __func__);
+  }
+}
+
+void LinkLayerController::IncomingIoCapabilityNegativeResponsePacket(LinkLayerPacketView incoming) {
+  LOG_DEBUG(LOG_TAG, "%s", __func__);
+  Address peer = incoming.GetSourceAddress();
+
+  CHECK(security_manager_.GetAuthenticationAddress() == peer);
+
+  security_manager_.InvalidateIoCapabilities();
+}
+
+void LinkLayerController::IncomingLeAdvertisementPacket(LinkLayerPacketView incoming) {
+  // TODO: Handle multiple advertisements per packet.
+
+  LeAdvertisementView advertisement = LeAdvertisementView::GetLeAdvertisementView(incoming);
+  LeAdvertisement::AdvertisementType adv_type = advertisement.GetAdvertisementType();
+  LeAdvertisement::AddressType addr_type = advertisement.GetAddressType();
+
+  if (le_scan_enable_) {
+    vector<uint8_t> ad;
+    auto itr = advertisement.GetData();
+    size_t ad_size = itr.NumBytesRemaining();
+    for (size_t i = 0; i < ad_size; i++) {
+      ad.push_back(itr.extract<uint8_t>());
+    }
+    std::unique_ptr<EventPacketBuilder> le_adverts = EventPacketBuilder::CreateLeAdvertisingReportEvent();
+
+    if (!le_adverts->AddLeAdvertisingReport(adv_type, addr_type, incoming.GetSourceAddress(), ad, GetRssi())) {
+      LOG_INFO(LOG_TAG, "Couldn't add the advertising report.");
+    } else {
+      send_event_(le_adverts->ToVector());
+    }
+  }
+
+#if 0
+      // Connect
+      if (le_connect_ && (adv_type == BTM_BLE_CONNECT_EVT ||
+                          adv_type == BTM_BLE_CONNECT_DIR_EVT)) {
+        LOG_INFO(LOG_TAG, "Connecting to device %d", static_cast<int>(dev));
+        if (le_peer_address_ == addr && le_peer_address_type_ == addr_type &&
+            remote_devices_[dev]->LeConnect()) {
+          uint16_t handle = LeGetHandle();
+          send_event_(EventPacketBuilder::CreateLeConnectionCompleteEvent(
+              hci::Status::SUCCESS, handle, HCI_ROLE_MASTER, addr_type, addr, 1,
+              2, 3)->ToVector());
+
+          // TODO: LeGetConnInterval(), LeGetConnLatency(),
+          // LeGetSupervisionTimeout()));
+          le_connect_ = false;
+
+          std::shared_ptr<Connection> new_connection =
+              std::make_shared<Connection>(remote_devices_[dev], handle);
+          /*
+          connections_.push_back(new_connection);
+
+          remote_devices_[dev]->SetConnection(new_connection);
+          */
+        }
+
+        if (LeWhiteListContainsDevice(addr, addr_type) &&
+            remote_devices_[dev]->LeConnect()) {
+          LOG_INFO(LOG_TAG, "White List Connecting to device %d",
+                   static_cast<int>(dev));
+          uint16_t handle = LeGetHandle();
+          send_event_(EventPacketBuilder::CreateLeConnectionCompleteEvent(
+              hci::Status::SUCCESS, handle, HCI_ROLE_MASTER, addr_type, addr, 1,
+              2, 3)->ToVector());
+          // TODO: LeGetConnInterval(), LeGetConnLatency(),
+          // LeGetSupervisionTimeout()));
+          le_connect_ = false;
+
+          std::shared_ptr<Connection> new_connection =
+              std::make_shared<Connection>(remote_devices_[dev], handle);
+          /*
+          connections_.push_back(new_connection);
+          remote_devices_[dev]->SetConnection(new_connection);
+          */
+        }
+      }
+#endif
+
+  // Active scanning
+  if (le_scan_enable_ && le_scan_type_ == 1) {
+    std::shared_ptr<LinkLayerPacketBuilder> to_send =
+        LinkLayerPacketBuilder::WrapLeScan(properties_.GetLeAddress(), incoming.GetSourceAddress());
+    SendLELinkLayerPacket(to_send);
+  }
+}
+
+void LinkLayerController::IncomingLeScanPacket(LinkLayerPacketView incoming) {
+  LOG_INFO(LOG_TAG, "LE Scan Packet");
+  std::unique_ptr<LeAdvertisementBuilder> response = LeAdvertisementBuilder::Create(
+      static_cast<LeAdvertisement::AddressType>(properties_.GetLeAddressType()),
+      static_cast<LeAdvertisement::AdvertisementType>(properties_.GetLeAdvertisementType()),
+      properties_.GetLeScanResponse());
+  std::shared_ptr<LinkLayerPacketBuilder> to_send = LinkLayerPacketBuilder::WrapLeScanResponse(
+      std::move(response), properties_.GetLeAddress(), incoming.GetSourceAddress());
+  SendLELinkLayerPacket(to_send);
+}
+
+void LinkLayerController::IncomingLeScanResponsePacket(LinkLayerPacketView incoming) {
+  LeAdvertisementView scan_response = LeAdvertisementView::GetLeAdvertisementView(incoming);
+  vector<uint8_t> ad;
+  auto itr = scan_response.GetData();
+  size_t scan_size = itr.NumBytesRemaining();
+  for (size_t i = 0; i < scan_size; i++) {
+    ad.push_back(itr.extract<uint8_t>());
+  }
+
+  std::unique_ptr<EventPacketBuilder> le_adverts = EventPacketBuilder::CreateLeAdvertisingReportEvent();
+
+  if (!le_adverts->AddLeAdvertisingReport(scan_response.GetAdvertisementType(), scan_response.GetAddressType(),
+                                          incoming.GetSourceAddress(), ad, GetRssi())) {
+    LOG_INFO(LOG_TAG, "Couldn't add the scan response.");
+  } else {
+    LOG_INFO(LOG_TAG, "Sending scan response");
+    send_event_(le_adverts->ToVector());
+  }
+}
+
+void LinkLayerController::IncomingPagePacket(LinkLayerPacketView incoming) {
+  PageView page = PageView::GetPage(incoming);
+  LOG_INFO(LOG_TAG, "%s from %s", __func__, incoming.GetSourceAddress().ToString().c_str());
+
+  if (!classic_connections_.CreatePendingConnection(incoming.GetSourceAddress())) {
+    // Send a response to indicate that we're busy, or drop the packet?
+    LOG_WARN(LOG_TAG, "%s: Failed to create a pending connection", __func__);
+  }
+
+  send_event_(EventPacketBuilder::CreateConnectionRequestEvent(incoming.GetSourceAddress(), page.GetClassOfDevice(),
+                                                               hci::LinkType::ACL)
+                  ->ToVector());
+}
+
+void LinkLayerController::IncomingPageResponsePacket(LinkLayerPacketView incoming) {
+  LOG_INFO(LOG_TAG, "%s: %s", __func__, incoming.GetSourceAddress().ToString().c_str());
+  uint16_t handle = classic_connections_.CreateConnection(incoming.GetSourceAddress());
+  if (handle == acl::kReservedHandle) {
+    LOG_WARN(LOG_TAG, "%s: No free handles", __func__);
+    return;
+  }
+  LOG_INFO(LOG_TAG, "%s: Sending CreateConnectionComplete", __func__);
+  send_event_(EventPacketBuilder::CreateConnectionCompleteEvent(hci::Status::SUCCESS, handle,
+                                                                incoming.GetSourceAddress(), hci::LinkType::ACL, false)
+                  ->ToVector());
+}
+
+void LinkLayerController::IncomingResponsePacket(LinkLayerPacketView incoming) {
+  ResponseView response = ResponseView::GetResponse(incoming);
+
+  // TODO: Check to see if I'm expecting this response.
+
+  hci::OpCode opcode = static_cast<hci::OpCode>(response.GetOpcode());
+  auto args = response.GetResponseData();
+  hci::Status status = static_cast<hci::Status>(args.extract<uint64_t>());
+
+  uint16_t handle = classic_connections_.GetHandle(incoming.GetSourceAddress());
+
+  switch (opcode) {
+    case (hci::OpCode::REMOTE_NAME_REQUEST): {
+      std::string remote_name = "";
+      size_t length = args.extract<uint64_t>();
+      uint64_t word = 0;
+      for (size_t b = 0; b < length; b++) {
+        size_t byte = b % 8;
+        if (byte == 0) {
+          word = args.extract<uint64_t>();
+        }
+        remote_name += static_cast<uint8_t>(word >> (byte * 8));
+      }
+      send_event_(
+          EventPacketBuilder::CreateRemoteNameRequestCompleteEvent(status, incoming.GetSourceAddress(), remote_name)
+              ->ToVector());
+    } break;
+    case (hci::OpCode::READ_REMOTE_SUPPORTED_FEATURES): {
+      send_event_(
+          EventPacketBuilder::CreateRemoteSupportedFeaturesEvent(status, handle, args.extract<uint64_t>())->ToVector());
+    } break;
+    case (hci::OpCode::READ_REMOTE_EXTENDED_FEATURES): {
+      if (status == hci::Status::SUCCESS) {
+        send_event_(EventPacketBuilder::CreateReadRemoteExtendedFeaturesEvent(
+                        status, handle, args.extract<uint64_t>(), args.extract<uint64_t>(), args.extract<uint64_t>())
+                        ->ToVector());
+      } else {
+        send_event_(EventPacketBuilder::CreateReadRemoteExtendedFeaturesEvent(status, handle, 0, 0, 0)->ToVector());
+      }
+    } break;
+    case (hci::OpCode::READ_REMOTE_VERSION_INFORMATION): {
+      send_event_(EventPacketBuilder::CreateReadRemoteVersionInformationEvent(
+                      status, handle, args.extract<uint64_t>(), args.extract<uint64_t>(), args.extract<uint64_t>())
+                      ->ToVector());
+      LOG_INFO(LOG_TAG, "Read remote version handle 0x%04x", handle);
+    } break;
+    case (hci::OpCode::READ_CLOCK_OFFSET): {
+      send_event_(EventPacketBuilder::CreateReadClockOffsetEvent(status, handle, args.extract<uint64_t>())->ToVector());
+    } break;
+    default:
+      LOG_INFO(LOG_TAG, "Unhandled response to command 0x%04x", static_cast<uint16_t>(opcode));
+  }
+}
+
+void LinkLayerController::TimerTick() {
+  if (inquiry_state_ == Inquiry::InquiryState::INQUIRY) Inquiry();
+  if (inquiry_state_ == Inquiry::InquiryState::INQUIRY) PageScan();
+  Connections();
+}
+
+void LinkLayerController::Connections() {
+  // TODO: Keep connections alive?
+}
+
+void LinkLayerController::RegisterEventChannel(
+    const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+  send_event_ = callback;
+}
+
+void LinkLayerController::RegisterAclChannel(
+    const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+  send_acl_ = callback;
+}
+
+void LinkLayerController::RegisterScoChannel(
+    const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& callback) {
+  send_sco_ = callback;
+}
+
+void LinkLayerController::RegisterRemoteChannel(
+    const std::function<void(std::shared_ptr<LinkLayerPacketBuilder>, Phy::Type)>& callback) {
+  send_to_remote_ = callback;
+}
+
+void LinkLayerController::RegisterTaskScheduler(
+    std::function<AsyncTaskId(milliseconds, const TaskCallback&)> event_scheduler) {
+  schedule_task_ = event_scheduler;
+}
+
+void LinkLayerController::RegisterPeriodicTaskScheduler(
+    std::function<AsyncTaskId(milliseconds, milliseconds, const TaskCallback&)> periodic_event_scheduler) {
+  schedule_periodic_task_ = periodic_event_scheduler;
+}
+
+void LinkLayerController::RegisterTaskCancel(std::function<void(AsyncTaskId)> task_cancel) {
+  cancel_task_ = task_cancel;
+}
+
+void LinkLayerController::AddControllerEvent(milliseconds delay, const TaskCallback& task) {
+  controller_events_.push_back(schedule_task_(delay, task));
+}
+
+void LinkLayerController::WriteSimplePairingMode(bool enabled) {
+  CHECK(enabled) << "The spec says don't disable this!";
+  simple_pairing_mode_enabled_ = enabled;
+}
+
+void LinkLayerController::StartSimplePairing(const Address& address) {
+  // IO Capability Exchange (See the Diagram in the Spec)
+  send_event_(EventPacketBuilder::CreateIoCapabilityRequestEvent(address)->ToVector());
+
+  // Get a Key, then authenticate
+  // PublicKeyExchange(address);
+  // AuthenticateRemoteStage1(address);
+  // AuthenticateRemoteStage2(address);
+}
+
+void LinkLayerController::AuthenticateRemoteStage1(const Address& peer, PairingType pairing_type) {
+  CHECK(security_manager_.GetAuthenticationAddress() == peer);
+  // TODO: Public key exchange first?
+  switch (pairing_type) {
+    case PairingType::AUTO_CONFIRMATION:
+      send_event_(EventPacketBuilder::CreateUserConfirmationRequestEvent(peer, 123456)->ToVector());
+      break;
+    case PairingType::CONFIRM_Y_N:
+      CHECK(false) << __func__ << "Unimplemented PairingType" << static_cast<int>(pairing_type);
+      break;
+    case PairingType::DISPLAY_PIN:
+      CHECK(false) << __func__ << "Unimplemented PairingType" << static_cast<int>(pairing_type);
+      break;
+    case PairingType::DISPLAY_AND_CONFIRM:
+      CHECK(false) << __func__ << "Unimplemented PairingType" << static_cast<int>(pairing_type);
+      break;
+    case PairingType::INPUT_PIN:
+      CHECK(false) << __func__ << "Unimplemented PairingType" << static_cast<int>(pairing_type);
+      break;
+    case PairingType::INVALID:
+      CHECK(false) << __func__ << "Unimplemented PairingType" << static_cast<int>(pairing_type);
+      break;
+    default:
+      CHECK(false) << __func__ << ": Invalid PairingType " << static_cast<int>(pairing_type);
+  }
+}
+
+void LinkLayerController::AuthenticateRemoteStage2(const Address& peer) {
+  uint16_t handle = security_manager_.GetAuthenticationHandle();
+  CHECK(security_manager_.GetAuthenticationAddress() == peer);
+  // Check key in security_manager_ ?
+  send_event_(EventPacketBuilder::CreateAuthenticationCompleteEvent(hci::Status::SUCCESS, handle)->ToVector());
+}
+
+hci::Status LinkLayerController::LinkKeyRequestReply(const Address& peer, PacketView<true> key) {
+  std::vector<uint8_t> key_vec(key.begin(), key.end());
+  security_manager_.WriteKey(peer, key_vec);
+  security_manager_.AuthenticationRequestFinished();
+
+  schedule_task_(milliseconds(5), [this, peer]() { AuthenticateRemoteStage2(peer); });
+
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::LinkKeyRequestNegativeReply(const Address& address) {
+  security_manager_.DeleteKey(address);
+  // Simple pairing to get a key
+  uint16_t handle = classic_connections_.GetHandle(address);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO(LOG_TAG, "%s: Device not connected %s", __func__, address.ToString().c_str());
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  security_manager_.AuthenticationRequest(address, handle);
+
+  schedule_task_(milliseconds(5), [this, address]() { StartSimplePairing(address); });
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::IoCapabilityRequestReply(const Address& peer, uint8_t io_capability,
+                                                          uint8_t oob_data_present_flag,
+                                                          uint8_t authentication_requirements) {
+  security_manager_.SetLocalIoCapability(peer, io_capability, oob_data_present_flag, authentication_requirements);
+
+  PairingType pairing_type = security_manager_.GetSimplePairingType();
+  if (pairing_type != PairingType::INVALID) {
+    schedule_task_(milliseconds(5), [this, peer, pairing_type]() { AuthenticateRemoteStage1(peer, pairing_type); });
+    SendLinkLayerPacket(LinkLayerPacketBuilder::WrapIoCapabilityResponse(
+        IoCapabilityBuilder::Create(io_capability, oob_data_present_flag, authentication_requirements),
+        properties_.GetAddress(), peer));
+  } else {
+    LOG_INFO(LOG_TAG, "%s: Requesting remote capability", __func__);
+    SendLinkLayerPacket(LinkLayerPacketBuilder::WrapIoCapabilityRequest(
+        IoCapabilityBuilder::Create(io_capability, oob_data_present_flag, authentication_requirements),
+        properties_.GetAddress(), peer));
+  }
+
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::IoCapabilityRequestNegativeReply(const Address& peer, hci::Status reason) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+
+  security_manager_.InvalidateIoCapabilities();
+
+  SendLinkLayerPacket(LinkLayerPacketBuilder::WrapIoCapabilityNegativeResponse(
+      IoCapabilityNegativeResponseBuilder::Create(static_cast<uint8_t>(reason)), properties_.GetAddress(), peer));
+
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::UserConfirmationRequestReply(const Address& peer) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+  // TODO: Key could be calculated here.
+  std::vector<uint8_t> key_vec{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  security_manager_.WriteKey(peer, key_vec);
+
+  security_manager_.AuthenticationRequestFinished();
+
+  schedule_task_(milliseconds(5), [this, peer]() { AuthenticateRemoteStage2(peer); });
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::UserConfirmationRequestNegativeReply(const Address& peer) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::UserPasskeyRequestReply(const Address& peer, uint32_t numeric_value) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+  LOG_INFO(LOG_TAG, "TODO:Do something with the passkey %06d", numeric_value);
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::UserPasskeyRequestNegativeReply(const Address& peer) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::RemoteOobDataRequestReply(const Address& peer, const std::vector<uint8_t>& c,
+                                                           const std::vector<uint8_t>& r) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+  LOG_INFO(LOG_TAG, "TODO:Do something with the OOB data c=%d r=%d", c[0], r[0]);
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::RemoteOobDataRequestNegativeReply(const Address& peer) {
+  if (security_manager_.GetAuthenticationAddress() != peer) {
+    return hci::Status::AUTHENTICATION_FAILURE;
+  }
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::HandleAuthenticationRequest(const Address& address, uint16_t handle) {
+  if (simple_pairing_mode_enabled_ == true) {
+    security_manager_.AuthenticationRequest(address, handle);
+    send_event_(EventPacketBuilder::CreateLinkKeyRequestEvent(address)->ToVector());
+  } else {  // Should never happen for our phones
+    // Check for a key, try to authenticate, ask for a PIN.
+    send_event_(
+        EventPacketBuilder::CreateAuthenticationCompleteEvent(hci::Status::AUTHENTICATION_FAILURE, handle)->ToVector());
+  }
+}
+
+hci::Status LinkLayerController::AuthenticationRequested(uint16_t handle) {
+  if (!classic_connections_.HasHandle(handle)) {
+    LOG_INFO(LOG_TAG, "Authentication Requested for unknown handle %04x", handle);
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  Address remote = classic_connections_.GetAddress(handle);
+
+  schedule_task_(milliseconds(5), [this, remote, handle]() { HandleAuthenticationRequest(remote, handle); });
+
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::HandleSetConnectionEncryption(const Address& peer, uint16_t handle,
+                                                        uint8_t encryption_enable) {
+  // TODO: Block ACL traffic or at least guard against it
+
+  if (classic_connections_.IsEncrypted(handle) && encryption_enable) {
+    send_event_(
+        EventPacketBuilder::CreateEncryptionChange(hci::Status::SUCCESS, handle, encryption_enable)->ToVector());
+    return;
+  }
+
+  SendLinkLayerPacket(LinkLayerPacketBuilder::WrapEncryptConnection(
+      EncryptConnectionBuilder::Create(security_manager_.GetKey(peer)), properties_.GetAddress(), peer));
+}
+
+hci::Status LinkLayerController::SetConnectionEncryption(uint16_t handle, uint8_t encryption_enable) {
+  if (!classic_connections_.HasHandle(handle)) {
+    LOG_INFO(LOG_TAG, "Authentication Requested for unknown handle %04x", handle);
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  if (classic_connections_.IsEncrypted(handle) && !encryption_enable) {
+    return hci::Status::ENCRYPTION_MODE_NOT_ACCEPTABLE;
+  }
+  Address remote = classic_connections_.GetAddress(handle);
+
+  schedule_task_(milliseconds(5), [this, remote, handle, encryption_enable]() {
+    HandleSetConnectionEncryption(remote, handle, encryption_enable);
+  });
+
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::AcceptConnectionRequest(const Address& addr, bool try_role_switch) {
+  if (!classic_connections_.HasPendingConnection(addr)) {
+    LOG_INFO(LOG_TAG, "%s: No pending connection", __func__);
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  LOG_INFO(LOG_TAG, "%s: Accept in 200ms", __func__);
+  schedule_task_(milliseconds(200), [this, addr, try_role_switch]() {
+    LOG_INFO(LOG_TAG, "%s: Accepted", __func__);
+    MakeSlaveConnection(addr, try_role_switch);
+  });
+
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::MakeSlaveConnection(const Address& addr, bool try_role_switch) {
+  std::shared_ptr<LinkLayerPacketBuilder> to_send = LinkLayerPacketBuilder::WrapPageResponse(
+      PageResponseBuilder::Create(try_role_switch), properties_.GetAddress(), addr);
+  LOG_INFO(LOG_TAG, "%s sending page response to %s", __func__, addr.ToString().c_str());
+  SendLinkLayerPacket(to_send);
+
+  uint16_t handle = classic_connections_.CreateConnection(addr);
+  if (handle == acl::kReservedHandle) {
+    LOG_INFO(LOG_TAG, "%s CreateConnection failed", __func__);
+    return;
+  }
+  LOG_INFO(LOG_TAG, "%s CreateConnection returned handle 0x%x", __func__, handle);
+  send_event_(
+      EventPacketBuilder::CreateConnectionCompleteEvent(hci::Status::SUCCESS, handle, addr, hci::LinkType::ACL, false)
+          ->ToVector());
+}
+
+hci::Status LinkLayerController::RejectConnectionRequest(const Address& addr, uint8_t reason) {
+  if (!classic_connections_.HasPendingConnection(addr)) {
+    LOG_INFO(LOG_TAG, "%s: No pending connection", __func__);
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  LOG_INFO(LOG_TAG, "%s: Reject in 200ms", __func__);
+  schedule_task_(milliseconds(200), [this, addr, reason]() {
+    LOG_INFO(LOG_TAG, "%s: Reject", __func__);
+    RejectSlaveConnection(addr, reason);
+  });
+
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::RejectSlaveConnection(const Address& addr, uint8_t reason) {
+  CHECK(reason > 0x0f || reason < 0x0d);
+  send_event_(EventPacketBuilder::CreateConnectionCompleteEvent(static_cast<hci::Status>(reason), 0xeff, addr,
+                                                                hci::LinkType::ACL, false)
+                  ->ToVector());
+}
+
+hci::Status LinkLayerController::CreateConnection(const Address& addr, uint16_t, uint8_t, uint16_t,
+                                                  uint8_t allow_role_switch) {
+  if (!classic_connections_.CreatePendingConnection(addr)) {
+    return hci::Status::CONTROLLER_BUSY;
+  }
+
+  std::unique_ptr<PageBuilder> page = PageBuilder::Create(properties_.GetClassOfDevice(), allow_role_switch);
+  SendLinkLayerPacket(LinkLayerPacketBuilder::WrapPage(std::move(page), properties_.GetAddress(), addr));
+
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::CreateConnectionCancel(const Address& addr) {
+  if (!classic_connections_.CancelPendingConnection(addr)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::Disconnect(uint16_t handle, uint8_t reason) {
+  // TODO: Handle LE
+  if (!classic_connections_.HasHandle(handle)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+
+  const Address& remote = classic_connections_.GetAddress(handle);
+  std::shared_ptr<LinkLayerPacketBuilder> to_send =
+      LinkLayerPacketBuilder::WrapDisconnect(DisconnectBuilder::Create(reason), properties_.GetAddress(), remote);
+  SendLinkLayerPacket(to_send);
+  CHECK(classic_connections_.Disconnect(handle)) << "Disconnecting " << handle;
+
+  schedule_task_(milliseconds(20), [this, handle]() {
+    DisconnectCleanup(handle, static_cast<uint8_t>(hci::Status::CONNECTION_TERMINATED_BY_LOCAL_HOST));
+  });
+
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::DisconnectCleanup(uint16_t handle, uint8_t reason) {
+  // TODO: Clean up other connection state.
+  send_event_(EventPacketBuilder::CreateDisconnectionCompleteEvent(hci::Status::SUCCESS, handle, reason)->ToVector());
+}
+
+hci::Status LinkLayerController::ChangeConnectionPacketType(uint16_t handle, uint16_t types) {
+  if (!classic_connections_.HasHandle(handle)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+  std::unique_ptr<EventPacketBuilder> packet =
+      EventPacketBuilder::CreateConnectionPacketTypeChangedEvent(hci::Status::SUCCESS, handle, types);
+  std::shared_ptr<std::vector<uint8_t>> raw_packet = packet->ToVector();
+  if (schedule_task_) {
+    schedule_task_(milliseconds(20), [this, raw_packet]() { send_event_(raw_packet); });
+  } else {
+    send_event_(raw_packet);
+  }
+
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::WriteLinkPolicySettings(uint16_t handle, uint16_t) {
+  if (!classic_connections_.HasHandle(handle)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+  return hci::Status::SUCCESS;
+}
+
+hci::Status LinkLayerController::WriteLinkSupervisionTimeout(uint16_t handle, uint16_t) {
+  if (!classic_connections_.HasHandle(handle)) {
+    return hci::Status::UNKNOWN_CONNECTION;
+  }
+  return hci::Status::SUCCESS;
+}
+
+void LinkLayerController::LeWhiteListClear() {
+  le_white_list_.clear();
+}
+
+void LinkLayerController::LeWhiteListAddDevice(Address addr, uint8_t addr_type) {
+  std::tuple<Address, uint8_t> new_tuple = std::make_tuple(addr, addr_type);
+  for (auto dev : le_white_list_) {
+    if (dev == new_tuple) {
+      return;
+    }
+  }
+  le_white_list_.emplace_back(new_tuple);
+}
+
+void LinkLayerController::LeWhiteListRemoveDevice(Address addr, uint8_t addr_type) {
+  // TODO: Add checks to see if advertising, scanning, or a connection request
+  // with the white list is ongoing.
+  std::tuple<Address, uint8_t> erase_tuple = std::make_tuple(addr, addr_type);
+  for (size_t i = 0; i < le_white_list_.size(); i++) {
+    if (le_white_list_[i] == erase_tuple) {
+      le_white_list_.erase(le_white_list_.begin() + i);
+    }
+  }
+}
+
+bool LinkLayerController::LeWhiteListContainsDevice(Address addr, uint8_t addr_type) {
+  std::tuple<Address, uint8_t> sought_tuple = std::make_tuple(addr, addr_type);
+  for (size_t i = 0; i < le_white_list_.size(); i++) {
+    if (le_white_list_[i] == sought_tuple) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool LinkLayerController::LeWhiteListFull() {
+  return le_white_list_.size() >= properties_.GetLeWhiteListSize();
+}
+
+void LinkLayerController::Reset() {
+  inquiry_state_ = Inquiry::InquiryState::STANDBY;
+  last_inquiry_ = steady_clock::now();
+  le_scan_enable_ = 0;
+  le_connect_ = 0;
+}
+
+void LinkLayerController::PageScan() {}
+
+void LinkLayerController::StartInquiry(milliseconds timeout) {
+  schedule_task_(milliseconds(timeout), [this]() { LinkLayerController::InquiryTimeout(); });
+  inquiry_state_ = Inquiry::InquiryState::INQUIRY;
+  LOG_INFO(LOG_TAG, "InquiryState = %d ", static_cast<int>(inquiry_state_));
+}
+
+void LinkLayerController::InquiryCancel() {
+  CHECK(inquiry_state_ == Inquiry::InquiryState::INQUIRY);
+  inquiry_state_ = Inquiry::InquiryState::STANDBY;
+}
+
+void LinkLayerController::InquiryTimeout() {
+  if (inquiry_state_ == Inquiry::InquiryState::INQUIRY) {
+    inquiry_state_ = Inquiry::InquiryState::STANDBY;
+    send_event_(EventPacketBuilder::CreateInquiryCompleteEvent(hci::Status::SUCCESS)->ToVector());
+  }
+}
+
+void LinkLayerController::SetInquiryMode(uint8_t mode) {
+  inquiry_mode_ = static_cast<Inquiry::InquiryType>(mode);
+}
+
+void LinkLayerController::SetInquiryLAP(uint64_t lap) {
+  inquiry_lap_ = lap;
+}
+
+void LinkLayerController::SetInquiryMaxResponses(uint8_t max) {
+  inquiry_max_responses_ = max;
+}
+
+void LinkLayerController::Inquiry() {
+  steady_clock::time_point now = steady_clock::now();
+  if (duration_cast<milliseconds>(now - last_inquiry_) < milliseconds(2000)) {
+    return;
+  }
+  LOG_INFO(LOG_TAG, "Inquiry ");
+  std::unique_ptr<InquiryBuilder> inquiry = InquiryBuilder::Create(inquiry_mode_);
+  std::shared_ptr<LinkLayerPacketBuilder> to_send =
+      LinkLayerPacketBuilder::WrapInquiry(std::move(inquiry), properties_.GetAddress());
+  SendLinkLayerPacket(to_send);
+  last_inquiry_ = now;
+}
+
+void LinkLayerController::SetInquiryScanEnable(bool enable) {
+  inquiry_scans_enabled_ = enable;
+}
+
+void LinkLayerController::SetPageScanEnable(bool enable) {
+  page_scans_enabled_ = enable;
+}
+
+/* TODO: Connection handling
+  // TODO: Handle in the link manager.
+  uint16_t handle = LeGetHandle();
+
+  std::shared_ptr<Connection> new_connection =
+      std::make_shared<Connection>(peer, handle);
+  connections_.push_back(new_connection);
+  peer->SetConnection(new_connection);
+
+  send_event_(EventPacketBuilder::CreateLeEnhancedConnectionCompleteEvent(
+      hci::Status::SUCCESS, handle, 0x00,  // role
+      le_peer_address_type_, le_peer_address_, Address::kEmpty,
+  Address::kEmpty, 0x0024, 0x0000, 0x01f4)->ToVector());
+*/
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
new file mode 100644
index 0000000..5cec196
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/link_layer_controller.h
@@ -0,0 +1,269 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "acl_connection_handler.h"
+#include "include/hci.h"
+#include "include/inquiry.h"
+#include "include/link.h"
+#include "include/phy.h"
+#include "model/devices/device_properties.h"
+#include "model/setup/async_manager.h"
+#include "packets/hci/acl_packet_view.h"
+#include "packets/hci/sco_packet_view.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "security_manager.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+
+class LinkLayerController {
+ public:
+  LinkLayerController(const DeviceProperties& properties) : properties_(properties) {}
+  hci::Status SendCommandToRemoteByAddress(hci::OpCode opcode, packets::PacketView<true> args, const Address& remote,
+                                           bool use_public_address);
+  hci::Status SendCommandToRemoteByHandle(hci::OpCode opcode, packets::PacketView<true> args, uint16_t handle);
+  hci::Status SendScoToRemote(packets::ScoPacketView sco_packet);
+  hci::Status SendAclToRemote(packets::AclPacketView acl_packet);
+
+  void WriteSimplePairingMode(bool enabled);
+  void StartSimplePairing(const Address& address);
+  void AuthenticateRemoteStage1(const Address& address, PairingType pairing_type);
+  void AuthenticateRemoteStage2(const Address& address);
+  hci::Status LinkKeyRequestReply(const Address& address, packets::PacketView<true> key);
+  hci::Status LinkKeyRequestNegativeReply(const Address& address);
+  hci::Status IoCapabilityRequestReply(const Address& peer, uint8_t io_capability, uint8_t oob_data_present_flag,
+                                       uint8_t authentication_requirements);
+  hci::Status IoCapabilityRequestNegativeReply(const Address& peer, hci::Status reason);
+  hci::Status UserConfirmationRequestReply(const Address& peer);
+  hci::Status UserConfirmationRequestNegativeReply(const Address& peer);
+  hci::Status UserPasskeyRequestReply(const Address& peer, uint32_t numeric_value);
+  hci::Status UserPasskeyRequestNegativeReply(const Address& peer);
+  hci::Status RemoteOobDataRequestReply(const Address& peer, const std::vector<uint8_t>& c,
+                                        const std::vector<uint8_t>& r);
+  hci::Status RemoteOobDataRequestNegativeReply(const Address& peer);
+  void HandleSetConnectionEncryption(const Address& address, uint16_t handle, uint8_t encryption_enable);
+  hci::Status SetConnectionEncryption(uint16_t handle, uint8_t encryption_enable);
+  void HandleAuthenticationRequest(const Address& address, uint16_t handle);
+  hci::Status AuthenticationRequested(uint16_t handle);
+
+  hci::Status AcceptConnectionRequest(const Address& addr, bool try_role_switch);
+  void MakeSlaveConnection(const Address& addr, bool try_role_switch);
+  hci::Status RejectConnectionRequest(const Address& addr, uint8_t reason);
+  void RejectSlaveConnection(const Address& addr, uint8_t reason);
+  hci::Status CreateConnection(const Address& addr, uint16_t packet_type, uint8_t page_scan_mode, uint16_t clock_offset,
+                               uint8_t allow_role_switch);
+  hci::Status CreateConnectionCancel(const Address& addr);
+  hci::Status Disconnect(uint16_t handle, uint8_t reason);
+
+ private:
+  void DisconnectCleanup(uint16_t handle, uint8_t reason);
+
+ public:
+  void IncomingPacket(packets::LinkLayerPacketView incoming);
+
+  void TimerTick();
+
+  // Set the callbacks for sending packets to the HCI.
+  void RegisterEventChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_event);
+
+  void RegisterAclChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_acl);
+
+  void RegisterScoChannel(const std::function<void(std::shared_ptr<std::vector<uint8_t>>)>& send_sco);
+
+  void RegisterRemoteChannel(
+      const std::function<void(std::shared_ptr<packets::LinkLayerPacketBuilder>, Phy::Type)>& send_to_remote);
+
+  // Set the callbacks for scheduling tasks.
+  void RegisterTaskScheduler(
+      std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> event_scheduler);
+
+  void RegisterPeriodicTaskScheduler(
+      std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+          periodic_event_scheduler);
+
+  void RegisterTaskCancel(std::function<void(AsyncTaskId)> cancel);
+  void Reset();
+  void AddControllerEvent(std::chrono::milliseconds delay, const TaskCallback& task);
+
+  void PageScan();
+  void Connections();
+
+  void LeWhiteListClear();
+  void LeWhiteListAddDevice(Address addr, uint8_t addr_type);
+  void LeWhiteListRemoveDevice(Address addr, uint8_t addr_type);
+  bool LeWhiteListContainsDevice(Address addr, uint8_t addr_type);
+  bool LeWhiteListFull();
+
+  void SetLeScanEnable(uint8_t le_scan_enable) {
+    le_scan_enable_ = le_scan_enable;
+  }
+  void SetLeScanType(uint8_t le_scan_type) {
+    le_scan_type_ = le_scan_type;
+  }
+  void SetLeScanInterval(uint16_t le_scan_interval) {
+    le_scan_interval_ = le_scan_interval;
+  }
+  void SetLeScanWindow(uint16_t le_scan_window) {
+    le_scan_window_ = le_scan_window;
+  }
+  void SetLeScanFilterPolicy(uint8_t le_scan_filter_policy) {
+    le_scan_filter_policy_ = le_scan_filter_policy;
+  }
+  void SetLeFilterDuplicates(uint8_t le_scan_filter_duplicates) {
+    le_scan_filter_duplicates_ = le_scan_filter_duplicates;
+  }
+  void SetLeAddressType(uint8_t le_address_type) {
+    le_address_type_ = le_address_type;
+  }
+  hci::Status SetLeConnect(bool le_connect) {
+    le_connect_ = le_connect;
+    return hci::Status::SUCCESS;
+  }
+  void SetLeConnectionIntervalMin(uint16_t min) {
+    le_connection_interval_min_ = min;
+  }
+  void SetLeConnectionIntervalMax(uint16_t max) {
+    le_connection_interval_max_ = max;
+  }
+  void SetLeConnectionLatency(uint16_t latency) {
+    le_connection_latency_ = latency;
+  }
+  void SetLeSupervisionTimeout(uint16_t timeout) {
+    le_connection_supervision_timeout_ = timeout;
+  }
+  void SetLeMinimumCeLength(uint16_t min) {
+    le_connection_minimum_ce_length_ = min;
+  }
+  void SetLeMaximumCeLength(uint16_t max) {
+    le_connection_maximum_ce_length_ = max;
+  }
+  void SetLeInitiatorFilterPolicy(uint8_t le_initiator_filter_policy) {
+    le_initiator_filter_policy_ = le_initiator_filter_policy;
+  }
+  void SetLePeerAddressType(uint8_t peer_address_type) {
+    le_peer_address_type_ = peer_address_type;
+  }
+  void SetLePeerAddress(const Address& peer_address) {
+    le_peer_address_ = peer_address;
+  }
+
+  // Classic
+  void StartInquiry(std::chrono::milliseconds timeout);
+  void InquiryCancel();
+  void InquiryTimeout();
+  void SetInquiryMode(uint8_t mode);
+  void SetInquiryLAP(uint64_t lap);
+  void SetInquiryMaxResponses(uint8_t max);
+  void Inquiry();
+
+  void SetInquiryScanEnable(bool enable);
+  void SetPageScanEnable(bool enable);
+
+  hci::Status ChangeConnectionPacketType(uint16_t handle, uint16_t types);
+  hci::Status WriteLinkPolicySettings(uint16_t handle, uint16_t settings);
+  hci::Status WriteLinkSupervisionTimeout(uint16_t handle, uint16_t timeout);
+
+ protected:
+  void SendLELinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> packet);
+  void SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> packet);
+  void IncomingAclPacket(packets::LinkLayerPacketView packet);
+  void IncomingAclAckPacket(packets::LinkLayerPacketView packet);
+  void IncomingCommandPacket(packets::LinkLayerPacketView packet);
+  void IncomingCreateConnectionPacket(packets::LinkLayerPacketView packet);
+  void IncomingDisconnectPacket(packets::LinkLayerPacketView packet);
+  void IncomingEncryptConnection(packets::LinkLayerPacketView packet);
+  void IncomingEncryptConnectionResponse(packets::LinkLayerPacketView packet);
+  void IncomingInquiryPacket(packets::LinkLayerPacketView packet);
+  void IncomingInquiryResponsePacket(packets::LinkLayerPacketView packet);
+  void IncomingIoCapabilityRequestPacket(packets::LinkLayerPacketView packet);
+  void IncomingIoCapabilityResponsePacket(packets::LinkLayerPacketView packet);
+  void IncomingIoCapabilityNegativeResponsePacket(packets::LinkLayerPacketView packet);
+  void IncomingLeAdvertisementPacket(packets::LinkLayerPacketView packet);
+  void IncomingLeScanPacket(packets::LinkLayerPacketView packet);
+  void IncomingLeScanResponsePacket(packets::LinkLayerPacketView packet);
+  void IncomingPagePacket(packets::LinkLayerPacketView packet);
+  void IncomingPageResponsePacket(packets::LinkLayerPacketView packet);
+  void IncomingResponsePacket(packets::LinkLayerPacketView packet);
+
+ private:
+  const DeviceProperties& properties_;
+  AclConnectionHandler classic_connections_;
+  // Add timestamps?
+  std::vector<std::shared_ptr<packets::LinkLayerPacketBuilder>> commands_awaiting_responses_;
+
+  // Timing related state
+  std::vector<AsyncTaskId> controller_events_;
+  AsyncTaskId timer_tick_task_;
+  std::chrono::milliseconds timer_period_ = std::chrono::milliseconds(100);
+
+  // Callbacks to schedule tasks.
+  std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> schedule_task_;
+  std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+      schedule_periodic_task_;
+  std::function<void(AsyncTaskId)> cancel_task_;
+
+  // Callbacks to send packets back to the HCI.
+  std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_acl_;
+  std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_event_;
+  std::function<void(std::shared_ptr<std::vector<uint8_t>>)> send_sco_;
+
+  // Callback to send packets to remote devices.
+  std::function<void(std::shared_ptr<packets::LinkLayerPacketBuilder>, Phy::Type phy_type)> send_to_remote_;
+
+  // LE state
+  std::vector<uint8_t> le_event_mask_;
+
+  std::vector<std::tuple<Address, uint8_t>> le_white_list_;
+
+  uint8_t le_scan_enable_;
+  uint8_t le_scan_type_;
+  uint16_t le_scan_interval_;
+  uint16_t le_scan_window_;
+  uint8_t le_scan_filter_policy_;
+  uint8_t le_scan_filter_duplicates_;
+  uint8_t le_address_type_;
+
+  bool le_connect_;
+  uint16_t le_connection_interval_min_;
+  uint16_t le_connection_interval_max_;
+  uint16_t le_connection_latency_;
+  uint16_t le_connection_supervision_timeout_;
+  uint16_t le_connection_minimum_ce_length_;
+  uint16_t le_connection_maximum_ce_length_;
+  uint8_t le_initiator_filter_policy_;
+
+  Address le_peer_address_;
+  uint8_t le_peer_address_type_;
+
+  // Classic state
+
+  SecurityManager security_manager_{10};
+  std::chrono::steady_clock::time_point last_inquiry_;
+  Inquiry::InquiryType inquiry_mode_;
+  Inquiry::InquiryState inquiry_state_;
+  uint64_t inquiry_lap_;
+  uint8_t inquiry_max_responses_;
+
+  bool page_scans_enabled_{false};
+  bool inquiry_scans_enabled_{false};
+
+  bool simple_pairing_mode_enabled_{false};
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/security_manager.cc b/vendor_libs/test_vendor_lib/model/controller/security_manager.cc
new file mode 100644
index 0000000..6ab1351
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/security_manager.cc
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "security_manager"
+
+#include "security_manager.h"
+
+#include "base/logging.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+uint16_t SecurityManager::DeleteAllKeys() {
+  uint16_t size = key_store_.size();
+  key_store_.clear();
+  return size;
+}
+
+uint16_t SecurityManager::DeleteKey(const Address& addr) {
+  uint16_t count = key_store_.count(addr.ToString());
+  if (count) {
+    key_store_.erase(addr.ToString());
+  }
+  return count;
+}
+
+uint16_t SecurityManager::ReadAllKeys() const {
+  return key_store_.size();
+}
+
+uint16_t SecurityManager::ReadKey(const Address& addr) const {
+  return key_store_.count(addr.ToString());
+}
+
+uint16_t SecurityManager::WriteKey(const Address& addr, const std::vector<uint8_t>& key) {
+  if (key_store_.size() >= max_keys_) {
+    return 0;
+  }
+  key_store_[addr.ToString()] = key;
+  return 1;
+}
+
+const std::vector<uint8_t>& SecurityManager::GetKey(const Address& addr) const {
+  CHECK(ReadKey(addr)) << "No such key";
+  return key_store_.at(addr.ToString());
+}
+
+void SecurityManager::AuthenticationRequest(const Address& addr, uint16_t handle) {
+  authenticating_ = true;
+  current_handle_ = handle;
+  peer_address_ = addr;
+}
+
+void SecurityManager::AuthenticationRequestFinished() {
+  authenticating_ = false;
+}
+
+bool SecurityManager::AuthenticationInProgress() {
+  return authenticating_;
+}
+
+uint16_t SecurityManager::GetAuthenticationHandle() {
+  return current_handle_;
+}
+
+Address SecurityManager::GetAuthenticationAddress() {
+  return peer_address_;
+}
+
+void SecurityManager::SetPeerIoCapability(const Address& addr, uint8_t io_capability, uint8_t oob_present_flag,
+                                          uint8_t authentication_requirements) {
+  CHECK_EQ(addr, peer_address_);
+  peer_capabilities_valid_ = true;
+  if (io_capability <= static_cast<uint8_t>(IoCapabilityType::NO_INPUT_NO_OUTPUT)) {
+    peer_io_capability_ = static_cast<IoCapabilityType>(io_capability);
+  } else {
+    peer_io_capability_ = IoCapabilityType::INVALID;
+    peer_capabilities_valid_ = false;
+  }
+  peer_oob_present_flag_ = (oob_present_flag == 1);
+  if (authentication_requirements <= static_cast<uint8_t>(AuthenticationType::GENERAL_BONDING_MITM)) {
+    peer_authentication_requirements_ = static_cast<AuthenticationType>(authentication_requirements);
+  } else {
+    peer_authentication_requirements_ = AuthenticationType::INVALID;
+    peer_capabilities_valid_ = false;
+  }
+}
+
+void SecurityManager::SetLocalIoCapability(const Address& peer, uint8_t io_capability, uint8_t oob_present_flag,
+                                           uint8_t authentication_requirements) {
+  CHECK_EQ(peer, peer_address_);
+  CHECK(io_capability <= static_cast<uint8_t>(IoCapabilityType::NO_INPUT_NO_OUTPUT))
+      << "io_capability = " << io_capability;
+  CHECK(oob_present_flag <= 1) << "oob_present_flag = " << oob_present_flag;
+  CHECK(authentication_requirements <= static_cast<uint8_t>(AuthenticationType::GENERAL_BONDING_MITM))
+      << "authentication_requirements = " << authentication_requirements;
+  host_io_capability_ = static_cast<IoCapabilityType>(io_capability);
+  host_oob_present_flag_ = (oob_present_flag == 1);
+  host_authentication_requirements_ = static_cast<AuthenticationType>(authentication_requirements);
+  host_capabilities_valid_ = true;
+}
+
+void SecurityManager::InvalidateIoCapabilities() {
+  host_capabilities_valid_ = false;
+  peer_capabilities_valid_ = false;
+}
+
+PairingType SecurityManager::GetSimplePairingType() {
+  if (!host_capabilities_valid_ || !peer_capabilities_valid_) {
+    return PairingType::INVALID;
+  }
+  bool host_requires_mitm = (host_authentication_requirements_ == AuthenticationType::NO_BONDING_MITM) ||
+                            (host_authentication_requirements_ == AuthenticationType::DEDICATED_BONDING_MITM) ||
+                            (host_authentication_requirements_ == AuthenticationType::GENERAL_BONDING_MITM);
+  bool peer_requires_mitm = (peer_authentication_requirements_ == AuthenticationType::NO_BONDING_MITM) ||
+                            (peer_authentication_requirements_ == AuthenticationType::DEDICATED_BONDING_MITM) ||
+                            (peer_authentication_requirements_ == AuthenticationType::GENERAL_BONDING_MITM);
+  if (!(peer_requires_mitm || host_requires_mitm)) {
+    return PairingType::AUTO_CONFIRMATION;
+  }
+  return PairingType::INVALID;
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/controller/security_manager.h b/vendor_libs/test_vendor_lib/model/controller/security_manager.h
new file mode 100644
index 0000000..94284cb
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/controller/security_manager.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2017 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "types/address.h"
+
+namespace test_vendor_lib {
+
+enum class PairingType : uint8_t {
+  AUTO_CONFIRMATION,
+  CONFIRM_Y_N,
+  DISPLAY_PIN,
+  DISPLAY_AND_CONFIRM,
+  INPUT_PIN,
+  INVALID = 0xff,
+};
+
+enum class IoCapabilityType : uint8_t {
+  DISPLAY_ONLY = 0,
+  DISPLAY_YES_NO = 1,
+  KEYBOARD_ONLY = 2,
+  NO_INPUT_NO_OUTPUT = 3,
+  INVALID = 0xff,
+};
+
+enum class AuthenticationType : uint8_t {
+  NO_BONDING = 0,
+  NO_BONDING_MITM = 1,
+  DEDICATED_BONDING = 2,
+  DEDICATED_BONDING_MITM = 3,
+  GENERAL_BONDING = 4,
+  GENERAL_BONDING_MITM = 5,
+  INVALID = 0xff,
+};
+
+// Encapsulate the details of storing and retrieving keys.
+class SecurityManager {
+ public:
+  SecurityManager(uint16_t num_keys) : max_keys_(num_keys) {}
+  virtual ~SecurityManager() = default;
+
+  uint16_t DeleteAllKeys();
+  uint16_t DeleteKey(const Address& addr);
+  uint16_t ReadAllKeys() const;
+  uint16_t ReadKey(const Address& addr) const;
+  uint16_t WriteKey(const Address& addr, const std::vector<uint8_t>& key);
+  uint16_t ReadCapacity() const {
+    return max_keys_;
+  };
+
+  const std::vector<uint8_t>& GetKey(const Address& addr) const;
+
+  void AuthenticationRequest(const Address& addr, uint16_t handle);
+  void AuthenticationRequestFinished();
+
+  bool AuthenticationInProgress();
+  uint16_t GetAuthenticationHandle();
+  Address GetAuthenticationAddress();
+
+  void SetPeerIoCapability(const Address& addr, uint8_t io_capability, uint8_t oob_present_flag,
+                           uint8_t authentication_requirements);
+  void SetLocalIoCapability(const Address& peer, uint8_t io_capability, uint8_t oob_present_flag,
+                            uint8_t authentication_requirements);
+
+  PairingType GetSimplePairingType();
+
+  void InvalidateIoCapabilities();
+
+ private:
+  uint16_t max_keys_;
+  std::unordered_map<std::string, std::vector<uint8_t>> key_store_;
+
+  bool peer_capabilities_valid_{false};
+  IoCapabilityType peer_io_capability_;
+  bool peer_oob_present_flag_;
+  AuthenticationType peer_authentication_requirements_;
+
+  bool host_capabilities_valid_{false};
+  IoCapabilityType host_io_capability_;
+  bool host_oob_present_flag_;
+  AuthenticationType host_authentication_requirements_;
+
+  bool authenticating_{false};
+  uint16_t current_handle_;
+  Address peer_address_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/beacon.cc b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
new file mode 100644
index 0000000..10ebf5c
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon.cc
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "beacon"
+
+#include "beacon.h"
+
+#include "le_advertisement.h"
+#include "model/setup/device_boutique.h"
+#include "osi/include/log.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+bool Beacon::registered_ = DeviceBoutique::Register(LOG_TAG, &Beacon::Create);
+
+Beacon::Beacon() {
+  advertising_interval_ms_ = std::chrono::milliseconds(1280);
+  properties_.SetLeAdvertisementType(BTM_BLE_NON_CONNECT_EVT);
+  properties_.SetLeAdvertisement({0x0F,  // Length
+                                  BTM_BLE_AD_TYPE_NAME_CMPL, 'g', 'D', 'e', 'v', 'i', 'c', 'e', '-', 'b', 'e', 'a', 'c',
+                                  'o', 'n',
+                                  0x02,  // Length
+                                  BTM_BLE_AD_TYPE_FLAG, BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG});
+
+  properties_.SetLeScanResponse({0x05,  // Length
+                                 BTM_BLE_AD_TYPE_NAME_SHORT, 'b', 'e', 'a', 'c'});
+}
+
+std::string Beacon::GetTypeString() const {
+  return "beacon";
+}
+
+std::string Beacon::ToString() const {
+  std::string dev = GetTypeString() + "@" + properties_.GetLeAddress().ToString();
+
+  return dev;
+}
+
+void Beacon::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+
+  if (args.size() < 3) return;
+
+  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+void Beacon::TimerTick() {
+  if (IsAdvertisementAvailable(std::chrono::milliseconds(5000))) {
+    std::unique_ptr<packets::LeAdvertisementBuilder> ad = packets::LeAdvertisementBuilder::Create(
+        LeAdvertisement::AddressType::PUBLIC,
+        static_cast<LeAdvertisement::AdvertisementType>(properties_.GetLeAdvertisementType()),
+        properties_.GetLeAdvertisement());
+    std::shared_ptr<packets::LinkLayerPacketBuilder> to_send =
+        packets::LinkLayerPacketBuilder::WrapLeAdvertisement(std::move(ad), properties_.GetLeAddress());
+    std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
+    for (std::shared_ptr<PhyLayer> phy : le_phys) {
+      phy->Send(to_send);
+    }
+  }
+}
+
+void Beacon::IncomingPacket(packets::LinkLayerPacketView packet) {
+  if (packet.GetDestinationAddress() == properties_.GetLeAddress() && packet.GetType() == Link::PacketType::LE_SCAN) {
+    std::unique_ptr<packets::LeAdvertisementBuilder> scan_response = packets::LeAdvertisementBuilder::Create(
+        LeAdvertisement::AddressType::PUBLIC, LeAdvertisement::AdvertisementType::SCAN_RESPONSE,
+        properties_.GetLeScanResponse());
+    std::shared_ptr<packets::LinkLayerPacketBuilder> to_send = packets::LinkLayerPacketBuilder::WrapLeScanResponse(
+        std::move(scan_response), properties_.GetLeAddress(), packet.GetSourceAddress());
+    std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
+    for (auto phy : le_phys) {
+      phy->Send(to_send);
+    }
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/beacon.h b/vendor_libs/test_vendor_lib/model/devices/beacon.h
similarity index 74%
rename from vendor_libs/test_vendor_lib/include/beacon.h
rename to vendor_libs/test_vendor_lib/model/devices/beacon.h
index 8943b96..faac5cc 100644
--- a/vendor_libs/test_vendor_lib/include/beacon.h
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon.h
@@ -19,7 +19,6 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
 #include "device.h"
 #include "stack/include/btm_ble_api.h"
 
@@ -31,11 +30,25 @@
   Beacon();
   virtual ~Beacon() = default;
 
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<Beacon>();
+  }
+
   // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const override { return "beacon"; }
+  virtual std::string GetTypeString() const override;
+
+  // Return a string representation of the device.
+  virtual std::string ToString() const override;
 
   // Set the address and advertising interval from string args.
   virtual void Initialize(const std::vector<std::string>& args) override;
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+  virtual void TimerTick() override;
+
+ private:
+  static bool registered_;
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/beacon_swarm.cc b/vendor_libs/test_vendor_lib/model/devices/beacon_swarm.cc
new file mode 100644
index 0000000..a065c36
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon_swarm.cc
@@ -0,0 +1,82 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "beacon_swarm"
+
+#include "beacon_swarm.h"
+
+#include "model/setup/device_boutique.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+bool BeaconSwarm::registered_ = DeviceBoutique::Register(LOG_TAG, &BeaconSwarm::Create);
+
+BeaconSwarm::BeaconSwarm() {
+  advertising_interval_ms_ = std::chrono::milliseconds(1280);
+  properties_.SetLeAdvertisementType(BTM_BLE_NON_CONNECT_EVT);
+  properties_.SetLeAdvertisement({
+      0x15,  // Length
+      BTM_BLE_AD_TYPE_NAME_CMPL,
+      'g',
+      'D',
+      'e',
+      'v',
+      'i',
+      'c',
+      'e',
+      '-',
+      'b',
+      'e',
+      'a',
+      'c',
+      'o',
+      'n',
+      '_',
+      's',
+      'w',
+      'a',
+      'r',
+      'm',
+      0x02,  // Length
+      BTM_BLE_AD_TYPE_FLAG,
+      BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG,
+  });
+
+  properties_.SetLeScanResponse({0x06,  // Length
+                                 BTM_BLE_AD_TYPE_NAME_SHORT, 'c', 'b', 'e', 'a', 'c'});
+}
+
+void BeaconSwarm::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+
+  if (args.size() < 3) return;
+
+  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+void BeaconSwarm::TimerTick() {
+  Address beacon_addr = properties_.GetLeAddress();
+  uint8_t* low_order_byte = (uint8_t*)(&beacon_addr);
+  *low_order_byte += 1;
+  properties_.SetLeAddress(beacon_addr);
+  Beacon::TimerTick();
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/beacon_swarm.h b/vendor_libs/test_vendor_lib/model/devices/beacon_swarm.h
similarity index 77%
rename from vendor_libs/test_vendor_lib/include/beacon_swarm.h
rename to vendor_libs/test_vendor_lib/model/devices/beacon_swarm.h
index e07ae55..e1bfd75 100644
--- a/vendor_libs/test_vendor_lib/include/beacon_swarm.h
+++ b/vendor_libs/test_vendor_lib/model/devices/beacon_swarm.h
@@ -19,25 +19,32 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
-#include "device.h"
-#include "stack/include/btm_ble_api.h"
+#include "beacon.h"
 
 namespace test_vendor_lib {
 
 // Pretend to be a lot of beacons by changing the advertising address.
-class BeaconSwarm : public Device {
+class BeaconSwarm : public Beacon {
  public:
   BeaconSwarm();
   virtual ~BeaconSwarm() = default;
 
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<BeaconSwarm>();
+  }
+
+  // Return a string representation of the type of device.
+  virtual std::string GetTypeString() const override {
+    return "beacon_swarm";
+  }
+
   // Set the address and advertising interval from string args.
   virtual void Initialize(const std::vector<std::string>& args) override;
 
-  // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const override { return "beacon_swarm"; }
+  virtual void TimerTick() override;
 
-  void TimerTick() override;
+ private:
+  static bool registered_;
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/broken_adv.cc b/vendor_libs/test_vendor_lib/model/devices/broken_adv.cc
similarity index 66%
rename from vendor_libs/test_vendor_lib/src/broken_adv.cc
rename to vendor_libs/test_vendor_lib/model/devices/broken_adv.cc
index 92f47fa..c7d6822 100644
--- a/vendor_libs/test_vendor_lib/src/broken_adv.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/broken_adv.cc
@@ -18,17 +18,19 @@
 
 #include "broken_adv.h"
 
+#include "model/setup/device_boutique.h"
 #include "osi/include/log.h"
-#include "stack/include/hcidefs.h"
 
 using std::vector;
 
 namespace test_vendor_lib {
 
+bool BrokenAdv::registered_ = DeviceBoutique::Register(LOG_TAG, &BrokenAdv::Create);
+
 BrokenAdv::BrokenAdv() {
   advertising_interval_ms_ = std::chrono::milliseconds(1280);
-  advertising_type_ = BTM_BLE_NON_CONNECT_EVT;
-  adv_data_ = {
+  properties_.SetLeAdvertisementType(BTM_BLE_NON_CONNECT_EVT);
+  constant_adv_data_ = {
       0x02,  // Length
       BTM_BLE_AD_TYPE_FLAG,
       BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG,
@@ -53,40 +55,22 @@
       'd',
       'v',
   };
+  properties_.SetLeAdvertisement(constant_adv_data_);
 
-  constant_adv_data_ = adv_data_;
+  properties_.SetLeScanResponse({0x0b,  // Length
+                                 BTM_BLE_AD_TYPE_NAME_SHORT, 'b', 'r', 'o', 'k', 'e', 'n', 'n', 'e', 's', 's'});
 
-  scan_response_present_ = true;
-  scan_data_ = {0x0b,  // Length
-                BTM_BLE_AD_TYPE_NAME_SHORT,
-                'b',
-                'r',
-                'o',
-                'k',
-                'e',
-                'n',
-                'n',
-                'e',
-                's',
-                's'};
-
-  extended_inquiry_data_ = {0x07,  // Length
-                            BT_EIR_COMPLETE_LOCAL_NAME_TYPE,
-                            'B',
-                            'R',
-                            '0',
-                            'K',
-                            '3',
-                            'N'};
-  page_scan_repetition_mode_ = 0;
+  properties_.SetExtendedInquiryData({0x07,  // Length
+                                      BT_EIR_COMPLETE_LOCAL_NAME_TYPE, 'B', 'R', '0', 'K', '3', 'N'});
+  properties_.SetPageScanRepetitionMode(0);
   page_scan_delay_ms_ = std::chrono::milliseconds(600);
 }
 
 void BrokenAdv::Initialize(const vector<std::string>& args) {
   if (args.size() < 2) return;
 
-  BtAddress addr;
-  if (addr.FromString(args[1])) SetBtAddress(addr);
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
 
   if (args.size() < 3) return;
 
@@ -153,39 +137,35 @@
 }
 
 void BrokenAdv::UpdateAdvertisement() {
-  adv_data_.clear();
-  for (size_t i = 0; i < constant_adv_data_.size(); i++)
-    adv_data_.push_back(constant_adv_data_[i]);
+  std::vector<uint8_t> adv_data;
+  for (size_t i = 0; i < constant_adv_data_.size(); i++) adv_data.push_back(constant_adv_data_[i]);
 
-  RandomizeAdvertisement(adv_data_, 31 - adv_data_.size());
+  RandomizeAdvertisement(adv_data, 31 - adv_data.size());
+  properties_.SetLeAdvertisement(adv_data);
 
-  RandomizeAdvertisement(scan_data_, 31);
+  adv_data.clear();
+  RandomizeAdvertisement(adv_data, 31);
+  properties_.SetLeScanResponse(adv_data);
 
-  std::vector<uint8_t> curr_addr;
-  BtAddress next_addr;
-  GetBtAddress().ToVector(curr_addr);
-  curr_addr[0]++;
-  next_addr.FromVector(curr_addr);
-
-  SetBtAddress(next_addr);
+  Address le_addr = properties_.GetLeAddress();
+  uint8_t* low_order_byte = (uint8_t*)(&le_addr);
+  *low_order_byte += 1;
+  properties_.SetLeAddress(le_addr);
 }
 
 std::string BrokenAdv::ToString() const {
-  std::string str = Device::ToString() + std::string(": Interval = ") +
-                    std::to_string(advertising_interval_ms_.count());
+  std::string str =
+      Device::ToString() + std::string(": Interval = ") + std::to_string(advertising_interval_ms_.count());
   return str;
 }
 
 void BrokenAdv::UpdatePageScan() {
-  std::vector<uint8_t> broken_addr;
-  RandomizeAdvertisement(scan_data_, 31);
+  RandomizeAdvertisement(constant_scan_data_, 31);
 
-  BtAddress next_addr;
-  GetBtAddress().ToVector(broken_addr);
-  broken_addr[1]++;
-  next_addr.FromVector(broken_addr);
-
-  SetBtAddress(next_addr);
+  Address page_addr = properties_.GetAddress();
+  uint8_t* low_order_byte = (uint8_t*)(&page_addr);
+  *low_order_byte += 1;
+  properties_.SetAddress(page_addr);
 }
 
 void BrokenAdv::TimerTick() {
diff --git a/vendor_libs/test_vendor_lib/include/broken_adv.h b/vendor_libs/test_vendor_lib/model/devices/broken_adv.h
similarity index 85%
rename from vendor_libs/test_vendor_lib/include/broken_adv.h
rename to vendor_libs/test_vendor_lib/model/devices/broken_adv.h
index 9f7cd87..2431676 100644
--- a/vendor_libs/test_vendor_lib/include/broken_adv.h
+++ b/vendor_libs/test_vendor_lib/model/devices/broken_adv.h
@@ -19,7 +19,6 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
 #include "device.h"
 
 namespace test_vendor_lib {
@@ -29,11 +28,17 @@
   BrokenAdv();
   ~BrokenAdv() = default;
 
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<BrokenAdv>();
+  }
+
   // Initialize the device based on the values of |args|.
   virtual void Initialize(const std::vector<std::string>& args) override;
 
   // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const override { return "broken_adv"; }
+  virtual std::string GetTypeString() const override {
+    return "broken_adv";
+  }
 
   // Return the string representation of the device.
   virtual std::string ToString() const override;
@@ -49,6 +54,8 @@
 
  private:
   std::vector<uint8_t> constant_adv_data_;
+  std::vector<uint8_t> constant_scan_data_;
+  static bool registered_;
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/car_kit.cc b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
new file mode 100644
index 0000000..5f7fa4a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/car_kit.cc
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "car_kit"
+
+#include "car_kit.h"
+
+#include "osi/include/log.h"
+
+#include "model/setup/device_boutique.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+bool CarKit::registered_ = DeviceBoutique::Register(LOG_TAG, &CarKit::Create);
+
+CarKit::CarKit() : Device(kCarKitPropertiesFile) {
+  advertising_interval_ms_ = std::chrono::milliseconds(0);
+
+  page_scan_delay_ms_ = std::chrono::milliseconds(600);
+
+  // Stub in packet handling for now
+  link_layer_controller_.RegisterAclChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
+  link_layer_controller_.RegisterEventChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
+  link_layer_controller_.RegisterScoChannel([](std::shared_ptr<std::vector<uint8_t>>) {});
+  link_layer_controller_.RegisterRemoteChannel(
+      [this](std::shared_ptr<packets::LinkLayerPacketBuilder> packet, Phy::Type phy_type) {
+        CarKit::SendLinkLayerPacket(packet, phy_type);
+      });
+
+  properties_.SetPageScanRepetitionMode(0);
+  properties_.SetClassOfDevice(0x600420);
+  properties_.SetSupportedFeatures(0x8779ff9bfe8defff);
+  properties_.SetExtendedInquiryData({
+      16,  // length
+      9,   // Type: Device Name
+      'g',  'D', 'e', 'v', 'i', 'c', 'e', '-', 'c', 'a', 'r', '_', 'k', 'i', 't',
+      7,     // length
+      3,     // Type: 16-bit UUIDs
+      0x0e,  // AVRC
+      0x11,
+      0x0B,  // Audio Sink
+      0x11,
+      0x00,  // PnP Information
+      0x12,
+  });
+  properties_.SetName({
+      'g',
+      'D',
+      'e',
+      'v',
+      'i',
+      'c',
+      'e',
+      '-',
+      'C',
+      'a',
+      'r',
+      '_',
+      'K',
+      'i',
+      't',
+  });
+}
+
+void CarKit::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
+  LOG_INFO(LOG_TAG, "%s SetAddress %s", ToString().c_str(), addr.ToString().c_str());
+
+  if (args.size() < 3) return;
+
+  properties_.SetClockOffset(std::stoi(args[2]));
+}
+
+void CarKit::TimerTick() {
+  link_layer_controller_.TimerTick();
+}
+
+void CarKit::IncomingPacket(packets::LinkLayerPacketView packet) {
+  LOG_WARN(LOG_TAG, "Incoming Packet");
+  link_layer_controller_.IncomingPacket(packet);
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/car_kit.h b/vendor_libs/test_vendor_lib/model/devices/car_kit.h
new file mode 100644
index 0000000..94057ad
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/car_kit.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "device.h"
+#include "model/controller/link_layer_controller.h"
+
+namespace {
+const std::string kCarKitPropertiesFile = "/etc/bluetooth/car_kit_controller_properties.json";
+}  // namespace
+
+namespace test_vendor_lib {
+
+class CarKit : public Device {
+ public:
+  CarKit();
+  ~CarKit() = default;
+
+  static std::shared_ptr<CarKit> Create() {
+    return std::make_shared<CarKit>();
+  }
+
+  // Initialize the device based on the values of |args|.
+  virtual void Initialize(const std::vector<std::string>& args) override;
+
+  // Return a string representation of the type of device.
+  virtual std::string GetTypeString() const override {
+    return "car_kit";
+  }
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+  virtual void TimerTick() override;
+
+ private:
+  LinkLayerController link_layer_controller_{properties_};
+  static bool registered_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/classic.cc b/vendor_libs/test_vendor_lib/model/devices/classic.cc
new file mode 100644
index 0000000..a8f8a99
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/classic.cc
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "classic"
+
+#include "classic.h"
+#include "model/setup/device_boutique.h"
+#include "osi/include/log.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+bool Classic::registered_ = DeviceBoutique::Register(LOG_TAG, &Classic::Create);
+
+Classic::Classic() {
+  advertising_interval_ms_ = std::chrono::milliseconds(0);
+  properties_.SetClassOfDevice(0x30201);
+
+  properties_.SetExtendedInquiryData({0x10,                             // Length
+                                      BT_EIR_COMPLETE_LOCAL_NAME_TYPE,  // Type
+                                      'g', 'D', 'e', 'v', 'i', 'c', 'e', '-', 'c', 'l', 'a', 's', 's', 'i', 'c',
+                                      '\0'});  // End of data
+  properties_.SetPageScanRepetitionMode(0);
+  properties_.SetSupportedFeatures(0x87593F9bFE8FFEFF);
+
+  page_scan_delay_ms_ = std::chrono::milliseconds(600);
+}
+
+void Classic::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
+
+  if (args.size() < 3) return;
+
+  properties_.SetClockOffset(std::stoi(args[2]));
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/classic.h b/vendor_libs/test_vendor_lib/model/devices/classic.h
similarity index 82%
rename from vendor_libs/test_vendor_lib/include/classic.h
rename to vendor_libs/test_vendor_lib/model/devices/classic.h
index 0aeba2f..16b466b 100644
--- a/vendor_libs/test_vendor_lib/include/classic.h
+++ b/vendor_libs/test_vendor_lib/model/devices/classic.h
@@ -19,7 +19,6 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
 #include "device.h"
 
 namespace test_vendor_lib {
@@ -29,11 +28,20 @@
   Classic();
   ~Classic() = default;
 
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<Classic>();
+  }
+
   // Initialize the device based on the values of |args|.
   virtual void Initialize(const std::vector<std::string>& args) override;
 
   // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const override { return "classic"; }
+  virtual std::string GetTypeString() const override {
+    return "classic";
+  }
+
+ private:
+  static bool registered_;
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/device.cc b/vendor_libs/test_vendor_lib/model/devices/device.cc
new file mode 100644
index 0000000..52a37c1
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/device.cc
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "device"
+
+#include <vector>
+
+#include "device.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+std::string Device::ToString() const {
+  std::string dev = GetTypeString() + "@" + properties_.GetAddress().ToString();
+
+  return dev;
+}
+
+void Device::RegisterPhyLayer(std::shared_ptr<PhyLayer> phy) {
+  phy_layers_[phy->GetType()].push_back(phy);
+}
+
+void Device::UnregisterPhyLayer(std::shared_ptr<PhyLayer> phy) {
+  for (auto phy_pair : phy_layers_) {
+    auto phy_list = std::get<1>(phy_pair);
+    for (size_t i = 0; i < phy_list.size(); i++) {
+      if (phy == phy_list[i]) {
+        phy_list.erase(phy_list.begin() + i);
+      }
+    }
+  }
+}
+
+bool Device::IsAdvertisementAvailable(std::chrono::milliseconds scan_time) const {
+  if (advertising_interval_ms_ == std::chrono::milliseconds(0)) return false;
+
+  std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
+
+  std::chrono::steady_clock::time_point last_interval =
+      ((now - time_stamp_) / advertising_interval_ms_) * advertising_interval_ms_ + time_stamp_;
+
+  std::chrono::steady_clock::time_point next_interval = last_interval + advertising_interval_ms_;
+
+  return ((now + scan_time) >= next_interval);
+}
+
+void Device::SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> to_send, Phy::Type phy_type) {
+  auto phy_list = phy_layers_[phy_type];
+  for (auto phy : phy_list) {
+    phy->Send(to_send);
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/device.h b/vendor_libs/test_vendor_lib/model/devices/device.h
new file mode 100644
index 0000000..18842cd
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/device.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <chrono>
+#include <cstdint>
+#include <map>
+#include <string>
+#include <vector>
+
+#include "model/devices/device_properties.h"
+#include "model/setup/phy_layer.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "types/address.h"
+
+#include "stack/include/btm_ble_api.h"
+
+namespace test_vendor_lib {
+
+// Represent a Bluetooth Device
+//  - Provide Get*() and Set*() functions for device attributes.
+class Device {
+ public:
+  Device(const std::string properties_filename = "")
+      : time_stamp_(std::chrono::steady_clock::now()), properties_(properties_filename) {}
+  virtual ~Device() = default;
+
+  // Initialize the device based on the values of |args|.
+  virtual void Initialize(const std::vector<std::string>& args) = 0;
+
+  // Return a string representation of the type of device.
+  virtual std::string GetTypeString() const = 0;
+
+  // Return the string representation of the device.
+  virtual std::string ToString() const;
+
+  // Decide whether to accept a connection request
+  // May need to be extended to check peer address & type, and other
+  // connection parameters.
+  // Return true if the device accepts the connection request.
+  virtual bool LeConnect() {
+    return false;
+  }
+
+  // Set the advertisement interval in milliseconds.
+  void SetAdvertisementInterval(std::chrono::milliseconds ms) {
+    advertising_interval_ms_ = ms;
+  }
+
+  // Returns true if the host could see an advertisement in the next
+  // |scan_time| milliseconds.
+  virtual bool IsAdvertisementAvailable(std::chrono::milliseconds scan_time) const;
+
+  // Let the device know that time has passed.
+  virtual void TimerTick() {}
+
+  void RegisterPhyLayer(std::shared_ptr<PhyLayer> phy);
+
+  void UnregisterPhyLayer(std::shared_ptr<PhyLayer> phy);
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView){};
+
+  virtual void SendLinkLayerPacket(std::shared_ptr<packets::LinkLayerPacketBuilder> packet, Phy::Type phy_type);
+
+ protected:
+  std::map<Phy::Type, std::vector<std::shared_ptr<PhyLayer>>> phy_layers_;
+
+  std::chrono::steady_clock::time_point time_stamp_;
+
+  // The time between page scans.
+  std::chrono::milliseconds page_scan_delay_ms_;
+
+  // The spec defines the advertising interval as a 16-bit value, but since it
+  // is never sent in packets, we use std::chrono::milliseconds.
+  std::chrono::milliseconds advertising_interval_ms_;
+
+  DeviceProperties properties_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/device_properties.cc b/vendor_libs/test_vendor_lib/model/devices/device_properties.cc
similarity index 63%
rename from vendor_libs/test_vendor_lib/src/device_properties.cc
rename to vendor_libs/test_vendor_lib/model/devices/device_properties.cc
index 672dd65..164160a 100644
--- a/vendor_libs/test_vendor_lib/src/device_properties.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/device_properties.cc
@@ -25,20 +25,20 @@
 #include "base/json/json_reader.h"
 #include "base/values.h"
 
+#include "hci.h"
 #include "osi/include/log.h"
 #include "osi/include/osi.h"
-#include "stack/include/hcidefs.h"
 
 using std::vector;
 
 namespace {
 // Functions used by JSONValueConverter to read stringified JSON.
-bool ParseUint8t(const base::StringPiece& value, uint8_t* field) {
+bool ParseUint8t(base::StringPiece value, uint8_t* field) {
   *field = std::stoi(value.as_string());
   return true;
 }
 
-bool ParseUint16t(const base::StringPiece& value, uint16_t* field) {
+bool ParseUint16t(base::StringPiece value, uint16_t* field) {
   *field = std::stoi(value.as_string());
   return true;
 }
@@ -48,46 +48,37 @@
 namespace test_vendor_lib {
 
 DeviceProperties::DeviceProperties(const std::string& file_name)
-    : acl_data_packet_size_(1024),
-      sco_data_packet_size_(255),
-      num_acl_data_packets_(10),
-      num_sco_data_packets_(10),
-      version_(HCI_PROTO_VERSION_4_1),
-      revision_(0),
-      lmp_pal_version_(7), /* 4.1 */
-      manufacturer_name_(0),
-      lmp_pal_subversion_(0),
-      le_data_packet_length_(27),
-      num_le_data_packets_(15),
-      le_white_list_size_(15) {
+    : acl_data_packet_size_(1024), sco_data_packet_size_(255), num_acl_data_packets_(10), num_sco_data_packets_(10),
+      version_(static_cast<uint8_t>(hci::Version::V4_1)), revision_(0),
+      lmp_pal_version_(static_cast<uint8_t>(hci::Version::V4_1)), manufacturer_name_(0), lmp_pal_subversion_(0),
+      le_data_packet_length_(27), num_le_data_packets_(15), le_white_list_size_(15) {
   std::string properties_raw;
 
-  local_extended_features_ = {0xffffffffffffffff, 0x7};
+  CHECK(Address::FromString("BB:BB:BB:BB:BB:AD", address_));
+  CHECK(Address::FromString("BB:BB:BB:BB:AD:1E", le_address_));
+  name_ = {'D', 'e', 'f', 'a', 'u', 'l', 't'};
 
-  CHECK(address_.FromString("01:02:03:04:05:06"));
-  local_name_ = "DefaultName";
-
-  supported_codecs_ = {1};
+  supported_codecs_ = {0};  // Only SBC is supported.
   vendor_specific_codecs_ = {};
 
-  for (int i = 0; i < 64; i++) local_supported_commands_.push_back(0xff);
+  for (int i = 0; i < 64; i++) supported_commands_.push_back(0xff);
 
   le_supported_features_ = 0x1f;
   le_supported_states_ = 0x3ffffffffff;
   le_vendor_cap_ = {};
 
-  LOG_INFO(LOG_TAG, "Reading controller properties from %s.",
-           file_name.c_str());
+  if (file_name.size() == 0) {
+    return;
+  }
+  LOG_INFO(LOG_TAG, "Reading controller properties from %s.", file_name.c_str());
   if (!base::ReadFileToString(base::FilePath(file_name), &properties_raw)) {
     LOG_ERROR(LOG_TAG, "Error reading controller properties from file.");
     return;
   }
 
-  std::unique_ptr<base::Value> properties_value_ptr =
-      base::JSONReader::Read(properties_raw);
+  std::unique_ptr<base::Value> properties_value_ptr = base::JSONReader::Read(properties_raw);
   if (properties_value_ptr.get() == nullptr)
-    LOG_INFO(LOG_TAG,
-             "Error controller properties may consist of ill-formed JSON.");
+    LOG_INFO(LOG_TAG, "Error controller properties may consist of ill-formed JSON.");
 
   // Get the underlying base::Value object, which is of type
   // base::Value::TYPE_DICTIONARY, and read it into member variables.
@@ -95,20 +86,16 @@
   base::JSONValueConverter<DeviceProperties> converter;
 
   if (!converter.Convert(properties_dictionary, this))
-    LOG_INFO(LOG_TAG,
-             "Error converting JSON properties into Properties object.");
+    LOG_INFO(LOG_TAG, "Error converting JSON properties into Properties object.");
 }
 
 // static
-void DeviceProperties::RegisterJSONConverter(
-    base::JSONValueConverter<DeviceProperties>* converter) {
+void DeviceProperties::RegisterJSONConverter(base::JSONValueConverter<DeviceProperties>* converter) {
 // TODO(dennischeng): Use RegisterIntField() here?
 #define REGISTER_UINT8_T(field_name, field) \
-  converter->RegisterCustomField<uint8_t>(  \
-      field_name, &DeviceProperties::field, &ParseUint8t);
+  converter->RegisterCustomField<uint8_t>(field_name, &DeviceProperties::field, &ParseUint8t);
 #define REGISTER_UINT16_T(field_name, field) \
-  converter->RegisterCustomField<uint16_t>(  \
-      field_name, &DeviceProperties::field, &ParseUint16t);
+  converter->RegisterCustomField<uint16_t>(field_name, &DeviceProperties::field, &ParseUint16t);
   REGISTER_UINT16_T("AclDataPacketSize", acl_data_packet_size_);
   REGISTER_UINT8_T("ScoDataPacketSize", sco_data_packet_size_);
   REGISTER_UINT16_T("NumAclDataPackets", num_acl_data_packets_);
diff --git a/vendor_libs/test_vendor_lib/model/devices/device_properties.h b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
new file mode 100644
index 0000000..6960553
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/device_properties.h
@@ -0,0 +1,286 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "base/json/json_value_converter.h"
+#include "types/address.h"
+#include "types/class_of_device.h"
+
+namespace test_vendor_lib {
+
+class DeviceProperties {
+ public:
+  explicit DeviceProperties(const std::string& file_name = "");
+
+  // Access private configuration data
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.4.1
+  const std::vector<uint8_t>& GetVersionInformation() const;
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.4.2
+  const std::vector<uint8_t>& GetSupportedCommands() const {
+    return supported_commands_;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.4.3
+  uint64_t GetSupportedFeatures() const {
+    return extended_features_[0];
+  }
+
+  void SetSupportedFeatures(uint64_t features) {
+    extended_features_[0] = features;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.4.4
+  uint8_t GetExtendedFeaturesMaximumPageNumber() const {
+    return extended_features_.size() - 1;
+  }
+
+  uint64_t GetExtendedFeatures(uint8_t page_number) const {
+    CHECK(page_number < extended_features_.size());
+    return extended_features_[page_number];
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.4.5
+  uint16_t GetAclDataPacketSize() const {
+    return acl_data_packet_size_;
+  }
+
+  uint8_t GetSynchronousDataPacketSize() const {
+    return sco_data_packet_size_;
+  }
+
+  uint16_t GetTotalNumAclDataPackets() const {
+    return num_acl_data_packets_;
+  }
+
+  uint16_t GetTotalNumSynchronousDataPackets() const {
+    return num_sco_data_packets_;
+  }
+
+  const Address& GetAddress() const {
+    return address_;
+  }
+
+  void SetAddress(const Address& address) {
+    address_ = address;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.4.8
+  const std::vector<uint8_t>& GetSupportedCodecs() const {
+    return supported_codecs_;
+  }
+
+  const std::vector<uint32_t>& GetVendorSpecificCodecs() const {
+    return vendor_specific_codecs_;
+  }
+
+  uint8_t GetVersion() const {
+    return version_;
+  }
+
+  uint16_t GetRevision() const {
+    return revision_;
+  }
+
+  uint8_t GetLmpPalVersion() const {
+    return lmp_pal_version_;
+  }
+
+  uint16_t GetLmpPalSubversion() const {
+    return lmp_pal_subversion_;
+  }
+
+  uint16_t GetManufacturerName() const {
+    return manufacturer_name_;
+  }
+
+  uint8_t GetAuthenticationEnable() const {
+    return authentication_enable_;
+  }
+
+  void SetAuthenticationEnable(uint8_t enable) {
+    authentication_enable_ = enable;
+  }
+
+  ClassOfDevice GetClassOfDevice() const {
+    return class_of_device_;
+  }
+
+  void SetClassOfDevice(uint8_t b0, uint8_t b1, uint8_t b2) {
+    class_of_device_.cod[0] = b0;
+    class_of_device_.cod[1] = b1;
+    class_of_device_.cod[2] = b2;
+  }
+
+  void SetClassOfDevice(uint32_t class_of_device) {
+    class_of_device_.cod[0] = class_of_device & 0xff;
+    class_of_device_.cod[1] = (class_of_device >> 8) & 0xff;
+    class_of_device_.cod[2] = (class_of_device >> 16) & 0xff;
+  }
+
+  void SetName(const std::vector<uint8_t>& name) {
+    name_ = name;
+  }
+
+  const std::vector<uint8_t>& GetName() const {
+    return name_;
+  }
+
+  void SetExtendedInquiryData(const std::vector<uint8_t>& eid) {
+    extended_inquiry_data_ = eid;
+  }
+
+  const std::vector<uint8_t>& GetExtendedInquiryData() const {
+    return extended_inquiry_data_;
+  }
+
+  uint8_t GetPageScanRepetitionMode() const {
+    return page_scan_repetition_mode_;
+  }
+
+  void SetPageScanRepetitionMode(uint8_t mode) {
+    page_scan_repetition_mode_ = mode;
+  }
+
+  uint16_t GetClockOffset() const {
+    return clock_offset_;
+  }
+
+  void SetClockOffset(uint16_t offset) {
+    clock_offset_ = offset;
+  }
+
+  // Low-Energy functions
+  const Address& GetLeAddress() const {
+    return le_address_;
+  }
+
+  void SetLeAddress(const Address& address) {
+    le_address_ = address;
+  }
+
+  uint8_t GetLeAddressType() const {
+    return le_address_type_;
+  }
+
+  void SetLeAddressType(uint8_t addr_type) {
+    le_address_type_ = addr_type;
+  }
+
+  uint8_t GetLeAdvertisementType() const {
+    return le_advertisement_type_;
+  }
+
+  void SetLeAdvertisementType(uint8_t ad_type) {
+    le_advertisement_type_ = ad_type;
+  }
+
+  void SetLeAdvertisement(const std::vector<uint8_t>& ad) {
+    le_advertisement_ = ad;
+  }
+
+  const std::vector<uint8_t>& GetLeAdvertisement() const {
+    return le_advertisement_;
+  }
+
+  void SetLeScanResponse(const std::vector<uint8_t>& response) {
+    le_scan_response_ = response;
+  }
+
+  const std::vector<uint8_t>& GetLeScanResponse() const {
+    return le_scan_response_;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.8.2
+  uint16_t GetLeDataPacketLength() const {
+    return le_data_packet_length_;
+  }
+
+  uint8_t GetTotalNumLeDataPackets() const {
+    return num_le_data_packets_;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.8.3
+  uint64_t GetLeSupportedFeatures() const {
+    return le_supported_features_;
+  }
+
+  void SetLeSupportedFeatures(uint64_t features) {
+    le_supported_features_ = features;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.8.14
+  uint8_t GetLeWhiteListSize() const {
+    return le_white_list_size_;
+  }
+
+  // Specification Version 4.2, Volume 2, Part E, Section 7.8.27
+  uint64_t GetLeSupportedStates() const {
+    return le_supported_states_;
+  }
+
+  // Vendor-specific commands
+  const std::vector<uint8_t>& GetLeVendorCap() const {
+    return le_vendor_cap_;
+  }
+
+  static void RegisterJSONConverter(base::JSONValueConverter<DeviceProperties>* converter);
+
+ private:
+  // Classic
+  uint16_t acl_data_packet_size_;
+  uint8_t sco_data_packet_size_;
+  uint16_t num_acl_data_packets_;
+  uint16_t num_sco_data_packets_;
+  uint8_t version_;
+  uint16_t revision_;
+  uint8_t lmp_pal_version_;
+  uint16_t manufacturer_name_;
+  uint16_t lmp_pal_subversion_;
+  uint64_t supported_features_;
+  uint8_t authentication_enable_;
+  std::vector<uint8_t> supported_codecs_;
+  std::vector<uint32_t> vendor_specific_codecs_;
+  std::vector<uint8_t> supported_commands_;
+  std::vector<uint64_t> extended_features_{{0x875b3fd8fe8ffeff, 0x07}};
+  ClassOfDevice class_of_device_{{0, 0, 0}};
+  std::vector<uint8_t> extended_inquiry_data_;
+  std::vector<uint8_t> name_;
+  Address address_;
+  uint8_t page_scan_repetition_mode_;
+  uint16_t clock_offset_;
+
+  // Low Energy
+  uint16_t le_data_packet_length_;
+  uint8_t num_le_data_packets_;
+  uint8_t le_white_list_size_;
+  uint64_t le_supported_features_{0x075b3fd8fe8ffeff};
+  uint64_t le_supported_states_;
+  std::vector<uint8_t> le_vendor_cap_;
+  Address le_address_;
+  uint8_t le_address_type_;
+  uint8_t le_advertisement_type_;
+  std::vector<uint8_t> le_advertisement_;
+  std::vector<uint8_t> le_scan_response_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/h4_packetizer.cc b/vendor_libs/test_vendor_lib/model/devices/h4_packetizer.cc
new file mode 100644
index 0000000..49e8727
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/h4_packetizer.cc
@@ -0,0 +1,194 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "h4_packetizer.h"
+
+#define LOG_TAG "h4_packetizer"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+namespace test_vendor_lib {
+namespace hci {
+constexpr size_t H4Packetizer::COMMAND_PREAMBLE_SIZE;
+constexpr size_t H4Packetizer::COMMAND_LENGTH_OFFSET;
+constexpr size_t H4Packetizer::ACL_PREAMBLE_SIZE;
+constexpr size_t H4Packetizer::ACL_LENGTH_OFFSET;
+constexpr size_t H4Packetizer::SCO_PREAMBLE_SIZE;
+constexpr size_t H4Packetizer::SCO_LENGTH_OFFSET;
+constexpr size_t H4Packetizer::EVENT_PREAMBLE_SIZE;
+constexpr size_t H4Packetizer::EVENT_LENGTH_OFFSET;
+
+constexpr size_t H4Packetizer::PREAMBLE_SIZE_MAX;
+
+size_t H4Packetizer::HciGetPacketLengthForType(hci::PacketType type, const uint8_t* preamble) {
+  static const size_t packet_length_offset[static_cast<size_t>(hci::PacketType::EVENT) + 1] = {
+      0,
+      H4Packetizer::COMMAND_LENGTH_OFFSET,
+      H4Packetizer::ACL_LENGTH_OFFSET,
+      H4Packetizer::SCO_LENGTH_OFFSET,
+      H4Packetizer::EVENT_LENGTH_OFFSET,
+  };
+
+  size_t offset = packet_length_offset[static_cast<size_t>(type)];
+  if (type != hci::PacketType::ACL) return preamble[offset];
+  return (((preamble[offset + 1]) << 8) | preamble[offset]);
+}
+
+H4Packetizer::H4Packetizer(int fd, PacketReadCallback command_cb, PacketReadCallback event_cb,
+                           PacketReadCallback acl_cb, PacketReadCallback sco_cb)
+    : uart_fd_(fd), command_cb_(command_cb), event_cb_(event_cb), acl_cb_(acl_cb), sco_cb_(sco_cb) {}
+
+size_t H4Packetizer::Send(uint8_t type, const uint8_t* data, size_t length) {
+  struct iovec iov[] = {{&type, sizeof(type)}, {const_cast<uint8_t*>(data), length}};
+  ssize_t ret = 0;
+  do {
+    ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, sizeof(iov) / sizeof(iov[0])));
+  } while (-1 == ret && EAGAIN == errno);
+
+  if (ret == -1) {
+    ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
+  } else if (ret < static_cast<ssize_t>(length + 1)) {
+    ALOGE("%s: %d / %d bytes written - something went wrong...", __func__, static_cast<int>(ret),
+          static_cast<int>(length + 1));
+  }
+  return ret;
+}
+
+void H4Packetizer::OnPacketReady() {
+  ALOGE("%s: before switch", __func__);
+  switch (hci_packet_type_) {
+    case hci::PacketType::COMMAND:
+      command_cb_(packet_);
+      break;
+    case hci::PacketType::ACL:
+      acl_cb_(packet_);
+      break;
+    case hci::PacketType::SCO:
+      sco_cb_(packet_);
+      break;
+    case hci::PacketType::EVENT:
+      event_cb_(packet_);
+      break;
+    default:
+      LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__, static_cast<int>(hci_packet_type_));
+  }
+  // Get ready for the next type byte.
+  hci_packet_type_ = hci::PacketType::UNKNOWN;
+}
+
+void H4Packetizer::OnDataReady(int fd) {
+  if (hci_packet_type_ == hci::PacketType::UNKNOWN) {
+    uint8_t buffer[1] = {0};
+    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, 1));
+    if (bytes_read != 1) {
+      if (bytes_read == 0) {
+        ALOGI("%s: Nothing ready, will retry!", __func__);
+        return;
+      } else if (bytes_read < 0) {
+        if (errno == EAGAIN) {
+          // No data, try again later.
+          return;
+        } else {
+          LOG_ALWAYS_FATAL("%s: Read packet type error: %s", __func__, strerror(errno));
+        }
+      } else {
+        LOG_ALWAYS_FATAL("%s: More bytes read than expected (%u)!", __func__, static_cast<unsigned int>(bytes_read));
+      }
+    }
+    hci_packet_type_ = static_cast<hci::PacketType>(buffer[0]);
+    if (hci_packet_type_ != hci::PacketType::ACL && hci_packet_type_ != hci::PacketType::SCO &&
+        hci_packet_type_ != hci::PacketType::COMMAND && hci_packet_type_ != hci::PacketType::EVENT) {
+      LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__, static_cast<int>(hci_packet_type_));
+    }
+  } else {
+    static const size_t preamble_size[static_cast<size_t>(hci::PacketType::EVENT) + 1] = {
+        0,
+        H4Packetizer::COMMAND_PREAMBLE_SIZE,
+        H4Packetizer::ACL_PREAMBLE_SIZE,
+        H4Packetizer::SCO_PREAMBLE_SIZE,
+        H4Packetizer::EVENT_PREAMBLE_SIZE,
+    };
+
+    switch (state_) {
+      case HCI_PREAMBLE: {
+        size_t preamble_bytes = preamble_size[static_cast<size_t>(hci_packet_type_)];
+        ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, preamble_ + bytes_read_, preamble_bytes - bytes_read_));
+        if (bytes_read == 0) {
+          ALOGE("%s: Will try again to read the header!", __func__);
+          return;
+        }
+        if (bytes_read < 0) {
+          // Ignore temporary failures.
+          if (errno == EAGAIN) {
+            return;
+          }
+          LOG_ALWAYS_FATAL("%s: Read header error: %s", __func__, strerror(errno));
+        }
+        bytes_read_ += bytes_read;
+        if (bytes_read_ == preamble_bytes) {
+          size_t packet_length = HciGetPacketLengthForType(hci_packet_type_, preamble_);
+          packet_.resize(preamble_bytes + packet_length);
+          memcpy(packet_.data(), preamble_, preamble_bytes);
+          ALOGI("%s: Read a preamble of size %d length %d %0x %0x %0x", __func__, static_cast<int>(bytes_read_),
+                static_cast<int>(packet_length), preamble_[0], preamble_[1], preamble_[2]);
+          bytes_remaining_ = packet_length;
+          if (bytes_remaining_ == 0) {
+            OnPacketReady();
+            state_ = HCI_PREAMBLE;
+            bytes_read_ = 0;
+          } else {
+            state_ = HCI_PAYLOAD;
+            bytes_read_ = 0;
+          }
+        }
+        break;
+      }
+
+      case HCI_PAYLOAD: {
+        size_t preamble_bytes = preamble_size[static_cast<size_t>(hci_packet_type_)];
+        ssize_t bytes_read =
+            TEMP_FAILURE_RETRY(read(fd, packet_.data() + preamble_bytes + bytes_read_, bytes_remaining_));
+        if (bytes_read == 0) {
+          ALOGI("%s: Will try again to read the payload!", __func__);
+          return;
+        }
+        if (bytes_read < 0) {
+          // Ignore temporary failures.
+          if (errno == EAGAIN) {
+            return;
+          }
+          LOG_ALWAYS_FATAL("%s: Read payload error: %s", __func__, strerror(errno));
+        }
+        bytes_remaining_ -= bytes_read;
+        bytes_read_ += bytes_read;
+        if (bytes_remaining_ == 0) {
+          OnPacketReady();
+          state_ = HCI_PREAMBLE;
+          bytes_read_ = 0;
+        }
+        break;
+      }
+    }
+  }
+}
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/h4_packetizer.h b/vendor_libs/test_vendor_lib/model/devices/h4_packetizer.h
new file mode 100644
index 0000000..f81cf77
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/h4_packetizer.h
@@ -0,0 +1,81 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#pragma once
+
+#include <functional>
+#include <vector>
+
+#include "hci.h"
+#include "hci_protocol.h"
+
+namespace test_vendor_lib {
+namespace hci {
+
+using HciPacketReadyCallback = std::function<void(void)>;
+
+class H4Packetizer : public HciProtocol {
+ public:
+  H4Packetizer(int fd, PacketReadCallback command_cb, PacketReadCallback event_cb, PacketReadCallback acl_cb,
+               PacketReadCallback sco_cb);
+
+  size_t Send(uint8_t type, const uint8_t* data, size_t length);
+
+  void OnPacketReady();
+
+  void OnDataReady(int fd);
+
+ private:
+  int uart_fd_;
+
+  PacketReadCallback command_cb_;
+  PacketReadCallback event_cb_;
+  PacketReadCallback acl_cb_;
+  PacketReadCallback sco_cb_;
+
+  hci::PacketType hci_packet_type_{hci::PacketType::UNKNOWN};
+
+  // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
+  static constexpr size_t COMMAND_PREAMBLE_SIZE = 3;
+  static constexpr size_t COMMAND_LENGTH_OFFSET = 2;
+
+  // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
+  static constexpr size_t ACL_PREAMBLE_SIZE = 4;
+  static constexpr size_t ACL_LENGTH_OFFSET = 2;
+
+  // 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
+  static constexpr size_t SCO_PREAMBLE_SIZE = 3;
+  static constexpr size_t SCO_LENGTH_OFFSET = 2;
+
+  // 1 byte for event code, 1 byte for parameter length (Volume 2, Part
+  // E, 5.4.4)
+  static constexpr size_t EVENT_PREAMBLE_SIZE = 2;
+  static constexpr size_t EVENT_LENGTH_OFFSET = 1;
+
+  static constexpr size_t PREAMBLE_SIZE_MAX = ACL_PREAMBLE_SIZE;
+
+  size_t HciGetPacketLengthForType(hci::PacketType type, const uint8_t* preamble);
+
+  enum State { HCI_PREAMBLE, HCI_PAYLOAD };
+  State state_{HCI_PREAMBLE};
+  uint8_t preamble_[PREAMBLE_SIZE_MAX];
+  std::vector<uint8_t> packet_;
+  size_t bytes_remaining_{0};
+  size_t bytes_read_{0};
+};
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/h4_protocol.cc b/vendor_libs/test_vendor_lib/model/devices/h4_protocol.cc
new file mode 100644
index 0000000..c4704ea
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/h4_protocol.cc
@@ -0,0 +1,106 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "h4_protocol.h"
+
+#define LOG_TAG "hci-h4_protocol"
+
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <sys/uio.h>
+#include <unistd.h>
+
+namespace test_vendor_lib {
+namespace hci {
+
+H4Protocol::H4Protocol(int fd, PacketReadCallback command_cb, PacketReadCallback event_cb, PacketReadCallback acl_cb,
+                       PacketReadCallback sco_cb)
+    : uart_fd_(fd), command_cb_(command_cb), event_cb_(event_cb), acl_cb_(acl_cb), sco_cb_(sco_cb),
+      hci_packetizer_([this]() {
+        ALOGI("in lambda");
+        this->OnPacketReady();
+      }) {}
+
+size_t H4Protocol::Send(uint8_t type, const uint8_t* data, size_t length) {
+  struct iovec iov[] = {{&type, sizeof(type)}, {const_cast<uint8_t*>(data), length}};
+  ssize_t ret = 0;
+  do {
+    ret = TEMP_FAILURE_RETRY(writev(uart_fd_, iov, sizeof(iov) / sizeof(iov[0])));
+  } while (-1 == ret && EAGAIN == errno);
+
+  if (ret == -1) {
+    ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
+  } else if (ret < static_cast<ssize_t>(length + 1)) {
+    ALOGE("%s: %d / %d bytes written - something went wrong...", __func__, static_cast<int>(ret),
+          static_cast<int>(length + 1));
+  }
+  return ret;
+}
+
+void H4Protocol::OnPacketReady() {
+  ALOGE("%s: before switch", __func__);
+  switch (hci_packet_type_) {
+    case hci::PacketType::COMMAND:
+      command_cb_(hci_packetizer_.GetPacket());
+      break;
+    case hci::PacketType::ACL:
+      acl_cb_(hci_packetizer_.GetPacket());
+      break;
+    case hci::PacketType::SCO:
+      sco_cb_(hci_packetizer_.GetPacket());
+      break;
+    case hci::PacketType::EVENT:
+      event_cb_(hci_packetizer_.GetPacket());
+      break;
+    default:
+      LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__, static_cast<int>(hci_packet_type_));
+  }
+  // Get ready for the next type byte.
+  hci_packet_type_ = hci::PacketType::UNKNOWN;
+}
+
+void H4Protocol::OnDataReady(int fd) {
+  if (hci_packet_type_ == hci::PacketType::UNKNOWN) {
+    uint8_t buffer[1] = {0};
+    ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, buffer, 1));
+    if (bytes_read != 1) {
+      if (bytes_read == 0) {
+        ALOGI("%s: Nothing ready, will retry!", __func__);
+        return;
+      } else if (bytes_read < 0) {
+        if (errno == EAGAIN) {
+          // No data, try again later.
+          return;
+        } else {
+          LOG_ALWAYS_FATAL("%s: Read packet type error: %s", __func__, strerror(errno));
+        }
+      } else {
+        LOG_ALWAYS_FATAL("%s: More bytes read than expected (%u)!", __func__, static_cast<unsigned int>(bytes_read));
+      }
+    }
+    hci_packet_type_ = static_cast<hci::PacketType>(buffer[0]);
+    if (hci_packet_type_ != hci::PacketType::ACL && hci_packet_type_ != hci::PacketType::SCO &&
+        hci_packet_type_ != hci::PacketType::COMMAND && hci_packet_type_ != hci::PacketType::EVENT) {
+      LOG_ALWAYS_FATAL("%s: Unimplemented packet type %d", __func__, static_cast<int>(hci_packet_type_));
+    }
+  } else {
+    hci_packetizer_.OnDataReady(fd, hci_packet_type_);
+  }
+}
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/h4_protocol.h b/vendor_libs/test_vendor_lib/model/devices/h4_protocol.h
new file mode 100644
index 0000000..5e261d5
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/h4_protocol.h
@@ -0,0 +1,49 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#pragma once
+
+#include "hci_protocol.h"
+#include "include/hci.h"
+
+namespace test_vendor_lib {
+namespace hci {
+
+class H4Protocol : public HciProtocol {
+ public:
+  H4Protocol(int fd, PacketReadCallback command_cb, PacketReadCallback event_cb, PacketReadCallback acl_cb,
+             PacketReadCallback sco_cb);
+
+  size_t Send(uint8_t type, const uint8_t* data, size_t length);
+
+  void OnPacketReady();
+
+  void OnDataReady(int fd);
+
+ private:
+  int uart_fd_;
+
+  PacketReadCallback command_cb_;
+  PacketReadCallback event_cb_;
+  PacketReadCallback acl_cb_;
+  PacketReadCallback sco_cb_;
+
+  hci::PacketType hci_packet_type_{hci::PacketType::UNKNOWN};
+  hci::HciPacketizer hci_packetizer_;
+};
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/hci_packetizer.cc b/vendor_libs/test_vendor_lib/model/devices/hci_packetizer.cc
new file mode 100644
index 0000000..cca7780
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/hci_packetizer.cc
@@ -0,0 +1,129 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "hci_packetizer.h"
+
+#define LOG_TAG "hci_packetizer"
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <unistd.h>
+
+namespace test_vendor_lib {
+namespace hci {
+constexpr size_t HciPacketizer::COMMAND_PREAMBLE_SIZE;
+constexpr size_t HciPacketizer::COMMAND_LENGTH_OFFSET;
+constexpr size_t HciPacketizer::ACL_PREAMBLE_SIZE;
+constexpr size_t HciPacketizer::ACL_LENGTH_OFFSET;
+constexpr size_t HciPacketizer::SCO_PREAMBLE_SIZE;
+constexpr size_t HciPacketizer::SCO_LENGTH_OFFSET;
+constexpr size_t HciPacketizer::EVENT_PREAMBLE_SIZE;
+constexpr size_t HciPacketizer::EVENT_LENGTH_OFFSET;
+
+constexpr size_t HciPacketizer::PREAMBLE_SIZE_MAX;
+
+size_t HciPacketizer::HciGetPacketLengthForType(hci::PacketType type, const uint8_t* preamble) {
+  static const size_t packet_length_offset[static_cast<size_t>(hci::PacketType::EVENT) + 1] = {
+      0,
+      HciPacketizer::COMMAND_LENGTH_OFFSET,
+      HciPacketizer::ACL_LENGTH_OFFSET,
+      HciPacketizer::SCO_LENGTH_OFFSET,
+      HciPacketizer::EVENT_LENGTH_OFFSET,
+  };
+
+  size_t offset = packet_length_offset[static_cast<size_t>(type)];
+  if (type != hci::PacketType::ACL) return preamble[offset];
+  return (((preamble[offset + 1]) << 8) | preamble[offset]);
+}
+
+const std::vector<uint8_t>& HciPacketizer::GetPacket() const {
+  return packet_;
+}
+
+void HciPacketizer::OnDataReady(int fd, hci::PacketType packet_type) {
+  static const size_t preamble_size[static_cast<size_t>(hci::PacketType::EVENT) + 1] = {
+      0,
+      HciPacketizer::COMMAND_PREAMBLE_SIZE,
+      HciPacketizer::ACL_PREAMBLE_SIZE,
+      HciPacketizer::SCO_PREAMBLE_SIZE,
+      HciPacketizer::EVENT_PREAMBLE_SIZE,
+  };
+
+  switch (state_) {
+    case HCI_PREAMBLE: {
+      ssize_t bytes_read = TEMP_FAILURE_RETRY(
+          read(fd, preamble_ + bytes_read_, preamble_size[static_cast<uint8_t>(packet_type)] - bytes_read_));
+      if (bytes_read == 0) {
+        ALOGE("%s: Will try again to read the header!", __func__);
+        return;
+      }
+      if (bytes_read < 0) {
+        // Ignore temporary failures.
+        if (errno == EAGAIN) {
+          return;
+        }
+        LOG_ALWAYS_FATAL("%s: Read header error: %s", __func__, strerror(errno));
+      }
+      bytes_read_ += bytes_read;
+      if (bytes_read_ == preamble_size[static_cast<uint8_t>(packet_type)]) {
+        size_t packet_length = HciGetPacketLengthForType(packet_type, preamble_);
+        packet_.resize(preamble_size[static_cast<uint8_t>(packet_type)] + packet_length);
+        memcpy(packet_.data(), preamble_, preamble_size[static_cast<uint8_t>(packet_type)]);
+        ALOGI("%s: Read a preamble of size %d length %d %0x %0x %0x", __func__, static_cast<int>(bytes_read_),
+              static_cast<int>(packet_length), preamble_[0], preamble_[1], preamble_[2]);
+        bytes_remaining_ = packet_length;
+        if (bytes_remaining_ == 0) {
+          packet_ready_cb_();
+          state_ = HCI_PREAMBLE;
+          bytes_read_ = 0;
+        } else {
+          state_ = HCI_PAYLOAD;
+          bytes_read_ = 0;
+        }
+      }
+      break;
+    }
+
+    case HCI_PAYLOAD: {
+      ssize_t bytes_read = TEMP_FAILURE_RETRY(
+          read(fd, packet_.data() + preamble_size[static_cast<uint8_t>(packet_type)] + bytes_read_, bytes_remaining_));
+      if (bytes_read == 0) {
+        ALOGI("%s: Will try again to read the payload!", __func__);
+        return;
+      }
+      if (bytes_read < 0) {
+        // Ignore temporary failures.
+        if (errno == EAGAIN) {
+          return;
+        }
+        LOG_ALWAYS_FATAL("%s: Read payload error: %s", __func__, strerror(errno));
+      }
+      bytes_remaining_ -= bytes_read;
+      bytes_read_ += bytes_read;
+      if (bytes_remaining_ == 0) {
+        packet_ready_cb_();
+        state_ = HCI_PREAMBLE;
+        bytes_read_ = 0;
+      }
+      break;
+    }
+  }
+}
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/hci_packetizer.h b/vendor_libs/test_vendor_lib/model/devices/hci_packetizer.h
new file mode 100644
index 0000000..4823008
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/hci_packetizer.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#pragma once
+
+#include <functional>
+#include <vector>
+
+#include "include/hci.h"
+
+namespace test_vendor_lib {
+namespace hci {
+
+using HciPacketReadyCallback = std::function<void(void)>;
+
+class HciPacketizer {
+ public:
+  HciPacketizer(HciPacketReadyCallback packet_cb) : packet_ready_cb_(packet_cb){};
+  void OnDataReady(int fd, hci::PacketType packet_type);
+  const std::vector<uint8_t>& GetPacket() const;
+
+ private:
+  // 2 bytes for opcode, 1 byte for parameter length (Volume 2, Part E, 5.4.1)
+  static constexpr size_t COMMAND_PREAMBLE_SIZE = 3;
+  static constexpr size_t COMMAND_LENGTH_OFFSET = 2;
+
+  // 2 bytes for handle, 2 bytes for data length (Volume 2, Part E, 5.4.2)
+  static constexpr size_t ACL_PREAMBLE_SIZE = 4;
+  static constexpr size_t ACL_LENGTH_OFFSET = 2;
+
+  // 2 bytes for handle, 1 byte for data length (Volume 2, Part E, 5.4.3)
+  static constexpr size_t SCO_PREAMBLE_SIZE = 3;
+  static constexpr size_t SCO_LENGTH_OFFSET = 2;
+
+  // 1 byte for event code, 1 byte for parameter length (Volume 2, Part
+  // E, 5.4.4)
+  static constexpr size_t EVENT_PREAMBLE_SIZE = 2;
+  static constexpr size_t EVENT_LENGTH_OFFSET = 1;
+
+  static constexpr size_t PREAMBLE_SIZE_MAX = ACL_PREAMBLE_SIZE;
+
+  size_t HciGetPacketLengthForType(hci::PacketType type, const uint8_t* preamble);
+
+ protected:
+  enum State { HCI_PREAMBLE, HCI_PAYLOAD };
+  State state_{HCI_PREAMBLE};
+  uint8_t preamble_[PREAMBLE_SIZE_MAX];
+  std::vector<uint8_t> packet_;
+  size_t bytes_remaining_{0};
+  size_t bytes_read_{0};
+  HciPacketReadyCallback packet_ready_cb_;
+};
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/hci_protocol.cc b/vendor_libs/test_vendor_lib/model/devices/hci_protocol.cc
new file mode 100644
index 0000000..e01bfa5
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/hci_protocol.cc
@@ -0,0 +1,53 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#include "hci_protocol.h"
+
+#define LOG_TAG "hci-hci_protocol"
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <log/log.h>
+#include <unistd.h>
+
+namespace test_vendor_lib {
+namespace hci {
+
+size_t HciProtocol::WriteSafely(int fd, const uint8_t* data, size_t length) {
+  size_t transmitted_length = 0;
+  while (length > 0) {
+    ssize_t ret = TEMP_FAILURE_RETRY(write(fd, data + transmitted_length, length));
+
+    if (ret == -1) {
+      if (errno == EAGAIN) continue;
+      ALOGE("%s error writing to UART (%s)", __func__, strerror(errno));
+      break;
+
+    } else if (ret == 0) {
+      // Nothing written :(
+      ALOGE("%s zero bytes written - something went wrong...", __func__);
+      break;
+    }
+
+    transmitted_length += ret;
+    length -= ret;
+  }
+
+  return transmitted_length;
+}
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/hci_protocol.h b/vendor_libs/test_vendor_lib/model/devices/hci_protocol.h
new file mode 100644
index 0000000..3aa7640
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/hci_protocol.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2017 The Android Open Source Project
+//
+// 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.
+//
+
+#pragma once
+
+#include "hci.h"
+#include "hci_packetizer.h"
+
+namespace test_vendor_lib {
+namespace hci {
+
+using PacketReadCallback = std::function<void(const std::vector<uint8_t>&)>;
+
+// Implementation of HCI protocol bits common to different transports
+class HciProtocol {
+ public:
+  HciProtocol() = default;
+  virtual ~HciProtocol(){};
+
+  // Protocol-specific implementation of sending packets.
+  virtual size_t Send(uint8_t type, const uint8_t* data, size_t length) = 0;
+
+ protected:
+  static size_t WriteSafely(int fd, const uint8_t* data, size_t length);
+};
+
+}  // namespace hci
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc b/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc
new file mode 100644
index 0000000..e146fcc
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.cc
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "hci_socket_device"
+
+#include "hci_socket_device.h"
+
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+
+#include "osi/include/log.h"
+
+#include "model/setup/device_boutique.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+HciSocketDevice::HciSocketDevice(int file_descriptor) : socket_file_descriptor_(file_descriptor) {
+  advertising_interval_ms_ = std::chrono::milliseconds(0);
+
+  page_scan_delay_ms_ = std::chrono::milliseconds(600);
+
+  properties_.SetPageScanRepetitionMode(0);
+  properties_.SetClassOfDevice(0x600420);
+  properties_.SetExtendedInquiryData({
+      16,  // length
+      9,   // Type: Device Name
+      'g',
+      'D',
+      'e',
+      'v',
+      'i',
+      'c',
+      'e',
+      '-',
+      'h',
+      'c',
+      'i',
+      '_',
+      'n',
+      'e',
+      't',
+  });
+  properties_.SetName({
+      'g',
+      'D',
+      'e',
+      'v',
+      'i',
+      'c',
+      'e',
+      '-',
+      'H',
+      'C',
+      'I',
+      '_',
+      'N',
+      'e',
+      't',
+  });
+
+  h4_ = hci::H4Packetizer(
+      socket_file_descriptor_,
+      [this](const std::vector<uint8_t>& raw_command) {
+        LOG_INFO(LOG_TAG, "Rx Command");
+        std::shared_ptr<std::vector<uint8_t>> packet_copy = std::make_shared<std::vector<uint8_t>>(raw_command);
+        HandleCommand(packet_copy);
+      },
+      [](const std::vector<uint8_t>&) { CHECK(false) << "Unexpected Event in HciSocketDevice!"; },
+      [this](const std::vector<uint8_t>& raw_acl) {
+        LOG_INFO(LOG_TAG, "Rx ACL");
+        std::shared_ptr<std::vector<uint8_t>> packet_copy = std::make_shared<std::vector<uint8_t>>(raw_acl);
+        HandleAcl(packet_copy);
+      },
+      [this](const std::vector<uint8_t>& raw_sco) {
+        LOG_INFO(LOG_TAG, "Rx SCO");
+        std::shared_ptr<std::vector<uint8_t>> packet_copy = std::make_shared<std::vector<uint8_t>>(raw_sco);
+        HandleSco(packet_copy);
+      });
+
+  RegisterEventChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+    LOG_INFO(LOG_TAG, "Tx Event");
+    SendHci(hci::PacketType::EVENT, packet);
+  });
+  RegisterAclChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+    LOG_INFO(LOG_TAG, "Tx ACL");
+    SendHci(hci::PacketType::ACL, packet);
+  });
+  RegisterScoChannel([this](std::shared_ptr<std::vector<uint8_t>> packet) {
+    LOG_INFO(LOG_TAG, "Tx SCO");
+    SendHci(hci::PacketType::SCO, packet);
+  });
+}
+
+void HciSocketDevice::TimerTick() {
+  LOG_INFO(LOG_TAG, "TimerTick fd = %d", socket_file_descriptor_);
+  h4_.OnDataReady(socket_file_descriptor_);
+  DualModeController::TimerTick();
+}
+
+void HciSocketDevice::SendHci(hci::PacketType packet_type, const std::shared_ptr<std::vector<uint8_t>> packet) {
+  if (socket_file_descriptor_ == -1) {
+    LOG_INFO(LOG_TAG, "socket_file_descriptor == -1");
+    return;
+  }
+  uint8_t type = static_cast<uint8_t>(packet_type);
+  int bytes_written;
+  bytes_written = write(socket_file_descriptor_, &type, sizeof(type));
+  if (bytes_written != sizeof(type)) {
+    LOG_INFO(LOG_TAG, "bytes_written %d != sizeof(type)", bytes_written);
+  }
+  bytes_written = write(socket_file_descriptor_, packet->data(), packet->size());
+  if (static_cast<size_t>(bytes_written) != packet->size()) {
+    LOG_INFO(LOG_TAG, "bytes_written %d != packet->size", bytes_written);
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.h b/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.h
new file mode 100644
index 0000000..11eddae
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/hci_socket_device.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "model/controller/dual_mode_controller.h"
+#include "model/devices/h4_packetizer.h"
+
+namespace {
+const std::string kHciSocketDevicePropertiesFile = "/etc/bluetooth/hci_socket_device_controller_properties.json";
+}  // namespace
+
+namespace test_vendor_lib {
+
+class HciSocketDevice : public DualModeController {
+ public:
+  HciSocketDevice(int socket_fd);
+  ~HciSocketDevice() = default;
+
+  static std::shared_ptr<HciSocketDevice> Create(int socket_fd) {
+    return std::make_shared<HciSocketDevice>(socket_fd);
+  }
+
+  virtual std::string GetTypeString() const override {
+    return "hci_socket_device";
+  }
+
+  virtual void TimerTick() override;
+
+  void SendHci(hci::PacketType packet_type, const std::shared_ptr<std::vector<uint8_t>> packet);
+
+ private:
+  int socket_file_descriptor_{-1};
+  hci::H4Packetizer h4_{socket_file_descriptor_, [](const std::vector<uint8_t>&) {}, [](const std::vector<uint8_t>&) {},
+                        [](const std::vector<uint8_t>&) {}, [](const std::vector<uint8_t>&) {}};
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/keyboard.cc b/vendor_libs/test_vendor_lib/model/devices/keyboard.cc
new file mode 100644
index 0000000..2cfc992
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/keyboard.cc
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "keyboard"
+
+#include "keyboard.h"
+
+#include "model/setup/device_boutique.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+bool Keyboard::registered_ = DeviceBoutique::Register(LOG_TAG, &Keyboard::Create);
+
+Keyboard::Keyboard() {
+  properties_.SetLeAdvertisementType(BTM_BLE_CONNECT_EVT);
+  properties_.SetLeAdvertisement({0x11,  // Length
+                                  BTM_BLE_AD_TYPE_NAME_CMPL,
+                                  'g',
+                                  'D',
+                                  'e',
+                                  'v',
+                                  'i',
+                                  'c',
+                                  'e',
+                                  '-',
+                                  'k',
+                                  'e',
+                                  'y',
+                                  'b',
+                                  'o',
+                                  'a',
+                                  'r',
+                                  'd',
+                                  0x03,  // Length
+                                  0x19,
+                                  0xC1,
+                                  0x03,
+                                  0x03,  // Length
+                                  0x03,
+                                  0x12,
+                                  0x18,
+                                  0x02,  // Length
+                                  BTM_BLE_AD_TYPE_FLAG,
+                                  BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG});
+
+  properties_.SetLeScanResponse({0x04,  // Length
+                                 BTM_BLE_AD_TYPE_NAME_SHORT, 'k', 'e', 'y'});
+}
+
+std::string Keyboard::GetTypeString() const {
+  return "keyboard";
+}
+
+void Keyboard::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+
+  if (args.size() < 3) return;
+
+  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+void Keyboard::TimerTick() {
+  if (!connected_) {
+    Beacon::TimerTick();
+  }
+}
+
+void Keyboard::IncomingPacket(packets::LinkLayerPacketView packet) {
+  if (!connected_) {
+    Beacon::IncomingPacket(packet);
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/keyboard.h b/vendor_libs/test_vendor_lib/model/devices/keyboard.h
similarity index 76%
rename from vendor_libs/test_vendor_lib/include/keyboard.h
rename to vendor_libs/test_vendor_lib/model/devices/keyboard.h
index 9d1cfbf..871fa52 100644
--- a/vendor_libs/test_vendor_lib/include/keyboard.h
+++ b/vendor_libs/test_vendor_lib/model/devices/keyboard.h
@@ -19,25 +19,33 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
 #include "device.h"
 
+#include "beacon.h"
+
 namespace test_vendor_lib {
 
-class Keyboard : public Device {
+class Keyboard : public Beacon {
  public:
   Keyboard();
   virtual ~Keyboard() = default;
 
-  // Initialize the device based on the values of |args|.
-  virtual void Initialize(const std::vector<std::string>& args) override;
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<Keyboard>();
+  }
 
   // Return a string representation of the type of device.
   virtual std::string GetTypeString() const override;
 
-  virtual bool LeConnect();
+  // Initialize the device based on the values of |args|.
+  virtual void Initialize(const std::vector<std::string>& args) override;
 
-  virtual bool IsPageScanAvailable() const override;
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+  virtual void TimerTick() override;
+
+ private:
+  bool connected_{false};
+  static bool registered_;
 };
-
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc
new file mode 100644
index 0000000..9ccfd61
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.cc
@@ -0,0 +1,66 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "link_layer_socket_device"
+
+#include "link_layer_socket_device.h"
+
+#include <unistd.h>
+
+#include "osi/include/log.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+#include "packets/view.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+LinkLayerSocketDevice::LinkLayerSocketDevice(int socket_fd, Phy::Type phy_type)
+    : socket_(socket_fd), phy_type_(phy_type) {}
+
+void LinkLayerSocketDevice::TimerTick() {
+  if (bytes_left_ == 0) {
+    received_ = std::make_shared<std::vector<uint8_t>>(Link::kSizeBytes);
+    size_t bytes_received = socket_.TryReceive(Link::kSizeBytes, received_->data());
+    if (bytes_received == 0) {
+      return;
+    }
+    CHECK(bytes_received == Link::kSizeBytes) << "bytes_received == " << bytes_received;
+    packets::PacketView<true> size({packets::View(received_, 0, Link::kSizeBytes)});
+    bytes_left_ = size.begin().extract<uint32_t>();
+    received_->resize(Link::kSizeBytes + bytes_left_);
+    offset_ = Link::kSizeBytes;
+  }
+  size_t bytes_received = socket_.TryReceive(bytes_left_, received_->data() + offset_);
+  if (bytes_received == 0) {
+    return;
+  }
+  bytes_left_ -= bytes_received;
+  offset_ += bytes_received;
+  if (bytes_left_ == 0) {
+    SendLinkLayerPacket(packets::LinkLayerPacketBuilder::ReWrap(received_), phy_type_);
+    offset_ = 0;
+    received_.reset();
+  }
+}
+
+void LinkLayerSocketDevice::IncomingPacket(packets::LinkLayerPacketView packet) {
+  socket_.TrySend(packet);
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h
new file mode 100644
index 0000000..d3bbb2e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/link_layer_socket_device.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "device.h"
+#include "include/link.h"
+#include "include/phy.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "polled_socket.h"
+
+namespace test_vendor_lib {
+
+class LinkLayerSocketDevice : public Device {
+ public:
+  LinkLayerSocketDevice(int socket_fd, Phy::Type phy_type);
+  LinkLayerSocketDevice(LinkLayerSocketDevice&& s) = default;
+  virtual ~LinkLayerSocketDevice() = default;
+
+  static std::shared_ptr<Device> Create(int socket_fd, Phy::Type phy_type) {
+    return std::make_shared<LinkLayerSocketDevice>(socket_fd, phy_type);
+  }
+
+  virtual std::string GetTypeString() const override {
+    return "link_layer_socket_device";
+  }
+
+  virtual void Initialize(const std::vector<std::string>&) override {}
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+  virtual void TimerTick() override;
+
+ private:
+  net::PolledSocket socket_;
+  Phy::Type phy_type_;
+  size_t bytes_left_{0};
+  size_t offset_;
+  std::shared_ptr<std::vector<uint8_t>> received_;
+  std::vector<packets::LinkLayerPacketView> packet_queue_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/loopback.cc b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
new file mode 100644
index 0000000..4d9078e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/loopback.cc
@@ -0,0 +1,100 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "loopback"
+
+#include "loopback.h"
+
+#include "le_advertisement.h"
+#include "model/setup/device_boutique.h"
+#include "osi/include/log.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+bool Loopback::registered_ = DeviceBoutique::Register(LOG_TAG, &Loopback::Create);
+
+Loopback::Loopback() {
+  advertising_interval_ms_ = std::chrono::milliseconds(1280);
+  properties_.SetLeAdvertisementType(BTM_BLE_NON_CONNECT_EVT);
+  properties_.SetLeAdvertisement({0x11,  // Length
+                                  BTM_BLE_AD_TYPE_NAME_CMPL,
+                                  'g',
+                                  'D',
+                                  'e',
+                                  'v',
+                                  'i',
+                                  'c',
+                                  'e',
+                                  '-',
+                                  'l',
+                                  'o',
+                                  'o',
+                                  'p',
+                                  'b',
+                                  'a',
+                                  'c',
+                                  'k',
+                                  0x02,  // Length
+                                  BTM_BLE_AD_TYPE_FLAG,
+                                  BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG});
+
+  properties_.SetLeScanResponse({0x05,  // Length
+                                 BTM_BLE_AD_TYPE_NAME_SHORT, 'l', 'o', 'o', 'p'});
+}
+
+std::string Loopback::GetTypeString() const {
+  return "loopback";
+}
+
+std::string Loopback::ToString() const {
+  std::string dev = GetTypeString() + "@" + properties_.GetLeAddress().ToString();
+
+  return dev;
+}
+
+void Loopback::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetLeAddress(addr);
+
+  if (args.size() < 3) return;
+
+  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
+}
+
+void Loopback::TimerTick() {}
+
+void Loopback::IncomingPacket(packets::LinkLayerPacketView packet) {
+  LOG_INFO(LOG_TAG, "Got a packet of type %d", static_cast<int>(packet.GetType()));
+  if (packet.GetDestinationAddress() == properties_.GetLeAddress() && packet.GetType() == Link::PacketType::LE_SCAN) {
+    LOG_INFO(LOG_TAG, "Got a scan");
+    std::unique_ptr<packets::LeAdvertisementBuilder> scan_response = packets::LeAdvertisementBuilder::Create(
+        LeAdvertisement::AddressType::PUBLIC, LeAdvertisement::AdvertisementType::SCAN_RESPONSE,
+        properties_.GetLeScanResponse());
+    std::shared_ptr<packets::LinkLayerPacketBuilder> to_send = packets::LinkLayerPacketBuilder::WrapLeScanResponse(
+        std::move(scan_response), properties_.GetLeAddress(), packet.GetSourceAddress());
+    std::vector<std::shared_ptr<PhyLayer>> le_phys = phy_layers_[Phy::Type::LOW_ENERGY];
+    for (auto phy : le_phys) {
+      LOG_INFO(LOG_TAG, "Sending a Scan Response on a Phy");
+      phy->Send(to_send);
+    }
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/beacon.h b/vendor_libs/test_vendor_lib/model/devices/loopback.h
similarity index 67%
copy from vendor_libs/test_vendor_lib/include/beacon.h
copy to vendor_libs/test_vendor_lib/model/devices/loopback.h
index 8943b96..31dd1cd 100644
--- a/vendor_libs/test_vendor_lib/include/beacon.h
+++ b/vendor_libs/test_vendor_lib/model/devices/loopback.h
@@ -19,23 +19,35 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
 #include "device.h"
-#include "stack/include/btm_ble_api.h"
 
 namespace test_vendor_lib {
 
 // A simple device that advertises periodically and is not connectable.
-class Beacon : public Device {
+class Loopback : public Device {
  public:
-  Beacon();
-  virtual ~Beacon() = default;
+  Loopback();
+  virtual ~Loopback() = default;
+
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<Loopback>();
+  }
 
   // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const override { return "beacon"; }
+  virtual std::string GetTypeString() const override;
+
+  // Return a string representation of the device.
+  virtual std::string ToString() const override;
 
   // Set the address and advertising interval from string args.
   virtual void Initialize(const std::vector<std::string>& args) override;
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+  virtual void TimerTick() override;
+
+ private:
+  static bool registered_;
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/polled_socket.cc b/vendor_libs/test_vendor_lib/model/devices/polled_socket.cc
new file mode 100644
index 0000000..5719132
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/polled_socket.cc
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "polled_socket"
+
+#include "polled_socket.h"
+
+#include <base/logging.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include "osi/include/log.h"
+
+namespace test_vendor_lib {
+namespace net {
+
+PolledSocket::PolledSocket(int file_descriptor) : file_descriptor_(file_descriptor) {}
+
+PolledSocket::PolledSocket(PolledSocket&& p) : file_descriptor_(p.file_descriptor_) {
+  p.file_descriptor_ = -1;
+}
+
+PolledSocket::~PolledSocket() {
+  CleanUp();
+}
+
+void PolledSocket::CleanUp() {
+  if (file_descriptor_ != -1) {
+    WHILE_EINTR(close(file_descriptor_));
+  }
+  file_descriptor_ = -1;
+}
+
+size_t PolledSocket::TrySend(packets::PacketView<true> packet) {
+  if (file_descriptor_ == -1) {
+    return 0;
+  }
+  // Could skip this copy if the packet is guaranteed to be contiguous.
+  std::vector<uint8_t> copy;
+  copy.reserve(packet.size());
+  for (const auto&& c : packet) {
+    copy.push_back(c);
+  }
+  int ret = write(file_descriptor_, copy.data(), copy.size());
+  if (ret == -1) {
+    ALOGW("%s error %s", __func__, strerror(errno));
+    return 0;
+  } else {
+    return static_cast<size_t>(ret);
+  }
+}
+
+/*
+void PolledSocket::TrySendVector(
+  const std::vector<std::vector<uint8_t>&>& raw_vectors) {
+if (file_descriptor_ < 0) {
+  return;
+}
+for (const std::vector<uint8_t>& v : raw_vectors) {
+  Send(v);
+}
+  std::vector<struct iovec> iovecs;
+  for (auto v : raw_vectors) {
+    struct iovec one_iovec;
+    one_iovec.iov_base = v.data();
+    one_iovec.iov_base = v.size();
+    iovecs.push_back(one_iovec);
+  }
+  int ret = writev(file_descriptor_, iovecs.data(), iovecs.size());
+  if (ret == -1) {
+    return 0;
+  } else {
+    return static_cast<size_t>(ret);
+  }
+}
+*/
+
+size_t PolledSocket::TryReceive(size_t num_bytes, uint8_t* data) {
+  if (file_descriptor_ == -1) return 0;
+  int ret;
+  WHILE_EINTR(ret = read(file_descriptor_, data, num_bytes));
+  if (ret < 0) {
+    if (errno == EAGAIN) {
+      return 0;
+    } else {
+      ALOGW("%s error %s", __func__, strerror(errno));
+      CleanUp();
+      return 0;
+    }
+  }
+  return ret;
+}
+
+}  // namespace net
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/polled_socket.h b/vendor_libs/test_vendor_lib/model/devices/polled_socket.h
new file mode 100644
index 0000000..b697f56
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/polled_socket.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <unistd.h>
+
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace net {
+
+#define WHILE_EINTR(fn) \
+  do {                  \
+  } while ((fn) == -1 && errno == EINTR)
+
+class PolledSocket {
+ public:
+  PolledSocket(int file_descriptor);
+  PolledSocket(PolledSocket&& p);
+  virtual ~PolledSocket();
+
+  size_t TrySend(packets::PacketView<true> packet);
+  // size_t TrySendVector(const std::vector<const std::vector<uint8_t>&>& data);
+  size_t TryReceive(size_t num_bytes, uint8_t* data);
+
+ private:
+  void CleanUp();
+  int file_descriptor_{-1};
+};
+
+}  // namespace net
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc
new file mode 100644
index 0000000..787e2f7
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.cc
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "remote_loopback_device"
+
+#include "remote_loopback_device.h"
+
+#include "model/setup/device_boutique.h"
+
+#include "osi/include/log.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+using packets::LinkLayerPacketBuilder;
+using packets::LinkLayerPacketView;
+using packets::PageResponseBuilder;
+
+bool RemoteLoopbackDevice::registered_ = DeviceBoutique::Register(LOG_TAG, &RemoteLoopbackDevice::Create);
+
+RemoteLoopbackDevice::RemoteLoopbackDevice() {}
+
+std::string RemoteLoopbackDevice::ToString() const {
+  return GetTypeString() + " (no address)";
+}
+
+void RemoteLoopbackDevice::Initialize(const std::vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  Address addr;
+  if (Address::FromString(args[1], addr)) properties_.SetAddress(addr);
+}
+
+void RemoteLoopbackDevice::IncomingPacket(LinkLayerPacketView packet) {
+  // TODO: Check sender?
+  // TODO: Handle other packet types
+  Phy::Type phy_type = Phy::Type::BR_EDR;
+
+  Link::PacketType type = packet.GetType();
+  switch (type) {
+    case Link::PacketType::PAGE:
+      SendLinkLayerPacket(LinkLayerPacketBuilder::WrapPageResponse(
+                              PageResponseBuilder::Create(true), packet.GetSourceAddress(), packet.GetSourceAddress()),
+                          Phy::Type::BR_EDR);
+      break;
+    default: {
+      ALOGW("Resend = %d", static_cast<int>(packet.size()));
+      std::shared_ptr<std::vector<uint8_t>> extracted_packet = std::make_shared<std::vector<uint8_t>>();
+      extracted_packet->reserve(packet.size());
+      for (const auto byte : packet) {
+        extracted_packet->push_back(byte);
+      }
+
+      SendLinkLayerPacket(LinkLayerPacketBuilder::ReWrap(extracted_packet), phy_type);
+    }
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h
new file mode 100644
index 0000000..5513677
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/remote_loopback_device.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "device.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+
+namespace test_vendor_lib {
+
+class RemoteLoopbackDevice : public Device {
+ public:
+  RemoteLoopbackDevice();
+  virtual ~RemoteLoopbackDevice() = default;
+
+  static std::shared_ptr<Device> Create() {
+    return std::make_shared<RemoteLoopbackDevice>();
+  }
+
+  virtual std::string GetTypeString() const override {
+    return "remote_loopback_device";
+  }
+
+  virtual std::string ToString() const override;
+
+  virtual void Initialize(const std::vector<std::string>& args) override;
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+ private:
+  static bool registered_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/test_channel_transport.cc b/vendor_libs/test_vendor_lib/model/devices/server_port_factory.cc
similarity index 68%
rename from vendor_libs/test_vendor_lib/src/test_channel_transport.cc
rename to vendor_libs/test_vendor_lib/model/devices/server_port_factory.cc
index 0d9bc2e..72008a6 100644
--- a/vendor_libs/test_vendor_lib/src/test_channel_transport.cc
+++ b/vendor_libs/test_vendor_lib/model/devices/server_port_factory.cc
@@ -14,9 +14,9 @@
  * limitations under the License.
  */
 
-#define LOG_TAG "test_channel_transport"
+#define LOG_TAG "server_port_factory"
 
-#include "test_channel_transport.h"
+#include "server_port_factory.h"
 
 #include <base/logging.h>
 
@@ -29,8 +29,14 @@
 using std::vector;
 
 namespace test_vendor_lib {
+namespace net {
 
-int TestChannelTransport::SetUp(int port) {
+ServerPortFactory::ServerPortFactory(int port, std::function<void(int fd)>& callback) {
+  port_ = port;
+  callback_ = callback;
+}
+
+int ServerPortFactory::SetUp(int port) {
   struct sockaddr_in listen_address;
   socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
   memset(&listen_address, 0, sockaddr_in_size);
@@ -46,8 +52,7 @@
   listen_address.sin_port = htons(port);
   listen_address.sin_addr.s_addr = htonl(INADDR_ANY);
 
-  if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address),
-           sockaddr_in_size) < 0) {
+  if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address), sockaddr_in_size) < 0) {
     LOG_INFO(LOG_TAG, "Error binding test channel listener socket to address.");
     close(listen_fd_);
     return -1;
@@ -61,7 +66,7 @@
   return listen_fd_;
 }
 
-void TestChannelTransport::CleanUp() {
+void ServerPortFactory::CleanUp() {
   if (listen_fd_ == -1) {
     return;
   }
@@ -71,19 +76,15 @@
   listen_fd_ = -1;
 }
 
-int TestChannelTransport::Accept(int listen_fd_) {
+int ServerPortFactory::Accept(int listen_fd_) {
   int accept_fd = -1;
   struct sockaddr_in test_channel_address;
   socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
   memset(&test_channel_address, 0, sockaddr_in_size);
 
-  OSI_NO_INTR(accept_fd =
-                  accept(listen_fd_,
-                         reinterpret_cast<sockaddr*>(&test_channel_address),
-                         &sockaddr_in_size));
+  OSI_NO_INTR(accept_fd = accept(listen_fd_, reinterpret_cast<sockaddr*>(&test_channel_address), &sockaddr_in_size));
   if (accept_fd < 0) {
-    LOG_INFO(LOG_TAG, "Error accepting test channel connection errno=%d (%s).",
-             errno, strerror(errno));
+    LOG_INFO(LOG_TAG, "Error accepting test channel connection errno=%d (%s).", errno, strerror(errno));
 
     if (errno != EAGAIN && errno != EWOULDBLOCK) {
       LOG_ERROR(LOG_TAG, "Closing listen_fd_ (won't try again).");
@@ -97,16 +98,13 @@
   return accept_fd;
 }
 
-void TestChannelTransport::OnCommandReady(int fd,
-                                          std::function<void(void)> unwatch) {
+void ServerPortFactory::OnCommandReady(int fd, std::function<void(void)> unwatch) {
   uint8_t command_name_size = 0;
   read(fd, &command_name_size, 1);
   vector<uint8_t> command_name_raw;
   command_name_raw.resize(command_name_size);
   read(fd, &command_name_raw[0], command_name_size);
   std::string command_name(command_name_raw.begin(), command_name_raw.end());
-  LOG_INFO(LOG_TAG, "Received command from test channel: %s",
-           command_name.data());
 
   if (command_name == "CLOSE_TEST_CHANNEL" || command_name == "") {
     LOG_INFO(LOG_TAG, "Test channel closed");
@@ -117,7 +115,6 @@
 
   uint8_t num_args = 0;
   read(fd, &num_args, 1);
-  LOG_INFO(LOG_TAG, "num_args: %d", num_args);
   vector<std::string> args;
   for (uint8_t i = 0; i < num_args; ++i) {
     uint8_t arg_size = 0;
@@ -128,16 +125,27 @@
     args.push_back(std::string(arg.begin(), arg.end()));
   }
 
-  for (size_t i = 0; i < args.size(); ++i)
-    LOG_INFO(LOG_TAG, "Command argument %zu: %s", i, args[i].data());
-
   command_handler_(command_name, args);
 }
 
-void TestChannelTransport::RegisterCommandHandler(
-    const std::function<void(const std::string&, const vector<std::string>&)>&
-        callback) {
+void ServerPortFactory::SendResponse(int fd, const std::string& response) const {
+  size_t size = response.size();
+  // Cap to 64K
+  if (size > 0xffff) {
+    size = 0xffff;
+  }
+  char size_buf[4] = {static_cast<uint8_t>(size & 0xff), static_cast<uint8_t>((size >> 8) & 0xff),
+                      static_cast<uint8_t>((size >> 16) & 0xff), static_cast<uint8_t>((size >> 24) & 0xff)};
+  int written = write(fd, size_buf, 4);
+  CHECK(written == 4) << "What happened? written = " << written << "errno =" << errno;
+  written = write(fd, response.c_str(), size);
+  CHECK(written == static_cast<int>(size)) << "What happened? written = " << written << "errno =" << errno;
+}
+
+void ServerPortFactory::RegisterCommandHandler(
+    const std::function<void(const std::string&, const std::vector<std::string>&)>& callback) {
   command_handler_ = callback;
 }
 
+}  // namespace net
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/server_port_factory.h b/vendor_libs/test_vendor_lib/model/devices/server_port_factory.h
new file mode 100644
index 0000000..5f19c49
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/server_port_factory.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2015 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
+namespace test_vendor_lib {
+namespace net {
+
+// Starts a server and calls the registered lambda for each connection.
+class ServerPortFactory {
+ public:
+  // Opens a server port and sets the listen file descriptor.
+  ServerPortFactory(int port, std::function<void(int fd)>& on_connection);
+
+  // Closes the port (if succesfully opened in SetUp).
+  ~ServerPortFactory() {}
+
+  // Waits for a connection request and returns the file descriptor to watch.
+  // Returns -1 on an error.
+  void Accept(int listen_fd);
+
+ private:
+  std::function<void(int fd)> on_connection_;
+
+  int port;
+  int listen_fd_ = -1;
+
+  ServerPortFactory(const ServerPortFactory&) = delete;
+  ServerPortFactory& operator=(const ServerPortFactory&) = delete;
+};
+
+}  // namespace net
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/devices/sniffer.cc b/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
new file mode 100644
index 0000000..903ecac
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/devices/sniffer.cc
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "sniffer"
+
+#include "sniffer.h"
+
+#include "osi/include/log.h"
+
+#include "model/setup/device_boutique.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+bool Sniffer::registered_ = DeviceBoutique::Register(LOG_TAG, &Sniffer::Create);
+
+Sniffer::Sniffer() {}
+
+void Sniffer::Initialize(const vector<std::string>& args) {
+  if (args.size() < 2) return;
+
+  if (Address::FromString(args[1], device_to_sniff_)) {
+    properties_.SetAddress(device_to_sniff_);
+  }
+
+  if (args.size() < 3) return;
+}
+
+void Sniffer::TimerTick() {}
+
+void Sniffer::IncomingPacket(packets::LinkLayerPacketView packet) {
+  Address source = packet.GetSourceAddress();
+  Address dest = packet.GetDestinationAddress();
+  bool match_source = device_to_sniff_ == source;
+  bool match_dest = device_to_sniff_ == dest;
+  if (!match_source && !match_dest) {
+    return;
+  }
+  LOG_INFO(LOG_TAG, "%s %s -> %s (Type %d)", (match_source ? (match_dest ? "<->" : "<--") : "-->"),
+           source.ToString().c_str(), dest.ToString().c_str(), static_cast<int>(packet.GetType()));
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/include/classic.h b/vendor_libs/test_vendor_lib/model/devices/sniffer.h
similarity index 61%
copy from vendor_libs/test_vendor_lib/include/classic.h
copy to vendor_libs/test_vendor_lib/model/devices/sniffer.h
index 0aeba2f..3e0cfef 100644
--- a/vendor_libs/test_vendor_lib/include/classic.h
+++ b/vendor_libs/test_vendor_lib/model/devices/sniffer.h
@@ -1,5 +1,5 @@
 /*
- * Copyright 2016 The Android Open Source Project
+ * Copyright 2018 The Android Open Source Project
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -19,21 +19,36 @@
 #include <cstdint>
 #include <vector>
 
-#include "bt_address.h"
 #include "device.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "types/address.h"
 
 namespace test_vendor_lib {
 
-class Classic : public Device {
+class Sniffer : public Device {
  public:
-  Classic();
-  ~Classic() = default;
+  Sniffer();
+  ~Sniffer() = default;
+
+  static std::shared_ptr<Sniffer> Create() {
+    return std::make_shared<Sniffer>();
+  }
 
   // Initialize the device based on the values of |args|.
   virtual void Initialize(const std::vector<std::string>& args) override;
 
   // Return a string representation of the type of device.
-  virtual std::string GetTypeString() const override { return "classic"; }
+  virtual std::string GetTypeString() const override {
+    return "sniffer";
+  }
+
+  virtual void IncomingPacket(packets::LinkLayerPacketView packet) override;
+
+  virtual void TimerTick() override;
+
+ private:
+  static bool registered_;
+  Address device_to_sniff_;
 };
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/async_manager.cc b/vendor_libs/test_vendor_lib/model/setup/async_manager.cc
similarity index 86%
rename from vendor_libs/test_vendor_lib/src/async_manager.cc
rename to vendor_libs/test_vendor_lib/model/setup/async_manager.cc
index 0e30af7..fb9b1ad 100644
--- a/vendor_libs/test_vendor_lib/src/async_manager.cc
+++ b/vendor_libs/test_vendor_lib/model/setup/async_manager.cc
@@ -76,8 +76,7 @@
 
 // This number also states the maximum number of scheduled tasks we can handle
 // at a given time
-static const uint16_t kMaxTaskId =
-    -1; /* 2^16 - 1, permisible ids are {1..2^16-1}*/
+static const uint16_t kMaxTaskId = -1; /* 2^16 - 1, permisible ids are {1..2^16-1}*/
 static inline AsyncTaskId NextAsyncTaskId(const AsyncTaskId id) {
   return (id == kMaxTaskId) ? 1 : id + 1;
 }
@@ -96,8 +95,7 @@
 // Async File Descriptor Watcher Implementation:
 class AsyncManager::AsyncFdWatcher {
  public:
-  int WatchFdForNonBlockingReads(
-      int file_descriptor, const ReadCallback& on_read_fd_ready_callback) {
+  int WatchFdForNonBlockingReads(int file_descriptor, const ReadCallback& on_read_fd_ready_callback) {
     // add file descriptor and callback
     {
       std::unique_lock<std::mutex> guard(internal_mutex_);
@@ -136,9 +134,7 @@
     if (std::this_thread::get_id() != thread_.get_id()) {
       thread_.join();
     } else {
-      LOG_WARN(LOG_TAG,
-               "%s: Starting thread stop from inside the reading thread itself",
-               __func__);
+      LOG_WARN(LOG_TAG, "%s: Starting thread stop from inside the reading thread itself", __func__);
     }
 
     {
@@ -182,8 +178,7 @@
   int notifyThread() {
     char buffer = '0';
     if (TEMP_FAILURE_RETRY(write(notification_write_fd_, &buffer, 1)) < 0) {
-      LOG_ERROR(LOG_TAG, "%s: Unable to send message to reading thread",
-                __func__);
+      LOG_ERROR(LOG_TAG, "%s: Unable to send message to reading thread", __func__);
       return -1;
     }
     return 0;
@@ -209,8 +204,7 @@
   bool consumeThreadNotifications(fd_set& read_fds) {
     if (FD_ISSET(notification_listen_fd_, &read_fds)) {
       char buffer[kNotificationBufferSize];
-      while (TEMP_FAILURE_RETRY(read(notification_listen_fd_, buffer,
-                                     kNotificationBufferSize)) ==
+      while (TEMP_FAILURE_RETRY(read(notification_listen_fd_, buffer, kNotificationBufferSize)) ==
              kNotificationBufferSize) {
       }
       return true;
@@ -247,8 +241,8 @@
       if (retval <= 0) {  // there was some error or a timeout
         LOG_ERROR(LOG_TAG,
                   "%s: There was an error while waiting for data on the file "
-                  "descriptors",
-                  __func__);
+                  "descriptors: %s",
+                  __func__, strerror(errno));
         continue;
       }
 
@@ -277,17 +271,13 @@
 // Async task manager implementation
 class AsyncManager::AsyncTaskManager {
  public:
-  AsyncTaskId ExecAsync(std::chrono::milliseconds delay,
-                        const TaskCallback& callback) {
-    return scheduleTask(std::make_shared<Task>(
-        std::chrono::steady_clock::now() + delay, callback));
+  AsyncTaskId ExecAsync(std::chrono::milliseconds delay, const TaskCallback& callback) {
+    return scheduleTask(std::make_shared<Task>(std::chrono::steady_clock::now() + delay, callback));
   }
 
-  AsyncTaskId ExecAsyncPeriodically(std::chrono::milliseconds delay,
-                                    std::chrono::milliseconds period,
+  AsyncTaskId ExecAsyncPeriodically(std::chrono::milliseconds delay, std::chrono::milliseconds period,
                                     const TaskCallback& callback) {
-    return scheduleTask(std::make_shared<Task>(
-        std::chrono::steady_clock::now() + delay, period, callback));
+    return scheduleTask(std::make_shared<Task>(std::chrono::steady_clock::now() + delay, period, callback));
   }
 
   bool CancelAsyncTask(AsyncTaskId async_task_id) {
@@ -320,9 +310,7 @@
     if (std::this_thread::get_id() != thread_.get_id()) {
       thread_.join();
     } else {
-      LOG_WARN(LOG_TAG,
-               "%s: Starting thread stop from inside the task thread itself",
-               __func__);
+      LOG_WARN(LOG_TAG, "%s: Starting thread stop from inside the task thread itself", __func__);
     }
     return 0;
   }
@@ -331,27 +319,19 @@
   // Holds the data for each task
   class Task {
    public:
-    Task(std::chrono::steady_clock::time_point time,
-         std::chrono::milliseconds period, const TaskCallback& callback)
-        : time(time),
-          periodic(true),
-          period(period),
-          callback(callback),
-          task_id(kInvalidTaskId) {}
-    Task(std::chrono::steady_clock::time_point time,
-         const TaskCallback& callback)
-        : time(time),
-          periodic(false),
-          callback(callback),
-          task_id(kInvalidTaskId) {}
+    Task(std::chrono::steady_clock::time_point time, std::chrono::milliseconds period, const TaskCallback& callback)
+        : time(time), periodic(true), period(period), callback(callback), task_id(kInvalidTaskId) {}
+    Task(std::chrono::steady_clock::time_point time, const TaskCallback& callback)
+        : time(time), periodic(false), callback(callback), task_id(kInvalidTaskId) {}
 
     // Operators needed to be in a collection
     bool operator<(const Task& another) const {
-      return std::make_pair(time, task_id) <
-             std::make_pair(another.time, another.task_id);
+      return std::make_pair(time, task_id) < std::make_pair(another.time, another.task_id);
     }
 
-    bool isPeriodic() const { return periodic; }
+    bool isPeriodic() const {
+      return periodic;
+    }
 
     // These fields should no longer be public if the class ever becomes
     // public or gets more complex
@@ -364,8 +344,7 @@
 
   // A comparator class to put shared pointers to tasks in an ordered set
   struct task_p_comparator {
-    bool operator()(const std::shared_ptr<Task>& t1,
-                    const std::shared_ptr<Task>& t2) const {
+    bool operator()(const std::shared_ptr<Task>& t1, const std::shared_ptr<Task>& t2) const {
       return *t1 < *t2;
     }
   };
@@ -473,9 +452,7 @@
 };
 
 // Async Manager Implementation:
-AsyncManager::AsyncManager()
-    : fdWatcher_p_(new AsyncFdWatcher()),
-      taskManager_p_(new AsyncTaskManager()) {}
+AsyncManager::AsyncManager() : fdWatcher_p_(new AsyncFdWatcher()), taskManager_p_(new AsyncTaskManager()) {}
 
 AsyncManager::~AsyncManager() {
   // Make sure the threads are stopped before destroying the object.
@@ -488,24 +465,20 @@
   taskManager_p_->stopThread();
 }
 
-int AsyncManager::WatchFdForNonBlockingReads(
-    int file_descriptor, const ReadCallback& on_read_fd_ready_callback) {
-  return fdWatcher_p_->WatchFdForNonBlockingReads(file_descriptor,
-                                                  on_read_fd_ready_callback);
+int AsyncManager::WatchFdForNonBlockingReads(int file_descriptor, const ReadCallback& on_read_fd_ready_callback) {
+  return fdWatcher_p_->WatchFdForNonBlockingReads(file_descriptor, on_read_fd_ready_callback);
 }
 
 void AsyncManager::StopWatchingFileDescriptor(int file_descriptor) {
   fdWatcher_p_->StopWatchingFileDescriptor(file_descriptor);
 }
 
-AsyncTaskId AsyncManager::ExecAsync(std::chrono::milliseconds delay,
-                                    const TaskCallback& callback) {
+AsyncTaskId AsyncManager::ExecAsync(std::chrono::milliseconds delay, const TaskCallback& callback) {
   return taskManager_p_->ExecAsync(delay, callback);
 }
 
-AsyncTaskId AsyncManager::ExecAsyncPeriodically(
-    std::chrono::milliseconds delay, std::chrono::milliseconds period,
-    const TaskCallback& callback) {
+AsyncTaskId AsyncManager::ExecAsyncPeriodically(std::chrono::milliseconds delay, std::chrono::milliseconds period,
+                                                const TaskCallback& callback) {
   return taskManager_p_->ExecAsyncPeriodically(delay, period, callback);
 }
 
diff --git a/vendor_libs/test_vendor_lib/include/async_manager.h b/vendor_libs/test_vendor_lib/model/setup/async_manager.h
similarity index 93%
rename from vendor_libs/test_vendor_lib/include/async_manager.h
rename to vendor_libs/test_vendor_lib/model/setup/async_manager.h
index 1e94edf..e1ad888 100644
--- a/vendor_libs/test_vendor_lib/include/async_manager.h
+++ b/vendor_libs/test_vendor_lib/model/setup/async_manager.h
@@ -51,23 +51,20 @@
   // made about when in the future the callback will be called, in particular,
   // it is perfectly possible to have it called before this function returns. A
   // return of 0 means success, an error code is returned otherwise.
-  int WatchFdForNonBlockingReads(int file_descriptor,
-                                 const ReadCallback& on_read_fd_ready_callback);
+  int WatchFdForNonBlockingReads(int file_descriptor, const ReadCallback& on_read_fd_ready_callback);
 
   // If the fd was not being watched before the call will be ignored.
   void StopWatchingFileDescriptor(int file_descriptor);
 
   // Schedules an action to occur in the future. Even if the delay given is not
   // positive the callback will be called asynchronously.
-  AsyncTaskId ExecAsync(std::chrono::milliseconds delay,
-                        const TaskCallback& callback);
+  AsyncTaskId ExecAsync(std::chrono::milliseconds delay, const TaskCallback& callback);
 
   // Schedules an action to occur periodically in the future. If the delay given
   // is not positive the callback will be asynchronously called once for each
   // time in the past that it should have been called and then scheduled for
   // future times.
-  AsyncTaskId ExecAsyncPeriodically(std::chrono::milliseconds delay,
-                                    std::chrono::milliseconds period,
+  AsyncTaskId ExecAsyncPeriodically(std::chrono::milliseconds delay, std::chrono::milliseconds period,
                                     const TaskCallback& callback);
 
   // Cancels the/every future ocurrence of the action specified by this id. It
diff --git a/vendor_libs/test_vendor_lib/model/setup/device_boutique.cc b/vendor_libs/test_vendor_lib/model/setup/device_boutique.cc
new file mode 100644
index 0000000..18de1b1
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/device_boutique.cc
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "device_boutique"
+
+#include "device_boutique.h"
+
+#include "base/logging.h"
+#include "osi/include/log.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+std::unordered_map<std::string, std::function<std::shared_ptr<Device>()>>& DeviceBoutique::GetMap() {
+  static std::unordered_map<std::string, std::function<std::shared_ptr<Device>()>> impl;
+  return impl;
+}
+
+// Register a constructor for a device type.
+bool DeviceBoutique::Register(const std::string& device_type,
+                              const std::function<std::shared_ptr<Device>()> device_constructor) {
+  LOG_INFO(LOG_TAG, "Registering %s", device_type.c_str());
+  GetMap()[device_type] = device_constructor;
+  return true;
+}
+
+std::shared_ptr<Device> DeviceBoutique::Create(const vector<std::string>& args) {
+  CHECK(!args.empty());
+
+  if (GetMap().find(args[0]) == GetMap().end()) {
+    LOG_WARN(LOG_TAG, "No constructor registered for %s", args[0].c_str());
+    return std::shared_ptr<Device>(nullptr);
+  }
+
+  std::shared_ptr<Device> new_device = GetMap()[args[0]]();
+  if (new_device != nullptr) new_device->Initialize(args);
+
+  return new_device;
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/device_boutique.h b/vendor_libs/test_vendor_lib/model/setup/device_boutique.h
new file mode 100644
index 0000000..64137a0
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/device_boutique.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "model/devices/device.h"
+
+namespace test_vendor_lib {
+
+// Create customized devices from a centralized shop.
+class DeviceBoutique {
+ public:
+  DeviceBoutique();
+  virtual ~DeviceBoutique() = default;
+
+  // Register a constructor for a device type.
+  static bool Register(const std::string& device_type, const std::function<std::shared_ptr<Device>()> method);
+
+  // Call the constructor that matches arg[0], then call dev->Initialize(args).
+  static std::shared_ptr<Device> Create(const std::vector<std::string>& args);
+
+  template <typename D>
+  struct Registrar {
+    explicit Registrar(std::string const& name) {
+      DeviceBoutique::Register(name, &D::Create);
+    }
+    static Registrar<D> registrar_;
+  };
+
+ private:
+  static std::unordered_map<std::string, std::function<std::shared_ptr<Device>()>>& GetMap();
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer.h b/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
new file mode 100644
index 0000000..84e4cba
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include "include/phy.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+
+namespace test_vendor_lib {
+
+class PhyLayer {
+ public:
+  PhyLayer(Phy::Type phy_type, uint32_t id, const std::function<void(packets::LinkLayerPacketView)>& device_receive)
+      : phy_type_(phy_type), id_(id), transmit_to_device_(device_receive) {}
+
+  virtual void Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet) = 0;
+
+  virtual void Receive(packets::LinkLayerPacketView packet) = 0;
+
+  virtual void TimerTick() = 0;
+
+  Phy::Type GetType() {
+    return phy_type_;
+  }
+
+  uint32_t GetId() {
+    return id_;
+  }
+
+  virtual ~PhyLayer() = default;
+
+ private:
+  Phy::Type phy_type_;
+  uint32_t id_;
+
+ protected:
+  const std::function<void(packets::LinkLayerPacketView)> transmit_to_device_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
new file mode 100644
index 0000000..182416a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "phy_layer_factory"
+
+#include "phy_layer_factory.h"
+
+#include "base/logging.h"
+
+#include "osi/include/log.h"
+
+namespace test_vendor_lib {
+
+PhyLayerFactory::PhyLayerFactory(Phy::Type phy_type) : phy_type_(phy_type) {}
+
+Phy::Type PhyLayerFactory::GetType() {
+  return phy_type_;
+}
+
+std::shared_ptr<PhyLayer> PhyLayerFactory::GetPhyLayer(
+    const std::function<void(packets::LinkLayerPacketView)>& device_receive) {
+  std::shared_ptr<PhyLayer> new_phy =
+      std::make_shared<PhyLayerImpl>(phy_type_, next_id_++, device_receive, std::shared_ptr<PhyLayerFactory>(this));
+  phy_layers_.push_back(new_phy);
+  return new_phy;
+}
+
+void PhyLayerFactory::UnregisterPhyLayer(uint32_t id) {
+  for (auto it = phy_layers_.begin(); it != phy_layers_.end();) {
+    if ((*it)->GetId() == id) {
+      it = phy_layers_.erase(it);
+    } else {
+      it++;
+    }
+  }
+}
+
+void PhyLayerFactory::Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet, uint32_t id) {
+  // Convert from a Builder to a View
+  std::shared_ptr<std::vector<uint8_t>> serialized_packet =
+      std::shared_ptr<std::vector<uint8_t>>(new std::vector<uint8_t>());
+  std::back_insert_iterator<std::vector<uint8_t>> itr(*serialized_packet);
+  serialized_packet->reserve(packet->size());
+  packet->Serialize(itr);
+  packets::LinkLayerPacketView packet_view = packets::LinkLayerPacketView::Create(serialized_packet);
+
+  for (const auto phy : phy_layers_) {
+    if (id != phy->GetId()) {
+      phy->Receive(packet_view);
+    }
+  }
+}
+
+void PhyLayerFactory::TimerTick() {
+  for (auto phy : phy_layers_) {
+    phy->TimerTick();
+  }
+}
+
+std::string PhyLayerFactory::ToString() const {
+  switch (phy_type_) {
+    case Phy::Type::LOW_ENERGY:
+      return "LOW_ENERGY";
+      break;
+    case Phy::Type::BR_EDR:
+      return "BR_EDR";
+      break;
+    default:
+      return "Unknown";
+  }
+}
+
+PhyLayerImpl::PhyLayerImpl(Phy::Type phy_type, uint32_t id,
+                           const std::function<void(packets::LinkLayerPacketView)>& device_receive,
+                           const std::shared_ptr<PhyLayerFactory>& factory)
+    : PhyLayer(phy_type, id, device_receive), factory_(factory) {}
+
+PhyLayerImpl::~PhyLayerImpl() {
+  factory_->UnregisterPhyLayer(GetId());
+  PhyLayer::~PhyLayer();
+}
+
+void PhyLayerImpl::Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet) {
+  factory_->Send(packet, GetId());
+}
+
+void PhyLayerImpl::Receive(packets::LinkLayerPacketView packet) {
+  transmit_to_device_(packet);
+}
+
+void PhyLayerImpl::TimerTick() {}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
new file mode 100644
index 0000000..018ff78
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/phy_layer_factory.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <memory>
+#include <vector>
+
+#include "include/phy.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "phy_layer.h"
+
+namespace test_vendor_lib {
+
+class PhyLayerFactory {
+  friend class PhyLayerImpl;
+
+ public:
+  PhyLayerFactory(Phy::Type phy_type);
+
+  virtual ~PhyLayerFactory() = default;
+
+  Phy::Type GetType();
+
+  std::shared_ptr<PhyLayer> GetPhyLayer(const std::function<void(packets::LinkLayerPacketView)>& device_receive);
+
+  void UnregisterPhyLayer(uint32_t id);
+
+  virtual void TimerTick();
+
+  virtual std::string ToString() const;
+
+ protected:
+  virtual void Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet, uint32_t id);
+
+ private:
+  Phy::Type phy_type_;
+  std::vector<std::shared_ptr<PhyLayer>> phy_layers_;
+  uint32_t next_id_{1};
+};
+
+class PhyLayerImpl : public PhyLayer {
+ public:
+  PhyLayerImpl(Phy::Type phy_type, uint32_t id, const std::function<void(packets::LinkLayerPacketView)>& device_receive,
+               const std::shared_ptr<PhyLayerFactory>& factory);
+  virtual ~PhyLayerImpl() override;
+
+  virtual void Send(const std::shared_ptr<packets::LinkLayerPacketBuilder> packet) override;
+  virtual void Receive(packets::LinkLayerPacketView packet) override;
+  virtual void TimerTick() override;
+
+ private:
+  std::shared_ptr<PhyLayerFactory> factory_;
+};
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/test_channel_transport.cc b/vendor_libs/test_vendor_lib/model/setup/test_channel_transport.cc
similarity index 62%
copy from vendor_libs/test_vendor_lib/src/test_channel_transport.cc
copy to vendor_libs/test_vendor_lib/model/setup/test_channel_transport.cc
index 0d9bc2e..d291896 100644
--- a/vendor_libs/test_vendor_lib/src/test_channel_transport.cc
+++ b/vendor_libs/test_vendor_lib/model/setup/test_channel_transport.cc
@@ -46,8 +46,7 @@
   listen_address.sin_port = htons(port);
   listen_address.sin_addr.s_addr = htonl(INADDR_ANY);
 
-  if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address),
-           sockaddr_in_size) < 0) {
+  if (bind(listen_fd_, reinterpret_cast<sockaddr*>(&listen_address), sockaddr_in_size) < 0) {
     LOG_INFO(LOG_TAG, "Error binding test channel listener socket to address.");
     close(listen_fd_);
     return -1;
@@ -73,17 +72,11 @@
 
 int TestChannelTransport::Accept(int listen_fd_) {
   int accept_fd = -1;
-  struct sockaddr_in test_channel_address;
-  socklen_t sockaddr_in_size = sizeof(struct sockaddr_in);
-  memset(&test_channel_address, 0, sockaddr_in_size);
 
-  OSI_NO_INTR(accept_fd =
-                  accept(listen_fd_,
-                         reinterpret_cast<sockaddr*>(&test_channel_address),
-                         &sockaddr_in_size));
+  OSI_NO_INTR(accept_fd = accept(listen_fd_, NULL, NULL));
+
   if (accept_fd < 0) {
-    LOG_INFO(LOG_TAG, "Error accepting test channel connection errno=%d (%s).",
-             errno, strerror(errno));
+    LOG_INFO(LOG_TAG, "Error accepting test channel connection errno=%d (%s).", errno, strerror(errno));
 
     if (errno != EAGAIN && errno != EWOULDBLOCK) {
       LOG_ERROR(LOG_TAG, "Closing listen_fd_ (won't try again).");
@@ -97,16 +90,19 @@
   return accept_fd;
 }
 
-void TestChannelTransport::OnCommandReady(int fd,
-                                          std::function<void(void)> unwatch) {
+void TestChannelTransport::OnCommandReady(int fd, std::function<void(void)> unwatch) {
   uint8_t command_name_size = 0;
-  read(fd, &command_name_size, 1);
+  int bytes_read = read(fd, &command_name_size, 1);
+  if (bytes_read != 1) {
+    LOG_INFO(LOG_TAG, "Unexpected (command_name_size) bytes_read: %d != %d", bytes_read, 1);
+  }
   vector<uint8_t> command_name_raw;
   command_name_raw.resize(command_name_size);
-  read(fd, &command_name_raw[0], command_name_size);
+  bytes_read = read(fd, &command_name_raw[0], command_name_size);
+  if (bytes_read != command_name_size) {
+    LOG_INFO(LOG_TAG, "Unexpected (command_name) bytes_read: %d != %d", bytes_read, command_name_size);
+  }
   std::string command_name(command_name_raw.begin(), command_name_raw.end());
-  LOG_INFO(LOG_TAG, "Received command from test channel: %s",
-           command_name.data());
 
   if (command_name == "CLOSE_TEST_CHANNEL" || command_name == "") {
     LOG_INFO(LOG_TAG, "Test channel closed");
@@ -116,27 +112,45 @@
   }
 
   uint8_t num_args = 0;
-  read(fd, &num_args, 1);
-  LOG_INFO(LOG_TAG, "num_args: %d", num_args);
+  bytes_read = read(fd, &num_args, 1);
+  if (bytes_read != 1) {
+    LOG_INFO(LOG_TAG, "Unexpected (num_args) bytes_read: %d != %d", bytes_read, 1);
+  }
   vector<std::string> args;
   for (uint8_t i = 0; i < num_args; ++i) {
     uint8_t arg_size = 0;
-    read(fd, &arg_size, 1);
+    bytes_read = read(fd, &arg_size, 1);
+    if (bytes_read != 1) {
+      LOG_INFO(LOG_TAG, "Unexpected (arg_size) bytes_read: %d != %d", bytes_read, 1);
+    }
     vector<uint8_t> arg;
     arg.resize(arg_size);
-    read(fd, &arg[0], arg_size);
+    bytes_read = read(fd, &arg[0], arg_size);
+    if (bytes_read != arg_size) {
+      LOG_INFO(LOG_TAG, "Unexpected (arg) bytes_read: %d != %d", bytes_read, arg_size);
+    }
     args.push_back(std::string(arg.begin(), arg.end()));
   }
 
-  for (size_t i = 0; i < args.size(); ++i)
-    LOG_INFO(LOG_TAG, "Command argument %zu: %s", i, args[i].data());
-
   command_handler_(command_name, args);
 }
 
+void TestChannelTransport::SendResponse(int fd, const std::string& response) const {
+  size_t size = response.size();
+  // Cap to 64K
+  if (size > 0xffff) {
+    size = 0xffff;
+  }
+  uint8_t size_buf[4] = {static_cast<uint8_t>(size & 0xff), static_cast<uint8_t>((size >> 8) & 0xff),
+                         static_cast<uint8_t>((size >> 16) & 0xff), static_cast<uint8_t>((size >> 24) & 0xff)};
+  int written = write(fd, size_buf, 4);
+  CHECK(written == 4) << "What happened? written = " << written << "errno =" << errno;
+  written = write(fd, response.c_str(), size);
+  CHECK(written == static_cast<int>(size)) << "What happened? written = " << written << "errno =" << errno;
+}
+
 void TestChannelTransport::RegisterCommandHandler(
-    const std::function<void(const std::string&, const vector<std::string>&)>&
-        callback) {
+    const std::function<void(const std::string&, const std::vector<std::string>&)>& callback) {
   command_handler_ = callback;
 }
 
diff --git a/vendor_libs/test_vendor_lib/include/test_channel_transport.h b/vendor_libs/test_vendor_lib/model/setup/test_channel_transport.h
similarity index 85%
rename from vendor_libs/test_vendor_lib/include/test_channel_transport.h
rename to vendor_libs/test_vendor_lib/model/setup/test_channel_transport.h
index 069f91e..e9b390f 100644
--- a/vendor_libs/test_vendor_lib/include/test_channel_transport.h
+++ b/vendor_libs/test_vendor_lib/model/setup/test_channel_transport.h
@@ -21,7 +21,7 @@
 #include <string>
 #include <vector>
 
-#include "base/files/scoped_file.h"
+//#include "base/files/scoped_file.h"
 
 namespace test_vendor_lib {
 
@@ -46,15 +46,15 @@
   int Accept(int listen_fd);
 
   // Sets the callback that fires when data is read in WatchFd().
-  void RegisterCommandHandler(
-      const std::function<void(const std::string&,
-                               const std::vector<std::string>&)>& callback);
+  void RegisterCommandHandler(const std::function<void(const std::string&, const std::vector<std::string>&)>& callback);
+
+  // Send data back to the test channel.
+  void SendResponse(int fd, const std::string&) const;
 
   void OnCommandReady(int fd, std::function<void(void)> unwatch);
 
  private:
-  std::function<void(const std::string&, const std::vector<std::string>&)>
-      command_handler_;
+  std::function<void(const std::string&, const std::vector<std::string>&)> command_handler_;
 
   int listen_fd_ = -1;
 
diff --git a/vendor_libs/test_vendor_lib/model/setup/test_command_handler.cc b/vendor_libs/test_vendor_lib/model/setup/test_command_handler.cc
new file mode 100644
index 0000000..ad8689d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/test_command_handler.cc
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "test_command_handler"
+
+#include "test_command_handler.h"
+#include "device_boutique.h"
+#include "phy.h"
+
+#include <memory>
+
+#include <stdlib.h>
+
+#include <base/logging.h>
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/values.h"
+
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+TestCommandHandler::TestCommandHandler(TestModel& test_model) : model_(test_model) {
+#define SET_HANDLER(command_name, method) \
+  active_commands_[command_name] = [this](const vector<std::string>& param) { method(param); };
+  SET_HANDLER("add", Add);
+  SET_HANDLER("add_remote", AddRemote);
+  SET_HANDLER("del", Del);
+  SET_HANDLER("add_phy", AddPhy);
+  SET_HANDLER("del_phy", DelPhy);
+  SET_HANDLER("add_device_to_phy", AddDeviceToPhy);
+  SET_HANDLER("del_device_from_phy", DelDeviceFromPhy);
+  SET_HANDLER("list", List);
+  SET_HANDLER("set_timer_period", SetTimerPeriod);
+  SET_HANDLER("start_timer", StartTimer);
+  SET_HANDLER("stop_timer", StopTimer);
+#undef SET_HANDLER
+}
+
+void TestCommandHandler::AddDefaults() {
+  // Add a phy for LE and one for BR/EDR
+  AddPhy({"LOW_ENERGY"});
+  AddPhy({"BR_EDR"});
+
+  // Add the controller to the Phys
+  AddDeviceToPhy({"0", "0"});
+  AddDeviceToPhy({"0", "1"});
+
+  // Add default test devices and add the devices to the phys
+  // Add({"beacon", "be:ac:10:00:00:01", "1000"});
+  // AddDeviceToPhy({"1", "0"});
+
+  // Add({"keyboard", "cc:1c:eb:0a:12:d1", "500"});
+  // AddDeviceToPhy({"2", "0"});
+
+  // Add({"classic", "c1:a5:51:c0:00:01", "22"});
+  // AddDeviceToPhy({"3", "1"});
+
+  // Add({"car_kit", "ca:12:1c:17:00:01", "238"});
+  // AddDeviceToPhy({"4", "1"});
+
+  // Add({"sniffer", "ca:12:1c:17:00:01"});
+  // AddDeviceToPhy({"5", "1"});
+
+  // Add({"sniffer", "3c:5a:b4:04:05:06"});
+  // AddDeviceToPhy({"1", "1"});
+  // Add({"remote_loopback_device", "10:0d:00:ba:c1:06"});
+  // AddDeviceToPhy({"2", "1"});
+  List({});
+
+  SetTimerPeriod({"10"});
+  StartTimer({});
+}
+
+void TestCommandHandler::HandleCommand(const std::string& name, const vector<std::string>& args) {
+  if (active_commands_.count(name) == 0) {
+    response_string_ = "Unhandled command: " + name;
+    send_response_(response_string_);
+    return;
+  }
+  active_commands_[name](args);
+}
+
+void TestCommandHandler::RegisterSendResponse(const std::function<void(const std::string&)> callback) {
+  send_response_ = callback;
+  send_response_("RegisterSendResponse called");
+}
+
+void TestCommandHandler::Add(const vector<std::string>& args) {
+  if (args.size() < 1) {
+    response_string_ = "TestCommandHandler 'add' takes an argument";
+    send_response_(response_string_);
+    return;
+  }
+  std::shared_ptr<Device> new_dev = DeviceBoutique::Create(args);
+
+  if (new_dev == NULL) {
+    response_string_ = "TestCommandHandler 'add' " + args[0] + " failed!";
+    send_response_(response_string_);
+    LOG_WARN(LOG_TAG, "%s", response_string_.c_str());
+    return;
+  }
+
+  LOG_INFO(LOG_TAG, "Add %s", new_dev->ToString().c_str());
+  size_t dev_index = model_.Add(new_dev);
+  response_string_ = std::to_string(dev_index) + std::string(":") + new_dev->ToString();
+  send_response_(response_string_);
+}
+
+void TestCommandHandler::AddRemote(const vector<std::string>& args) {
+  if (args.size() < 3) {
+    response_string_ = "TestCommandHandler usage: add_remote host port phy_type";
+    send_response_(response_string_);
+    return;
+  }
+
+  size_t port = std::stoi(args[1]);
+  Phy::Type phy_type = Phy::Type::BR_EDR;
+  if ("LOW_ENERGY" == args[2]) {
+    phy_type = Phy::Type::LOW_ENERGY;
+  }
+  if (port == 0 || port > 0xffff || args[0].size() < 2) {
+    response_string_ = "TestCommandHandler bad arguments to 'add_remote': ";
+    response_string_ += args[0];
+    response_string_ += "@";
+    response_string_ += args[1];
+    send_response_(response_string_);
+    return;
+  }
+
+  model_.AddRemote(args[0], port, phy_type);
+
+  response_string_ = args[0] + std::string("@") + std::to_string(port);
+  send_response_(response_string_);
+}
+
+void TestCommandHandler::Del(const vector<std::string>& args) {
+  size_t dev_index = std::stoi(args[0]);
+
+  model_.Del(dev_index);
+  response_string_ = "TestCommandHandler 'del' called with device at index " + std::to_string(dev_index);
+  send_response_(response_string_);
+}
+
+void TestCommandHandler::AddPhy(const vector<std::string>& args) {
+  if (args[0] == "LOW_ENERGY") {
+    std::shared_ptr<PhyLayerFactory> new_phy = std::make_shared<PhyLayerFactory>(Phy::Type::LOW_ENERGY);
+    model_.AddPhy(new_phy);
+  } else if (args[0] == "BR_EDR") {
+    std::shared_ptr<PhyLayerFactory> new_phy = std::make_shared<PhyLayerFactory>(Phy::Type::BR_EDR);
+    model_.AddPhy(new_phy);
+  } else {
+    response_string_ = "TestCommandHandler 'add_phy' with unrecognized type " + args[0];
+    send_response_(response_string_);
+  }
+}
+
+void TestCommandHandler::DelPhy(const vector<std::string>& args) {
+  size_t phy_index = std::stoi(args[0]);
+
+  model_.DelPhy(phy_index);
+  response_string_ = "TestCommandHandler 'del_phy' called with phy at index " + std::to_string(phy_index);
+  send_response_(response_string_);
+}
+
+void TestCommandHandler::AddDeviceToPhy(const vector<std::string>& args) {
+  if (args.size() != 2) {
+    response_string_ = "TestCommandHandler 'add_device_to_phy' takes two arguments";
+    send_response_(response_string_);
+    return;
+  }
+  size_t dev_index = std::stoi(args[0]);
+  size_t phy_index = std::stoi(args[1]);
+  model_.AddDeviceToPhy(dev_index, phy_index);
+  response_string_ = "TestCommandHandler 'add_device_to_phy' called with device " + std::to_string(dev_index) +
+                     " and phy " + std::to_string(phy_index);
+  send_response_(response_string_);
+  return;
+}
+
+void TestCommandHandler::DelDeviceFromPhy(const vector<std::string>& args) {
+  if (args.size() != 2) {
+    response_string_ = "TestCommandHandler 'del_device_from_phy' takes two arguments";
+    send_response_(response_string_);
+    return;
+  }
+  size_t dev_index = std::stoi(args[0]);
+  size_t phy_index = std::stoi(args[1]);
+  model_.DelDeviceFromPhy(dev_index, phy_index);
+  response_string_ = "TestCommandHandler 'del_device_from_phy' called with device " + std::to_string(dev_index) +
+                     " and phy " + std::to_string(phy_index);
+  send_response_(response_string_);
+  return;
+}
+
+void TestCommandHandler::List(const vector<std::string>& args) {
+  if (args.size() > 0) {
+    LOG_INFO(LOG_TAG, "Unused args: arg[0] = %s", args[0].c_str());
+    return;
+  }
+  send_response_(model_.List());
+}
+
+void TestCommandHandler::SetTimerPeriod(const vector<std::string>& args) {
+  if (args.size() != 1) {
+    LOG_INFO(LOG_TAG, "SetTimerPeriod takes 1 argument");
+  }
+  size_t period = std::stoi(args[0]);
+  model_.SetTimerPeriod(std::chrono::milliseconds(period));
+}
+
+void TestCommandHandler::StartTimer(const vector<std::string>& args) {
+  if (args.size() > 0) {
+    LOG_INFO(LOG_TAG, "Unused args: arg[0] = %s", args[0].c_str());
+  }
+  model_.StartTimer();
+}
+
+void TestCommandHandler::StopTimer(const vector<std::string>& args) {
+  if (args.size() > 0) {
+    LOG_INFO(LOG_TAG, "Unused args: arg[0] = %s", args[0].c_str());
+  }
+  model_.StopTimer();
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/test_command_handler.h b/vendor_libs/test_vendor_lib/model/setup/test_command_handler.h
new file mode 100644
index 0000000..409966a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/test_command_handler.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "model/devices/device.h"
+#include "phy_layer_factory.h"
+#include "test_channel_transport.h"
+#include "test_model.h"
+
+namespace test_vendor_lib {
+
+class TestCommandHandler {
+ public:
+  // Sets all of the methods to be used as callbacks in the HciHandler.
+  TestCommandHandler(TestModel& test_model);
+
+  ~TestCommandHandler() = default;
+
+  // Dispatches the action corresponding to the command specified by |name|.
+  void HandleCommand(const std::string& name, const std::vector<std::string>& args);
+
+  // Dispatches the action corresponding to the command specified by |name|.
+  void RegisterSendResponse(const std::function<void(const std::string&)> callback);
+
+  // Commands:
+
+  // Add a device
+  void Add(const std::vector<std::string>& args);
+
+  // Add a remote device
+  void AddRemote(const std::vector<std::string>& args);
+
+  // Remove devices by index
+  void Del(const std::vector<std::string>& args);
+
+  // Add phy
+  void AddPhy(const std::vector<std::string>& args);
+
+  // Remove phy by name
+  void DelPhy(const std::vector<std::string>& args);
+
+  // Add device to phy
+  void AddDeviceToPhy(const std::vector<std::string>& args);
+
+  // Remove device from phy
+  void DelDeviceFromPhy(const std::vector<std::string>& args);
+
+  // List the devices that the test knows about
+  void List(const std::vector<std::string>& args);
+
+  // Timer management functions
+  void SetTimerPeriod(const std::vector<std::string>& args);
+
+  void StartTimer(const std::vector<std::string>& args);
+
+  void StopTimer(const std::vector<std::string>& args);
+
+  // For manual testing
+  void AddDefaults();
+
+ private:
+  TestModel& model_;
+
+  std::string response_string_;
+
+  std::unordered_map<std::string, std::function<void(const std::vector<std::string>&)>> active_commands_;
+
+  std::function<void(const std::string&)> send_response_;
+
+  TestCommandHandler(const TestCommandHandler& cmdPckt) = delete;
+  TestCommandHandler& operator=(const TestCommandHandler& cmdPckt) = delete;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/test_model.cc b/vendor_libs/test_vendor_lib/model/setup/test_model.cc
new file mode 100644
index 0000000..3572761
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/test_model.cc
@@ -0,0 +1,209 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "test_model"
+
+#include "test_model.h"
+
+// TODO: Remove when registration works
+#include "model/devices/beacon.h"
+#include "model/devices/beacon_swarm.h"
+#include "model/devices/car_kit.h"
+#include "model/devices/classic.h"
+#include "model/devices/keyboard.h"
+#include "model/devices/remote_loopback_device.h"
+#include "model/devices/sniffer.h"
+
+#include <memory>
+
+#include <stdlib.h>
+
+#include <base/logging.h>
+#include "base/files/file_util.h"
+#include "base/json/json_reader.h"
+#include "base/values.h"
+
+#include "osi/include/log.h"
+#include "osi/include/osi.h"
+
+#include "device_boutique.h"
+#include "include/phy.h"
+#include "model/devices/hci_socket_device.h"
+#include "model/devices/link_layer_socket_device.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+TestModel::TestModel(
+    std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> event_scheduler,
+
+    std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+        periodic_event_scheduler,
+
+    std::function<void(AsyncTaskId)> cancel, std::function<int(const std::string&, int)> connect_to_remote)
+    : schedule_task_(event_scheduler), schedule_periodic_task_(periodic_event_scheduler), cancel_task_(cancel),
+      connect_to_remote_(connect_to_remote) {
+  // TODO: Remove when registration works!
+  example_devices_.push_back(std::make_shared<Beacon>());
+  example_devices_.push_back(std::make_shared<BeaconSwarm>());
+  example_devices_.push_back(std::make_shared<Keyboard>());
+  example_devices_.push_back(std::make_shared<CarKit>());
+  example_devices_.push_back(std::make_shared<Classic>());
+  example_devices_.push_back(std::make_shared<Sniffer>());
+  example_devices_.push_back(std::make_shared<RemoteLoopbackDevice>());
+}
+
+void TestModel::SetTimerPeriod(std::chrono::milliseconds new_period) {
+  timer_period_ = new_period;
+
+  if (timer_tick_task_ == kInvalidTaskId) return;
+
+  // Restart the timer with the new period
+  StopTimer();
+  StartTimer();
+}
+
+void TestModel::StartTimer() {
+  LOG_INFO(LOG_TAG, "StartTimer()");
+  timer_tick_task_ =
+      schedule_periodic_task_(std::chrono::milliseconds(0), timer_period_, [this]() { TestModel::TimerTick(); });
+}
+
+void TestModel::StopTimer() {
+  LOG_INFO(LOG_TAG, "StopTimer()");
+  cancel_task_(timer_tick_task_);
+  timer_tick_task_ = kInvalidTaskId;
+}
+
+size_t TestModel::Add(std::shared_ptr<Device> new_dev) {
+  devices_.push_back(new_dev);
+  return devices_.size() - 1;
+}
+
+void TestModel::Del(size_t dev_index) {
+  if (dev_index >= devices_.size()) {
+    LOG_WARN(LOG_TAG, "del: index out of range!");
+    return;
+  }
+  devices_.erase(devices_.begin() + dev_index);
+}
+
+size_t TestModel::AddPhy(std::shared_ptr<PhyLayerFactory> new_phy) {
+  phys_.push_back(new_phy);
+  return phys_.size() - 1;
+}
+
+void TestModel::DelPhy(size_t phy_index) {
+  if (phy_index >= phys_.size()) {
+    LOG_WARN(LOG_TAG, "del_phy: index %d out of range: ", static_cast<int>(phy_index));
+    return;
+  }
+}
+
+void TestModel::AddDeviceToPhy(size_t dev_index, size_t phy_index) {
+  if (dev_index >= devices_.size()) {
+    LOG_WARN(LOG_TAG, "add_device_to_phy: device out of range: ");
+    return;
+  }
+  if (phy_index >= phys_.size()) {
+    LOG_WARN(LOG_TAG, "add_device_to_phy: phy out of range: ");
+    return;
+  }
+  std::shared_ptr<Device> dev = devices_[dev_index];
+  dev->RegisterPhyLayer(
+      phys_[phy_index]->GetPhyLayer([dev](packets::LinkLayerPacketView packet) { dev->IncomingPacket(packet); }));
+}
+
+void TestModel::DelDeviceFromPhy(size_t dev_index, size_t phy_index) {
+  if (dev_index >= devices_.size()) {
+    LOG_WARN(LOG_TAG, "del_device_from_phy: device out of range: ");
+    return;
+  }
+  if (phy_index >= phys_.size()) {
+    LOG_WARN(LOG_TAG, "del_device_from_phy: phy out of range: ");
+    return;
+  }
+}
+
+void TestModel::AddLinkLayerConnection(int socket_fd, Phy::Type phy_type) {
+  std::shared_ptr<Device> dev = LinkLayerSocketDevice::Create(socket_fd, phy_type);
+  int index = Add(dev);
+  for (size_t phy_index = 0; phy_index < phys_.size(); phy_index++) {
+    if (phy_type == phys_[phy_index]->GetType()) {
+      AddDeviceToPhy(index, phy_index);
+    }
+  }
+}
+
+void TestModel::IncomingLinkLayerConnection(int socket_fd) {
+  // TODO: Handle other phys
+  AddLinkLayerConnection(socket_fd, Phy::Type::BR_EDR);
+}
+
+void TestModel::AddRemote(const std::string& server, int port, Phy::Type phy_type) {
+  int socket_fd = connect_to_remote_(server, port);
+  if (socket_fd < 0) {
+    return;
+  }
+  AddLinkLayerConnection(socket_fd, phy_type);
+}
+
+void TestModel::IncomingHciConnection(int socket_fd) {
+  std::shared_ptr<HciSocketDevice> dev = HciSocketDevice::Create(socket_fd);
+  // TODO: Auto-increment addresses?
+  static int hci_devs = 0;
+  int index = Add(std::static_pointer_cast<Device>(dev));
+  std::string addr = "da:4c:10:de:17:0";  // Da HCI dev
+  CHECK(hci_devs < 10) << "Why do you need more than 9?";
+  addr += '0' + hci_devs++;
+  dev->Initialize({"IgnoredTypeName", addr});
+  // TODO: Add device to all phys?  For now, just the first two.
+  for (size_t phy = 0; phy < 2 && phy < phys_.size(); phy++) {
+    AddDeviceToPhy(index, phy);
+  }
+  dev->RegisterTaskScheduler(schedule_task_);
+  dev->RegisterTaskCancel(cancel_task_);
+}
+
+const std::string& TestModel::List() {
+  list_string_ = "";
+  list_string_ += " Devices: \r\n";
+  for (size_t dev = 0; dev < devices_.size(); dev++) {
+    list_string_ += "  " + std::to_string(dev) + ":";
+    list_string_ += devices_[dev]->ToString() + " \r\n";
+  }
+  list_string_ += " Phys: \r\n";
+  for (size_t phy = 0; phy < phys_.size(); phy++) {
+    list_string_ += "  " + std::to_string(phy) + ":";
+    list_string_ += phys_[phy]->ToString() + " \r\n";
+  }
+  return list_string_;
+}
+
+void TestModel::TimerTick() {
+  for (size_t dev = 0; dev < devices_.size(); dev++) {
+    devices_[dev]->TimerTick();
+  }
+}
+
+void TestModel::Reset() {
+  StopTimer();
+  devices_.clear();
+  phys_.clear();
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/model/setup/test_model.h b/vendor_libs/test_vendor_lib/model/setup/test_model.h
new file mode 100644
index 0000000..c799f3f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/model/setup/test_model.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <unordered_map>
+#include <vector>
+
+#include "async_manager.h"
+#include "model/devices/device.h"
+#include "phy_layer_factory.h"
+#include "test_channel_transport.h"
+
+namespace test_vendor_lib {
+
+class TestModel {
+ public:
+  TestModel(std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> evtScheduler,
+            std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+                periodicEvtScheduler,
+            std::function<void(AsyncTaskId)> cancel, std::function<int(const std::string&, int)> connect_to_remote);
+  ~TestModel() = default;
+
+  // Commands:
+
+  // Add a device, return its index
+  size_t Add(std::shared_ptr<Device> device);
+
+  // Remove devices by index
+  void Del(size_t device_index);
+
+  // Add phy, return its index
+  size_t AddPhy(std::shared_ptr<PhyLayerFactory> phy);
+
+  // Remove phy by index
+  void DelPhy(size_t phy_index);
+
+  // Add device to phy
+  void AddDeviceToPhy(size_t device_index, size_t phy_index);
+
+  // Remove device from phy
+  void DelDeviceFromPhy(size_t device_index, size_t phy_index);
+
+  // Handle incoming remote connections
+  void AddLinkLayerConnection(int socket_fd, Phy::Type phy_type);
+  void IncomingLinkLayerConnection(int socket_fd);
+  void IncomingHciConnection(int socket_fd);
+
+  // Connect to a remote device
+  void AddRemote(const std::string& server, int port, Phy::Type phy_type);
+
+  // Let devices know about the passage of time
+  void TimerTick();
+  void StartTimer();
+  void StopTimer();
+  void SetTimerPeriod(std::chrono::milliseconds new_period);
+
+  // List the devices that the test knows about
+  const std::string& List();
+
+  // Clear all devices and phys.
+  void Reset();
+
+ private:
+  std::vector<std::shared_ptr<PhyLayerFactory>> phys_;
+  std::vector<std::shared_ptr<Device>> devices_;
+  std::string list_string_;
+
+  // Callbacks to schedule tasks.
+  std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)> schedule_task_;
+  std::function<AsyncTaskId(std::chrono::milliseconds, std::chrono::milliseconds, const TaskCallback&)>
+      schedule_periodic_task_;
+  std::function<void(AsyncTaskId)> cancel_task_;
+  std::function<int(const std::string&, int)> connect_to_remote_;
+
+  AsyncTaskId timer_tick_task_{kInvalidTaskId};
+  std::chrono::milliseconds timer_period_;
+
+  TestModel(TestModel& model) = delete;
+  TestModel& operator=(const TestModel& model) = delete;
+
+  std::vector<std::shared_ptr<Device>> example_devices_;
+};
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/Android.bp b/vendor_libs/test_vendor_lib/packets/Android.bp
new file mode 100644
index 0000000..8a73a64
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/Android.bp
@@ -0,0 +1,83 @@
+// packet library for libbt-rootcanal
+// ========================================================
+cc_library_static {
+    name: "libbt-rootcanal-packets",
+    defaults: [
+        "libchrome_support_defaults",
+        "clang_file_coverage",
+    ],
+    host_supported: true,
+    proprietary: true,
+    srcs: [
+        "iterator.cc",
+        "counted_builder.cc",
+        "packet_view.cc",
+        "raw_builder.cc",
+        "view.cc",
+        "hci/acl_packet_builder.cc",
+        "hci/acl_packet_view.cc",
+        "hci/command_packet_builder.cc",
+        "hci/command_packet_view.cc",
+        "hci/event_packet_builder.cc",
+        "hci/event_payload_builder.cc",
+        "hci/hci_packet_builder.cc",
+        "hci/le_meta_event_builder.cc",
+        "hci/sco_packet_builder.cc",
+        "hci/sco_packet_view.cc",
+        "link_layer/link_layer_packet_builder.cc",
+        "link_layer/link_layer_packet_view.cc",
+    ],
+    cflags: [
+        "-fvisibility=hidden",
+    ],
+    local_include_dirs: [
+        ".",
+    ],
+    export_include_dirs: ["."],
+    include_dirs: [
+        "system/bt/vendor_libs/test_vendor_lib/include",
+        "system/bt/vendor_libs/test_vendor_lib/",
+        "system/bt/",
+    ],
+    shared_libs: [
+        "libbase",
+        "liblog",
+    ],
+}
+
+// Unit tests for the host
+// ========================================================
+cc_test_host {
+    name: "rootcanal-packets_test_host",
+    defaults: [
+        "libchrome_support_defaults",
+        "clang_file_coverage",
+        "clang_coverage_bin",
+    ],
+    srcs: [
+        "test/link_layer_packet_builder_test.cc",
+        "test/packet_builder_test.cc",
+        "test/packet_view_test.cc",
+        "hci/test/acl_builder_test.cc",
+        "hci/test/event_builder_test.cc",
+    ],
+    header_libs: [
+        "libbluetooth_headers",
+    ],
+    local_include_dirs: [
+        ".",
+    ],
+    include_dirs: [
+        "system/bt",
+        "system/bt/hci/include",
+        "system/bt/vendor_libs/test_vendor_lib",
+        "system/bt/vendor_libs/test_vendor_lib/include",
+    ],
+    shared_libs: [
+        "liblog",
+    ],
+    static_libs: [
+        "libbt-rootcanal-types",
+        "libbt-rootcanal-packets",
+    ],
+}
diff --git a/vendor_libs/test_vendor_lib/packets/base_packet_builder.h b/vendor_libs/test_vendor_lib/packets/base_packet_builder.h
new file mode 100644
index 0000000..92ae3a9
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/base_packet_builder.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+namespace test_vendor_lib {
+namespace packets {
+
+// A little-endian PacketBuilder might contain a big-endian PacketBuilder,
+// so BasePacketBuilder provides a common base class.
+class BasePacketBuilder {
+ public:
+  virtual ~BasePacketBuilder() = default;
+
+  virtual size_t size() const = 0;
+
+  // Write to the vector with the given iterator.
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const = 0;
+
+ protected:
+  BasePacketBuilder() = default;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/counted_builder.cc b/vendor_libs/test_vendor_lib/packets/counted_builder.cc
new file mode 100644
index 0000000..10d3ceb
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/counted_builder.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "counted_builder.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+namespace packets {
+
+size_t CountedBuilder::size() const {
+  size_t payload_size = sizeof(uint8_t);
+  for (size_t i = 0; i < sub_builders_.size(); i++) {
+    payload_size += sub_builders_[i]->size();
+  }
+  return payload_size;
+}
+
+void CountedBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint8_t>(sub_builders_.size()), it);
+  for (size_t i = 0; i < sub_builders_.size(); i++) {
+    sub_builders_[i]->Serialize(it);
+  }
+}
+
+void CountedBuilder::Add(std::unique_ptr<BasePacketBuilder> builder) {
+  sub_builders_.push_back(std::move(builder));
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/counted_builder.h b/vendor_libs/test_vendor_lib/packets/counted_builder.h
new file mode 100644
index 0000000..fed88c5
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/counted_builder.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+#include <memory>
+#include <vector>
+
+#include "packets/base_packet_builder.h"
+#include "packets/packet_builder.h"
+#include "packets/raw_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class CountedBuilder : public RawBuilder {
+ public:
+  CountedBuilder() = default;
+  virtual ~CountedBuilder() = default;
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
+
+  void Add(std::unique_ptr<BasePacketBuilder> builder);
+
+ private:
+  std::vector<std::unique_ptr<BasePacketBuilder>> sub_builders_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.cc
new file mode 100644
index 0000000..00b0ba8
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.cc
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/acl_packet_builder.h"
+
+#include <base/logging.h>
+
+using std::vector;
+using test_vendor_lib::acl::BroadcastFlagsType;
+using test_vendor_lib::acl::PacketBoundaryFlagsType;
+
+namespace test_vendor_lib {
+namespace packets {
+
+AclPacketBuilder::AclPacketBuilder(uint16_t handle, PacketBoundaryFlagsType packet_boundary_flags,
+                                   BroadcastFlagsType broadcast_flags, std::unique_ptr<BasePacketBuilder> payload)
+    : handle_(handle), packet_boundary_flags_(packet_boundary_flags), broadcast_flags_(broadcast_flags),
+      payload_(std::move(payload)) {}
+
+std::unique_ptr<AclPacketBuilder> AclPacketBuilder::Create(uint16_t handle,
+                                                           PacketBoundaryFlagsType packet_boundary_flags,
+                                                           BroadcastFlagsType broadcast_flags,
+                                                           std::unique_ptr<BasePacketBuilder> payload) {
+  return std::unique_ptr<AclPacketBuilder>(
+      new AclPacketBuilder(handle, packet_boundary_flags, broadcast_flags, std::move(payload)));
+}
+
+size_t AclPacketBuilder::size() const {
+  return 2 * sizeof(uint16_t) + payload_->size();
+}
+
+void AclPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint16_t>((handle_ & 0xfff) | (static_cast<uint16_t>(packet_boundary_flags_) << 12) |
+                               (static_cast<uint16_t>(broadcast_flags_) << 14)),
+         it);
+  uint16_t payload_size = payload_->size();
+
+  CHECK(static_cast<size_t>(payload_size) == payload_->size())
+      << "Payload too large for an ACL packet: " << payload_->size();
+  insert(payload_size, it);
+  payload_->Serialize(it);
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.h
new file mode 100644
index 0000000..cd2a607
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_builder.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "include/acl.h"
+#include "packets/hci/hci_packet_builder.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// ACL data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.2
+class AclPacketBuilder : public HciPacketBuilder {
+ public:
+  virtual ~AclPacketBuilder() override = default;
+
+  static std::unique_ptr<AclPacketBuilder> Create(uint16_t handle, acl::PacketBoundaryFlagsType packet_boundary_flags,
+                                                  acl::BroadcastFlagsType broadcast_flags,
+                                                  std::unique_ptr<BasePacketBuilder> payload);
+
+  virtual size_t size() const override;
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const;
+
+ private:
+  AclPacketBuilder(uint16_t handle, acl::PacketBoundaryFlagsType packet_boundary_flags,
+                   acl::BroadcastFlagsType broadcast_flags, std::unique_ptr<BasePacketBuilder> payload);
+  AclPacketBuilder() = delete;
+  uint16_t handle_;
+  acl::PacketBoundaryFlagsType packet_boundary_flags_;
+  acl::BroadcastFlagsType broadcast_flags_;
+  std::unique_ptr<BasePacketBuilder> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.cc b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.cc
new file mode 100644
index 0000000..bfec835e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.cc
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/acl_packet_view.h"
+
+#include <base/logging.h>
+
+using std::vector;
+using test_vendor_lib::acl::BroadcastFlagsType;
+using test_vendor_lib::acl::PacketBoundaryFlagsType;
+
+namespace test_vendor_lib {
+namespace packets {
+
+AclPacketView::AclPacketView(std::shared_ptr<std::vector<uint8_t>> packet) : PacketView<true>(packet) {}
+
+AclPacketView::AclPacketView(PacketView<true> packet_view) : PacketView<true>(packet_view) {}
+
+AclPacketView AclPacketView::Create(std::shared_ptr<std::vector<uint8_t>> packet) {
+  return AclPacketView(packet);
+}
+
+AclPacketView AclPacketView::Create(PacketView<true> packet_view) {
+  return AclPacketView(packet_view);
+}
+
+uint16_t AclPacketView::GetHandle() const {
+  return begin().extract<uint16_t>() & 0xfff;
+}
+
+PacketBoundaryFlagsType AclPacketView::GetPacketBoundaryFlags() const {
+  return static_cast<PacketBoundaryFlagsType>(((begin() + 1).extract<uint8_t>() & 0x30) >> 4);
+}
+
+BroadcastFlagsType AclPacketView::GetBroadcastFlags() const {
+  return static_cast<BroadcastFlagsType>(((begin() + 1).extract<uint8_t>() & 0xc0) >> 6);
+}
+
+PacketView<true> AclPacketView::GetPayload() const {
+  uint16_t payload_size = (begin() + sizeof(uint16_t)).extract<uint16_t>();
+  CHECK(static_cast<uint16_t>(size() - 2 * sizeof(uint16_t)) == payload_size)
+      << "Malformed ACL packet payload_size " << payload_size << " + 4 != " << size();
+  return SubViewLittleEndian(2 * sizeof(uint16_t), size());
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.h b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.h
new file mode 100644
index 0000000..1e69cda
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/acl_packet_view.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "include/acl.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// ACL data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.2
+class AclPacketView : public PacketView<true> {
+ public:
+  virtual ~AclPacketView() override = default;
+
+  static AclPacketView Create(std::shared_ptr<std::vector<uint8_t>> packet);
+  static AclPacketView Create(PacketView<true> packet_view);
+
+  uint16_t GetHandle() const;
+  acl::PacketBoundaryFlagsType GetPacketBoundaryFlags() const;
+  acl::BroadcastFlagsType GetBroadcastFlags() const;
+  PacketView<true> GetPayload() const;
+
+ private:
+  AclPacketView(std::shared_ptr<std::vector<uint8_t>> packet);
+  AclPacketView(PacketView<true> packet_view);
+  AclPacketView() = delete;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/command_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/command_packet_builder.cc
new file mode 100644
index 0000000..7074309
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/command_packet_builder.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/command_packet_builder.h"
+
+#include <base/logging.h>
+
+using std::vector;
+using test_vendor_lib::hci::OpCode;
+
+namespace test_vendor_lib {
+namespace packets {
+
+CommandPacketBuilder::CommandPacketBuilder(OpCode opcode, std::unique_ptr<BasePacketBuilder> payload)
+    : opcode_(opcode), payload_(std::move(payload)) {}
+
+size_t CommandPacketBuilder::size() const {
+  return sizeof(uint16_t) + sizeof(uint8_t) + payload_->size();
+}
+
+void CommandPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint16_t>(opcode_), it);
+  uint8_t payload_size = static_cast<uint8_t>(payload_->size());
+
+  CHECK(static_cast<size_t>(payload_size) == payload_->size())
+      << "Payload too large for a command packet: " << payload_->size();
+  insert(payload_size, it);
+  payload_->Serialize(it);
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/command_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/command_packet_builder.h
new file mode 100644
index 0000000..d8e86a0
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/command_packet_builder.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "include/hci.h"
+#include "packets/hci/hci_packet_builder.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// ACL data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.2
+class CommandPacketBuilder : public HciPacketBuilder {
+ public:
+  virtual ~CommandPacketBuilder() override = default;
+
+  static std::unique_ptr<CommandPacketBuilder> Create(hci::OpCode opcode, std::unique_ptr<BasePacketBuilder> payload);
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const;
+
+ private:
+  CommandPacketBuilder(hci::OpCode opcode, std::unique_ptr<BasePacketBuilder> payload);
+  CommandPacketBuilder() = delete;
+  hci::OpCode opcode_;
+  std::unique_ptr<BasePacketBuilder> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/command_packet_view.cc b/vendor_libs/test_vendor_lib/packets/hci/command_packet_view.cc
new file mode 100644
index 0000000..f0876c1
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/command_packet_view.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/command_packet_view.h"
+
+#include <base/logging.h>
+
+using std::vector;
+
+namespace test_vendor_lib {
+namespace packets {
+
+CommandPacketView::CommandPacketView(std::shared_ptr<std::vector<uint8_t>> packet) : PacketView<true>(packet) {}
+
+CommandPacketView CommandPacketView::Create(std::shared_ptr<std::vector<uint8_t>> packet) {
+  return CommandPacketView(packet);
+}
+
+uint16_t CommandPacketView::GetOpcode() const {
+  return begin().extract<uint16_t>();
+}
+
+PacketView<true> CommandPacketView::GetPayload() const {
+  uint8_t payload_size = (begin() + sizeof(uint16_t)).extract<uint8_t>();
+  CHECK(static_cast<uint8_t>(size() - sizeof(uint16_t) - sizeof(uint8_t)) == payload_size)
+      << "Malformed Command packet payload_size " << payload_size << " + 2 != " << size();
+  return SubViewLittleEndian(sizeof(uint16_t) + sizeof(uint8_t), size());
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/command_packet_view.h b/vendor_libs/test_vendor_lib/packets/hci/command_packet_view.h
new file mode 100644
index 0000000..6355c1e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/command_packet_view.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Command packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.1
+class CommandPacketView : public PacketView<true> {
+ public:
+  virtual ~CommandPacketView() override = default;
+
+  static CommandPacketView Create(std::shared_ptr<std::vector<uint8_t>> packet);
+
+  uint16_t GetOpcode() const;
+
+  PacketView<true> GetPayload() const;
+
+ private:
+  CommandPacketView(std::shared_ptr<std::vector<uint8_t>> packet);
+  CommandPacketView() = delete;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/event_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/event_packet_builder.cc
new file mode 100644
index 0000000..010decd
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/event_packet_builder.cc
@@ -0,0 +1,810 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/event_packet_builder.h"
+
+#include <base/logging.h>
+#include "hci.h"
+#include "packets/hci/le_meta_event_builder.h"
+
+using std::vector;
+using test_vendor_lib::hci::EventCode;
+using test_vendor_lib::hci::OpCode;
+using test_vendor_lib::hci::Status;
+
+namespace test_vendor_lib {
+namespace packets {
+
+EventPacketBuilder::EventPacketBuilder(EventCode event_code)
+    : event_code_(event_code), payload_(std::make_unique<RawBuilder>()) {}
+
+EventPacketBuilder::EventPacketBuilder(EventCode event_code, std::unique_ptr<RawBuilder> payload)
+    : event_code_(event_code), payload_(std::move(payload)) {}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.1
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateInquiryCompleteEvent(hci::Status status) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::INQUIRY_COMPLETE));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.14
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteEvent(
+    hci::OpCode command_opcode, const vector<uint8_t>& event_return_parameters) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::COMMAND_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
+  CHECK(evt_ptr->AddPayloadOctets2(static_cast<uint16_t>(command_opcode)));
+  CHECK(evt_ptr->AddPayloadOctets(event_return_parameters));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(hci::OpCode command_opcode,
+                                                                                             hci::Status status) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::COMMAND_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
+  CHECK(evt_ptr->AddPayloadOctets2(static_cast<uint16_t>(command_opcode)));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteStatusAndAddressEvent(
+    hci::OpCode command_opcode, hci::Status status, const Address& address) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::COMMAND_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
+  CHECK(evt_ptr->AddPayloadOctets2(static_cast<uint16_t>(command_opcode)));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadAddress(address));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteUnknownOpCodeEvent(
+    uint16_t command_opcode) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::COMMAND_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
+  CHECK(evt_ptr->AddPayloadOctets2(static_cast<uint16_t>(command_opcode)));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(Status::UNKNOWN_COMMAND)));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.15
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandStatusEvent(hci::Status status,
+                                                                                 hci::OpCode command_opcode) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::COMMAND_STATUS));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
+  CHECK(evt_ptr->AddPayloadOctets2(static_cast<uint16_t>(command_opcode)));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.19
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(
+    uint16_t handle, uint16_t num_completed_packets) {
+  std::unique_ptr<RawBuilder> payload = std::make_unique<CountedBuilder>();
+  std::unique_ptr<EventPacketBuilder> evt_ptr = std::unique_ptr<EventPacketBuilder>(
+      new EventPacketBuilder(EventCode::NUMBER_OF_COMPLETED_PACKETS, std::move(payload)));
+
+  evt_ptr->AddCompletedPackets(handle, num_completed_packets);
+
+  return evt_ptr;
+}
+
+void EventPacketBuilder::AddCompletedPackets(uint16_t handle, uint16_t num_completed_packets) {
+  CHECK(event_code_ == EventCode::NUMBER_OF_COMPLETED_PACKETS);
+
+  std::unique_ptr<RawBuilder> handle_pair = std::make_unique<RawBuilder>();
+  CHECK(handle_pair->AddOctets2(handle));
+  CHECK(handle_pair->AddOctets2(num_completed_packets));
+  AddBuilder(std::move(handle_pair));
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.10
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteDeleteStoredLinkKey(
+    hci::Status status, uint16_t num_keys_deleted) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::DELETE_STORED_LINK_KEY, status);
+
+  CHECK(evt_ptr->AddPayloadOctets2(num_keys_deleted));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.12
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadLocalName(
+    hci::Status status, const std::vector<uint8_t>& local_name) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOCAL_NAME, status);
+
+  size_t len = local_name.size();
+  if (len > 247) {
+    len = 247;
+  }
+  CHECK(evt_ptr->AddPayloadOctets(len, local_name));
+  CHECK(evt_ptr->AddPayloadOctets1(0));  // Null terminated
+  for (size_t i = 0; i < 248 - len - 1; i++) CHECK(evt_ptr->AddPayloadOctets1(0xFF));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.23
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadAuthenticationEnable(
+    hci::Status status, uint8_t enable) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOCAL_NAME, status);
+  CHECK(evt_ptr->AddPayloadOctets1(enable));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.1
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadLocalVersionInformation(
+    hci::Status status, uint8_t hci_version, uint16_t hci_revision, uint8_t lmp_pal_version, uint16_t manufacturer_name,
+    uint16_t lmp_pal_subversion) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOCAL_VERSION_INFORMATION, status);
+
+  CHECK(evt_ptr->AddPayloadOctets1(hci_version));
+  CHECK(evt_ptr->AddPayloadOctets2(hci_revision));
+  CHECK(evt_ptr->AddPayloadOctets1(lmp_pal_version));
+  CHECK(evt_ptr->AddPayloadOctets2(manufacturer_name));
+  CHECK(evt_ptr->AddPayloadOctets2(lmp_pal_subversion));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateReadRemoteVersionInformationEvent(
+    hci::Status status, uint16_t connection_handle, uint8_t lmp_pal_version, uint16_t manufacturer_name,
+    uint16_t lmp_pal_subversion) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::READ_REMOTE_VERSION_INFORMATION_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets2(connection_handle));
+  CHECK(evt_ptr->AddPayloadOctets1(lmp_pal_version));
+  CHECK(evt_ptr->AddPayloadOctets2(manufacturer_name));
+  CHECK(evt_ptr->AddPayloadOctets2(lmp_pal_subversion));
+
+  return evt_ptr;
+}
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.2
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadLocalSupportedCommands(
+    hci::Status status, const vector<uint8_t>& supported_commands) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOCAL_SUPPORTED_COMMANDS, status);
+
+  CHECK(evt_ptr->AddPayloadOctets(64, supported_commands));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.4
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadLocalExtendedFeatures(
+    hci::Status status, uint8_t page_number, uint8_t maximum_page_number, uint64_t extended_lmp_features) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOCAL_EXTENDED_FEATURES, status);
+
+  CHECK(evt_ptr->AddPayloadOctets1(page_number));
+  CHECK(evt_ptr->AddPayloadOctets1(maximum_page_number));
+  CHECK(evt_ptr->AddPayloadOctets8(extended_lmp_features));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateReadRemoteExtendedFeaturesEvent(
+    hci::Status status, uint16_t handle, uint8_t page_number, uint8_t maximum_page_number,
+    uint64_t extended_lmp_features) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::READ_REMOTE_EXTENDED_FEATURES_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadOctets1(page_number));
+  CHECK(evt_ptr->AddPayloadOctets1(maximum_page_number));
+  CHECK(evt_ptr->AddPayloadOctets8(extended_lmp_features));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.5
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadBufferSize(
+    hci::Status status, uint16_t hc_acl_data_packet_length, uint8_t hc_synchronous_data_packet_length,
+    uint16_t hc_total_num_acl_data_packets, uint16_t hc_total_synchronous_data_packets) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_BUFFER_SIZE, status);
+
+  CHECK(evt_ptr->AddPayloadOctets2(hc_acl_data_packet_length));
+  CHECK(evt_ptr->AddPayloadOctets1(hc_synchronous_data_packet_length));
+  CHECK(evt_ptr->AddPayloadOctets2(hc_total_num_acl_data_packets));
+  CHECK(evt_ptr->AddPayloadOctets2(hc_total_synchronous_data_packets));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.6
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadBdAddr(hci::Status status,
+                                                                                        const Address& address) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_BD_ADDR, status);
+
+  CHECK(evt_ptr->AddPayloadAddress(address));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.8
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadLocalSupportedCodecs(
+    hci::Status status, const vector<uint8_t>& supported_codecs, const vector<uint32_t>& vendor_specific_codecs) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOCAL_SUPPORTED_CODECS, status);
+
+  CHECK(evt_ptr->AddPayloadOctets1(supported_codecs.size()));
+  CHECK(evt_ptr->AddPayloadOctets(supported_codecs));
+  CHECK(evt_ptr->AddPayloadOctets1(vendor_specific_codecs.size()));
+  for (size_t i = 0; i < vendor_specific_codecs.size(); i++)
+    CHECK(evt_ptr->AddPayloadOctets4(vendor_specific_codecs[i]));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.6.1
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteReadLoopbackMode(hci::Status status,
+                                                                                              hci::LoopbackMode mode) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::READ_LOOPBACK_MODE, status);
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(mode)));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.2
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateInquiryResultEvent() {
+  std::unique_ptr<RawBuilder> payload = std::unique_ptr<RawBuilder>(new CountedBuilder());
+  std::unique_ptr<EventPacketBuilder> evt_ptr(new EventPacketBuilder(EventCode::INQUIRY_RESULT, std::move(payload)));
+
+  return evt_ptr;
+}
+
+bool EventPacketBuilder::AddInquiryResult(const Address& address, uint8_t page_scan_repetition_mode,
+                                          ClassOfDevice class_of_device, uint16_t clock_offset) {
+  CHECK(event_code_ == EventCode::INQUIRY_RESULT);
+
+  if (!CanAddPayloadOctets(14)) return false;
+
+  std::unique_ptr<RawBuilder> result = std::make_unique<RawBuilder>();
+
+  CHECK(result->AddAddress(address));
+  CHECK(result->AddOctets1(page_scan_repetition_mode));
+  CHECK(result->AddOctets2(0));  // Reserved
+  CHECK(result->AddOctets1(class_of_device.cod[0]));
+  CHECK(result->AddOctets1(class_of_device.cod[1]));
+  CHECK(result->AddOctets1(class_of_device.cod[2]));
+  CHECK(!(clock_offset & 0x8000));
+  CHECK(result->AddOctets2(clock_offset));
+  AddBuilder(std::move(result));
+  return true;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.3
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateConnectionCompleteEvent(
+    hci::Status status, uint16_t handle, const Address& address, hci::LinkType link_type, bool encryption_enabled) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::CONNECTION_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK((handle & 0xf000) == 0);  // Handles are 12-bit values.
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadAddress(address));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(link_type)));
+  CHECK(evt_ptr->AddPayloadOctets1(encryption_enabled ? 1 : 0));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.4
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateConnectionRequestEvent(const Address& address,
+                                                                                     ClassOfDevice class_of_device,
+                                                                                     hci::LinkType link_type) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::CONNECTION_REQUEST));
+
+  CHECK(evt_ptr->AddPayloadAddress(address));
+  CHECK(evt_ptr->AddPayloadOctets1(class_of_device.cod[0]));
+  CHECK(evt_ptr->AddPayloadOctets1(class_of_device.cod[1]));
+  CHECK(evt_ptr->AddPayloadOctets1(class_of_device.cod[2]));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(link_type)));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.5
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateDisconnectionCompleteEvent(hci::Status status,
+                                                                                         uint16_t handle,
+                                                                                         uint8_t reason) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::DISCONNECTION_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK((handle & 0xf000) == 0);  // Handles are 12-bit values.
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadOctets1(reason));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.6
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateAuthenticationCompleteEvent(hci::Status status,
+                                                                                          uint16_t handle) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::AUTHENTICATION_COMPLETE));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK((handle & 0xf000) == 0);  // Handles are 12-bit values.
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.7
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateRemoteNameRequestCompleteEvent(
+    hci::Status status, const Address& address, const std::string& remote_name) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::REMOTE_NAME_REQUEST_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadAddress(address));
+  for (size_t i = 0; i < remote_name.length(); i++) CHECK(evt_ptr->AddPayloadOctets1(remote_name[i]));
+  CHECK(evt_ptr->AddPayloadOctets1(0));  // Null terminated
+  for (size_t i = 0; i < 248 - remote_name.length() - 1; i++) CHECK(evt_ptr->AddPayloadOctets1(0xFF));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.23
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLinkKeyRequestEvent(const Address& remote) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LINK_KEY_REQUEST));
+  CHECK(evt_ptr->AddPayloadAddress(remote));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.24
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLinkKeyNotificationEvent(const Address& remote,
+                                                                                       const std::vector<uint8_t>& key,
+                                                                                       uint8_t key_type) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LINK_KEY_NOTIFICATION));
+  CHECK(evt_ptr->AddPayloadAddress(remote));
+  CHECK(key.size() == 16);
+  CHECK(evt_ptr->AddPayloadOctets(key));
+  CHECK(evt_ptr->AddPayloadOctets1(key_type));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.25
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLoopbackCommandEvent(hci::OpCode opcode,
+                                                                                   PacketView<true> payload) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LOOPBACK_COMMAND));
+  CHECK(evt_ptr->AddPayloadOctets2(static_cast<uint16_t>(opcode)));
+  for (const auto& payload_byte : payload)  // Fill the packet.
+    evt_ptr->AddPayloadOctets1(payload_byte);
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.28
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateReadClockOffsetEvent(hci::Status status, uint16_t handle,
+                                                                                   uint16_t offset) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::READ_CLOCK_OFFSET_COMPLETE));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadOctets2(offset));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.29
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateConnectionPacketTypeChangedEvent(hci::Status status,
+                                                                                               uint16_t handle,
+                                                                                               uint16_t packet_type) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::CONNECTION_PACKET_TYPE_CHANGE));
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadOctets2(packet_type));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.37
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateSniffSubratingEvent(const hci::Status status,
+                                                                                  uint16_t handle) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::SNIFF_SUBRATING, status);
+
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.38
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateExtendedInquiryResultEvent(
+    const Address& address, uint8_t page_scan_repetition_mode, ClassOfDevice class_of_device, uint16_t clock_offset,
+    uint8_t rssi, const vector<uint8_t>& extended_inquiry_response) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::EXTENDED_INQUIRY_RESULT));
+
+  CHECK(evt_ptr->AddPayloadOctets1(1));  // Always contains a single response
+
+  CHECK(evt_ptr->AddPayloadAddress(address));
+  CHECK(evt_ptr->AddPayloadOctets1(page_scan_repetition_mode));
+  CHECK(evt_ptr->AddPayloadOctets1(0));  // Reserved
+  CHECK(evt_ptr->AddPayloadOctets1(class_of_device.cod[0]));
+  CHECK(evt_ptr->AddPayloadOctets1(class_of_device.cod[1]));
+  CHECK(evt_ptr->AddPayloadOctets1(class_of_device.cod[2]));
+  CHECK(!(clock_offset & 0x8000));
+  CHECK(evt_ptr->AddPayloadOctets2(clock_offset));
+  CHECK(evt_ptr->AddPayloadOctets1(rssi));
+  CHECK(evt_ptr->AddPayloadOctets(extended_inquiry_response));
+  evt_ptr->AddPayloadOctets1(0x00);  // End marker
+  while (evt_ptr->AddPayloadOctets1(0x00))
+    ;  // Fill packet
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.40
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateIoCapabilityRequestEvent(const Address& peer) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::IO_CAPABILITY_REQUEST));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  return evt_ptr;
+}  // namespace packets
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.41
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateIoCapabilityResponseEvent(
+    const Address& peer, uint8_t io_capability, bool oob_data_present, uint8_t authentication_requirements) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::IO_CAPABILITY_RESPONSE));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  CHECK(evt_ptr->AddPayloadOctets1(io_capability));
+  CHECK(evt_ptr->AddPayloadOctets1(oob_data_present));
+  CHECK(evt_ptr->AddPayloadOctets1(authentication_requirements));
+  return evt_ptr;
+}  // namespace test_vendor_lib
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.42
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateUserConfirmationRequestEvent(const Address& peer,
+                                                                                           uint32_t numeric_value) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::USER_CONFIRMATION_REQUEST));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  CHECK(evt_ptr->AddPayloadOctets4(numeric_value));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.43
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateUserPasskeyRequestEvent(const Address& peer) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::USER_PASSKEY_REQUEST));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.44
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateRemoteOobDataRequestEvent(const Address& peer) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::REMOTE_OOB_DATA_REQUEST));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.45
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateSimplePairingCompleteEvent(hci::Status status,
+                                                                                         const Address& peer) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::SIMPLE_PAIRING_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.48
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateUserPasskeyNotificationEvent(const Address& peer,
+                                                                                           uint32_t passkey) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::USER_PASSKEY_NOTIFICATION));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  CHECK(evt_ptr->AddPayloadOctets4(passkey));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.49
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateKeypressNotificationEvent(const Address& peer,
+                                                                                        uint8_t notification_type) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::KEYPRESS_NOTIFICATION));
+
+  CHECK(evt_ptr->AddPayloadAddress(peer));
+  CHECK(evt_ptr->AddPayloadOctets1(notification_type));
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.1
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLeConnectionCompleteEvent(
+    hci::Status status, uint16_t handle, uint8_t role, uint8_t peer_address_type, const Address& peer,
+    uint16_t interval, uint16_t latency, uint16_t supervision_timeout) {
+  std::unique_ptr<RawBuilder> meta_evt = LeMetaEventBuilder::CreateLeConnectionCompleteEvent(
+      status, handle, role, peer_address_type, peer, interval, latency, supervision_timeout);
+
+  return std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LE_META_EVENT, std::move(meta_evt)));
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLeEnhancedConnectionCompleteEvent(
+    hci::Status status, uint16_t handle, uint8_t role, uint8_t peer_address_type, const Address& peer,
+    const Address& local_private_address, const Address& peer_private_address, uint16_t interval, uint16_t latency,
+    uint16_t supervision_timeout) {
+  std::unique_ptr<RawBuilder> meta_evt = LeMetaEventBuilder::CreateLeEnhancedConnectionCompleteEvent(
+      status, handle, role, peer_address_type, peer, local_private_address, peer_private_address, interval, latency,
+      supervision_timeout);
+
+  return std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LE_META_EVENT, std::move(meta_evt)));
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLeConnectionUpdateCompleteEvent(
+    hci::Status status, uint16_t handle, uint16_t interval, uint16_t latency, uint16_t supervision_timeout) {
+  std::unique_ptr<RawBuilder> meta_evt =
+      LeMetaEventBuilder::CreateLeConnectionUpdateCompleteEvent(status, handle, interval, latency, supervision_timeout);
+
+  return std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LE_META_EVENT, std::move(meta_evt)));
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.2
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLeAdvertisingReportEvent() {
+  std::unique_ptr<RawBuilder> meta_evt = LeMetaEventBuilder::CreateLeAdvertisingReportEvent();
+
+  return std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LE_META_EVENT, std::move(meta_evt)));
+}
+
+bool EventPacketBuilder::AddLeAdvertisingReport(LeAdvertisement::AdvertisementType event_type,
+                                                LeAdvertisement::AddressType addr_type, const Address& addr,
+                                                const vector<uint8_t>& data, uint8_t rssi) {
+  CHECK(event_code_ == EventCode::LE_META_EVENT);
+
+  // Upcast the payload to add the next report.
+  LeMetaEventBuilder* meta_ptr = static_cast<LeMetaEventBuilder*>(payload_.get());
+  return meta_ptr->AddLeAdvertisingReport(event_type, addr_type, addr, data, rssi);
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.4
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateLeRemoteUsedFeaturesEvent(hci::Status status,
+                                                                                        uint16_t handle,
+                                                                                        uint64_t features) {
+  std::unique_ptr<RawBuilder> meta_evt = LeMetaEventBuilder::CreateLeRemoteUsedFeaturesEvent(status, handle, features);
+  return std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::LE_META_EVENT, std::move(meta_evt)));
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateRemoteSupportedFeaturesEvent(hci::Status status,
+                                                                                           uint16_t handle,
+                                                                                           uint64_t features) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::READ_REMOTE_SUPPORTED_FEATURES_COMPLETE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadOctets8(features));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLinkKeyRequestReply(hci::Status status,
+                                                                                                 Address address) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LINK_KEY_REQUEST_REPLY, status);
+
+  CHECK(evt_ptr->AddPayloadAddress(address));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLinkKeyRequestNegativeReply(
+    hci::Status status, Address address) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LINK_KEY_REQUEST_NEGATIVE_REPLY, status);
+
+  CHECK(evt_ptr->AddPayloadAddress(address));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteWriteLinkPolicySettings(hci::Status status,
+                                                                                                     uint16_t handle) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::WRITE_LINK_POLICY_SETTINGS, status);
+
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteWriteLinkSupervisionTimeout(
+    hci::Status status, uint16_t handle) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::WRITE_LINK_SUPERVISION_TIMEOUT, status);
+
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.2
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLeReadBufferSize(
+    hci::Status status, uint16_t hc_le_data_packet_length, uint8_t hc_total_num_le_data_packets) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LE_READ_BUFFER_SIZE, status);
+
+  CHECK(evt_ptr->AddPayloadOctets2(hc_le_data_packet_length));
+  CHECK(evt_ptr->AddPayloadOctets1(hc_total_num_le_data_packets));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.3
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLeReadLocalSupportedFeatures(
+    hci::Status status, uint64_t le_features) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LE_READ_LOCAL_SUPPORTED_FEATURES, status);
+
+  CHECK(evt_ptr->AddPayloadOctets8(le_features));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.14
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLeReadWhiteListSize(
+    hci::Status status, uint8_t white_list_size) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LE_READ_WHITE_LIST_SIZE, status);
+
+  CHECK(evt_ptr->AddPayloadOctets8(white_list_size));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.23
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLeRand(hci::Status status,
+                                                                                    uint64_t random_val) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LE_RAND, status);
+
+  CHECK(evt_ptr->AddPayloadOctets8(random_val));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.27
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLeReadSupportedStates(hci::Status status,
+                                                                                                   uint64_t le_states) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LE_READ_SUPPORTED_STATES, status);
+
+  CHECK(evt_ptr->AddPayloadOctets8(le_states));
+
+  return evt_ptr;
+}
+
+// Vendor-specific commands
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateCommandCompleteLeGetVendorCapabilities(
+    hci::Status status, const vector<uint8_t>& vendor_cap) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      EventPacketBuilder::CreateCommandCompleteOnlyStatusEvent(OpCode::LE_GET_VENDOR_CAPABILITIES, status);
+
+  CHECK(evt_ptr->AddPayloadOctets(vendor_cap));
+
+  return evt_ptr;
+}
+
+std::unique_ptr<EventPacketBuilder> EventPacketBuilder::CreateEncryptionChange(hci::Status status, uint16_t handle,
+                                                                               uint8_t encryption_enable) {
+  std::unique_ptr<EventPacketBuilder> evt_ptr =
+      std::unique_ptr<EventPacketBuilder>(new EventPacketBuilder(EventCode::ENCRYPTION_CHANGE));
+
+  CHECK(evt_ptr->AddPayloadOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddPayloadOctets2(handle));
+  CHECK(evt_ptr->AddPayloadOctets1(encryption_enable));
+
+  return evt_ptr;
+}
+
+size_t EventPacketBuilder::size() const {
+  size_t header_size = 2;  // Event code and payload size
+  return header_size + payload_->size();
+}
+
+void EventPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint8_t>(event_code_), it);
+  uint8_t payload_size = size() - 2;  // Event code and payload size
+  CHECK(size() - 2 == static_cast<size_t>(payload_size)) << "Payload too large for an event: " << size();
+  insert(payload_size, it);
+  payload_->Serialize(it);
+}
+
+bool EventPacketBuilder::CanAddPayloadOctets(size_t octets) {
+  return payload_->CanAddOctets(octets);
+}
+
+bool EventPacketBuilder::AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes) {
+  return payload_->AddOctets(octets, bytes);
+}
+
+bool EventPacketBuilder::AddPayloadOctets(const std::vector<uint8_t>& bytes) {
+  return payload_->AddOctets(bytes);
+}
+
+bool EventPacketBuilder::AddPayloadOctets1(uint8_t value) {
+  return payload_->AddOctets1(value);
+}
+
+bool EventPacketBuilder::AddPayloadOctets2(uint16_t value) {
+  return payload_->AddOctets2(value);
+}
+
+bool EventPacketBuilder::AddPayloadOctets3(uint32_t value) {
+  return payload_->AddOctets3(value);
+}
+
+bool EventPacketBuilder::AddPayloadOctets4(uint32_t value) {
+  return payload_->AddOctets4(value);
+}
+
+bool EventPacketBuilder::AddPayloadOctets6(uint64_t value) {
+  return payload_->AddOctets6(value);
+}
+
+bool EventPacketBuilder::AddPayloadOctets8(uint64_t value) {
+  return payload_->AddOctets8(value);
+}
+
+bool EventPacketBuilder::AddPayloadAddress(Address address) {
+  return payload_->AddAddress(address);
+}
+
+bool EventPacketBuilder::AddBuilder(std::unique_ptr<BasePacketBuilder> builder) {
+  // Upcast the payload to add the next builder.
+  CountedBuilder* temp_ptr = static_cast<CountedBuilder*>(payload_.get());
+  temp_ptr->Add(std::move(builder));
+  return true;
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/event_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/event_packet_builder.h
new file mode 100644
index 0000000..495e47a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/event_packet_builder.h
@@ -0,0 +1,328 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "include/hci.h"
+#include "include/le_advertisement.h"
+#include "packets/counted_builder.h"
+#include "packets/hci/hci_packet_builder.h"
+#include "packets/packet_builder.h"
+#include "packets/packet_view.h"
+#include "packets/raw_builder.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Event Packets are specified in the Bluetooth Core Specification Version 4.2,
+// Volume 2, Part E, Section 5.4.4 (page 477). Event Packets begin with a 2
+// octet header formatted as follows:
+// - Event Code: 1 octet
+// - Parameter Total Length: 1 octet
+class EventPacketBuilder : public HciPacketBuilder {
+ public:
+  virtual ~EventPacketBuilder() override = default;
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.1
+  static std::unique_ptr<EventPacketBuilder> CreateInquiryCompleteEvent(hci::Status status);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.14
+  // This should only be used for testing to send non-standard packets
+  // Most code should use the more specific functions that follow
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteEvent(
+      hci::OpCode command_opcode, const std::vector<uint8_t>& event_return_parameters);
+
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteOnlyStatusEvent(hci::OpCode command_opcode,
+                                                                                  hci::Status status);
+
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteStatusAndAddressEvent(hci::OpCode command_opcode,
+                                                                                        hci::Status status,
+                                                                                        const Address& address);
+
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteUnknownOpCodeEvent(uint16_t command_opcode);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.15
+  static std::unique_ptr<EventPacketBuilder> CreateCommandStatusEvent(hci::Status status, hci::OpCode command_opcode);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.19
+  static std::unique_ptr<EventPacketBuilder> CreateNumberOfCompletedPacketsEvent(uint16_t handle,
+                                                                                 uint16_t num_completed_packets);
+
+  void AddCompletedPackets(uint16_t handle, uint16_t num_completed_packets);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.1.10
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLinkKeyRequestReply(hci::Status status,
+                                                                                      Address address);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.1.11
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLinkKeyRequestNegativeReply(hci::Status status,
+                                                                                              Address address);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.2.10
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteWriteLinkPolicySettings(hci::Status status,
+                                                                                          uint16_t handle);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.10
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteDeleteStoredLinkKey(hci::Status status,
+                                                                                      uint16_t num_keys_deleted);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.12
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadLocalName(hci::Status status,
+                                                                                const std::vector<uint8_t>& local_name);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.23
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadAuthenticationEnable(hci::Status status,
+                                                                                           uint8_t enable);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.42
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteWriteLinkSupervisionTimeout(hci::Status status,
+                                                                                              uint16_t handle);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.1
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadLocalVersionInformation(
+      hci::Status status, uint8_t hci_version, uint16_t hci_revision, uint8_t lmp_pal_version,
+      uint16_t manufacturer_name, uint16_t lmp_pal_subversion);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.2
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadLocalSupportedCommands(
+      hci::Status status, const std::vector<uint8_t>& supported_commands);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.4
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadLocalExtendedFeatures(
+      hci::Status status, uint8_t page_number, uint8_t maximum_page_number, uint64_t extended_lmp_features);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.5
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadBufferSize(
+      hci::Status status, uint16_t hc_acl_data_packet_length, uint8_t hc_synchronous_data_packet_length,
+      uint16_t hc_total_num_acl_data_packets, uint16_t hc_total_synchronous_data_packets);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.6
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadBdAddr(hci::Status status,
+                                                                             const Address& bt_address);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.8
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadLocalSupportedCodecs(
+      hci::Status status, const std::vector<uint8_t>& supported_codecs,
+      const std::vector<uint32_t>& vendor_specific_codecs);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.6.1
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteReadLoopbackMode(hci::Status status,
+                                                                                   hci::LoopbackMode mode);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.2
+  static std::unique_ptr<EventPacketBuilder> CreateInquiryResultEvent();
+
+  // Returns true if the result can be added to the event packet.
+  bool AddInquiryResult(const Address& bt_address, uint8_t page_scan_repetition_mode, ClassOfDevice class_of_device,
+                        uint16_t clock_offset);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.3
+  static std::unique_ptr<EventPacketBuilder> CreateConnectionCompleteEvent(hci::Status status, uint16_t handle,
+                                                                           const Address& address,
+                                                                           hci::LinkType link_type,
+                                                                           bool encryption_enabled);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.4
+  static std::unique_ptr<EventPacketBuilder> CreateConnectionRequestEvent(const Address& address,
+                                                                          ClassOfDevice class_of_device,
+                                                                          hci::LinkType link_type);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.5
+  static std::unique_ptr<EventPacketBuilder> CreateDisconnectionCompleteEvent(hci::Status status, uint16_t handle,
+                                                                              uint8_t reason);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.6
+  static std::unique_ptr<EventPacketBuilder> CreateAuthenticationCompleteEvent(hci::Status status, uint16_t handle);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.7
+  static std::unique_ptr<EventPacketBuilder> CreateRemoteNameRequestCompleteEvent(hci::Status status,
+                                                                                  const Address& bt_address,
+                                                                                  const std::string& name);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.11
+  static std::unique_ptr<EventPacketBuilder> CreateRemoteSupportedFeaturesEvent(hci::Status status, uint16_t handle,
+                                                                                uint64_t features);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.12
+  static std::unique_ptr<EventPacketBuilder> CreateReadRemoteVersionInformationEvent(hci::Status status,
+                                                                                     uint16_t connection_handle,
+                                                                                     uint8_t lmp_pal_version,
+                                                                                     uint16_t manufacturer_name,
+                                                                                     uint16_t lmp_pal_subversion);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.23
+  static std::unique_ptr<EventPacketBuilder> CreateLinkKeyRequestEvent(const Address& remote);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.24
+  static std::unique_ptr<EventPacketBuilder> CreateLinkKeyNotificationEvent(const Address& remote,
+                                                                            const std::vector<uint8_t>& key,
+                                                                            uint8_t key_type);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.25
+  static std::unique_ptr<EventPacketBuilder> CreateLoopbackCommandEvent(hci::OpCode opcode, PacketView<true> payload);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.28
+  static std::unique_ptr<EventPacketBuilder> CreateReadClockOffsetEvent(hci::Status status, uint16_t handle,
+                                                                        uint16_t packet_type);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.29
+  static std::unique_ptr<EventPacketBuilder> CreateConnectionPacketTypeChangedEvent(hci::Status status, uint16_t handle,
+                                                                                    uint16_t offset);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.34
+  static std::unique_ptr<EventPacketBuilder> CreateReadRemoteExtendedFeaturesEvent(hci::Status status, uint16_t handle,
+                                                                                   uint8_t page_number,
+                                                                                   uint8_t maximum_page_number,
+                                                                                   uint64_t extended_lmp_features);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.37
+  static std::unique_ptr<EventPacketBuilder> CreateSniffSubratingEvent(hci::Status status, uint16_t handle);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.38
+  static std::unique_ptr<EventPacketBuilder> CreateExtendedInquiryResultEvent(
+      const Address& bt_address, uint8_t page_scan_repetition_mode, ClassOfDevice class_of_device,
+      uint16_t clock_offset, uint8_t rssi, const std::vector<uint8_t>& extended_inquiry_response);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.40
+  static std::unique_ptr<EventPacketBuilder> CreateIoCapabilityRequestEvent(const Address& peer);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.41
+  static std::unique_ptr<EventPacketBuilder> CreateIoCapabilityResponseEvent(const Address& peer, uint8_t io_capability,
+                                                                             bool oob_data_present,
+                                                                             uint8_t authentication_requirements);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.42
+  static std::unique_ptr<EventPacketBuilder> CreateUserConfirmationRequestEvent(const Address& peer,
+                                                                                uint32_t numeric_value);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.43
+  static std::unique_ptr<EventPacketBuilder> CreateUserPasskeyRequestEvent(const Address& peer);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.44
+  static std::unique_ptr<EventPacketBuilder> CreateRemoteOobDataRequestEvent(const Address& peer);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.45
+  static std::unique_ptr<EventPacketBuilder> CreateSimplePairingCompleteEvent(hci::Status status, const Address& peer);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.48
+  static std::unique_ptr<EventPacketBuilder> CreateUserPasskeyNotificationEvent(const Address& peer, uint32_t passkey);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.49
+  static std::unique_ptr<EventPacketBuilder> CreateKeypressNotificationEvent(const Address& peer,
+                                                                             uint8_t notification_type);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.1
+  static std::unique_ptr<EventPacketBuilder> CreateLeConnectionCompleteEvent(hci::Status status, uint16_t handle,
+                                                                             uint8_t role, uint8_t peer_address_type,
+                                                                             const Address& peer, uint16_t interval,
+                                                                             uint16_t latency,
+                                                                             uint16_t supervision_timeout);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.2
+  static std::unique_ptr<EventPacketBuilder> CreateLeAdvertisingReportEvent();
+
+  // Returns true if the report can be added to the event packet.
+  bool AddLeAdvertisingReport(LeAdvertisement::AdvertisementType event_type, LeAdvertisement::AddressType addr_type,
+                              const Address& addr, const std::vector<uint8_t>& data, uint8_t rssi);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.3
+  static std::unique_ptr<EventPacketBuilder> CreateLeConnectionUpdateCompleteEvent(hci::Status status, uint16_t handle,
+                                                                                   uint16_t interval, uint16_t latency,
+                                                                                   uint16_t supervision_timeout);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.4
+  static std::unique_ptr<EventPacketBuilder> CreateLeRemoteUsedFeaturesEvent(hci::Status status, uint16_t handle,
+                                                                             uint64_t features);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.10
+  static std::unique_ptr<EventPacketBuilder> CreateLeEnhancedConnectionCompleteEvent(
+      hci::Status status, uint16_t handle, uint8_t role, uint8_t peer_address_type, const Address& peer,
+      const Address& local_private_address, const Address& peer_private_address, uint16_t interval, uint16_t latency,
+      uint16_t supervision_timeout);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.2
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLeReadBufferSize(
+      hci::Status status, uint16_t hc_le_data_packet_length, uint8_t hc_total_num_le_data_packets);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.3
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLeReadLocalSupportedFeatures(hci::Status status,
+                                                                                               uint64_t le_features);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.14
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLeReadWhiteListSize(hci::Status status,
+                                                                                      uint8_t white_list_size);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.23
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLeRand(hci::Status status, uint64_t random_val);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.27
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLeReadSupportedStates(hci::Status status,
+                                                                                        uint64_t le_states);
+
+  /*
+  static std::unique_ptr<EventPacketBuilder>
+      CreateLeStartEncryption(hci::Status status, uint8_t encryption_enable);
+*/
+  static std::unique_ptr<EventPacketBuilder> CreateEncryptionChange(hci::Status status, uint16_t handle,
+                                                                    uint8_t encryption_enable);
+
+  // Vendor-specific commands
+
+  static std::unique_ptr<EventPacketBuilder> CreateCommandCompleteLeGetVendorCapabilities(
+      hci::Status status, const std::vector<uint8_t>& vendor_cap);
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
+
+  bool CanAddPayloadOctets(size_t octets);
+
+  bool AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes);
+
+  bool AddPayloadOctets(const std::vector<uint8_t>& bytes);
+
+  bool AddPayloadOctets1(uint8_t value);
+  bool AddPayloadOctets2(uint16_t value);
+  bool AddPayloadOctets3(uint32_t value);
+  bool AddPayloadOctets4(uint32_t value);
+  bool AddPayloadOctets6(uint64_t value);
+  bool AddPayloadOctets8(uint64_t value);
+
+  bool AddPayloadAddress(Address address);
+
+  bool AddBuilder(std::unique_ptr<BasePacketBuilder> builder);
+
+ private:
+  explicit EventPacketBuilder(hci::EventCode event_code);
+  explicit EventPacketBuilder(hci::EventCode event_code, std::unique_ptr<RawBuilder> payload);
+  hci::EventCode event_code_;
+  std::unique_ptr<RawBuilder> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/event_payload_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/event_payload_builder.cc
new file mode 100644
index 0000000..dd866a2
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/event_payload_builder.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "event_payload_builder.h"
+
+#include <base/logging.h>
+#include <algorithm>
+
+using std::vector;
+
+namespace test_vendor_lib {
+namespace packets {
+
+EventPayloadBuilder::EventPayloadBuilder(size_t max_bytes) : max_bytes_(max_bytes) {}
+
+bool EventPayloadBuilder::AddPayloadOctets(size_t octets, const vector<uint8_t>& bytes) {
+  if (payload_.size() + octets > max_bytes_) return false;
+
+  if (octets != bytes.size()) return false;
+
+  payload_.insert(payload_.end(), bytes.begin(), bytes.end());
+
+  return true;
+}
+
+bool EventPayloadBuilder::AddPayloadOctets(const vector<uint8_t>& bytes) {
+  return AddPayloadOctets(bytes.size(), bytes);
+}
+
+bool EventPayloadBuilder::AddPayloadOctets(size_t octets, uint64_t value) {
+  vector<uint8_t> val_vector;
+
+  uint64_t v = value;
+
+  if (octets > sizeof(uint64_t)) return false;
+
+  for (size_t i = 0; i < octets; i++) {
+    val_vector.push_back(v & 0xff);
+    v = v >> 8;
+  }
+
+  if (v != 0) return false;
+
+  return AddPayloadOctets(octets, val_vector);
+}
+
+bool EventPayloadBuilder::AddPayloadAddress(const Address& address) {
+  if (payload_.size() + Address::kLength > max_bytes_) return false;
+
+  for (size_t i = 0; i < Address::kLength; i++) {
+    payload_.push_back(address.address[i]);
+  }
+  return true;
+}
+
+bool EventPayloadBuilder::AddPayloadOctets1(uint8_t value) {
+  return AddPayloadOctets(1, value);
+}
+
+bool EventPayloadBuilder::AddPayloadOctets2(uint16_t value) {
+  return AddPayloadOctets(2, value);
+}
+
+bool EventPayloadBuilder::AddPayloadOctets3(uint32_t value) {
+  return AddPayloadOctets(3, value);
+}
+
+bool EventPayloadBuilder::AddPayloadOctets4(uint32_t value) {
+  return AddPayloadOctets(4, value);
+}
+
+bool EventPayloadBuilder::AddPayloadOctets6(uint64_t value) {
+  return AddPayloadOctets(6, value);
+}
+
+bool EventPayloadBuilder::AddPayloadOctets8(uint64_t value) {
+  return AddPayloadOctets(8, value);
+}
+
+bool EventPayloadBuilder::CanAddPayloadOctets(size_t num_bytes) const {
+  return payload_.size() + num_bytes <= max_bytes_;
+}
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/event_payload_builder.h b/vendor_libs/test_vendor_lib/packets/hci/event_payload_builder.h
new file mode 100644
index 0000000..b656edf
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/event_payload_builder.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "packets/packet_builder.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class EventPayloadBuilder : public PacketBuilder<true> {
+ public:
+  EventPayloadBuilder() = default;
+  EventPayloadBuilder(size_t max_bytes);
+  virtual ~EventPayloadBuilder() = default;
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const;
+
+  // Add |octets| bytes to the payload.  Return true if:
+  // - the size of |bytes| is equal to |octets| and
+  // - the new size of the payload is still < |max_bytes_|
+  bool AddPayloadOctets(size_t octets, const std::vector<uint8_t>& bytes);
+
+  bool AddPayloadOctets(const std::vector<uint8_t>& bytes);
+
+  bool AddPayloadOctets1(uint8_t value);
+  bool AddPayloadOctets2(uint16_t value);
+  bool AddPayloadOctets3(uint32_t value);
+  bool AddPayloadOctets4(uint32_t value);
+  bool AddPayloadOctets6(uint64_t value);
+  bool AddPayloadOctets8(uint64_t value);
+
+ private:
+  // Add |octets| bytes to the payload.  Return true if:
+  // - the value of |value| fits in |octets| bytes and
+  // - the new size of the payload is still < |max_bytes_|
+  bool AddPayloadOctets(size_t octets, uint64_t value);
+
+  // Add |address| to the payload.  Return true if:
+  // - the new size of the payload is still < |max_bytes_|
+  bool AddPayloadAddress(const Address& address);
+
+  // Return true if |num_bytes| can be added to the payload.
+  bool CanAddPayloadOctets(size_t num_bytes) const;
+
+  size_t max_bytes_{255};
+
+  // Underlying containers for storing the actual packet
+  std::vector<uint8_t> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/hci_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/hci_packet_builder.cc
new file mode 100644
index 0000000..1d5689b
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/hci_packet_builder.cc
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/hci_packet_builder.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+namespace packets {
+
+std::shared_ptr<std::vector<uint8_t>> HciPacketBuilder::ToVector() {
+  std::shared_ptr<std::vector<uint8_t>> to_return = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*to_return);
+  Serialize(it);
+  return to_return;
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/hci_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/hci_packet_builder.h
new file mode 100644
index 0000000..d508696
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/hci_packet_builder.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Base packet for HCI packets specified in the Bluetooth Core Specification
+// Version 4.2, Volume 2, Part E, Section 5.4
+class HciPacketBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~HciPacketBuilder() override = default;
+
+  std::shared_ptr<std::vector<uint8_t>> ToVector();
+
+ protected:
+  HciPacketBuilder() = default;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/le_meta_event_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/le_meta_event_builder.cc
new file mode 100644
index 0000000..f0599a7
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/le_meta_event_builder.cc
@@ -0,0 +1,148 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/le_meta_event_builder.h"
+
+#include <base/logging.h>
+
+using std::vector;
+using test_vendor_lib::hci::LeSubEventCode;
+using test_vendor_lib::hci::Status;
+
+namespace test_vendor_lib {
+namespace packets {
+
+LeMetaEventBuilder::LeMetaEventBuilder(LeSubEventCode sub_event_code)
+    : sub_event_code_(sub_event_code), payload_(std::make_unique<RawBuilder>()) {}
+
+LeMetaEventBuilder::LeMetaEventBuilder(LeSubEventCode sub_event_code, std::unique_ptr<RawBuilder> payload)
+    : sub_event_code_(sub_event_code), payload_(std::move(payload)) {}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.1
+std::unique_ptr<LeMetaEventBuilder> LeMetaEventBuilder::CreateLeConnectionCompleteEvent(
+    Status status, uint16_t handle, uint8_t role, uint8_t peer_address_type, const Address& peer, uint16_t interval,
+    uint16_t latency, uint16_t supervision_timeout) {
+  std::unique_ptr<LeMetaEventBuilder> evt_ptr =
+      std::unique_ptr<LeMetaEventBuilder>(new LeMetaEventBuilder(LeSubEventCode::CONNECTION_COMPLETE));
+
+  CHECK(evt_ptr->AddOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddOctets2(handle));
+  CHECK(evt_ptr->AddOctets1(role));
+  CHECK(evt_ptr->AddOctets1(peer_address_type));
+  CHECK(evt_ptr->AddAddress(peer));
+  CHECK(evt_ptr->AddOctets2(interval));
+  CHECK(evt_ptr->AddOctets2(latency));
+  CHECK(evt_ptr->AddOctets2(supervision_timeout));
+  CHECK(evt_ptr->AddOctets1(0x00));  // Master Clock Accuracy (unused for master)
+
+  return evt_ptr;
+}
+
+std::unique_ptr<LeMetaEventBuilder> LeMetaEventBuilder::CreateLeEnhancedConnectionCompleteEvent(
+    Status status, uint16_t handle, uint8_t role, uint8_t peer_address_type, const Address& peer,
+    const Address& local_private_address, const Address& peer_private_address, uint16_t interval, uint16_t latency,
+    uint16_t supervision_timeout) {
+  std::unique_ptr<LeMetaEventBuilder> evt_ptr =
+      std::unique_ptr<LeMetaEventBuilder>(new LeMetaEventBuilder(LeSubEventCode::ENHANCED_CONNECTION_COMPLETE));
+
+  CHECK(evt_ptr->AddOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddOctets2(handle));
+  CHECK(evt_ptr->AddOctets1(role));
+  CHECK(evt_ptr->AddOctets1(peer_address_type));
+  CHECK(evt_ptr->AddAddress(peer));
+  CHECK(evt_ptr->AddAddress(local_private_address));
+  CHECK(evt_ptr->AddAddress(peer_private_address));
+  CHECK(evt_ptr->AddOctets2(interval));
+  CHECK(evt_ptr->AddOctets2(latency));
+  CHECK(evt_ptr->AddOctets2(supervision_timeout));
+  CHECK(evt_ptr->AddOctets1(0x00));  // Master Clock Accuracy (unused for master)
+
+  return evt_ptr;
+}
+
+std::unique_ptr<LeMetaEventBuilder> LeMetaEventBuilder::CreateLeConnectionUpdateCompleteEvent(
+    Status status, uint16_t handle, uint16_t interval, uint16_t latency, uint16_t supervision_timeout) {
+  std::unique_ptr<LeMetaEventBuilder> evt_ptr =
+      std::unique_ptr<LeMetaEventBuilder>(new LeMetaEventBuilder(LeSubEventCode::CONNECTION_UPDATE_COMPLETE));
+
+  CHECK(evt_ptr->AddOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddOctets2(handle));
+  CHECK(evt_ptr->AddOctets2(interval));
+  CHECK(evt_ptr->AddOctets2(latency));
+  CHECK(evt_ptr->AddOctets2(supervision_timeout));
+
+  return evt_ptr;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.2
+std::unique_ptr<LeMetaEventBuilder> LeMetaEventBuilder::CreateLeAdvertisingReportEvent() {
+  std::unique_ptr<LeMetaEventBuilder> evt_ptr = std::unique_ptr<LeMetaEventBuilder>(
+      new LeMetaEventBuilder(LeSubEventCode::ADVERTISING_REPORT, std::unique_ptr<RawBuilder>(new CountedBuilder())));
+
+  return evt_ptr;
+}
+
+bool LeMetaEventBuilder::AddLeAdvertisingReport(LeAdvertisement::AdvertisementType event_type,
+                                                LeAdvertisement::AddressType addr_type, const Address& addr,
+                                                const vector<uint8_t>& data, uint8_t rssi) {
+  if (!CanAddOctets(10 + data.size())) return false;
+
+  CHECK(sub_event_code_ == LeSubEventCode::ADVERTISING_REPORT);
+
+  std::unique_ptr<RawBuilder> ad = std::make_unique<RawBuilder>();
+
+  CHECK(ad->AddOctets1(static_cast<uint8_t>(event_type)));
+  CHECK(ad->AddOctets1(static_cast<uint8_t>(addr_type)));
+  CHECK(ad->AddAddress(addr));
+  CHECK(ad->AddOctets1(data.size()));
+  CHECK(ad->AddOctets(data));
+  CHECK(ad->AddOctets1(rssi));
+  AddBuilder(std::move(ad));
+  return true;
+}
+
+// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.4
+std::unique_ptr<LeMetaEventBuilder> LeMetaEventBuilder::CreateLeRemoteUsedFeaturesEvent(Status status, uint16_t handle,
+                                                                                        uint64_t features) {
+  std::unique_ptr<LeMetaEventBuilder> evt_ptr =
+      std::unique_ptr<LeMetaEventBuilder>(new LeMetaEventBuilder(LeSubEventCode::READ_REMOTE_FEATURES_COMPLETE));
+
+  CHECK(evt_ptr->AddOctets1(static_cast<uint8_t>(status)));
+  CHECK(evt_ptr->AddOctets2(handle));
+  CHECK(evt_ptr->AddOctets8(features));
+
+  return evt_ptr;
+}
+
+size_t LeMetaEventBuilder::size() const {
+  return 1 + payload_->size();  // Add the sub_event_code
+}
+
+void LeMetaEventBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint8_t>(sub_event_code_), it);
+  uint8_t payload_size = size() - sizeof(uint8_t);
+  CHECK(size() - sizeof(uint8_t) == static_cast<size_t>(payload_size)) << "Payload too large for an event: " << size();
+  payload_->Serialize(it);
+}
+
+bool LeMetaEventBuilder::AddBuilder(std::unique_ptr<BasePacketBuilder> builder) {
+  // Upcast the payload to add the next builder.
+  CountedBuilder* temp_ptr = static_cast<CountedBuilder*>(payload_.get());
+  temp_ptr->Add(std::move(builder));
+  return true;
+}
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/le_meta_event_builder.h b/vendor_libs/test_vendor_lib/packets/hci/le_meta_event_builder.h
new file mode 100644
index 0000000..b1d713d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/le_meta_event_builder.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "include/hci.h"
+#include "include/le_advertisement.h"
+#include "packets/counted_builder.h"
+#include "packets/hci/hci_packet_builder.h"
+#include "packets/packet_builder.h"
+#include "packets/packet_view.h"
+#include "packets/raw_builder.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// LE Meta Event Packets are specified in the Bluetooth Core Specification
+// Version 4.2, Volume 2, Part E, Section 7.7.65. The first byte is the
+// Subevent_Code.
+class LeMetaEventBuilder : public RawBuilder {
+ public:
+  virtual ~LeMetaEventBuilder() override = default;
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.1
+  static std::unique_ptr<LeMetaEventBuilder> CreateLeConnectionCompleteEvent(hci::Status status, uint16_t handle,
+                                                                             uint8_t role, uint8_t peer_address_type,
+                                                                             const Address& peer, uint16_t interval,
+                                                                             uint16_t latency,
+                                                                             uint16_t supervision_timeout);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.2
+  static std::unique_ptr<LeMetaEventBuilder> CreateLeAdvertisingReportEvent();
+
+  // Returns true if the report can be added to the event packet.
+  bool AddLeAdvertisingReport(LeAdvertisement::AdvertisementType event_type, LeAdvertisement::AddressType addr_type,
+                              const Address& addr, const std::vector<uint8_t>& data, uint8_t rssi);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.3
+  static std::unique_ptr<LeMetaEventBuilder> CreateLeConnectionUpdateCompleteEvent(hci::Status status, uint16_t handle,
+                                                                                   uint16_t interval, uint16_t latency,
+                                                                                   uint16_t supervision_timeout);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.4
+  static std::unique_ptr<LeMetaEventBuilder> CreateLeRemoteUsedFeaturesEvent(hci::Status status, uint16_t handle,
+                                                                             uint64_t features);
+
+  // Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section
+  // 7.7.65.10
+  static std::unique_ptr<LeMetaEventBuilder> CreateLeEnhancedConnectionCompleteEvent(
+      hci::Status status, uint16_t handle, uint8_t role, uint8_t peer_address_type, const Address& peer,
+      const Address& local_private_address, const Address& peer_private_address, uint16_t interval, uint16_t latency,
+      uint16_t supervision_timeout);
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
+
+  bool AddBuilder(std::unique_ptr<BasePacketBuilder> builder);
+
+ private:
+  explicit LeMetaEventBuilder(hci::LeSubEventCode sub_event_code);
+  explicit LeMetaEventBuilder(hci::LeSubEventCode sub_event_code, std::unique_ptr<RawBuilder> payload);
+  hci::LeSubEventCode sub_event_code_;
+  std::unique_ptr<RawBuilder> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.cc
new file mode 100644
index 0000000..57203ed
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.cc
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/sco_packet_builder.h"
+
+#include <base/logging.h>
+
+using std::vector;
+using test_vendor_lib::sco::PacketStatusFlagsType;
+
+namespace test_vendor_lib {
+namespace packets {
+
+ScoPacketBuilder::ScoPacketBuilder(uint16_t handle, PacketStatusFlagsType packet_status_flags,
+                                   std::unique_ptr<BasePacketBuilder> payload)
+    : handle_(handle), packet_status_flags_(packet_status_flags), payload_(std::move(payload)) {}
+
+size_t ScoPacketBuilder::size() const {
+  return 2 * sizeof(uint16_t) + payload_->size();
+}
+
+void ScoPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint16_t>((handle_ & 0xfff) | (static_cast<uint16_t>(packet_status_flags_) << 12)), it);
+  uint8_t payload_size = payload_->size();
+
+  CHECK(static_cast<size_t>(payload_size) == payload_->size())
+      << "Payload too large for a SCO packet: " << payload_->size();
+  insert(payload_size, it);
+  payload_->Serialize(it);
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.h b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.h
new file mode 100644
index 0000000..a2d8561
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_builder.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "include/sco.h"
+#include "packets/hci/hci_packet_builder.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// SCO data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.3
+class ScoPacketBuilder : public HciPacketBuilder {
+ public:
+  virtual ~ScoPacketBuilder() override = default;
+
+  static std::unique_ptr<ScoPacketBuilder> Create(uint16_t handle, sco::PacketStatusFlagsType packet_status_flags,
+                                                  std::unique_ptr<BasePacketBuilder> payload);
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
+
+ private:
+  ScoPacketBuilder(uint16_t handle, sco::PacketStatusFlagsType packet_status_flags,
+                   std::unique_ptr<BasePacketBuilder> payload);
+  ScoPacketBuilder() = delete;
+  uint16_t handle_;
+  sco::PacketStatusFlagsType packet_status_flags_;
+  std::unique_ptr<BasePacketBuilder> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.cc b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.cc
new file mode 100644
index 0000000..9516ef4
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.cc
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/sco_packet_view.h"
+
+#include <base/logging.h>
+
+using test_vendor_lib::sco::PacketStatusFlagsType;
+
+namespace test_vendor_lib {
+namespace packets {
+
+ScoPacketView::ScoPacketView(std::shared_ptr<std::vector<uint8_t>> packet) : PacketView<true>(packet) {}
+
+ScoPacketView ScoPacketView::Create(std::shared_ptr<std::vector<uint8_t>> packet) {
+  return ScoPacketView(packet);
+}
+
+uint16_t ScoPacketView::GetHandle() const {
+  return begin().extract<uint16_t>() & 0xfff;
+}
+
+PacketStatusFlagsType ScoPacketView::GetPacketStatusFlags() const {
+  return static_cast<PacketStatusFlagsType>(((begin() + 1).extract<uint8_t>() & 0x30) >> 4);
+}
+
+PacketView<true> ScoPacketView::GetPayload() const {
+  uint8_t payload_size = (begin() + sizeof(uint16_t)).extract<uint8_t>();
+  CHECK(static_cast<uint8_t>(size() - sizeof(uint16_t) - sizeof(uint8_t)) == payload_size)
+      << "Malformed SCO packet payload_size " << payload_size << " + 4 != " << size();
+  return SubViewLittleEndian(sizeof(uint16_t) + sizeof(uint8_t), size());
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.h b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.h
new file mode 100644
index 0000000..26b9489
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/sco_packet_view.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <base/logging.h>
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "include/sco.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// SCO data packets are specified in the Bluetooth Core Specification Version
+// 4.2, Volume 2, Part E, Section 5.4.3
+class ScoPacketView : public PacketView<true> {
+ public:
+  virtual ~ScoPacketView() override = default;
+
+  static ScoPacketView Create(std::shared_ptr<std::vector<uint8_t>> packet);
+
+  uint16_t GetHandle() const;
+  sco::PacketStatusFlagsType GetPacketStatusFlags() const;
+  PacketView<true> GetPayload() const;
+
+ private:
+  ScoPacketView(std::shared_ptr<std::vector<uint8_t>> packet);
+  ScoPacketView() = delete;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/test/acl_builder_test.cc b/vendor_libs/test_vendor_lib/packets/hci/test/acl_builder_test.cc
new file mode 100644
index 0000000..61f8415
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/test/acl_builder_test.cc
@@ -0,0 +1,120 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/acl_packet_builder.h"
+#include "packets/hci/acl_packet_view.h"
+#include "packets/raw_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "types/address.h"
+
+using std::vector;
+using test_vendor_lib::acl::BroadcastFlagsType;
+using test_vendor_lib::acl::PacketBoundaryFlagsType;
+
+namespace {
+vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> information_request = {
+    0xfe, 0x2e, 0x0a, 0x00, 0x06, 0x00, 0x01, 0x00, 0x0a, 0x02, 0x02, 0x00, 0x02, 0x00,
+};
+
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+class AclBuilderTest : public ::testing::Test {
+ public:
+  AclBuilderTest() = default;
+  ~AclBuilderTest() = default;
+};
+
+TEST(AclBuilderTest, buildAclCountTest) {
+  uint16_t handle = 0x0102;
+  PacketBoundaryFlagsType packet_boundary_flags = PacketBoundaryFlagsType::FIRST_AUTOMATICALLY_FLUSHABLE;
+  BroadcastFlagsType broadcast_flags = BroadcastFlagsType::ACTIVE_SLAVE_BROADCAST;
+
+  std::unique_ptr<RawBuilder> count_payload = std::make_unique<RawBuilder>();
+  count_payload->AddOctets(count);
+  ASSERT_EQ(count.size(), count_payload->size());
+
+  std::unique_ptr<AclPacketBuilder> count_packet =
+      AclPacketBuilder::Create(handle, packet_boundary_flags, broadcast_flags, std::move(count_payload));
+
+  ASSERT_EQ(count.size() + 4, count_packet->size());
+
+  std::shared_ptr<std::vector<uint8_t>> count_packet_bytes = count_packet->ToVector();
+  AclPacketView count_packet_view = AclPacketView::Create(count_packet_bytes);
+
+  ASSERT_EQ(handle, count_packet_view.GetHandle());
+  ASSERT_EQ(packet_boundary_flags, count_packet_view.GetPacketBoundaryFlags());
+  ASSERT_EQ(broadcast_flags, count_packet_view.GetBroadcastFlags());
+  PacketView<true> count_view = count_packet_view.GetPayload();
+
+  ASSERT_EQ(count_view.size(), count.size());
+  for (size_t i = 0; i < count_view.size(); i++) {
+    ASSERT_EQ(count_view[i], count[i]);
+  }
+}
+
+TEST(AclBuilderTest, buildInformationRequest) {
+  uint16_t handle = 0x0efe;
+  PacketBoundaryFlagsType packet_boundary_flags = PacketBoundaryFlagsType::FIRST_AUTOMATICALLY_FLUSHABLE;
+  BroadcastFlagsType broadcast_flags = BroadcastFlagsType::POINT_TO_POINT;
+
+  std::vector<uint8_t> payload_bytes(information_request.begin() + 4, information_request.end());
+  std::unique_ptr<RawBuilder> payload = std::make_unique<RawBuilder>();
+  payload->AddOctets(payload_bytes);
+  ASSERT_EQ(payload_bytes.size(), payload->size());
+
+  std::unique_ptr<AclPacketBuilder> packet =
+      AclPacketBuilder::Create(handle, packet_boundary_flags, broadcast_flags, std::move(payload));
+
+  ASSERT_EQ(information_request.size(), packet->size());
+
+  std::shared_ptr<std::vector<uint8_t>> packet_bytes = packet->ToVector();
+  AclPacketView packet_view = AclPacketView::Create(packet_bytes);
+
+  ASSERT_EQ(packet_bytes->size(), information_request.size());
+  for (size_t i = 0; i < packet_bytes->size(); i++) {
+    ASSERT_EQ((*packet_bytes)[i], information_request[i]);
+  }
+
+  ASSERT_EQ(handle, packet_view.GetHandle());
+  ASSERT_EQ(packet_boundary_flags, packet_view.GetPacketBoundaryFlags());
+  ASSERT_EQ(broadcast_flags, packet_view.GetBroadcastFlags());
+  PacketView<true> payload_view = packet_view.GetPayload();
+
+  ASSERT_EQ(payload_view.size(), payload_bytes.size());
+  for (size_t i = 0; i < payload_view.size(); i++) {
+    ASSERT_EQ(payload_view[i], payload_bytes[i]);
+  }
+
+  ASSERT_EQ(packet_view.size(), information_request.size());
+  for (size_t i = 0; i < packet_view.size(); i++) {
+    ASSERT_EQ(packet_view[i], information_request[i]);
+  }
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/hci/test/event_builder_test.cc b/vendor_libs/test_vendor_lib/packets/hci/test/event_builder_test.cc
new file mode 100644
index 0000000..e63c866
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/hci/test/event_builder_test.cc
@@ -0,0 +1,161 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/hci/event_packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "types/address.h"
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+class EventBuilderTest : public ::testing::Test {
+ public:
+  EventBuilderTest() = default;
+  ~EventBuilderTest() = default;
+};
+
+TEST(EventBuilderTest, buildLeAdvertisementSmallTest) {
+  LeAdvertisement::AdvertisementType adv_type = LeAdvertisement::AdvertisementType::ADV_SCAN_IND;
+  LeAdvertisement::AddressType addr_type = LeAdvertisement::AddressType::RANDOM;
+  std::unique_ptr<EventPacketBuilder> le_adv = EventPacketBuilder::CreateLeAdvertisingReportEvent();
+  Address addr({1, 2, 3, 4, 5, 6});
+  uint8_t rssi = -93;
+
+  std::vector<uint8_t> payload({0x23});
+  le_adv->AddLeAdvertisingReport(adv_type, addr_type, addr, {payload}, rssi);
+
+  uint8_t payload_size = payload.size();
+  uint8_t event_size = payload_size + sizeof(Address) + sizeof(rssi) + 5;
+  std::vector<uint8_t> expected({
+      0x3e,  // HCI LE Event
+      event_size,
+      0x02,          // LE Advertising subevent code
+      0x01,          // Number of responses
+      0x02,          // Event type is scannable undirected
+      0x01,          // Address type is random
+      0x01,          // Address
+      0x02,          // Address
+      0x03,          // Address
+      0x04,          // Address
+      0x05,          // Address
+      0x06,          // Address
+      payload_size,  // Length of the data
+  });
+
+  expected.push_back(payload[0]);
+  expected.push_back(rssi);
+
+  ASSERT_EQ(expected.size(), le_adv->size());
+  ASSERT_EQ(expected, *le_adv->ToVector());
+}
+
+TEST(EventBuilderTest, buildLeAdvertisementTest) {
+  LeAdvertisement::AdvertisementType adv_type = LeAdvertisement::AdvertisementType::ADV_SCAN_IND;
+  LeAdvertisement::AddressType addr_type = LeAdvertisement::AddressType::RANDOM;
+  std::unique_ptr<EventPacketBuilder> le_adv = EventPacketBuilder::CreateLeAdvertisingReportEvent();
+  Address addr({1, 2, 3, 4, 5, 6});
+  uint8_t rssi = -93;
+
+  le_adv->AddLeAdvertisingReport(adv_type, addr_type, addr, count, rssi);
+
+  uint8_t count_size = static_cast<uint8_t>(count.size());
+  uint8_t event_size = count_size + sizeof(Address) + sizeof(rssi) + 5;
+  std::vector<uint8_t> expected({
+      0x3e,  // HCI LE Event
+      event_size,
+      0x02,        // LE Advertising subevent code
+      0x01,        // Number of responses
+      0x02,        // Event type is scannable undirected
+      0x01,        // Address type is random
+      0x01,        // Address
+      0x02,        // Address
+      0x03,        // Address
+      0x04,        // Address
+      0x05,        // Address
+      0x06,        // Address
+      count_size,  // Length of the data
+  });
+
+  for (size_t i = 0; i < count.size(); i++) {
+    expected.push_back(count[i]);
+  }
+  expected.push_back(rssi);
+
+  std::shared_ptr<std::vector<uint8_t>> raw_adv = le_adv->ToVector();
+  ASSERT_EQ(expected, *raw_adv);
+}
+
+TEST(EventBuilderTest, buildNumberOfCompletedPackets) {
+  uint16_t handle = 0x0102;
+  uint16_t num_packets = 0x0304;
+
+  std::unique_ptr<EventPacketBuilder> event =
+      EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(handle, num_packets);
+
+  uint8_t number_of_handles = 1;
+  uint8_t event_size = sizeof(uint8_t) + number_of_handles * 2 * sizeof(uint16_t);
+  std::vector<uint8_t> expected({
+      0x13,                           // HCI Number Of Completed Packets Event code
+      event_size, number_of_handles,  //
+      0x02, 0x01,                     // handle
+      0x04, 0x03,                     // count
+  });
+
+  std::shared_ptr<std::vector<uint8_t>> raw_event = event->ToVector();
+  ASSERT_EQ(expected, *raw_event);
+}
+
+TEST(EventBuilderTest, buildNumberOfCompletedPacketsMultiple) {
+  uint16_t handle = 0x0102;
+  uint16_t num_packets = 0x0304;
+  uint16_t handle2 = 0x0506;
+  uint16_t num_packets2 = 0x0708;
+
+  std::unique_ptr<EventPacketBuilder> event =
+      EventPacketBuilder::CreateNumberOfCompletedPacketsEvent(handle, num_packets);
+  event->AddCompletedPackets(handle2, num_packets2);
+
+  uint8_t number_of_handles = 2;
+  uint8_t event_size = sizeof(uint8_t) + number_of_handles * 2 * sizeof(uint16_t);
+  std::vector<uint8_t> expected({
+      0x13,                           // HCI Number Of Completed Packets Event code
+      event_size, number_of_handles,  //
+      0x02, 0x01,                     // handle
+      0x04, 0x03,                     // count
+      0x06, 0x05,                     // handle
+      0x08, 0x07,                     // count
+  });
+
+  std::shared_ptr<std::vector<uint8_t>> raw_event = event->ToVector();
+  ASSERT_EQ(expected, *raw_event);
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/iterator.cc b/vendor_libs/test_vendor_lib/packets/iterator.cc
new file mode 100644
index 0000000..65173ee
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/iterator.cc
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "iterator.h"
+
+#include <base/logging.h>
+
+namespace test_vendor_lib {
+namespace packets {
+
+template <bool little_endian>
+Iterator<little_endian>::Iterator(std::forward_list<View> data, size_t offset) {
+  data_ = data;
+  index_ = offset;
+  length_ = 0;
+  for (auto& view : data) {
+    length_ += view.size();
+  }
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator+(int offset) {
+  auto itr(*this);
+
+  return itr += offset;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator+=(int offset) {
+  index_ += offset;
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator++(int) {
+  auto itr(*this);
+  index_++;
+  return itr;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator++() {
+  index_++;
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator-(int offset) {
+  auto itr(*this);
+
+  return itr -= offset;
+}
+
+template <bool little_endian>
+int Iterator<little_endian>::operator-(Iterator<little_endian>& itr) {
+  return index_ - itr.index_;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator-=(int offset) {
+  index_ -= offset;
+
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian> Iterator<little_endian>::operator--(int) {
+  auto itr(*this);
+  if (index_ != 0) index_--;
+
+  return itr;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator--() {
+  if (index_ != 0) index_--;
+
+  return *this;
+}
+
+template <bool little_endian>
+Iterator<little_endian>& Iterator<little_endian>::operator=(const Iterator<little_endian>& itr) {
+  data_ = itr.data_;
+  index_ = itr.index_;
+
+  return *this;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator==(const Iterator<little_endian>& itr) const {
+  return index_ == itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator!=(const Iterator<little_endian>& itr) const {
+  return !(*this == itr);
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator<(const Iterator<little_endian>& itr) const {
+  return index_ < itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator>(const Iterator<little_endian>& itr) const {
+  return index_ > itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator<=(const Iterator<little_endian>& itr) const {
+  return index_ <= itr.index_;
+}
+
+template <bool little_endian>
+bool Iterator<little_endian>::operator>=(const Iterator<little_endian>& itr) const {
+  return index_ >= itr.index_;
+}
+
+template <bool little_endian>
+uint8_t Iterator<little_endian>::operator*() const {
+  CHECK(index_ < length_) << "Index " << index_ << " out of bounds: " << length_;
+  size_t index = index_;
+
+  for (auto view : data_) {
+    if (index < view.size()) {
+      return view[index];
+    }
+    index -= view.size();
+  }
+  CHECK(false) << "Out of fragments searching for Index " << index_;
+  return 0;
+}
+
+template <bool little_endian>
+size_t Iterator<little_endian>::NumBytesRemaining() const {
+  if (length_ > index_) {
+    return length_ - index_;
+  } else {
+    return 0;
+  }
+}
+
+// Explicit instantiations for both types of Iterators.
+template class Iterator<true>;
+template class Iterator<false>;
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/iterator.h b/vendor_libs/test_vendor_lib/packets/iterator.h
new file mode 100644
index 0000000..b84ce64
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/iterator.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+
+#include "types/address.h"
+#include "view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Templated Iterator for endianness
+template <bool little_endian>
+class Iterator : public std::iterator<std::random_access_iterator_tag, uint8_t> {
+ public:
+  Iterator(std::forward_list<View> data, size_t offset);
+  Iterator(const Iterator& itr) = default;
+  virtual ~Iterator() = default;
+
+  // All addition and subtraction operators are unbounded.
+  Iterator operator+(int offset);
+  Iterator& operator+=(int offset);
+  Iterator operator++(int);
+  Iterator& operator++();
+
+  Iterator operator-(int offset);
+  int operator-(Iterator& itr);
+  Iterator& operator-=(int offset);
+  Iterator operator--(int);
+  Iterator& operator--();
+
+  Iterator& operator=(const Iterator& itr);
+
+  bool operator!=(const Iterator& itr) const;
+  bool operator==(const Iterator& itr) const;
+
+  bool operator<(const Iterator& itr) const;
+  bool operator>(const Iterator& itr) const;
+
+  bool operator<=(const Iterator& itr) const;
+  bool operator>=(const Iterator& itr) const;
+
+  uint8_t operator*() const;
+  uint8_t operator->() const;
+
+  size_t NumBytesRemaining() const;
+
+  // Get the next sizeof(FixedWidthPODType) bytes and return the filled type
+  template <typename FixedWidthPODType>
+  FixedWidthPODType extract() {
+    static_assert(std::is_pod<FixedWidthPODType>::value, "Iterator::extract requires an fixed type.");
+    FixedWidthPODType extracted_value;
+    uint8_t* value_ptr = (uint8_t*)&extracted_value;
+
+    for (size_t i = 0; i < sizeof(FixedWidthPODType); i++) {
+      size_t index = (little_endian ? i : sizeof(FixedWidthPODType) - i - 1);
+      value_ptr[index] = *((*this)++);
+    }
+    return extracted_value;
+  }
+
+ private:
+  std::forward_list<View> data_;
+  size_t index_;
+  size_t length_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h
new file mode 100644
index 0000000..15a4ab8
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/command_builder.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class CommandBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~CommandBuilder() = default;
+
+  static std::unique_ptr<CommandBuilder> Create(uint16_t opcode, PacketView<true> args) {
+    return std::unique_ptr<CommandBuilder>(new CommandBuilder(opcode, args));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(opcode_) + args_.size();
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(opcode_, it);
+    for (const auto&& byte : args_) {
+      insert(byte, it);
+    }
+  }
+
+ private:
+  explicit CommandBuilder(uint16_t opcode, PacketView<true> args) : opcode_(opcode), args_(args) {}
+  uint16_t opcode_;
+  PacketView<true> args_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/command_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/command_view.h
new file mode 100644
index 0000000..0aa5683
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/command_view.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <log/log.h>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class CommandView : public PacketView<true> {
+ public:
+  CommandView(const CommandView&) = default;
+  virtual ~CommandView() = default;
+
+  static CommandView GetCommand(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::COMMAND);
+    return CommandView(view.GetPayload());
+  }
+
+  uint16_t GetOpcode() {
+    return begin().extract<uint16_t>();
+  }
+
+  Iterator<true> GetData() {
+    return begin() + sizeof(uint16_t);
+  }
+
+ private:
+  CommandView() = delete;
+  CommandView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h
new file mode 100644
index 0000000..3c5a9f4
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_builder.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class DisconnectBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~DisconnectBuilder() = default;
+
+  static std::unique_ptr<DisconnectBuilder> Create(uint8_t reason) {
+    return std::unique_ptr<DisconnectBuilder>(new DisconnectBuilder(reason));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(reason_);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    *it++ = reason_;
+  }
+
+ private:
+  explicit DisconnectBuilder(uint8_t reason) : reason_(reason) {}
+  uint8_t reason_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h
new file mode 100644
index 0000000..cdfcdc5
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/disconnect_view.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class DisconnectView : public PacketView<true> {
+ public:
+  DisconnectView(const DisconnectView&) = default;
+  virtual ~DisconnectView() = default;
+
+  static DisconnectView GetDisconnect(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::DISCONNECT);
+    return DisconnectView(view.GetPayload());
+  }
+
+  uint8_t GetReason() {
+    return at(0);
+  }
+
+ private:
+  DisconnectView() = delete;
+  DisconnectView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h
new file mode 100644
index 0000000..329ecdb
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_builder.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class EncryptConnectionBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~EncryptConnectionBuilder() = default;
+
+  static std::unique_ptr<EncryptConnectionBuilder> Create(const std::vector<uint8_t>& key) {
+    return std::unique_ptr<EncryptConnectionBuilder>(new EncryptConnectionBuilder(key));
+  }
+
+  virtual size_t size() const override {
+    return key_.size();
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert_vector(key_, it);
+  }
+
+ private:
+  explicit EncryptConnectionBuilder(const std::vector<uint8_t>& key) : key_(key.begin(), key.begin() + 16) {}
+  std::vector<uint8_t> key_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h
new file mode 100644
index 0000000..665fe98
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/encrypt_connection_view.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class EncryptConnectionView : public PacketView<true> {
+ public:
+  EncryptConnectionView(const EncryptConnectionView&) = default;
+  virtual ~EncryptConnectionView() = default;
+
+  static EncryptConnectionView GetEncryptConnection(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::ENCRYPT_CONNECTION ||
+          view.GetType() == Link::PacketType::ENCRYPT_CONNECTION_RESPONSE);
+    return EncryptConnectionView(view.GetPayload());
+  }
+
+  Iterator<true> GetKey() {
+    return begin();
+  }
+
+ private:
+  EncryptConnectionView() = delete;
+  EncryptConnectionView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h
new file mode 100644
index 0000000..6703316
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_builder.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "inquiry.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~InquiryBuilder() = default;
+
+  static std::unique_ptr<InquiryBuilder> Create(Inquiry::InquiryType inquiry_type) {
+    return std::unique_ptr<InquiryBuilder>(new InquiryBuilder(inquiry_type));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(uint8_t);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(static_cast<uint8_t>(inquiry_type_), it);
+  }
+
+ private:
+  explicit InquiryBuilder(Inquiry::InquiryType inquiry_type) : inquiry_type_(inquiry_type) {}
+  Inquiry::InquiryType inquiry_type_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h
new file mode 100644
index 0000000..694fe71
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_builder.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "include/inquiry.h"
+#include "packets/packet_builder.h"
+#include "types/class_of_device.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryResponseBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~InquiryResponseBuilder() = default;
+
+  static std::unique_ptr<InquiryResponseBuilder> CreateStandard(uint8_t page_scan_repetition_mode,
+                                                                const ClassOfDevice& class_of_device,
+                                                                uint16_t clock_offset) {
+    return std::unique_ptr<InquiryResponseBuilder>(new InquiryResponseBuilder(
+        Inquiry::InquiryType::STANDARD, page_scan_repetition_mode, class_of_device, clock_offset));
+  }
+  static std::unique_ptr<InquiryResponseBuilder> CreateRssi(uint8_t page_scan_repetition_mode,
+                                                            const ClassOfDevice& class_of_device, uint16_t clock_offset,
+                                                            uint8_t rssi) {
+    return std::unique_ptr<InquiryResponseBuilder>(new InquiryResponseBuilder(
+        Inquiry::InquiryType::RSSI, page_scan_repetition_mode, class_of_device, clock_offset, rssi));
+  }
+  static std::unique_ptr<InquiryResponseBuilder> CreateExtended(uint8_t page_scan_repetition_mode,
+                                                                const ClassOfDevice& class_of_device,
+                                                                uint16_t clock_offset, uint8_t rssi,
+                                                                const std::vector<uint8_t>& extended_data) {
+    return std::unique_ptr<InquiryResponseBuilder>(new InquiryResponseBuilder(
+        Inquiry::InquiryType::EXTENDED, page_scan_repetition_mode, class_of_device, clock_offset, rssi, extended_data));
+  }
+
+  virtual size_t size() const override {
+    size_t inquiry_size =
+        sizeof(inquiry_type_) + sizeof(page_scan_repetition_mode_) + sizeof(class_of_device_) + sizeof(clock_offset_);
+    if (inquiry_type_ == Inquiry::InquiryType::STANDARD) {
+      return inquiry_size;
+    }
+    inquiry_size += sizeof(rssi_);
+    if (inquiry_type_ == Inquiry::InquiryType::RSSI) {
+      return inquiry_size;
+    }
+
+    return inquiry_size + extended_data_.size();
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(static_cast<uint8_t>(inquiry_type_), it);
+    insert(page_scan_repetition_mode_, it);
+    insert_class_of_device(class_of_device_, it);
+    insert(clock_offset_, it);
+    if (inquiry_type_ == Inquiry::InquiryType::STANDARD) {
+      return;
+    }
+    insert(rssi_, it);
+    if (inquiry_type_ == Inquiry::InquiryType::RSSI) {
+      return;
+    }
+    insert_vector(extended_data_, it);
+  }
+
+ private:
+  Inquiry::InquiryType inquiry_type_;
+  uint8_t page_scan_repetition_mode_;
+  ClassOfDevice class_of_device_;
+  uint16_t clock_offset_;
+  uint8_t rssi_{0xff};
+  std::vector<uint8_t> extended_data_;
+  explicit InquiryResponseBuilder(Inquiry::InquiryType inquiry_type, uint8_t page_scan_repetition_mode,
+                                  const ClassOfDevice& class_of_device, uint16_t clock_offset)
+      : inquiry_type_(inquiry_type), page_scan_repetition_mode_(page_scan_repetition_mode),
+        class_of_device_(class_of_device), clock_offset_(clock_offset) {}
+  explicit InquiryResponseBuilder(Inquiry::InquiryType inquiry_type, uint8_t page_scan_repetition_mode,
+                                  const ClassOfDevice& class_of_device, uint16_t clock_offset, uint8_t rssi)
+      : inquiry_type_(inquiry_type), page_scan_repetition_mode_(page_scan_repetition_mode),
+        class_of_device_(class_of_device), clock_offset_(clock_offset), rssi_(rssi) {}
+  explicit InquiryResponseBuilder(Inquiry::InquiryType inquiry_type, uint8_t page_scan_repetition_mode,
+                                  const ClassOfDevice& class_of_device, uint16_t clock_offset, uint8_t rssi,
+                                  const std::vector<uint8_t>& extended_data)
+      : inquiry_type_(inquiry_type), page_scan_repetition_mode_(page_scan_repetition_mode),
+        class_of_device_(class_of_device), clock_offset_(clock_offset), rssi_(rssi), extended_data_(extended_data) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h
new file mode 100644
index 0000000..aac0585
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_response_view.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "include/inquiry.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryResponseView : public PacketView<true> {
+ public:
+  InquiryResponseView(const InquiryResponseView&) = default;
+  virtual ~InquiryResponseView() = default;
+
+  static InquiryResponseView GetInquiryResponse(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::INQUIRY_RESPONSE);
+    return InquiryResponseView(view.GetPayload());
+  }
+
+  Inquiry::InquiryType GetType() {
+    return static_cast<Inquiry::InquiryType>(at(0));
+  }
+
+  uint8_t GetPageScanRepetitionMode() {
+    return at(1);
+  }
+
+  ClassOfDevice GetClassOfDevice() {
+    size_t offset = 2 * sizeof(uint8_t);
+    return (begin() + offset).extract<ClassOfDevice>();
+  }
+
+  uint16_t GetClockOffset() {
+    size_t offset = 2 * sizeof(uint8_t) + 3;
+    return (begin() + offset).extract<uint16_t>();
+  }
+
+  uint8_t GetRssi() {
+    size_t offset = 2 * sizeof(uint8_t) + 3 + sizeof(uint16_t);
+    return at(offset);
+  }
+
+  Iterator<true> GetExtendedData() {
+    size_t offset = 2 * sizeof(uint8_t) + 3 + sizeof(uint16_t) + sizeof(uint8_t);
+    return begin() + offset;
+  }
+
+ private:
+  InquiryResponseView() = delete;
+  InquiryResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h
new file mode 100644
index 0000000..eee861c
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/inquiry_view.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "inquiry.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class InquiryView : public PacketView<true> {
+ public:
+  InquiryView(const InquiryView&) = default;
+  virtual ~InquiryView() = default;
+
+  static InquiryView GetInquiry(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::INQUIRY);
+    return InquiryView(view.GetPayload());
+  }
+
+  Inquiry::InquiryType GetType() {
+    return static_cast<Inquiry::InquiryType>(at(0));
+  }
+
+ private:
+  InquiryView() = delete;
+  InquiryView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h
new file mode 100644
index 0000000..79efb50
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_builder.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~IoCapabilityBuilder() = default;
+
+  static std::unique_ptr<IoCapabilityBuilder> Create(uint8_t io_capability, uint8_t oob_data_present,
+                                                     uint8_t authentication_requirements) {
+    return std::unique_ptr<IoCapabilityBuilder>(
+        new IoCapabilityBuilder(io_capability, oob_data_present, authentication_requirements));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(io_capability_) + sizeof(oob_data_present_) + sizeof(authentication_requirements_);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(io_capability_, it);
+    insert(oob_data_present_, it);
+    insert(authentication_requirements_, it);
+  }
+
+ private:
+  explicit IoCapabilityBuilder(uint8_t io_capability, uint8_t oob_data_present, uint8_t authentication_requirements)
+      : io_capability_(io_capability), oob_data_present_(oob_data_present),
+        authentication_requirements_(authentication_requirements) {}
+  uint8_t io_capability_;
+  uint8_t oob_data_present_;
+  uint8_t authentication_requirements_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h
new file mode 100644
index 0000000..c9e7601
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_builder.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityNegativeResponseBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~IoCapabilityNegativeResponseBuilder() = default;
+
+  static std::unique_ptr<IoCapabilityNegativeResponseBuilder> Create(uint8_t reason) {
+    return std::unique_ptr<IoCapabilityNegativeResponseBuilder>(new IoCapabilityNegativeResponseBuilder(reason));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(reason_);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(reason_, it);
+  }
+
+ private:
+  explicit IoCapabilityNegativeResponseBuilder(uint8_t reason) : reason_(reason) {}
+  uint8_t reason_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h
new file mode 100644
index 0000000..27c888f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_negative_response_view.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityNegativeResponseView : public PacketView<true> {
+ public:
+  IoCapabilityNegativeResponseView(const IoCapabilityNegativeResponseView&) = default;
+  virtual ~IoCapabilityNegativeResponseView() = default;
+
+  static IoCapabilityNegativeResponseView GetIoCapabilityNegativeResponse(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE);
+    return IoCapabilityNegativeResponseView(view.GetPayload());
+  }
+
+  uint8_t GetReason() {
+    return at(0);
+  }
+
+ private:
+  IoCapabilityNegativeResponseView() = delete;
+  IoCapabilityNegativeResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h
new file mode 100644
index 0000000..66c7564
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/io_capability_view.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class IoCapabilityView : public PacketView<true> {
+ public:
+  IoCapabilityView(const IoCapabilityView&) = default;
+  virtual ~IoCapabilityView() = default;
+
+  static IoCapabilityView GetIoCapability(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::IO_CAPABILITY_RESPONSE ||
+          view.GetType() == Link::PacketType::IO_CAPABILITY_REQUEST);
+    return IoCapabilityView(view.GetPayload());
+  }
+
+  uint8_t GetIoCapability() {
+    return at(0);
+  }
+  uint8_t GetOobDataPresent() {
+    return at(1);
+  }
+  uint8_t GetAuthenticationRequirements() {
+    return at(2);
+  }
+
+ private:
+  IoCapabilityView() = delete;
+  IoCapabilityView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h
new file mode 100644
index 0000000..18b3167
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_builder.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "include/le_advertisement.h"
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeAdvertisementBuilder : public PacketBuilder<true>, public LeAdvertisement {
+ public:
+  virtual ~LeAdvertisementBuilder() = default;
+
+  static std::unique_ptr<LeAdvertisementBuilder> Create(AddressType address_type, AdvertisementType advertisement_type,
+                                                        const std::vector<uint8_t>& advertisement) {
+    return std::unique_ptr<LeAdvertisementBuilder>(
+        new LeAdvertisementBuilder(address_type, advertisement_type, advertisement));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(address_type_) + sizeof(advertisement_type_) + advertisement_.size();
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(static_cast<uint8_t>(address_type_), it);
+    insert(static_cast<uint8_t>(advertisement_type_), it);
+    insert_vector(advertisement_, it);
+  }
+
+ private:
+  LeAdvertisementBuilder() = delete;
+  explicit LeAdvertisementBuilder(AddressType address_type, AdvertisementType advertisement_type,
+                                  const std::vector<uint8_t>& advertisement)
+      : address_type_(address_type), advertisement_type_(advertisement_type), advertisement_(advertisement) {}
+  AddressType address_type_;
+  AdvertisementType advertisement_type_;
+  std::vector<uint8_t> advertisement_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h
new file mode 100644
index 0000000..80e0367
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/le_advertisement_view.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <log/log.h>
+
+#include "include/link.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LeAdvertisementView : public PacketView<true>, public LeAdvertisement {
+ public:
+  LeAdvertisementView(const LeAdvertisementView&) = default;
+  virtual ~LeAdvertisementView() = default;
+
+  static LeAdvertisementView GetLeAdvertisementView(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::LE_ADVERTISEMENT || view.GetType() == Link::PacketType::LE_SCAN_RESPONSE);
+    return LeAdvertisementView(view.GetPayload());
+  }
+
+  AddressType GetAddressType() {
+    return static_cast<AddressType>(at(0));
+  }
+  AdvertisementType GetAdvertisementType() {
+    return static_cast<AdvertisementType>(at(1));
+  }
+  Iterator<true> GetData() {
+    return begin() + 2 * sizeof(uint8_t);
+  }
+
+ private:
+  LeAdvertisementView() = delete;
+  LeAdvertisementView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc
new file mode 100644
index 0000000..426244f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.cc
@@ -0,0 +1,170 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "link_layer_packet_builder.h"
+#include "link_layer_packet_view.h"
+
+#include "base/logging.h"
+
+using std::vector;
+
+namespace test_vendor_lib {
+
+namespace packets {
+
+LinkLayerPacketBuilder::LinkLayerPacketBuilder(Link::PacketType type, const Address& source, const Address& dest)
+    : type_(type), source_addr_(source), dest_addr_(dest) {}
+
+LinkLayerPacketBuilder::LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> packet,
+                                               const Address& source)
+    : type_(type), source_addr_(source), dest_addr_(Address::kEmpty), builder_(std::move(packet)) {}
+
+LinkLayerPacketBuilder::LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> packet,
+                                               const Address& source, const Address& dest)
+    : type_(type), source_addr_(source), dest_addr_(dest), builder_(std::move(packet)) {}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapAcl(std::unique_ptr<ViewForwarderBuilder> acl,
+                                                                        const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::ACL, std::move(acl), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapCommand(std::unique_ptr<CommandBuilder> command,
+                                                                            const Address& source,
+                                                                            const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::COMMAND, std::move(command), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapDisconnect(
+    std::unique_ptr<DisconnectBuilder> disconnect, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::DISCONNECT, std::move(disconnect), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapEncryptConnection(
+    std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::ENCRYPT_CONNECTION, std::move(encrypt_connection), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapEncryptConnectionResponse(
+    std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(new LinkLayerPacketBuilder(
+      Link::PacketType::ENCRYPT_CONNECTION_RESPONSE, std::move(encrypt_connection), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapInquiry(std::unique_ptr<InquiryBuilder> inquiry,
+                                                                            const Address& source) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::INQUIRY, std::move(inquiry), source));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapInquiryResponse(
+    std::unique_ptr<InquiryResponseBuilder> inquiry_response, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::INQUIRY_RESPONSE, std::move(inquiry_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapIoCapabilityRequest(
+    std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::IO_CAPABILITY_REQUEST, std::move(io_capability), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapIoCapabilityResponse(
+    std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::IO_CAPABILITY_RESPONSE, std::move(io_capability), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapIoCapabilityNegativeResponse(
+    std::unique_ptr<IoCapabilityNegativeResponseBuilder> io_capability_negative_response, const Address& source,
+    const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(new LinkLayerPacketBuilder(
+      Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE, std::move(io_capability_negative_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeAdvertisement(
+    std::unique_ptr<LeAdvertisementBuilder> advertisement, const Address& source) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::LE_ADVERTISEMENT, std::move(advertisement), source));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeScan(const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(new LinkLayerPacketBuilder(Link::PacketType::LE_SCAN, source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapLeScanResponse(
+    std::unique_ptr<LeAdvertisementBuilder> scan_response, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::LE_SCAN_RESPONSE, std ::move(scan_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapPage(std::unique_ptr<PageBuilder> page,
+                                                                         const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::PAGE, std::move(page), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapPageResponse(
+    std::unique_ptr<PageResponseBuilder> page_response, const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::PAGE_RESPONSE, std::move(page_response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapResponse(std::unique_ptr<ResponseBuilder> response,
+                                                                             const Address& source,
+                                                                             const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::RESPONSE, std::move(response), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::WrapSco(std::unique_ptr<ViewForwarderBuilder> sco,
+                                                                        const Address& source, const Address& dest) {
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(Link::PacketType::SCO, std::move(sco), source, dest));
+}
+
+std::shared_ptr<LinkLayerPacketBuilder> LinkLayerPacketBuilder::ReWrap(
+    const std::shared_ptr<std::vector<uint8_t>> raw_packet) {
+  LinkLayerPacketView received = LinkLayerPacketView::Create(raw_packet);
+  Link::PacketType packet_type = received.GetType();
+  Address source = received.GetSourceAddress();
+  Address dest = received.GetDestinationAddress();
+  PacketView<true> payload = received.GetPayload();
+  std::unique_ptr<PacketBuilder> builder = ViewForwarderBuilder::Create(payload);
+  return std::shared_ptr<LinkLayerPacketBuilder>(
+      new LinkLayerPacketBuilder(packet_type, std::move(builder), source, dest));
+}
+
+size_t LinkLayerPacketBuilder::size() const {
+  size_t builder_size = (builder_ ? builder_->size() : 0);
+  return Link::kTypeBytes + Link::kSizeBytes + 2 * Address::kLength + builder_size;
+}
+
+void LinkLayerPacketBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  insert(static_cast<uint32_t>(size() - Link::kSizeBytes), it);
+  insert(static_cast<uint8_t>(type_), it);
+  insert_address(source_addr_.address, it);
+  insert_address(dest_addr_.address, it);
+  if (builder_) {
+    builder_->Serialize(it);
+  }
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h
new file mode 100644
index 0000000..a9d7741
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_builder.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "link.h"
+#include "packets/link_layer/command_builder.h"
+#include "packets/link_layer/disconnect_builder.h"
+#include "packets/link_layer/encrypt_connection_builder.h"
+#include "packets/link_layer/inquiry_builder.h"
+#include "packets/link_layer/inquiry_response_builder.h"
+#include "packets/link_layer/io_capability_builder.h"
+#include "packets/link_layer/io_capability_negative_response_builder.h"
+#include "packets/link_layer/le_advertisement_builder.h"
+#include "packets/link_layer/page_builder.h"
+#include "packets/link_layer/page_response_builder.h"
+#include "packets/link_layer/response_builder.h"
+#include "packets/link_layer/view_forwarder_builder.h"
+#include "packets/packet_builder.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Link-layer packets are an abstraction of LMP PDUs.
+class LinkLayerPacketBuilder : PacketBuilder<true> {
+ public:
+  virtual ~LinkLayerPacketBuilder() = default;
+
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapAcl(std::unique_ptr<ViewForwarderBuilder> acl,
+                                                         const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapCommand(std::unique_ptr<CommandBuilder> command,
+                                                             const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapDisconnect(std::unique_ptr<DisconnectBuilder> disconnect,
+                                                                const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapEncryptConnection(
+      std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapEncryptConnectionResponse(
+      std::unique_ptr<EncryptConnectionBuilder> encrypt_connection, const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapInquiry(std::unique_ptr<InquiryBuilder> inquiry,
+                                                             const Address& source);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapInquiryResponse(
+      std::unique_ptr<InquiryResponseBuilder> inquiry_response, const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapIoCapabilityRequest(
+      std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapIoCapabilityResponse(
+      std::unique_ptr<IoCapabilityBuilder> io_capability, const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapIoCapabilityNegativeResponse(
+      std::unique_ptr<IoCapabilityNegativeResponseBuilder> io_capability_negative_response, const Address& source,
+      const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapLeAdvertisement(
+      std::unique_ptr<LeAdvertisementBuilder> advertisement, const Address& source);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapLeScan(const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapLeScanResponse(
+      std::unique_ptr<LeAdvertisementBuilder> scan_response, const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapPage(std::unique_ptr<PageBuilder> page, const Address& source,
+                                                          const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapPageResponse(std::unique_ptr<PageResponseBuilder> page_response,
+                                                                  const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapResponse(const std::unique_ptr<ResponseBuilder> response,
+                                                              const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> WrapSco(std::unique_ptr<ViewForwarderBuilder> sco,
+                                                         const Address& source, const Address& dest);
+  static std::shared_ptr<LinkLayerPacketBuilder> ReWrap(const std::shared_ptr<std::vector<uint8_t>> raw_packet);
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override;
+
+  virtual size_t size() const override;
+
+ private:
+  LinkLayerPacketBuilder(const LinkLayerPacketBuilder&) = delete;
+  LinkLayerPacketBuilder() = delete;
+  LinkLayerPacketBuilder(Link::PacketType type, const Address& source, const Address& dest);
+  LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> builder, const Address& source,
+                         const Address& dest);
+  LinkLayerPacketBuilder(Link::PacketType type, std::unique_ptr<PacketBuilder> builder, const Address& source);
+  Link::PacketType type_;
+  Address source_addr_;
+  Address dest_addr_;
+  std::unique_ptr<PacketBuilder> builder_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc
new file mode 100644
index 0000000..04518ca
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.cc
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "link_layer_packet_view.h"
+#include "base/logging.h"
+
+namespace test_vendor_lib {
+constexpr size_t Link::kSizeBytes;
+constexpr size_t Link::kTypeBytes;
+
+namespace packets {
+LinkLayerPacketView::LinkLayerPacketView(std::shared_ptr<std::vector<uint8_t>> raw) : PacketView<true>(raw) {}
+
+LinkLayerPacketView LinkLayerPacketView::Create(std::shared_ptr<std::vector<uint8_t>> raw) {
+  CHECK(raw->size() >= Link::kSizeBytes + Link::kTypeBytes + 2 * Address::kLength);
+  return LinkLayerPacketView(raw);
+}
+
+Link::PacketType LinkLayerPacketView::GetType() const {
+  return static_cast<Link::PacketType>(at(Link::kSizeBytes));
+}
+
+Address LinkLayerPacketView::GetSourceAddress() const {
+  size_t offset = Link::kSizeBytes + Link::kTypeBytes;
+  return (begin() + offset).extract<Address>();
+}
+
+Address LinkLayerPacketView::GetDestinationAddress() const {
+  size_t offset = Link::kSizeBytes + Link::kTypeBytes + Address::kLength;
+  return (begin() + offset).extract<Address>();
+}
+
+PacketView<true> LinkLayerPacketView::GetPayload() const {
+  return SubViewLittleEndian(Link::kSizeBytes + Link::kTypeBytes + 2 * Address::kLength, size());
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h
new file mode 100644
index 0000000..bdbfaa7
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/link_layer_packet_view.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "include/link.h"
+#include "packets/packet_view.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Link-layer packets are an abstraction of LMP PDUs.
+class LinkLayerPacketView : public PacketView<true> {
+ public:
+  LinkLayerPacketView(const LinkLayerPacketView&) = default;
+  virtual ~LinkLayerPacketView() = default;
+
+  static LinkLayerPacketView Create(std::shared_ptr<std::vector<uint8_t>> raw);
+
+  Link::PacketType GetType() const;
+  Address GetSourceAddress() const;
+  Address GetDestinationAddress() const;
+  PacketView<true> GetPayload() const;
+
+ private:
+  LinkLayerPacketView() = delete;
+  LinkLayerPacketView(std::shared_ptr<std::vector<uint8_t>> raw);
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h
new file mode 100644
index 0000000..0e18cb3
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_builder.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include <base/logging.h>
+
+#include "packets/packet_builder.h"
+#include "types/class_of_device.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~PageBuilder() = default;
+
+  static std::unique_ptr<PageBuilder> Create(const ClassOfDevice& class_of_device, uint8_t allow_role_switch) {
+    return std::unique_ptr<PageBuilder>(new PageBuilder(class_of_device, allow_role_switch));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(class_of_device_) + sizeof(allow_role_switch_);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert_class_of_device(class_of_device_, it);
+    insert(allow_role_switch_, it);
+  }
+
+ private:
+  explicit PageBuilder(const ClassOfDevice& class_of_device, uint8_t allow_role_switch)
+      : class_of_device_(class_of_device), allow_role_switch_(allow_role_switch) {}
+  ClassOfDevice class_of_device_;
+  uint8_t allow_role_switch_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h
new file mode 100644
index 0000000..78f9a80
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_builder.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageResponseBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~PageResponseBuilder() = default;
+
+  static std::unique_ptr<PageResponseBuilder> Create(uint8_t try_role_switch) {
+    return std::unique_ptr<PageResponseBuilder>(new PageResponseBuilder(try_role_switch));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(try_role_switch_);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(try_role_switch_, it);
+  }
+
+ private:
+  explicit PageResponseBuilder(uint8_t try_role_switch) : try_role_switch_(try_role_switch) {}
+  uint8_t try_role_switch_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h
new file mode 100644
index 0000000..20f0b68
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_response_view.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageResponseView : public PacketView<true> {
+ public:
+  PageResponseView(const PageResponseView&) = default;
+  virtual ~PageResponseView() = default;
+
+  static PageResponseView GetPageResponse(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::PAGE_RESPONSE);
+    return PageResponseView(view.GetPayload());
+  }
+
+  uint8_t GetTryRoleSwitch() {
+    return at(0);
+  }
+
+ private:
+  PageResponseView() = delete;
+  PageResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/page_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/page_view.h
new file mode 100644
index 0000000..a26446d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/page_view.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class PageView : public PacketView<true> {
+ public:
+  PageView(const PageView&) = default;
+  virtual ~PageView() = default;
+
+  static PageView GetPage(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::PAGE);
+    return PageView(view.GetPayload());
+  }
+
+  ClassOfDevice GetClassOfDevice() {
+    return begin().extract<ClassOfDevice>();
+  }
+
+  uint8_t GetAllowRoleSwitch() {
+    return at(3);
+  }
+
+ private:
+  PageView() = delete;
+  PageView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h
new file mode 100644
index 0000000..18f765d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/response_builder.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+#include <vector>
+
+#include "packets/packet_builder.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class ResponseBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~ResponseBuilder() = default;
+
+  static std::unique_ptr<ResponseBuilder> Create(uint16_t opcode, const std::vector<uint64_t>& data) {
+    return std::unique_ptr<ResponseBuilder>(new ResponseBuilder(opcode, data));
+  }
+
+  virtual size_t size() const override {
+    return sizeof(opcode_) + data_.size() * sizeof(uint64_t);
+  }
+
+ protected:
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    insert(opcode_, it);
+    insert_vector(data_, it);
+  }
+
+ private:
+  explicit ResponseBuilder(uint16_t opcode, const std::vector<uint64_t> data) : opcode_(opcode), data_(data) {}
+  uint16_t opcode_;
+  std::vector<uint64_t> data_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/response_view.h b/vendor_libs/test_vendor_lib/packets/link_layer/response_view.h
new file mode 100644
index 0000000..f1ff7c9
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/response_view.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+
+#include <log/log.h>
+
+#include "packets/link_layer/link_layer_packet_view.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class ResponseView : public PacketView<true> {
+ public:
+  ResponseView(const ResponseView&) = default;
+  virtual ~ResponseView() = default;
+
+  static ResponseView GetResponse(const LinkLayerPacketView& view) {
+    CHECK(view.GetType() == Link::PacketType::RESPONSE);
+    return ResponseView(view.GetPayload());
+  }
+
+  uint16_t GetOpcode() {
+    return begin().extract<uint16_t>();
+  }
+
+  Iterator<true> GetResponseData() {
+    return begin() + sizeof(uint16_t);
+  }
+
+ private:
+  ResponseView() = delete;
+  ResponseView(const PacketView<true>& view) : PacketView(view) {}
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h b/vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h
new file mode 100644
index 0000000..da0d827
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/link_layer/view_forwarder_builder.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <memory>
+
+#include "base/logging.h"
+
+#include "packets/packet_builder.h"
+#include "packets/packet_view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class ViewForwarderBuilder : public PacketBuilder<true> {
+ public:
+  virtual ~ViewForwarderBuilder() = default;
+
+  static std::unique_ptr<ViewForwarderBuilder> Create(PacketView<true> view) {
+    return std::unique_ptr<ViewForwarderBuilder>(new ViewForwarderBuilder(view));
+  }
+
+  virtual size_t size() const override {
+    return view_.size();
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    for (size_t i = 0; i < view_.size(); i++) {
+      insert(view_[i], it);
+    }
+  }
+
+ private:
+  explicit ViewForwarderBuilder(PacketView<true> view) : view_(view) {}
+  PacketView<true> view_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/packet_builder.h b/vendor_libs/test_vendor_lib/packets/packet_builder.h
new file mode 100644
index 0000000..947b02a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/packet_builder.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+#include <iterator>
+#include <memory>
+#include <vector>
+
+#include "base_packet_builder.h"
+#include "types/address.h"
+#include "types/class_of_device.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Abstract base class that is subclassed to build specifc packets.
+// The template parameter little_endian controls the generation of insert().
+template <bool little_endian>
+class PacketBuilder : public BasePacketBuilder {
+ public:
+  PacketBuilder() = default;
+  virtual ~PacketBuilder() = default;
+
+  // Classes which need fragmentation should define a function like this:
+  // std::forward_list<DerivedBuilder>& Fragment(size_t max_size);
+
+ protected:
+  // Write sizeof(FixedWidthIntegerType) bytes using the iterator
+  template <typename FixedWidthIntegerType,
+            typename std::enable_if<std::is_integral<FixedWidthIntegerType>::value, int>::type = 0>
+  void insert(FixedWidthIntegerType value, std::back_insert_iterator<std::vector<uint8_t>> it) const {
+    for (size_t i = 0; i < sizeof(FixedWidthIntegerType); i++) {
+      if (little_endian == true) {
+        *it = static_cast<uint8_t>(value >> (i * 8));
+      } else {
+        *it = static_cast<uint8_t>(value >> ((sizeof(FixedWidthIntegerType) - i - 1) * 8));
+      }
+      it++;
+    }
+  }
+
+  // Specialized insert that allows inserting enums without casting
+  template <typename Enum, typename std::enable_if<std::is_enum_v<Enum>, int>::type = 0>
+  inline void insert(Enum value, std::back_insert_iterator<std::vector<uint8_t>> it) const {
+    using enum_type = typename std::underlying_type_t<Enum>;
+    static_assert(std::is_unsigned_v<enum_type>, "Enum type is signed. Did you forget to specify the enum size?");
+    insert<enum_type>(static_cast<enum_type>(value), it);
+  }
+
+  // Write a vector of FixedWidthIntegerType using the iterator
+  template <typename FixedWidthIntegerType>
+  void insert_vector(const std::vector<FixedWidthIntegerType>& vec,
+                     std::back_insert_iterator<std::vector<uint8_t>> it) const {
+    static_assert(std::is_integral<FixedWidthIntegerType>::value,
+                  "PacketBuilder::insert requires an integral type vector.");
+    for (const auto& element : vec) {
+      insert(element, it);
+    }
+  }
+
+  void insert_address(const Address& addr, std::back_insert_iterator<std::vector<uint8_t>> it) const {
+    for (const auto& element : addr.address) {
+      insert(element, it);
+    }
+  }
+
+  void insert_class_of_device(const ClassOfDevice& cod, std::back_insert_iterator<std::vector<uint8_t>> it) const {
+    for (const auto& element : cod.cod) {
+      insert(element, it);
+    }
+  }
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/packet_view.cc b/vendor_libs/test_vendor_lib/packets/packet_view.cc
new file mode 100644
index 0000000..7ffe71a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/packet_view.cc
@@ -0,0 +1,106 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packet_view.h"
+
+#include <algorithm>
+
+#include <base/logging.h>
+
+namespace test_vendor_lib {
+namespace packets {
+
+template <bool little_endian>
+PacketView<little_endian>::PacketView(const std::forward_list<class View> fragments)
+    : fragments_(fragments), length_(0) {
+  for (auto fragment : fragments_) {
+    length_ += fragment.size();
+  }
+}
+
+template <bool little_endian>
+PacketView<little_endian>::PacketView(std::shared_ptr<std::vector<uint8_t>> packet)
+    : fragments_({View(packet, 0, packet->size())}), length_(packet->size()) {}
+
+template <bool little_endian>
+Iterator<little_endian> PacketView<little_endian>::begin() const {
+  return Iterator<little_endian>(this->fragments_, 0);
+}
+
+template <bool little_endian>
+Iterator<little_endian> PacketView<little_endian>::end() const {
+  return Iterator<little_endian>(this->fragments_, size());
+}
+
+template <bool little_endian>
+uint8_t PacketView<little_endian>::operator[](size_t index) const {
+  return at(index);
+}
+
+template <bool little_endian>
+uint8_t PacketView<little_endian>::at(size_t index) const {
+  CHECK(index < length_) << "Index " << index << " out of bounds";
+  for (const auto& fragment : fragments_) {
+    if (index < fragment.size()) {
+      return fragment[index];
+    }
+    index -= fragment.size();
+  }
+  CHECK(false) << "Out of fragments searching for Index " << index;
+  return 0;
+}
+
+template <bool little_endian>
+size_t PacketView<little_endian>::size() const {
+  return length_;
+}
+
+template <bool little_endian>
+std::forward_list<View> PacketView<little_endian>::SubViewList(size_t begin, size_t end) const {
+  CHECK(begin <= end) << "Begin " << begin << " is past end";
+  CHECK(end <= length_) << "End " << end << " is too large";
+  std::forward_list<View> view_list;
+  std::forward_list<View>::iterator it = view_list.before_begin();
+  size_t length = end - begin;
+  for (const auto& fragment : fragments_) {
+    if (begin >= fragment.size()) {
+      begin -= fragment.size();
+    } else {
+      View view(fragment, begin, begin + std::min(length, fragment.size() - begin));
+      length -= view.size();
+      it = view_list.insert_after(it, view);
+      begin = 0;
+    }
+  }
+  return view_list;
+}
+
+template <bool little_endian>
+PacketView<true> PacketView<little_endian>::SubViewLittleEndian(size_t begin, size_t end) const {
+  return PacketView<true>(SubViewList(begin, end));
+}
+
+template <bool little_endian>
+PacketView<false> PacketView<little_endian>::SubViewBigEndian(size_t begin, size_t end) const {
+  return PacketView<false>(SubViewList(begin, end));
+}
+
+// Explicit instantiations for both types of PacketViews.
+template class PacketView<true>;
+template class PacketView<false>;
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/packet_view.h b/vendor_libs/test_vendor_lib/packets/packet_view.h
new file mode 100644
index 0000000..16255fa
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/packet_view.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <forward_list>
+
+#include "iterator.h"
+#include "view.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Abstract base class that is subclassed to provide type-specifc accessors.
+// Holds a shared pointer to the underlying data.
+// The template parameter little_endian controls the generation of extract().
+template <bool little_endian>
+class PacketView {
+ public:
+  PacketView(const std::forward_list<class View> fragments);
+  PacketView(const PacketView& PacketView) = default;
+  virtual ~PacketView() = default;
+
+  virtual Iterator<little_endian> begin() const;
+
+  virtual Iterator<little_endian> end() const;
+
+  uint8_t operator[](size_t i) const;
+
+  uint8_t at(size_t index) const;
+
+  size_t size() const;
+
+  PacketView<true> SubViewLittleEndian(size_t begin, size_t end) const;
+
+  PacketView<false> SubViewBigEndian(size_t begin, size_t end) const;
+
+ protected:
+  PacketView(std::shared_ptr<std::vector<uint8_t>> packet);
+
+ private:
+  std::forward_list<View> fragments_;
+  size_t length_;
+  PacketView<little_endian>() = delete;
+  std::forward_list<View> SubViewList(size_t begin, size_t end) const;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/raw_builder.cc b/vendor_libs/test_vendor_lib/packets/raw_builder.cc
new file mode 100644
index 0000000..794fbb7
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/raw_builder.cc
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "raw_builder.h"
+
+#include <base/logging.h>
+#include <algorithm>
+
+using std::vector;
+
+namespace test_vendor_lib {
+namespace packets {
+
+RawBuilder::RawBuilder(size_t max_bytes) : max_bytes_(max_bytes) {}
+
+bool RawBuilder::AddOctets(size_t octets, const vector<uint8_t>& bytes) {
+  if (payload_.size() + octets > max_bytes_) return false;
+
+  if (octets != bytes.size()) return false;
+
+  payload_.insert(payload_.end(), bytes.begin(), bytes.end());
+
+  return true;
+}
+
+bool RawBuilder::AddOctets(const vector<uint8_t>& bytes) {
+  return AddOctets(bytes.size(), bytes);
+}
+
+bool RawBuilder::AddOctets(size_t octets, uint64_t value) {
+  vector<uint8_t> val_vector;
+
+  uint64_t v = value;
+
+  if (octets > sizeof(uint64_t)) return false;
+
+  for (size_t i = 0; i < octets; i++) {
+    val_vector.push_back(v & 0xff);
+    v = v >> 8;
+  }
+
+  if (v != 0) return false;
+
+  return AddOctets(octets, val_vector);
+}
+
+bool RawBuilder::AddAddress(const Address& address) {
+  if (payload_.size() + Address::kLength > max_bytes_) return false;
+
+  for (size_t i = 0; i < Address::kLength; i++) {
+    payload_.push_back(address.address[i]);
+  }
+  return true;
+}
+
+bool RawBuilder::AddOctets1(uint8_t value) {
+  return AddOctets(1, value);
+}
+
+bool RawBuilder::AddOctets2(uint16_t value) {
+  return AddOctets(2, value);
+}
+
+bool RawBuilder::AddOctets3(uint32_t value) {
+  return AddOctets(3, value);
+}
+
+bool RawBuilder::AddOctets4(uint32_t value) {
+  return AddOctets(4, value);
+}
+
+bool RawBuilder::AddOctets6(uint64_t value) {
+  return AddOctets(6, value);
+}
+
+bool RawBuilder::AddOctets8(uint64_t value) {
+  return AddOctets(8, value);
+}
+
+bool RawBuilder::CanAddOctets(size_t num_bytes) const {
+  return payload_.size() + num_bytes <= max_bytes_;
+}
+
+void RawBuilder::Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const {
+  for (const auto& val : payload_) {
+    insert(val, it);
+  }
+}
+
+size_t RawBuilder::size() const {
+  return payload_.size();
+}
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/raw_builder.h b/vendor_libs/test_vendor_lib/packets/raw_builder.h
new file mode 100644
index 0000000..cbc7d6f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/raw_builder.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+#include "packets/packet_builder.h"
+#include "types/address.h"
+
+namespace test_vendor_lib {
+namespace packets {
+
+class RawBuilder : public PacketBuilder<true> {
+ public:
+  RawBuilder() = default;
+  RawBuilder(size_t max_bytes);
+  virtual ~RawBuilder() = default;
+
+  virtual size_t size() const override;
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const;
+
+  // Add |address| to the payload.  Return true if:
+  // - the new size of the payload is still <= |max_bytes_|
+  bool AddAddress(const Address& address);
+
+  // Return true if |num_bytes| can be added to the payload.
+  bool CanAddOctets(size_t num_bytes) const;
+
+  // Add |octets| bytes to the payload.  Return true if:
+  // - the size of |bytes| is equal to |octets| and
+  // - the new size of the payload is still <= |max_bytes_|
+  bool AddOctets(size_t octets, const std::vector<uint8_t>& bytes);
+
+  bool AddOctets(const std::vector<uint8_t>& bytes);
+
+  bool AddOctets1(uint8_t value);
+  bool AddOctets2(uint16_t value);
+  bool AddOctets3(uint32_t value);
+  bool AddOctets4(uint32_t value);
+  bool AddOctets6(uint64_t value);
+  bool AddOctets8(uint64_t value);
+
+ private:
+  // Add |octets| bytes to the payload.  Return true if:
+  // - the value of |value| fits in |octets| bytes and
+  // - the new size of the payload is still <= |max_bytes_|
+  bool AddOctets(size_t octets, uint64_t value);
+
+  size_t max_bytes_{255};
+
+  // Underlying containers for storing the actual packet
+  std::vector<uint8_t> payload_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/test/counted_builder_test.cc b/vendor_libs/test_vendor_lib/packets/test/counted_builder_test.cc
new file mode 100644
index 0000000..8d4d53a
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/test/counted_builder_test.cc
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/counted_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "types/address.h"
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+class CountedBuilderTest : public ::testing::Test {
+ public:
+  CountedBuilderTest() = default;
+  ~CountedBuilderTest() = default;
+};
+
+TEST(CountedBuilderTest, buildCountTest) {
+  std::unique_ptr<CountedBuilder> count_builder = std::make_unique<CountedBuilder>();
+  ASSERT_EQ(1u, count_builder->size());
+  std::unique_ptr<RawBuilder> raw1 = std::make_unique<RawBuilder>();
+  std::unique_ptr<RawBuilder> raw2 = std::make_unique<RawBuilder>();
+  std::unique_ptr<RawBuilder> raw3 = std::make_unique<RawBuilder>();
+  std::unique_ptr<RawBuilder> raw4 = std::make_unique<RawBuilder>();
+  std::unique_ptr<RawBuilder> raw5 = std::make_unique<RawBuilder>();
+  std::unique_ptr<RawBuilder> raw6 = std::make_unique<RawBuilder>();
+  std::unique_ptr<RawBuilder> raw7 = std::make_unique<RawBuilder>();
+  raw1->AddOctets8(0x0706050403020100);
+  raw2->AddOctets4(0x0b0a0908);
+  raw3->AddOctets2(0x0d0c);
+  raw4->AddOctets1(0x0e);
+  raw5->AddOctets1(0x0f);
+  raw6->AddAddress(Address({0x10, 0x11, 0x12, 0x13, 0x14, 0x15}));
+  std::vector<uint8_t> count_subset(count.begin() + 0x16, count.end());
+  raw7->AddOctets(count_subset);
+
+  count_builder->Add(std::move(raw1));
+  count_builder->Add(std::move(raw2));
+  count_builder->Add(std::move(raw3));
+  count_builder->Add(std::move(raw4));
+  count_builder->Add(std::move(raw5));
+  count_builder->Add(std::move(raw6));
+  count_builder->Add(std::move(raw7));
+
+  ASSERT_EQ(count.size(), count_builder->size() - 1);
+
+  std::vector<uint8_t> packet;
+  std::back_insert_iterator<std::vector<uint8_t>> it(packet);
+
+  count_builder->Serialize(it);
+  ASSERT_EQ(7u, packet[0]);
+  std::vector<uint8_t> payload_packet(packet.begin() + 1, packet.end());
+
+  ASSERT_EQ(count, payload_packet);
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc b/vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc
new file mode 100644
index 0000000..cc6c460
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/test/link_layer_packet_builder_test.cc
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/link_layer/link_layer_packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "link.h"
+#include "packets/link_layer/command_view.h"
+#include "packets/link_layer/disconnect_view.h"
+#include "packets/link_layer/encrypt_connection_view.h"
+#include "packets/link_layer/inquiry_response_view.h"
+#include "packets/link_layer/inquiry_view.h"
+#include "packets/link_layer/io_capability_negative_response_view.h"
+#include "packets/link_layer/io_capability_view.h"
+#include "packets/link_layer/le_advertisement_view.h"
+#include "packets/link_layer/page_response_view.h"
+#include "packets/link_layer/page_view.h"
+#include "packets/link_layer/response_view.h"
+
+#include "base/logging.h"
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+class LinkLayerPacketBuilderTest : public ::testing::Test {
+ public:
+  LinkLayerPacketBuilderTest() = default;
+  ~LinkLayerPacketBuilderTest() = default;
+
+  Address source_{{0x01, 0x02, 0x03, 0x04, 0x05, 0x06}};
+  Address dest_{{0x11, 0x12, 0x13, 0x14, 0x15, 0x16}};
+};
+
+TEST_F(LinkLayerPacketBuilderTest, constructorTest) {
+  uint8_t reason = 0xf2;
+  auto disconnect = DisconnectBuilder::Create(reason);
+  ASSERT_EQ(disconnect->size(), sizeof(reason));
+  auto wrapped_disconnect = LinkLayerPacketBuilder::WrapDisconnect(std::move(disconnect), source_, dest_);
+
+  size_t wrapped_size = sizeof(uint8_t) + sizeof(uint32_t) + 2 * sizeof(Address) + sizeof(reason);
+  ASSERT_EQ(wrapped_disconnect->size(), wrapped_size);
+  std::vector<uint8_t> wrapped_vect;
+  std::back_insert_iterator<std::vector<uint8_t>> it(wrapped_vect);
+  wrapped_disconnect->Serialize(it);
+  ASSERT_EQ(wrapped_size, wrapped_vect.size());
+
+  std::vector<uint8_t> hand_wrapped_vect;
+  // Add the size
+  hand_wrapped_vect.push_back(sizeof(uint8_t) + 2 * sizeof(Address) + sizeof(reason));
+  hand_wrapped_vect.push_back(0);
+  hand_wrapped_vect.push_back(0);
+  hand_wrapped_vect.push_back(0);
+
+  hand_wrapped_vect.push_back(static_cast<uint8_t>(Link::PacketType::DISCONNECT));
+
+  for (auto byte : source_.address) {
+    hand_wrapped_vect.push_back(byte);
+  }
+  for (auto byte : dest_.address) {
+    hand_wrapped_vect.push_back(byte);
+  }
+  hand_wrapped_vect.push_back(reason);
+  ASSERT_EQ(wrapped_vect, hand_wrapped_vect);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, disconnectTest) {
+  uint8_t reason = 0x32;
+  auto disconnect_builder = DisconnectBuilder::Create(reason);
+  auto wrapped_disconnect = LinkLayerPacketBuilder::WrapDisconnect(std::move(disconnect_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_disconnect->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_disconnect->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::DISCONNECT);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  DisconnectView disconnect = DisconnectView::GetDisconnect(view);
+  ASSERT_EQ(disconnect.GetReason(), reason);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, encryptConnectionTest) {
+  std::vector<uint8_t> key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  auto encrypt_connection_builder = EncryptConnectionBuilder::Create(key);
+  auto wrapped_encrypt_connection =
+      LinkLayerPacketBuilder::WrapEncryptConnection(std::move(encrypt_connection_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_encrypt_connection->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_encrypt_connection->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::ENCRYPT_CONNECTION);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  EncryptConnectionView encrypt_connection = EncryptConnectionView::GetEncryptConnection(view);
+  auto key_itr = encrypt_connection.GetKey();
+  ASSERT_EQ(key_itr.NumBytesRemaining(), key.size());
+  for (size_t i = 0; i < key.size(); i++) {
+    ASSERT_EQ(key[i], key_itr.extract<uint8_t>());
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, encryptConnectionResponseTest) {
+  std::vector<uint8_t> key = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
+  auto encrypt_connection_builder = EncryptConnectionBuilder::Create(key);
+  auto wrapped_encrypt_connection_response =
+      LinkLayerPacketBuilder::WrapEncryptConnectionResponse(std::move(encrypt_connection_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_encrypt_connection_response->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_encrypt_connection_response->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::ENCRYPT_CONNECTION_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  EncryptConnectionView encrypt_connection = EncryptConnectionView::GetEncryptConnection(view);
+  auto key_itr = encrypt_connection.GetKey();
+  ASSERT_EQ(key_itr.NumBytesRemaining(), key.size());
+  for (size_t i = 0; i < key.size(); i++) {
+    ASSERT_EQ(key[i], key_itr.extract<uint8_t>());
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, inquiryTest) {
+  Inquiry::InquiryType inquiry_type = Inquiry::InquiryType::RSSI;
+  auto inquiry_builder = InquiryBuilder::Create(inquiry_type);
+  auto wrapped_inquiry = LinkLayerPacketBuilder::WrapInquiry(std::move(inquiry_builder), source_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_inquiry->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_inquiry->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(Address::kEmpty, view.GetDestinationAddress());
+  ASSERT_EQ(InquiryView::GetInquiry(view).GetType(), inquiry_type);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, standardInquiryResponseTest) {
+  uint8_t mode = 23;
+  ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+  uint16_t offset = 0x3456;
+  auto inquiry_response_builder = InquiryResponseBuilder::CreateStandard(mode, class_of_device, offset);
+  auto wrapped_inquiry =
+      LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_inquiry->Serialize(it);
+  ASSERT_EQ(packet_ptr->size(), 24u);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_inquiry->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  ASSERT_EQ(view.GetPayload().size(), 7u);
+  InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(view);
+  ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+  ASSERT_EQ(inquiry_response.GetType(), Inquiry::InquiryType::STANDARD);
+  ASSERT_EQ(inquiry_response.GetPageScanRepetitionMode(), mode);
+  ASSERT_EQ(inquiry_response.GetClassOfDevice(), class_of_device);
+  ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, rssiInquiryResponseTest) {
+  uint8_t mode = 23;
+  ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+  uint16_t offset = 0x3456;
+  uint8_t rssi = 0x78;
+  auto inquiry_response_builder = InquiryResponseBuilder::CreateRssi(mode, class_of_device, offset, rssi);
+  auto wrapped_inquiry =
+      LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_inquiry->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_inquiry->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(view);
+  ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+  ASSERT_EQ(inquiry_response.GetType(), Inquiry::InquiryType::RSSI);
+  ASSERT_EQ(inquiry_response.GetPageScanRepetitionMode(), mode);
+  ASSERT_EQ(inquiry_response.GetClassOfDevice(), class_of_device);
+  ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+  ASSERT_EQ(inquiry_response.GetRssi(), rssi);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, extendedInquiryResponseTest) {
+  uint8_t mode = 23;
+  ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+  uint16_t offset = 0x3456;
+  uint8_t rssi = 0x78;
+  auto inquiry_response_builder = InquiryResponseBuilder::CreateExtended(mode, class_of_device, offset, rssi, count);
+  auto wrapped_inquiry =
+      LinkLayerPacketBuilder::WrapInquiryResponse(std::move(inquiry_response_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_inquiry->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_inquiry->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::INQUIRY_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  InquiryResponseView inquiry_response = InquiryResponseView::GetInquiryResponse(view);
+  ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+  ASSERT_EQ(inquiry_response.GetType(), Inquiry::InquiryType::EXTENDED);
+  ASSERT_EQ(inquiry_response.GetPageScanRepetitionMode(), mode);
+  ASSERT_EQ(inquiry_response.GetClassOfDevice(), class_of_device);
+  ASSERT_EQ(inquiry_response.GetClockOffset(), offset);
+  ASSERT_EQ(inquiry_response.GetRssi(), rssi);
+  auto ext_it = inquiry_response.GetExtendedData();
+  ASSERT_EQ(ext_it.NumBytesRemaining(), count.size());
+  for (size_t i = 0; i < count.size(); i++) {
+    ASSERT_EQ(count[i], *(ext_it++));
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, ioCapabilityRequestTest) {
+  uint8_t io_cap = 0x2;
+  uint8_t oob_data_present = 0x1;
+  uint8_t authentication_requirements = 0x5;
+  auto io_capability_builder = IoCapabilityBuilder::Create(io_cap, oob_data_present, authentication_requirements);
+  auto wrapped_io_capability_request =
+      LinkLayerPacketBuilder::WrapIoCapabilityRequest(std::move(io_capability_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_io_capability_request->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_io_capability_request->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::IO_CAPABILITY_REQUEST);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  IoCapabilityView io_capability = IoCapabilityView::GetIoCapability(view);
+  ASSERT_EQ(io_capability.GetIoCapability(), io_cap);
+  ASSERT_EQ(io_capability.GetOobDataPresent(), oob_data_present);
+  ASSERT_EQ(io_capability.GetAuthenticationRequirements(), authentication_requirements);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, ioCapabilityResponseTest) {
+  uint8_t io_cap = 0x2;
+  uint8_t oob_data_present = 0x1;
+  uint8_t authentication_requirements = 0x5;
+  auto io_capability_builder = IoCapabilityBuilder::Create(io_cap, oob_data_present, authentication_requirements);
+  auto wrapped_io_capability_response =
+      LinkLayerPacketBuilder::WrapIoCapabilityResponse(std::move(io_capability_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_io_capability_response->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_io_capability_response->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::IO_CAPABILITY_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  IoCapabilityView io_capability = IoCapabilityView::GetIoCapability(view);
+  ASSERT_EQ(io_capability.GetIoCapability(), io_cap);
+  ASSERT_EQ(io_capability.GetOobDataPresent(), oob_data_present);
+  ASSERT_EQ(io_capability.GetAuthenticationRequirements(), authentication_requirements);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, ioCapabilityNegativeResponseTest) {
+  uint8_t reason = 23;
+  auto io_capability_negative_response_builder = IoCapabilityNegativeResponseBuilder::Create(reason);
+  auto wrapped_io_capability_negative_response = LinkLayerPacketBuilder::WrapIoCapabilityNegativeResponse(
+      std::move(io_capability_negative_response_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_io_capability_negative_response->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_io_capability_negative_response->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::IO_CAPABILITY_NEGATIVE_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  IoCapabilityNegativeResponseView io_capability_negative_response =
+      IoCapabilityNegativeResponseView::GetIoCapabilityNegativeResponse(view);
+  ASSERT_EQ(io_capability_negative_response.GetReason(), reason);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, pageTest) {
+  uint8_t allow_role_switch = 1;
+  ClassOfDevice class_of_device{{0x11, 0x22, 0x33}};
+  auto page_builder = PageBuilder::Create(class_of_device, allow_role_switch);
+  auto wrapped_page = LinkLayerPacketBuilder::WrapPage(std::move(page_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_page->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_page->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::PAGE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  PageView page = PageView::GetPage(view);
+  ASSERT_EQ(page.GetAllowRoleSwitch(), allow_role_switch);
+  ASSERT_EQ(page.GetClassOfDevice(), class_of_device);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, pageResponseTest) {
+  uint8_t try_role_switch = 2;
+  auto page_response_builder = PageResponseBuilder::Create(try_role_switch);
+  auto wrapped_page_response =
+      LinkLayerPacketBuilder::WrapPageResponse(std::move(page_response_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_page_response->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_page_response->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::PAGE_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  PageResponseView page_response = PageResponseView::GetPageResponse(view);
+  ASSERT_EQ(page_response.GetTryRoleSwitch(), try_role_switch);
+}
+
+TEST_F(LinkLayerPacketBuilderTest, responseTest) {
+  uint16_t opcode = 0x1234;
+  std::vector<uint64_t> data{
+      0x7060504030201000, 0x7161514131211101, 0x7262524232221202, 0x7363534333231303,
+      0x7464544434241404, 0x7565554535251505, 0x7666564636261606, 0x7767574737271707,
+      0x7868584838281808, 0x7969594939291909, 0x7a6a5a4a3a2a1a0a, 0x7b6b5b4b3b2b1b0b,
+      0x7c6c5c4c3c2c1c0c, 0x7d6d5d4d3d2d1d0d, 0x7e6e5e4e3e2e1e0e, 0x7f6f5f4f3f2f1f0f,
+  };
+  auto response_builder = ResponseBuilder::Create(opcode, data);
+  auto wrapped_response = LinkLayerPacketBuilder::WrapResponse(std::move(response_builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_response->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_response->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  ResponseView response = ResponseView::GetResponse(view);
+  ASSERT_EQ(opcode, response.GetOpcode());
+  auto data_it = response.GetResponseData();
+  ASSERT_EQ(data.size(), data_it.NumBytesRemaining() / sizeof(uint64_t));
+  ASSERT_EQ(0u, data_it.NumBytesRemaining() % sizeof(uint64_t));
+  for (size_t i = 0; i < data.size(); i++) {
+    ASSERT_EQ(data[i], data_it.extract<uint64_t>());
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapAclTest) {
+  std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+  View count_view(count_shared, 0, count_shared->size());
+  PacketView<true> count_packet_view({count_view});
+  auto builder = ViewForwarderBuilder::Create(count_packet_view);
+  auto wrapped_acl = LinkLayerPacketBuilder::WrapAcl(std::move(builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_acl->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_acl->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::ACL);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  auto acl_view = view.GetPayload();
+  ASSERT_EQ(acl_view.size(), count_view.size());
+  for (size_t i = 0; i < count_view.size(); i++) {
+    ASSERT_EQ(acl_view[i], count_view[i]);
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapCommandTest) {
+  uint16_t opcode = 0x0102;
+  std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+  View count_view(count_shared, 0, count_shared->size());
+  PacketView<true> args({count_view});
+  auto builder = CommandBuilder::Create(opcode, args);
+  auto wrapped_command = LinkLayerPacketBuilder::WrapCommand(std::move(builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_command->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_command->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::COMMAND);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  auto command_view = CommandView::GetCommand(view);
+  ASSERT_EQ(opcode, command_view.GetOpcode());
+  auto args_itr = command_view.GetData();
+  ASSERT_EQ(args_itr.NumBytesRemaining(), count.size());
+  for (size_t i = 0; i < count.size(); i++) {
+    ASSERT_EQ(*args_itr++, count[i]);
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapLeAdvertisementTest) {
+  LeAdvertisement::AddressType address_type = LeAdvertisement::AddressType::RANDOM;
+  LeAdvertisement::AdvertisementType advertisement_type = LeAdvertisement::AdvertisementType::ADV_NONCONN_IND;
+  auto builder = LeAdvertisementBuilder::Create(address_type, advertisement_type, count);
+  auto wrapped_le_advertisement = LinkLayerPacketBuilder::WrapLeAdvertisement(std::move(builder), source_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_le_advertisement->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_le_advertisement->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::LE_ADVERTISEMENT);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(Address::kEmpty, view.GetDestinationAddress());
+  LeAdvertisementView le_advertisement_view = LeAdvertisementView::GetLeAdvertisementView(view);
+  ASSERT_EQ(address_type, le_advertisement_view.GetAddressType());
+  ASSERT_EQ(advertisement_type, le_advertisement_view.GetAdvertisementType());
+  auto le_advertisement_itr = le_advertisement_view.GetData();
+  ASSERT_EQ(le_advertisement_itr.NumBytesRemaining(), count.size());
+  for (size_t i = 0; i < count.size(); i++) {
+    ASSERT_EQ(*(le_advertisement_itr++), count[i]);
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapLeScanTest) {
+  auto le_scan = LinkLayerPacketBuilder::WrapLeScan(source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  le_scan->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), le_scan->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::LE_SCAN);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  auto le_scan_view = view.GetPayload();
+  ASSERT_EQ(0u, le_scan_view.size());
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapLeScanResponseTest) {
+  LeAdvertisement::AddressType address_type = LeAdvertisement::AddressType::PUBLIC_IDENTITY;
+  LeAdvertisement::AdvertisementType advertisement_type = LeAdvertisement::AdvertisementType::SCAN_RESPONSE;
+  auto builder = LeAdvertisementBuilder::Create(address_type, advertisement_type, count);
+  auto wrapped_scan_response = LinkLayerPacketBuilder::WrapLeScanResponse(std::move(builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_scan_response->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_scan_response->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::LE_SCAN_RESPONSE);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  LeAdvertisementView le_advertisement_view = LeAdvertisementView::GetLeAdvertisementView(view);
+  ASSERT_EQ(address_type, le_advertisement_view.GetAddressType());
+  ASSERT_EQ(advertisement_type, le_advertisement_view.GetAdvertisementType());
+  auto scan_response_itr = le_advertisement_view.GetData();
+  ASSERT_EQ(scan_response_itr.NumBytesRemaining(), count.size());
+  for (size_t i = 0; i < count.size(); i++) {
+    ASSERT_EQ((*scan_response_itr++), count[i]);
+  }
+}
+
+TEST_F(LinkLayerPacketBuilderTest, wrapScoTest) {
+  std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+  View count_view(count_shared, 0, count_shared->size());
+  PacketView<true> count_packet_view({count_view});
+  auto builder = ViewForwarderBuilder::Create(count_packet_view);
+  auto wrapped_sco = LinkLayerPacketBuilder::WrapSco(std::move(builder), source_, dest_);
+  std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+  std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+  wrapped_sco->Serialize(it);
+
+  LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+  ASSERT_EQ(view.size(), wrapped_sco->size());
+  ASSERT_EQ(view.GetType(), Link::PacketType::SCO);
+  ASSERT_EQ(source_, view.GetSourceAddress());
+  ASSERT_EQ(dest_, view.GetDestinationAddress());
+  auto sco_view = view.GetPayload();
+  ASSERT_EQ(sco_view.size(), count.size());
+  for (size_t i = 0; i < count.size(); i++) {
+    ASSERT_EQ(sco_view[i], count[i]);
+  }
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/test/packet_builder_test.cc b/vendor_libs/test_vendor_lib/packets/test/packet_builder_test.cc
new file mode 100644
index 0000000..60e5d95
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/test/packet_builder_test.cc
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count_all = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> count_1 = {
+    0x00,
+    0x01,
+    0x02,
+};
+
+vector<uint8_t> count_2 = {
+    0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+vector<uint8_t> count_3 = {
+    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+template <bool little_endian>
+class EndianBuilder : public PacketBuilder<little_endian> {
+ public:
+  EndianBuilder(uint8_t byte, uint16_t two_bytes, uint32_t four_bytes, uint64_t eight_bytes)
+      : byte_(byte), two_bytes_(two_bytes), four_bytes_(four_bytes), eight_bytes_(eight_bytes) {}
+  ~EndianBuilder() = default;
+
+  virtual size_t size() const override {
+    return sizeof(signature_) + sizeof(byte_) + sizeof(two_bytes_) + sizeof(four_bytes_) + sizeof(eight_bytes_);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    PacketBuilder<little_endian>::insert(signature_, it);
+    PacketBuilder<little_endian>::insert(byte_, it);
+    PacketBuilder<little_endian>::insert(two_bytes_, it);
+    PacketBuilder<little_endian>::insert(four_bytes_, it);
+    PacketBuilder<little_endian>::insert(eight_bytes_, it);
+  }
+
+ private:
+  uint32_t signature_{(little_endian ? 0x03020100 : 0x00010203)};
+  uint8_t byte_;
+  uint16_t two_bytes_;
+  uint32_t four_bytes_;
+  uint64_t eight_bytes_;
+};
+
+class PacketBuilderEndianTest : public ::testing::Test {
+ public:
+  PacketBuilderEndianTest() = default;
+  ~PacketBuilderEndianTest() = default;
+};
+
+TEST(PacketBuilderEndianTest, insertTest) {
+  EndianBuilder<true> little(0x04, 0x0605, 0x0a090807, 0x1211100f0e0d0c0b);
+  EndianBuilder<false> big(0x04, 0x0506, 0x0708090a, 0x0b0c0d0e0f101112);
+  ASSERT_EQ(*big.FinalPacket(), *little.FinalPacket());
+}
+
+template <typename T>
+class VectorBuilder : public PacketBuilder<true> {
+ public:
+  VectorBuilder(std::vector<uint64_t> vect) {
+    for (uint64_t element : vect) {
+      vect.push_back(static_cast<T>(element));
+    }
+  }
+  ~VectorBuilder() = default;
+
+  virtual size_t size() const override {
+    return vect_.size() * sizeof(T);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    PacketBuilder<true>::insert_vector(vect_, it);
+  }
+
+ private:
+  std::vector<T> vect_;
+};
+
+template <typename T>
+class InsertElementsBuilder : public PacketBuilder<true> {
+ public:
+  InsertElementsBuilder(std::vector<uint64_t> vect) {
+    for (uint64_t element : vect) {
+      vect.push_back(static_cast<T>(element));
+    }
+  }
+  virtual ~InsertElementsBuilder() = default;
+
+  virtual size_t size() const override {
+    return vect_.size() * sizeof(T);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    for (T elem : vect_) {
+      PacketBuilder<true>::insert(elem, it);
+    }
+  }
+
+ private:
+  std::vector<T> vect_;
+};
+
+std::vector<uint64_t> vector_data{
+    0x7060504030201000, 0x7161514131211101, 0x7262524232221202, 0x7363534333231303, 0x7464544434241404,
+    0x7565554535251505, 0x7666564636261606, 0x7767574737271707, 0x7868584838281808,
+};
+
+template <typename T>
+class VectorBuilderTest : public ::testing::Test {
+ public:
+  VectorBuilderTest() = default;
+  ~VectorBuilderTest() = default;
+
+  void SetUp() {
+    packet_1_ = std::shared_ptr<VectorBuilder<T>>(new VectorBuilder<T>(vector_data));
+    packet_2_ = std::shared_ptr<InsertElementsBuilder<T>>(new InsertElementsBuilder<T>(vector_data));
+  }
+
+  void TearDown() {
+    packet_1_.reset();
+    packet_2_.reset();
+  }
+
+  std::shared_ptr<VectorBuilder<T>> packet_1_;
+  std::shared_ptr<InsertElementsBuilder<T>> packet_2_;
+};
+
+using VectorBaseTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t>;
+TYPED_TEST_CASE(VectorBuilderTest, VectorBaseTypes);
+
+TYPED_TEST(VectorBuilderTest, insertVectorTest) {
+  ASSERT_EQ(*(this->packet_1_->FinalPacket()), *(this->packet_2_->FinalPacket()));
+}
+
+class NestedBuilder : public PacketBuilder<true> {
+ public:
+  ~NestedBuilder() = default;
+
+  virtual size_t size() const override {
+    size_t payload_size = (payload_ ? payload_->size() : 0);
+    return 1 + payload_size;
+  }
+
+  static std::unique_ptr<NestedBuilder> Create(uint8_t level) {
+    return std::unique_ptr<NestedBuilder>(new NestedBuilder(level));
+  }
+
+  static std::unique_ptr<NestedBuilder> CreateNested(std::unique_ptr<BasePacketBuilder> payload, uint8_t level) {
+    return std::unique_ptr<NestedBuilder>(new NestedBuilder(std::move(payload), level));
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    PacketBuilder<true>::insert(level_, it);
+    if (payload_) {
+      payload_->Serialize(it);
+    }
+  }
+
+ private:
+  std::unique_ptr<BasePacketBuilder> payload_;
+  uint8_t level_;
+
+  NestedBuilder(std::unique_ptr<BasePacketBuilder> inner, uint8_t level) : payload_(std::move(inner)), level_(level) {}
+  NestedBuilder(uint8_t level) : level_(level) {}
+};
+
+class BuilderBuilderTest : public ::testing::Test {};
+
+TEST(BuilderBuilderTest, nestingTest) {
+  std::unique_ptr<BasePacketBuilder> innermost = NestedBuilder::Create(0);
+  std::unique_ptr<BasePacketBuilder> number_1 = NestedBuilder::CreateNested(std::move(innermost), 1);
+  std::unique_ptr<BasePacketBuilder> number_2 = NestedBuilder::CreateNested(std::move(number_1), 2);
+  std::unique_ptr<BasePacketBuilder> number_3 = NestedBuilder::CreateNested(std::move(number_2), 3);
+  std::unique_ptr<BasePacketBuilder> number_4 = NestedBuilder::CreateNested(std::move(number_3), 4);
+  std::unique_ptr<NestedBuilder> number_5 = NestedBuilder::CreateNested(std::move(number_4), 5);
+
+  std::vector<uint8_t> count_down{5, 4, 3, 2, 1, 0};
+  ASSERT_EQ(*number_5->FinalPacket(), count_down);
+}
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/test/packet_view_test.cc b/vendor_libs/test_vendor_lib/packets/test/packet_view_test.cc
new file mode 100644
index 0000000..65cd305
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/test/packet_view_test.cc
@@ -0,0 +1,507 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/packet_view.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "types/address.h"
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count_all = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> count_1 = {
+    0x00,
+    0x01,
+    0x02,
+};
+
+vector<uint8_t> count_2 = {
+    0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+vector<uint8_t> count_3 = {
+    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+template <typename T>
+class IteratorTest : public ::testing::Test {
+ public:
+  IteratorTest() = default;
+  ~IteratorTest() = default;
+
+  void SetUp() {
+    packet = std::shared_ptr<T>(new T({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())}));
+  }
+
+  void TearDown() {
+    packet.reset();
+  }
+
+  std::shared_ptr<T> packet;
+};
+
+using PacketViewTypes = ::testing::Types<PacketView<true>, PacketView<false>>;
+TYPED_TEST_CASE(IteratorTest, PacketViewTypes);
+
+class IteratorExtractTest : public ::testing::Test {
+ public:
+  IteratorExtractTest() = default;
+  ~IteratorExtractTest() = default;
+};
+
+template <typename T>
+class PacketViewTest : public IteratorTest<T> {
+ public:
+  PacketViewTest() = default;
+  ~PacketViewTest() = default;
+};
+
+using PacketViewTypes = ::testing::Types<PacketView<true>, PacketView<false>>;
+TYPED_TEST_CASE(PacketViewTest, PacketViewTypes);
+
+class PacketViewMultiViewTest : public ::testing::Test {
+ public:
+  PacketViewMultiViewTest() = default;
+  ~PacketViewMultiViewTest() = default;
+};
+
+class ViewTest : public ::testing::Test {
+ public:
+  ViewTest() = default;
+  ~ViewTest() = default;
+};
+
+TEST(IteratorExtractTest, extractLeTest) {
+  PacketView<true> packet({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  auto general_case = packet.begin();
+
+  ASSERT_EQ(0x00, general_case.extract<uint8_t>());
+  ASSERT_EQ(0x0201, general_case.extract<uint16_t>());
+  ASSERT_EQ(0x06050403u, general_case.extract<uint32_t>());
+  ASSERT_EQ(0x0e0d0c0b0a090807u, general_case.extract<uint64_t>());
+  ASSERT_EQ(0x0f, general_case.extract<uint8_t>());
+  Address raw({0x10, 0x11, 0x12, 0x13, 0x14, 0x15});
+  ASSERT_EQ(raw, general_case.extract<Address>());
+  ASSERT_EQ(0x16, general_case.extract<uint8_t>());
+}
+
+TEST(IteratorExtractTest, extractBeTest) {
+  PacketView<false> packet({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  auto general_case = packet.begin();
+
+  ASSERT_EQ(0x00, general_case.extract<uint8_t>());
+  ASSERT_EQ(0x0102, general_case.extract<uint16_t>());
+  ASSERT_EQ(0x03040506u, general_case.extract<uint32_t>());
+  ASSERT_EQ(0x0708090a0b0c0d0eu, general_case.extract<uint64_t>());
+  ASSERT_EQ(0x0f, general_case.extract<uint8_t>());
+  Address raw({0x15, 0x14, 0x13, 0x12, 0x11, 0x10});
+  ASSERT_EQ(raw, general_case.extract<Address>());
+  ASSERT_EQ(0x16, general_case.extract<uint8_t>());
+}
+
+TYPED_TEST(IteratorTest, extractBoundsDeathTest) {
+  auto bounds_test = this->packet->end();
+
+  ASSERT_DEATH(bounds_test.template extract<uint8_t>(), "");
+  ASSERT_DEATH(bounds_test.template extract<uint16_t>(), "");
+  ASSERT_DEATH(bounds_test.template extract<uint32_t>(), "");
+  ASSERT_DEATH(bounds_test.template extract<uint64_t>(), "");
+}
+
+TYPED_TEST(IteratorTest, dereferenceDeathTest) {
+  auto dereference_test = this->packet->end();
+
+  ASSERT_DEATH(*dereference_test, "");
+  ASSERT_EQ(0x1f, *(dereference_test - 1));
+}
+
+TYPED_TEST(IteratorTest, plusEqTest) {
+  auto plus_eq = this->packet->begin();
+  for (size_t i = 0; i < count_all.size(); i += 2) {
+    ASSERT_EQ(count_all[i], *plus_eq) << "+= test: Dereferenced iterator does not equal expected at index " << i;
+    plus_eq += 2;
+  }
+}
+
+TYPED_TEST(IteratorTest, preIncrementTest) {
+  auto plus_plus = this->packet->begin();
+  for (size_t i = 0; i < count_all.size() - 1; i++) {
+    ASSERT_EQ(count_all[i + 1], *(++plus_plus)) << "Pre-increment test: Dereferenced iterator does not equal expected "
+                                                << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, postIncrementTest) {
+  auto plus_plus = this->packet->begin();
+  for (size_t i = 0; i < count_all.size(); i++) {
+    ASSERT_EQ(count_all[i], *(plus_plus++)) << "Post-increment test: Dereferenced iterator does not equal expected "
+                                            << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, additionTest) {
+  auto plus = this->packet->begin();
+  for (size_t i = 0; i < count_all.size(); i++) {
+    ASSERT_EQ(count_all[i], *plus) << "+ test: Dereferenced iterator does not equal expected at index " << i;
+    plus = plus + 1;
+  }
+}
+
+TYPED_TEST(IteratorTest, minusEqTest) {
+  auto minus_eq = this->packet->end();
+  minus_eq -= 1;
+  size_t index = count_all.size() - 1;
+  for (size_t i = 0; index > i; i++) {
+    ASSERT_EQ(count_all[index], *minus_eq)
+        << "-= test: Dereferenced iterator does not equal expected at index " << index;
+    index -= i;
+    minus_eq -= i;
+  }
+}
+
+TYPED_TEST(IteratorTest, preDecrementTest) {
+  auto minus_minus = this->packet->end();
+  for (size_t i = count_all.size(); i > 0; i--) {
+    ASSERT_EQ(count_all[i - 1], *(--minus_minus))
+        << "Pre-decrement test: Dereferenced iterator does not equal expected "
+        << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, postDecrementTest) {
+  auto minus_minus = this->packet->end();
+  minus_minus--;
+  for (size_t i = count_all.size() - 1; i > 0; i--) {
+    ASSERT_EQ(count_all[i], *(minus_minus--)) << "Post-decrement test: Dereferenced iterator does not equal expected "
+                                              << "at index " << i;
+  }
+}
+
+TYPED_TEST(IteratorTest, subtractionTest) {
+  auto minus = this->packet->end();
+  minus = minus - 1;
+  for (size_t i = count_all.size() - 1; i > 0; i--) {
+    ASSERT_EQ(count_all[i], *minus) << "- test: Dereferenced iterator does not equal expected at index " << i;
+    minus = minus - 1;
+  }
+}
+
+TYPED_TEST(IteratorTest, differenceTest) {
+  auto begin = this->packet->begin();
+  auto end = this->packet->end();
+  int difference = end - begin;
+  ASSERT_EQ(difference, static_cast<int>(count_all.size()));
+  int neg_difference = begin - end;
+  ASSERT_EQ(neg_difference, -static_cast<int>(count_all.size()));
+}
+
+TYPED_TEST(IteratorTest, equalityTest) {
+  auto begin = this->packet->begin();
+  auto end = this->packet->end();
+  auto begin_copy = this->packet->begin();
+  auto end_copy = this->packet->end();
+  ASSERT_EQ(begin_copy, begin);
+  ASSERT_EQ(end_copy, end);
+}
+
+TYPED_TEST(IteratorTest, comparisonsTest) {
+  auto begin = this->packet->begin();
+  auto end = this->packet->end();
+  auto begin_copy = this->packet->begin();
+  auto end_copy = this->packet->end();
+  ASSERT_EQ(begin_copy, begin);
+  ASSERT_EQ(end_copy, end);
+  ASSERT_NE(begin, end);
+  ASSERT_TRUE(begin < end);
+  ASSERT_FALSE(end < end);
+  ASSERT_FALSE(end < begin);
+  ASSERT_FALSE(begin > end);
+  ASSERT_FALSE(end > end);
+  ASSERT_TRUE(end > begin);
+  ASSERT_TRUE(begin <= end);
+  ASSERT_TRUE(end <= end);
+  ASSERT_FALSE(end <= begin);
+  ASSERT_FALSE(begin >= end);
+  ASSERT_TRUE(end >= end);
+  ASSERT_TRUE(end >= begin);
+}
+
+TYPED_TEST(PacketViewTest, getLengthTest) {
+  size_t length = this->packet->size();
+  ASSERT_EQ(length, count_all.size());
+}
+
+TYPED_TEST(PacketViewTest, getAtIndexTest) {
+  size_t past_end = this->packet->size();
+  ASSERT_DEATH(this->packet->at(past_end), "");
+  size_t working_index = 0x1f;
+  ASSERT_EQ(0x1f, this->packet->at(working_index));
+}
+
+TYPED_TEST(PacketViewTest, arrayOperatorTest) {
+  size_t past_end = this->packet->size();
+  ASSERT_DEATH((*(this->packet))[past_end], "");
+  size_t working_index = 0x1f;
+  ASSERT_EQ(0x1f, (*(this->packet))[working_index]);
+}
+
+TYPED_TEST(PacketViewTest, numBytesRemainingTest) {
+  auto all = this->packet->begin();
+  size_t remaining = all.NumBytesRemaining();
+  for (size_t n = remaining; n > 0; n--) {
+    ASSERT_EQ(remaining, all.NumBytesRemaining());
+    all++;
+    remaining--;
+  }
+  ASSERT_EQ(static_cast<size_t>(0), all.NumBytesRemaining());
+  ASSERT_DEATH(*(all++), "");
+  all++;
+  ASSERT_EQ(static_cast<size_t>(0), all.NumBytesRemaining());
+  ASSERT_DEATH(*(all++), "");
+}
+
+using SubViewTestParam = std::pair<size_t, size_t>;
+class SubViewBaseTest : public ::testing::TestWithParam<SubViewTestParam> {
+ public:
+  class SubPacketView : public PacketView<true> {
+   public:
+    using PacketView<true>::PacketView;
+    PacketView<true> Slice(size_t header, size_t tail) {
+      return PacketView<true>::SubViewLittleEndian(header, tail);
+    }
+  };
+};
+
+class SubViewPassTest : public SubViewBaseTest {};
+
+TEST_P(SubViewPassTest, subViewTest) {
+  auto header = GetParam().first;
+  auto tail = GetParam().second;
+  SubPacketView single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  SubPacketView multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+
+  auto single_slice = single_view.Slice(header, tail);
+  auto multi_slice = multi_view.Slice(header, tail);
+
+  ASSERT_EQ(single_slice.size(), tail - header);
+  ASSERT_EQ(single_slice.size(), multi_slice.size());
+  for (size_t i = 0; i < single_slice.size(); i++) {
+    ASSERT_EQ(single_slice[i], multi_slice[i]);
+  }
+}
+
+static const size_t boundary_1 = count_1.size();
+static const size_t boundary_2 = count_1.size() + count_2.size();
+
+INSTANTIATE_TEST_CASE_P(
+    chopomatic, SubViewPassTest,
+    ::testing::Values(
+        // {begin, end} pairs for subsets into the PacketView
+        SubViewTestParam{0, 0}, SubViewTestParam{0, boundary_1}, SubViewTestParam{0, boundary_1 + 1},
+        SubViewTestParam{0, boundary_2}, SubViewTestParam{0, boundary_2 + 1}, SubViewTestParam{0, count_all.size()},
+        SubViewTestParam{boundary_1 - 1, boundary_1}, SubViewTestParam{boundary_1 - 1, boundary_1 + 1},
+        SubViewTestParam{boundary_1 - 1, boundary_2}, SubViewTestParam{boundary_1 - 1, boundary_2 + 1},
+        SubViewTestParam{boundary_1 - 1, count_all.size()}, SubViewTestParam{boundary_1, boundary_1},
+        SubViewTestParam{boundary_1, boundary_2}, SubViewTestParam{boundary_1, boundary_2 + 1},
+        SubViewTestParam{boundary_1, count_all.size()}, SubViewTestParam{boundary_2 - 1, boundary_2},
+        SubViewTestParam{boundary_2 - 1, boundary_2 + 1}, SubViewTestParam{boundary_2 - 1, count_all.size()},
+        SubViewTestParam{boundary_2, boundary_2}, SubViewTestParam{boundary_2, boundary_2 + 1},
+        SubViewTestParam{boundary_2, count_all.size()}, SubViewTestParam{count_all.size() - 1, count_all.size()},
+        SubViewTestParam{count_all.size(), count_all.size()}));
+
+class SubViewDeathTest : public SubViewBaseTest {};
+
+TEST_P(SubViewDeathTest, subViewDeathTest) {
+  auto header = GetParam().first;
+  auto tail = GetParam().second;
+  SubPacketView single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  SubPacketView multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+
+  ASSERT_DEATH(auto single_slice = single_view.Slice(header, tail), "");
+  ASSERT_DEATH(auto multi_slice = multi_view.Slice(header, tail), "");
+}
+
+INSTANTIATE_TEST_CASE_P(chopomaticDeath, SubViewDeathTest,
+                        ::testing::Values(
+                            // {begin, end} pairs for subsets into the PacketView
+                            SubViewTestParam{1, 0}, SubViewTestParam{count_all.size(), count_all.size() - 1},
+                            SubViewTestParam{count_all.size(), count_all.size() + 1}));
+
+TEST(SubViewTest, simpleSubViewTest) {
+  PacketView<true> view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> sub_1_view = view.SubViewLittleEndian(0, view.size());
+  PacketView<true> sub_2_view = sub_1_view.SubViewLittleEndian(0, sub_1_view.size());
+  PacketView<true> sub_3_view = sub_2_view.SubViewLittleEndian(0, sub_2_view.size());
+  PacketView<true> sub_4_view = sub_3_view.SubViewLittleEndian(0, sub_3_view.size());
+  ASSERT_EQ(sub_1_view.size(), view.size());
+  ASSERT_EQ(sub_2_view.size(), view.size());
+  ASSERT_EQ(sub_3_view.size(), view.size());
+  ASSERT_EQ(sub_4_view.size(), view.size());
+}
+
+TEST(SubViewTest, realSubViewTest) {
+  PacketView<true> view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  std::vector<PacketView<true>> sub_views{view};
+  for (size_t i = 1; i < 6; i++) {
+    size_t parent_size = sub_views[i - 1].size();
+    sub_views.push_back(sub_views[i - 1].SubViewLittleEndian(1, parent_size - 1));
+    ASSERT_EQ(sub_views[i][0], i);
+    ASSERT_EQ(sub_views[i].size(), parent_size - 2);
+  }
+}
+
+TEST(SubViewTest, subSubViewTest) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  ASSERT_EQ(single_view.size(), multi_view.size());
+  for (size_t i = 0; i < count_all.size() / 2; i++) {
+    PacketView<true> sub_single_view = single_view.SubViewLittleEndian(i, count_all.size() - i);
+    PacketView<true> sub_multi_view = multi_view.SubViewLittleEndian(i, count_all.size() - i);
+    ASSERT_EQ(count_all.size() - 2 * i, sub_single_view.size());
+    ASSERT_EQ(sub_single_view.size(), sub_multi_view.size());
+    for (size_t j = 0; j < sub_single_view.size() / 2; j++) {
+      PacketView<true> sub_sub_single_view = sub_single_view.SubViewLittleEndian(j, sub_single_view.size() - j);
+      PacketView<true> sub_sub_multi_view = sub_multi_view.SubViewLittleEndian(j, sub_multi_view.size() - j);
+      ASSERT_EQ(sub_single_view.size() - 2 * j, sub_sub_single_view.size());
+      ASSERT_EQ(sub_sub_single_view.size(), sub_sub_multi_view.size());
+    }
+  }
+}
+
+TEST(PacketViewMultiViewTest, sizeTest) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  ASSERT_EQ(single_view.size(), multi_view.size());
+}
+
+TEST(PacketViewMultiViewTest, dereferenceTestLittleEndian) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  auto single_itr = single_view.begin();
+  auto multi_itr = multi_view.begin();
+  for (size_t i = 0; i < single_view.size(); i++) {
+    ASSERT_EQ(*(single_itr++), *(multi_itr++));
+  }
+  ASSERT_DEATH(*multi_itr, "");
+}
+
+TEST(PacketViewMultiViewTest, dereferenceTestBigEndian) {
+  PacketView<false> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<false> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  auto single_itr = single_view.begin();
+  auto multi_itr = multi_view.begin();
+  for (size_t i = 0; i < single_view.size(); i++) {
+    ASSERT_EQ(*(single_itr++), *(multi_itr++));
+  }
+  ASSERT_DEATH(*multi_itr, "");
+}
+
+TEST(PacketViewMultiViewTest, arrayOperatorTest) {
+  PacketView<true> single_view({View(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size())});
+  PacketView<true> multi_view({
+      View(std::make_shared<const vector<uint8_t>>(count_1), 0, count_1.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_2), 0, count_2.size()),
+      View(std::make_shared<const vector<uint8_t>>(count_3), 0, count_3.size()),
+  });
+  for (size_t i = 0; i < single_view.size(); i++) {
+    ASSERT_EQ(single_view[i], multi_view[i]);
+  }
+  ASSERT_DEATH(multi_view[single_view.size()], "");
+}
+
+TEST(ViewTest, arrayOperatorTest) {
+  View view_all(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  size_t past_end = view_all.size();
+  for (size_t i = 0; i < past_end; i++) {
+    ASSERT_EQ(view_all[i], count_all[i]);
+  }
+  ASSERT_DEATH(view_all[past_end], "");
+
+  size_t header_size = 2;
+  size_t tail_size = 3;
+  View view_subset(std::make_shared<const vector<uint8_t>>(count_all), header_size, count_all.size() - tail_size);
+  View view_subset2(view_all, header_size, count_all.size() - tail_size);
+  size_t subset_length = view_subset.size();
+  for (size_t i = 0; i < subset_length; i++) {
+    ASSERT_EQ(view_subset[i], count_all[header_size + i]);
+    ASSERT_EQ(view_subset[i], view_subset2[i]);
+  }
+  ASSERT_DEATH(view_subset[subset_length + 1], "");
+  ASSERT_DEATH(view_subset2[subset_length + 1], "");
+}
+
+TEST(ViewTest, earlySubSubViewTest) {
+  View view(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  View sub_1_view(view, view.size() - 3, view.size() - 1);
+  View sub_2_view(sub_1_view, 1, 2);
+  ASSERT_EQ(sub_1_view.size(), 2u);
+  ASSERT_EQ(sub_2_view.size(), 1u);
+}
+
+TEST(ViewTest, subSubViewTest) {
+  View view(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  std::vector<View> sub_views{view};
+  for (size_t i = 1; i < 6; i++) {
+    size_t parent_size = sub_views[i - 1].size();
+    sub_views.push_back({View(sub_views[i - 1], 1, parent_size - 1)});
+    ASSERT_EQ(sub_views[i][0], i);
+    ASSERT_EQ(sub_views[i].size(), parent_size - 2);
+  }
+}
+
+TEST(ViewTest, zeroSubViewTest) {
+  View view(std::make_shared<const vector<uint8_t>>(count_all), 0, count_all.size());
+  View subview(view, view.size(), view.size() + 1);
+  ASSERT_EQ(subview.size(), 0u);
+}
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/test/raw_builder_test.cc b/vendor_libs/test_vendor_lib/packets/test/raw_builder_test.cc
new file mode 100644
index 0000000..f67ba0b
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/test/raw_builder_test.cc
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/raw_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+#include "types/address.h"
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+class RawBuilderTest : public ::testing::Test {
+ public:
+  RawBuilderTest() = default;
+  ~RawBuilderTest() = default;
+};
+
+TEST(RawBuilderTest, buildCountTest) {
+  std::unique_ptr<RawBuilder> count_builder = std::make_unique<RawBuilder>();
+  ASSERT_EQ(0u, count_builder->size());
+  count_builder->AddOctets8(0x0706050403020100);
+  count_builder->AddOctets4(0x0b0a0908);
+  count_builder->AddOctets2(0x0d0c);
+  count_builder->AddOctets1(0x0e);
+  count_builder->AddOctets1(0x0f);
+  count_builder->AddAddress(Address({0x10, 0x11, 0x12, 0x13, 0x14, 0x15}));
+  std::vector<uint8_t> count_subset(count.begin() + 0x16, count.end());
+  count_builder->AddOctets(count_subset);
+
+  ASSERT_EQ(count.size(), count_builder->size());
+
+  std::vector<uint8_t> packet;
+  std::back_insert_iterator<std::vector<uint8_t>> it(packet);
+
+  count_builder->Serialize(it);
+
+  ASSERT_EQ(count, packet);
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/view.cc b/vendor_libs/test_vendor_lib/packets/view.cc
new file mode 100644
index 0000000..7dbd8bd
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/view.cc
@@ -0,0 +1,45 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "view.h"
+
+#include <base/logging.h>
+
+namespace test_vendor_lib {
+namespace packets {
+
+View::View(std::shared_ptr<const std::vector<uint8_t>> data, size_t begin, size_t end)
+    : data_(data), begin_(begin < data_->size() ? begin : data_->size()),
+      end_(end < data_->size() ? end : data_->size()) {}
+
+View::View(const View& view, size_t begin, size_t end) : data_(view.data_) {
+  begin_ = (begin < view.size() ? begin : view.size());
+  begin_ += view.begin_;
+  end_ = (end < view.size() ? end : view.size());
+  end_ += view.begin_;
+}
+
+uint8_t View::operator[](size_t i) const {
+  CHECK(i + begin_ < end_) << "Out of bounds access at " << i;
+  return data_->operator[](i + begin_);
+}
+
+size_t View::size() const {
+  return end_ - begin_;
+}
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/packets/view.h b/vendor_libs/test_vendor_lib/packets/view.h
new file mode 100644
index 0000000..ca38875
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/packets/view.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * 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.
+ */
+
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+namespace test_vendor_lib {
+namespace packets {
+
+// Base class that holds a shared pointer to data with bounds.
+class View {
+ public:
+  View(std::shared_ptr<const std::vector<uint8_t>> data, size_t begin, size_t end);
+  View(const View& view, size_t begin, size_t end);
+  View(const View& view) = default;
+  virtual ~View() = default;
+
+  uint8_t operator[](size_t i) const;
+
+  size_t size() const;
+
+ private:
+  std::shared_ptr<const std::vector<uint8_t>> data_;
+  size_t begin_;
+  size_t end_;
+};
+
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/scripts/build_and_run.sh b/vendor_libs/test_vendor_lib/scripts/build_and_run.sh
index 34e0cfe..987a17f 100755
--- a/vendor_libs/test_vendor_lib/scripts/build_and_run.sh
+++ b/vendor_libs/test_vendor_lib/scripts/build_and_run.sh
@@ -108,7 +108,7 @@
   adb push ${VENDOR_SYMBOLS_ABS}/${VENDOR_LIB} /vendor/lib
 
   echo "Pushing controller properties."
-  adb push ${TEST_VENDOR_LIB_ABS}/data/${CONTROLLER_PROPERTIES} /etc/bluetooth/
+  adb push ${TEST_VENDOR_LIB_ABS}/data/${CONTROLLER_PROPERTIES} /vendor/etc/bluetooth/
 
   echo "Pushing libevent."
   adb push ${DEVICE_TARGET_ABS}/${DEVICE}/system/lib/libevent.so /system/lib/
diff --git a/vendor_libs/test_vendor_lib/scripts/hci_socket.py b/vendor_libs/test_vendor_lib/scripts/hci_socket.py
new file mode 100644
index 0000000..0c425af
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/scripts/hci_socket.py
@@ -0,0 +1,441 @@
+#
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+#
+"""Script for sending data to a port.
+
+This script provides a simple shell interface for sending data at run-time to a
+port.
+
+Usage:
+    1. Choose a port to use. Use 'adb forward tcp:<port>
+    tcp:<port>' to forward the port to the device.
+    2. In a separate shell, build and push the test vendor library to the device
+    using the script mentioned in option A (i.e. without the --test-channel flag
+    set).
+    3. Once logcat has started, turn Bluetooth on from the device.
+    4. Run this program, in the shell from step 1,  the port, also from step 1,
+    as arguments.
+
+    scapy is the tool we use to build packets in Python.
+
+    >>> d = HCI_Hdr(type=1) / HCI_Command_Hdr(opcode = 0x1004) /
+    Raw(load='\x01')
+    >>> print(d)
+    <HCI_Hdr  type=Command |<HCI_Command_Hdr  opcode=0x1004 |<Raw  load='\x01'
+    |>>>
+    >>> raw(d)
+    '\x01\x04\x10\x01\x01'
+    >>> hexdump(d)
+    0000  0104100101                       .....
+
+
+    >>> pkt = HCI_Hdr('\x02\x02\x20\x0a\x00\x06\x00\x01\x00') /
+    L2CAP_CmdHdr(code=10, id=2, len=2) /L2CAP_InfoReq(type=2)
+    >>> pkt
+    <HCI_Hdr  type=ACL Data |<HCI_ACL_Hdr  handle=2 PB=0 BC=2 len=10 |<L2CAP_Hdr
+    len=6 cid=control |<L2CAP_CmdHdr  code=info_req id=2 len=2 |<L2CAP_InfoReq
+    type=FEAT_MASK |>>>>>
+    >>> pkt = HCI_Hdr(type='ACL Data') / HCI_ACL_Hdr(handle=2, PB=0, BC=2,
+    len=10) / L2CAP_Hdr(len=6, cid='control') / L2CAP_CmdHdr(code='info_req',
+    id=2, len=2) / L2CAP_InfoReq(type='FEAT_MASK')
+    >>> raw(pkt)
+    '\x02\x02 \n\x00\x06\x00\x01\x00\n\x02\x02\x00\x02\x00'
+    >>> hexdump(pkt)
+    0000  0202200A00060001000A0202000200   .. ............
+
+
+"""
+
+#!/usr/bin/env python
+
+import binascii
+import cmd
+import queue
+import random
+import socket
+import string
+import struct
+import sys
+from scapy.all import *
+""" Add some more SCAPY stuff"""
+
+
+class HCI_Cmd_Create_Connection(Packet):
+  name = 'Create Connection'
+  fields_desc = [
+      LEMACField('addr', None),
+      LEShortField('packet_type', 8),
+      ByteEnumField('page_scan_repetition_mode', 0, {
+          0: 'R0',
+          1: 'R1',
+          2: 'R2'
+      }),
+      ByteEnumField('rsvd', 0, {0: 'Reserved'}),
+      LEShortField('clock_offset', 0),
+      ByteEnumField('allow_role_switch', 1, {
+          0: 'false',
+          1: 'true'
+      }),
+  ]
+
+
+class HCI_Cmd_Inquiry(Packet):
+  name = 'Inquiry'
+  fields_desc = [
+      X3BytesField('LAP', 0x9e8b0),
+      ByteField('length', 1),
+      ByteField('max_responses', 0),
+  ]
+
+
+bind_layers(HCI_Command_Hdr, HCI_Cmd_Inquiry, opcode=0x0401)
+bind_layers(HCI_Command_Hdr, HCI_Cmd_Create_Connection, opcode=0x0405)
+
+
+class HCI_Event_Inquiry_Result(Packet):
+  name = 'Inquiry Result'
+  fields_desc = [
+      ByteField('num_responses', 0),
+      LEMACField('addr', None),
+      ByteEnumField('page_scan_repetition_mode', 0, {
+          0: 'R0',
+          1: 'R1',
+          2: 'R2'
+      }),
+      LEShortEnumField('rsvd', 0, {0: 'Reserved'}),
+      X3BytesField('class_of_device', 0),
+      LEShortField('clock_offset', 0),
+  ]
+
+
+class HCI_Event_Connection_Complete(Packet):
+  name = 'Connection Complete'
+  fields_desc = [
+      ByteField('status', 0),
+      LEShortField('handle', 0xffff),
+      LEMACField('addr', None),
+      ByteField('link_type', 1),
+      ByteField('encryption_mode', 0),
+  ]
+
+
+class HCI_Event_Remote_Name_Request_Complete(Packet):
+  name = 'Remote Name Request Complete'
+  fields_desc = [
+      ByteField('status', 0),
+      LEMACField('addr', None),
+  ]
+
+
+class HCI_Event_Read_Remote_Supported_Features_Complete(Packet):
+  name = 'Read Remote Supported Features Complete'
+  fields_desc = [
+      ByteField('status', 0),
+      LEShortField('handle', 0xffff),
+      XLELongField('features', 0x0123456789abcdef),
+  ]
+
+
+class HCI_Event_Read_Remote_Version_Information_Complete(Packet):
+  name = 'Read Remote Version Information Complete'
+  fields_desc = [
+      ByteField('status', 0),
+      LEShortField('handle', 0xffff),
+      ByteField('version', 0),
+      LEShortField('manufacturer_name', 0),
+      LEShortField('subversion', 0),
+  ]
+
+
+class HCI_Event_Read_Clock_Offset_Complete(Packet):
+  name = 'Read Clock Offset Complete'
+  fields_desc = [
+      ByteField('status', 0),
+      LEShortField('handle', 0xffff),
+      LEShortField('offset', 0xffff),
+  ]
+
+
+class HCI_Event_Read_Remote_Extended_Features_Complete(Packet):
+  name = 'Read Remote Supported Features Complete'
+  fields_desc = [
+      ByteField('status', 0),
+      LEShortField('handle', 0xffff),
+      ByteField('page_number', 0),
+      ByteField('max_page_number', 0),
+      XLELongField('features', 0x0123456789abcdef),
+  ]
+
+
+class HCI_Event_Extended_Inquiry_Result(Packet):
+  name = 'Extended Inquiry Result'
+  fields_desc = [
+      ByteField('num_responses', 1),
+      LEMACField('addr', None),
+      ByteEnumField('page_scan_repetition_mode', 0, {
+          0: 'R0',
+          1: 'R1',
+          2: 'R2'
+      }),
+      ByteEnumField('rsvd', 0, {0: 'Reserved'}),
+      X3BytesField('class_of_device', 0),
+      LEShortField('clock_offset', 0),
+      SignedByteField('rssi', -20),
+      PacketListField('extended_inquiry_response', [], EIR_Hdr, 1),
+  ]
+
+
+bind_layers(HCI_Event_Hdr, HCI_Event_Inquiry_Result, code=0x02)
+bind_layers(HCI_Event_Hdr, HCI_Event_Connection_Complete, code=0x03)
+bind_layers(HCI_Event_Hdr, HCI_Event_Remote_Name_Request_Complete, code=0x07)
+bind_layers(
+    HCI_Event_Hdr, HCI_Event_Read_Remote_Supported_Features_Complete, code=0x0b)
+bind_layers(
+    HCI_Event_Hdr,
+    HCI_Event_Read_Remote_Version_Information_Complete,
+    code=0x0c)
+bind_layers(HCI_Event_Hdr, HCI_Event_Read_Clock_Offset_Complete, code=0x1c)
+bind_layers(
+    HCI_Event_Hdr, HCI_Event_Read_Remote_Extended_Features_Complete, code=0x23)
+bind_layers(HCI_Event_Hdr, HCI_Event_Extended_Inquiry_Result, code=0x2f)
+""" END SCAPY stuff"""
+
+
+class HCISocket(SuperSocket):
+  """Simple wrapper class for a socket object.
+
+  Attributes:
+    socket: The underlying socket created for the specified address and port.
+  """
+
+  def __init__(self, port):
+    self.done_ = False
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    s.connect(('localhost', port))
+    self.ins = self.outs = s
+    self.packets_ = queue.Queue()
+    self.rx_thread_ = threading.Thread(target=self.rx_thread_body)
+    self.rx_thread_.start()
+
+  def rx_bytes(self, size):
+    while not self.done_:
+      raw_bytes = b''
+      while len(raw_bytes) < size and not self.done_:
+        more_raw_bytes = self.ins.recv(min(size - len(raw_bytes), 2048))
+        if more_raw_bytes:
+          raw_bytes += more_raw_bytes
+      return raw_bytes
+
+  def rx_thread_body(self):
+    while not self.done_:
+      payload_length = 0
+      # Read the type
+      type_byte = self.rx_bytes(1)
+      if not type_byte:
+        continue
+      # Read the Header
+      header = b''
+      if type_byte == b'\x01':  # Command
+        header = self.rx_bytes(3)
+        if not header:
+          continue
+        payload_length = header[2]
+      elif type_byte == b'\x02':  # ACL
+        header = self.rx_bytes(4)
+        if not header:
+          continue
+        payload_length = header[3] << 8
+        payload_length |= header[2]
+      elif type_byte == b'\x03':  # SCO
+        header = self.rx_bytes(3)
+        if not header:
+          continue
+        payload_length = header[2]
+      elif type_byte == b'\x04':  # Event
+        header = self.rx_bytes(2)
+        if not header:
+          continue
+        payload_length = header[1]
+      else:
+        self.done_ = True
+        print('Rx: type_byte ' + hex(type_byte[0]))
+      # Read the Payload
+      payload = self.rx_bytes(payload_length) if payload_length != 0 else b''
+      packet_bytes = type_byte + header + payload
+      packet = HCI_Hdr(packet_bytes)
+      print('Rx: ' + packet.__repr__())
+      self.packets_.put(packet)
+
+  def get_packet(self):
+    if self.packets_.empty():
+      return False
+    return self.packets_.get()
+
+  def tell_rx_thread_to_quit(self):
+    self.done_ = True
+    self.rx_thread_.join()
+
+
+class HCIShell(cmd.Cmd):
+  """Shell for sending binary data to a port.
+
+  """
+
+  def __init__(self, hci):
+    cmd.Cmd.__init__(self)
+    self._hci = hci
+
+  def do_send(self, args):
+    """Arguments: dev_type_str Add a new device of type dev_type_str.
+
+    """
+    self._hci.send_binary(args.split())
+
+  def do_connect(self, args):
+    """Arguments: bluetooth_address xx:xx:xx:xx:xx:xx, timeout (seconds)
+
+    """
+    split_args = args.split()
+    address = split_args[0] if len(split_args) > 0 else 'NULL'
+    timeout = int(split_args[1]) if len(split_args) > 1 else 2
+    num_responses = 0
+    connect = HCI_Hdr(type='Command') / HCI_Command_Hdr(
+        opcode=0x0405) / HCI_Cmd_Create_Connection(addr=address)
+    self._hci.send(connect)
+    status = None
+    while status == None:
+      response = self._hci.get_packet()
+      if response == False:
+        continue
+      if response[HCI_Hdr].type == HCI_Hdr(
+          type='Event'
+      ).type and response[HCI_Event_Hdr].code == 0xf and response[
+          HCI_Event_Command_Status].opcode == connect[HCI_Command_Hdr].opcode:
+        status = response[HCI_Event_Command_Status].status
+    if status != HCI_Event_Command_Status(status='pending').status:
+      print('Connection failed with status = ' + str(status))
+      return
+
+    handle = None
+    while handle == None:
+      connection_complete = self._hci.get_packet()
+      if connection_complete == False:
+        continue
+      if (connection_complete[HCI_Hdr].type == HCI_Hdr(type='Event').type) and (
+          connection_complete[HCI_Event_Hdr].code == 0x3):
+        status = connection_complete[HCI_Event_Connection_Complete].status
+        if status != 0:
+          print('Connection complete with failed status = ' + str(status))
+          return
+        handle = connection_complete[HCI_Event_Connection_Complete].handle
+        print('Connection established with handle ' + str(handle))
+        connection_complete.show()
+        hexdump(connection_complete)
+
+    l2cap_done = False
+    while l2cap_done == None:
+      l2cap_req = self._hci.get_packet()
+      if l2cap_req == False:
+        continue
+      if (l2cap_req[HCI_Hdr].type == HCI_Hdr(type='ACL Data').type) and (
+          l2cap_req[L2CAP_Hdr].cid == L2CAP_Hdr(cid='control').cid) and (
+              l2cap_req[L2CAP_CmdHdr].code == L2CAP_CmdHdr(code='info_req').code
+          ) and (l2cap_req[L2CAP_InfoReq].type == L2CAP_InfoReq(
+              type='FEAT_MASK').type):
+        print('Send Features packet' + HCI_Hdr(type='ACL Data') / HCI_ACL_Hdr(
+            handle=l2cap_req[HCI_ACL_Hdr].handle, PB=0, BC=2, len=16) /
+              L2CAP_Hdr(len=12, cid='control') /
+              L2CAP_CmdHdr(code='info_resp', id=146, len=8) / L2CAP_InfoResp(
+                  type=l2cap_req[L2CAP_InfoResp].type,
+                  result='success',
+                  data=b'\xb8\x00\x00\x00').__repr__())
+        self._hci.send(
+            HCI_Hdr(type='ACL Data') / HCI_ACL_Hdr(
+                handle=l2cap_req[HCI_ACL_Hdr].handle, PB=0, BC=2, len=16) /
+            L2CAP_Hdr(len=12, cid='control') / L2CAP_CmdHdr(
+                code='info_resp', id=146, len=8) / L2CAP_InfoResp(
+                    type=l2cap_req[L2CAP_InfoResp].type,
+                    result='success',
+                    data=b'\xb8\x00\x00\x00'))
+
+  def do_le_scan(self, args):
+    """Arguments: enable (0 or 1), filter duplicates (0 or 1) Print the scan responses from reachable devices
+
+    """
+    split_args = args.split()
+    enable = int(split_args[0]) if len(split_args) > 0 else 1
+    filter_dups = int(split_args[1]) if len(split_args) > 1 else 1
+    set_scan_enable = HCI_Hdr(type=1) / HCI_Command_Hdr(
+        opcode=0x200c) / HCI_Cmd_LE_Set_Scan_Enable(
+            enable=enable, filter_dups=filter_dups)
+    print('Tx: ' + set_scan_enable.__repr__())
+    self._hci.send(set_scan_enable)
+
+  def do_scan(self, args):
+    """Arguments: timeout (seconds), max_results Print the scan responses from reachable devices
+
+    """
+    split_args = args.split()
+    scan_time = int(split_args[0]) if len(split_args) > 0 else 0
+    max_responses = int(split_args[1]) if len(split_args) > 1 else 0
+    num_responses = 0
+    inquiry = HCI_Hdr(type='Command') / HCI_Command_Hdr(
+        opcode=0x0401) / HCI_Cmd_Inquiry(
+            length=scan_time, max_responses=max_responses)
+    print('Tx: ' + inquiry.__repr__())
+    self._hci.send(inquiry)
+
+  def do_quit(self, args):
+    """Arguments: None.
+
+    Exits.
+    """
+    self._hci.tell_rx_thread_to_quit()
+    self._hci.close()
+    print('Goodbye.')
+    return True
+
+  def do_help(self, args):
+    """Arguments: [dev_num [attr]] List the commands available, optionally filtered by device and attr.
+
+    """
+    if (len(args) == 0):
+      cmd.Cmd.do_help(self, args)
+
+
+def main(argv):
+  if len(argv) != 2:
+    print('Usage: python hci_socket.py [port]')
+    return
+  try:
+    port = int(argv[1])
+  except ValueError:
+    print('Error parsing port.')
+  else:
+    try:
+      hci = HCISocket(port)
+    except socket.error as e:
+      print('Error connecting to socket: %s' % e)
+    except:
+      print('Error creating (check arguments).')
+    else:
+      hci_shell = HCIShell(hci)
+      hci_shell.prompt = '$ '
+      hci_shell.cmdloop('Welcome to the RootCanal HCI Console \n' +
+                        'Type \'help\' for more information.')
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/vendor_libs/test_vendor_lib/scripts/link_layer_socket.py b/vendor_libs/test_vendor_lib/scripts/link_layer_socket.py
new file mode 100644
index 0000000..c7b3045
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/scripts/link_layer_socket.py
@@ -0,0 +1,192 @@
+#
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+#
+"""Script for sending data to a port.
+
+This script provides a simple shell interface for sending data at run-time to a
+port.
+
+Usage:
+    1. Choose a port to use. Use 'adb forward tcp:<port>
+    tcp:<port>' to forward the port to the device.
+    2. In a separate shell, build and push the test vendor library to the device
+    using the script mentioned in option A (i.e. without the --test-channel flag
+    set).
+    3. Once logcat has started, turn Bluetooth on from the device.
+    4. Run this program, in the shell from step 1,  the port, also from step 1,
+    as arguments.
+
+    scapy is the tool we use to build packets in Python.
+
+    >>> d = HCI_Hdr(type=1) / HCI_Command_Hdr(opcode = 0x1004) /
+    Raw(load='\x01')
+    >>> print(d)
+    <HCI_Hdr  type=Command |<HCI_Command_Hdr  opcode=0x1004 |<Raw  load='\x01'
+    |>>>
+    >>> raw(d)
+    '\x01\x04\x10\x01\x01'
+    >>> hexdump(d)
+    0000  0104100101                       .....
+
+
+    >>> pkt = HCI_Hdr('\x02\x02\x20\x0a\x00\x06\x00\x01\x00') /
+    L2CAP_CmdHdr(code=10, id=2, len=2) /L2CAP_InfoReq(type=2)
+    >>> pkt
+    <HCI_Hdr  type=ACL Data |<HCI_ACL_Hdr  handle=2 PB=0 BC=2 len=10 |<L2CAP_Hdr
+    len=6 cid=control |<L2CAP_CmdHdr  code=info_req id=2 len=2 |<L2CAP_InfoReq
+    type=FEAT_MASK |>>>>>
+    >>> pkt = HCI_Hdr(type='ACL Data') / HCI_ACL_Hdr(handle=2, PB=0, BC=2,
+    len=10) / L2CAP_Hdr(len=6, cid='control') / L2CAP_CmdHdr(code='info_req',
+    id=2, len=2) / L2CAP_InfoReq(type='FEAT_MASK')
+    >>> raw(pkt)
+    '\x02\x02 \n\x00\x06\x00\x01\x00\n\x02\x02\x00\x02\x00'
+    >>> hexdump(pkt)
+    0000  0202200A00060001000A0202000200   .. ............
+
+
+"""
+
+#!/usr/bin/env python
+
+import binascii
+import cmd
+import queue
+import random
+import socket
+import string
+import struct
+import sys
+
+class LinkLayerSocket(object):
+  """Simple wrapper class for a socket object.
+
+  Attributes:
+    socket: The underlying socket created for the specified address and port.
+  """
+
+  def __init__(self, port):
+    print('port = ' + port)
+    self.done_ = False
+    self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    self._socket.connect(('localhost', port))
+    # Should it be a non-blocking socket?
+    # self._socket.setblocking(0)
+    self.packets_ = queue.Queue()
+    self.rx_thread_ = threading.Thread(target=self.rx_thread_body)
+    self.rx_thread_.start()
+
+  def rx_bytes(self, size):
+    while not self.done_:
+      raw_bytes = b''
+      while len(raw_bytes) < size and not self.done_:
+        more_raw_bytes = self._socket.recv(min(size - len(raw_bytes), 2048))
+        if more_raw_bytes:
+          raw_bytes += more_raw_bytes
+      return raw_bytes
+
+  def rx_thread_body(self):
+    while not self.done_:
+      payload_length = 0
+      # Read the size (4B), the type (1B), and the addresses (2*6B)
+      header = self.rx_bytes(17)
+      if not header:
+        continue
+      payload_length = header[0]
+      payload_length |= header[1] << 8
+      payload_length |= header[2] << 16
+      payload_length |= header[3] << 24
+      print('Rx: type_byte ' + hex(header[4]))
+      print('Rx: from ' + hex(header[5]) + ':' + hex(header[6]) + ':' + hex(header[7]) + ':' + hex(header[8]) + ':' + hex(header[9]) + ':' + hex(header[10]))
+      print('Rx: to ' + hex(header[11]) + ':' + hex(header[12]) + ':' + hex(header[13]) + ':' + hex(header[14]) + ':' + hex(header[15]) + ':' + hex(header[16]))
+      # Read the Payload
+      payload = self.rx_bytes(payload_length) if payload_length != 0 else b''
+      packet_bytes = header + payload
+      self.packets_.put(packet_bytes)
+
+  def get_packet(self):
+    if self.packets_.empty():
+      return False
+    return self.packets_.get()
+
+  def send_binary(self, args):
+    joined_args = ''.join(arg for arg in args)
+    print(joined_args)
+    packet = binascii.a2b_hex(joined_args)
+    if self._done:
+      return
+    self._connection.send(packet)
+
+  def tell_rx_thread_to_quit(self):
+    self.done_ = True
+    self.rx_thread_.join()
+
+
+class LinkLayerShell(cmd.Cmd):
+  """Shell for sending binary data to a port.
+
+  """
+
+  def __init__(self, link_layer):
+    cmd.Cmd.__init__(self)
+    self._link_layer = link_layer
+
+  def do_send(self, args):
+    """Arguments: binary representation of a packet.
+
+    """
+    self._link_layer.send_binary(args.split())
+
+  def do_quit(self, args):
+    """Arguments: None.
+
+    Exits.
+    """
+    self._link_layer.tell_rx_thread_to_quit()
+    self._link_layer.close()
+    print('Goodbye.')
+    return True
+
+  def do_help(self, args):
+    """Arguments: [dev_num [attr]] List the commands available, optionally filtered by device and attr.
+
+    """
+    if (len(args) == 0):
+      cmd.Cmd.do_help(self, args)
+
+
+def main(argv):
+  if len(argv) != 2:
+    print('Usage: python link_layer_socket.py [port]')
+    return
+  try:
+    port = int(argv[1])
+  except ValueError:
+    print('Error parsing port.')
+  else:
+    try:
+      link_layer = LinkLayerSocket(port)
+    except socket.error as e:
+      print('Error connecting to socket: %s' % e)
+    except:
+      print('Error creating (check arguments).')
+    else:
+      link_layer_shell = LinkLayerShell(link_layer)
+      link_layer_shell.prompt = '$ '
+      link_layer_shell.cmdloop('Welcome to the RootCanal LinkLayer Console \n' +
+                        'Type \'help\' for more information.')
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/vendor_libs/test_vendor_lib/scripts/send_simple_commands.py b/vendor_libs/test_vendor_lib/scripts/send_simple_commands.py
new file mode 100644
index 0000000..cadeab3
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/scripts/send_simple_commands.py
@@ -0,0 +1,220 @@
+#
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+#
+"""Script for sending data to a port.
+
+This script provides a simple shell interface for sending data at run-time to a
+port.
+
+Usage:
+    1. Choose a port to use. Use 'adb forward tcp:<port>
+    tcp:<port>' to forward the port to the device.
+    2. In a separate shell, build and push the test vendor library to the device
+    using the script mentioned in option A (i.e. without the --test-channel flag
+    set).
+    3. Once logcat has started, turn Bluetooth on from the device.
+    4. Run this program, in the shell from step 1,  the port, also from step 1,
+    as arguments.
+
+    scapy is the tool we use to build packets in Python.
+
+    >>> d = HCI_Hdr(type=1) / HCI_Command_Hdr(opcode = 0x1004) /
+    Raw(load='\x01')
+    >>> print(d)
+    <HCI_Hdr  type=Command |<HCI_Command_Hdr  opcode=0x1004 |<Raw  load='\x01'
+    |>>>
+    >>> raw(d)
+    '\x01\x04\x10\x01\x01'
+    >>> hexdump(d)
+    0000  0104100101                       .....
+
+
+    >>> pkt = HCI_Hdr('\x02\x02\x20\x0a\x00\x06\x00\x01\x00') /
+    L2CAP_CmdHdr(code=10, id=2, len=2) /L2CAP_InfoReq(type=2)
+    >>> pkt
+    <HCI_Hdr  type=ACL Data |<HCI_ACL_Hdr  handle=2 PB=0 BC=2 len=10 |<L2CAP_Hdr
+    len=6 cid=control |<L2CAP_CmdHdr  code=info_req id=2 len=2 |<L2CAP_InfoReq
+    type=FEAT_MASK |>>>>>
+    >>> pkt = HCI_Hdr(type="ACL Data") / HCI_ACL_Hdr(handle=2, PB=0, BC=2,
+    len=10) / L2CAP_Hdr(len=6, cid="control") / L2CAP_CmdHdr(code="info_req",
+    id=2, len=2) / L2CAP_InfoReq(type="FEAT_MASK")
+    >>> raw(pkt)
+    '\x02\x02 \n\x00\x06\x00\x01\x00\n\x02\x02\x00\x02\x00'
+    >>> hexdump(pkt)
+    0000  0202200A00060001000A0202000200   .. ............
+
+
+"""
+
+#!/usr/bin/env python
+
+import binascii
+import cmd
+import random
+import socket
+import string
+import struct
+import sys
+from scapy.all import *
+
+DEVICE_NAME_LENGTH = 6
+DEVICE_ADDRESS_LENGTH = 6
+
+
+# Used to generate fake device names and addresses during discovery.
+def generate_random_name():
+  return ''.join(random.SystemRandom().choice(string.ascii_uppercase + \
+    string.digits) for _ in range(DEVICE_NAME_LENGTH))
+
+
+def generate_random_address():
+  return ''.join(random.SystemRandom().choice(string.digits) for _ in \
+    range(DEVICE_ADDRESS_LENGTH))
+
+
+class Connection(object):
+  """Simple wrapper class for a socket object.
+
+  Attributes:
+    socket: The underlying socket created for the specified address and port.
+  """
+
+  def __init__(self, port):
+    self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    self._socket.connect(('localhost', port))
+    self._socket.setblocking(0)
+
+  def close(self):
+    self._socket.close()
+
+  def send(self, data):
+    self._socket.sendall(data)
+
+  def receive(self, size):
+    return self._socket.recv(size)
+
+
+class RawPort(object):
+  """Checks outgoing commands and sends them once verified.
+
+  Attributes:
+    connection: The connection to the HCI port.
+  """
+
+  def __init__(self, port):
+    self._connection = Connection(port)
+    self._closed = False
+
+  def close(self):
+    self._connection.close()
+    self._closed = True
+
+  def send_binary(self, args):
+    joined_args = ''.join(arg for arg in args)
+    print(joined_args)
+    packet = binascii.a2b_hex(joined_args)
+    if self._closed:
+      return
+    self._connection.send(packet)
+    received = self.receive_response()
+    received_bytes = bytearray(received)
+    print(raw(received_bytes))
+
+  def receive_response(self):
+    if self._closed:
+      return
+    size_chars = self._connection.receive(4)
+    if not size_chars:
+      print('Debug: No response')
+      return False
+    size_bytes = bytearray(size_chars)
+    response_size = 0
+    for i in range(0, len(size_chars) - 1):
+      response_size |= ord(size_chars[i]) << (8 * i)
+    response = self._connection.receive(response_size)
+    return response
+
+  def lint_command(self, name, args, name_size, args_size):
+    assert name_size == len(name) and args_size == len(args)
+    try:
+      name.encode('utf-8')
+      for arg in args:
+        arg.encode('utf-8')
+    except UnicodeError:
+      print('Unrecognized characters.')
+      raise
+    if name_size > 255 or args_size > 255:
+      raise ValueError  # Size must be encodable in one octet.
+    for arg in args:
+      if len(arg) > 255:
+        raise ValueError  # Size must be encodable in one octet.
+
+
+class RawPortShell(cmd.Cmd):
+  """Shell for sending binary data to a port.
+
+  """
+
+  def __init__(self, raw_port):
+    cmd.Cmd.__init__(self)
+    self._raw_port = raw_port
+
+  def do_send(self, args):
+    """Arguments: dev_type_str Add a new device of type dev_type_str.
+
+    """
+    self._raw_port.send_binary(args.split())
+
+  def do_quit(self, args):
+    """Arguments: None.
+
+    Exits.
+    """
+    self._raw_port.close()
+    print('Goodbye.')
+    return True
+
+  def do_help(self, args):
+    """Arguments: [dev_num [attr]] List the commands available, optionally filtered by device and attr.
+
+    """
+    if (len(args) == 0):
+      cmd.Cmd.do_help(self, args)
+
+
+def main(argv):
+  if len(argv) != 2:
+    print('Usage: python raw_port.py [port]')
+    return
+  try:
+    port = int(argv[1])
+  except ValueError:
+    print('Error parsing port.')
+  else:
+    try:
+      raw_port = RawPort(port)
+    except (socket.error, e):
+      print('Error connecting to socket: %s' % e)
+    except:
+      print('Error creating (check arguments).')
+    else:
+      raw_port_shell = RawPortShell(raw_port)
+      raw_port_shell.prompt = '$ '
+      raw_port_shell.cmdloop('Welcome to the RootCanal Console \n' +
+                             'Type \'help\' for more information.')
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/vendor_libs/test_vendor_lib/scripts/simple_link_layer_socket.py b/vendor_libs/test_vendor_lib/scripts/simple_link_layer_socket.py
new file mode 100644
index 0000000..982aee2
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/scripts/simple_link_layer_socket.py
@@ -0,0 +1,197 @@
+#
+# Copyright 2018 The Android Open Source Project
+#
+# 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.
+#
+"""Script for sending data to a port.
+
+This script provides a simple shell interface for sending data at run-time to a
+port.
+
+Usage:
+    1. Choose a port to use. Use 'adb forward tcp:<port>
+    tcp:<port>' to forward the port to the device.
+    2. In a separate shell, build and push the test vendor library to the device
+    using the script mentioned in option A (i.e. without the --test-channel flag
+    set).
+    3. Once logcat has started, turn Bluetooth on from the device.
+    4. Run this program, in the shell from step 1,  the port, also from step 1,
+    as arguments.
+
+
+     length   type   source    dest      addr_type  adv_type     EIR Data
+
+              adv                          public  connectable  Name (TATA)
+send 18000000 07 010203040506 000000000000   00      00         050954415441
+                                                                020106
+
+     length   adv   source    dest        public   non-conn     Name (TETE)
+send 18000000 07 010203040507 000000000000   00       03        050954455445
+                                                                020106
+
+     length scan_rsp  source    dest        public  scan_rsp    Name (TFTF)
+send 18000000 09 010203040506 4de24c67454b    00      04        050954465446
+                                                                020106
+
+"""
+
+#!/usr/bin/env python
+
+import binascii
+import cmd
+import random
+import socket
+import string
+import struct
+import sys
+
+DEVICE_NAME_LENGTH = 6
+DEVICE_ADDRESS_LENGTH = 6
+
+
+# Used to generate fake device names and addresses during discovery.
+def generate_random_name():
+  return ''.join(random.SystemRandom().choice(string.ascii_uppercase + \
+    string.digits) for _ in range(DEVICE_NAME_LENGTH))
+
+
+def generate_random_address():
+  return ''.join(random.SystemRandom().choice(string.digits) for _ in \
+    range(DEVICE_ADDRESS_LENGTH))
+
+
+class Connection(object):
+  """Simple wrapper class for a socket object.
+
+  Attributes:
+    socket: The underlying socket created for the specified address and port.
+  """
+
+  def __init__(self, port):
+    self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    self._socket.connect(('localhost', port))
+    self._socket.setblocking(0)
+
+  def close(self):
+    self._socket.close()
+
+  def send(self, data):
+    self._socket.sendall(data)
+
+  def receive(self, size):
+    return self._socket.recv(size)
+
+
+class RawPort(object):
+  """Checks outgoing commands and sends them once verified.
+
+  Attributes:
+    connection: The connection to the HCI port.
+  """
+
+  def __init__(self, port):
+    self._connection = Connection(port)
+    self._closed = False
+
+  def close(self):
+    self._connection.close()
+    self._closed = True
+
+  def send_binary(self, args):
+    joined_args = ''.join(arg for arg in args)
+    print(joined_args)
+    packet = binascii.a2b_hex(joined_args)
+    if self._closed:
+      return
+    self._connection.send(packet)
+
+  def receive_response(self):
+    if self._closed:
+      return
+    size_chars = self._connection.receive(4)
+    if not size_chars:
+      print('Debug: No response')
+      return False
+    size_bytes = bytearray(size_chars)
+    response_size = 0
+    for i in range(0, len(size_chars) - 1):
+      response_size |= ord(size_chars[i]) << (8 * i)
+    response = self._connection.receive(response_size)
+    return response
+
+  def lint_command(self, name, args, name_size, args_size):
+    assert name_size == len(name) and args_size == len(args)
+    try:
+      name.encode('utf-8')
+      for arg in args:
+        arg.encode('utf-8')
+    except UnicodeError:
+      print('Unrecognized characters.')
+      raise
+    if name_size > 255 or args_size > 255:
+      raise ValueError  # Size must be encodable in one octet.
+    for arg in args:
+      if len(arg) > 255:
+        raise ValueError  # Size must be encodable in one octet.
+
+
+class RawPortShell(cmd.Cmd):
+  """Shell for sending binary data to a port."""
+
+  def __init__(self, raw_port):
+    cmd.Cmd.__init__(self)
+    self._raw_port = raw_port
+
+  def do_send(self, args):
+    """Arguments: dev_type_str Add a new device of type dev_type_str."""
+    self._raw_port.send_binary(args.split())
+
+  def do_quit(self, args):
+    """Arguments: None.
+
+    Exits.
+    """
+    self._raw_port.close()
+    print('Goodbye.')
+    return True
+
+  def do_help(self, args):
+    """Arguments: [dev_num [attr]] List the commands available, optionally filtered by device and attr."""
+    if (len(args) == 0):
+      cmd.Cmd.do_help(self, args)
+
+
+def main(argv):
+  if len(argv) != 2:
+    print('Usage: python raw_port.py [port]')
+    return
+  try:
+    port = int(argv[1])
+  except ValueError:
+    print('Error parsing port.')
+  else:
+    try:
+      raw_port = RawPort(port)
+    except (socket.error, e):
+      print('Error connecting to socket: %s' % e)
+    except:
+      print('Error creating (check arguments).')
+    else:
+      raw_port_shell = RawPortShell(raw_port)
+      raw_port_shell.prompt = '$ '
+      raw_port_shell.cmdloop('Welcome to the RootCanal Console \n' +
+                             'Type \'help\' for more information.')
+
+
+if __name__ == '__main__':
+  main(sys.argv)
diff --git a/vendor_libs/test_vendor_lib/scripts/simple_stack.py b/vendor_libs/test_vendor_lib/scripts/simple_stack.py
new file mode 100644
index 0000000..4f42bf2
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/scripts/simple_stack.py
@@ -0,0 +1,238 @@
+#
+# Copyright 2015 The Android Open Source Project
+#
+# 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.
+#
+"""Script for sending data to a port.
+
+This script provides a simple shell interface for sending data at run-time to a
+port.
+
+Usage:
+    1. Choose a port to use. Use 'adb forward tcp:<port>
+    tcp:<port>' to forward the port to the device.
+    2. In a separate shell, build and push the test vendor library to the device
+    using the script mentioned in option A (i.e. without the --test-channel flag
+    set).
+    3. Once logcat has started, turn Bluetooth on from the device.
+    4. Run this program, in the shell from step 1,  the port, also from step 1,
+    as arguments.
+
+    scapy is the tool we use to build packets in Python.
+
+    >>> d = HCI_Hdr(type=1) / HCI_Command_Hdr(opcode = 0x1004) /
+    Raw(load='\x01')
+    >>> print(d)
+    <HCI_Hdr  type=Command |<HCI_Command_Hdr  opcode=0x1004 |<Raw  load='\x01'
+    |>>>
+    >>> raw(d)
+    '\x01\x04\x10\x01\x01'
+    >>> hexdump(d)
+    0000  0104100101                       .....
+
+
+    >>> pkt = HCI_Hdr('\x02\x02\x20\x0a\x00\x06\x00\x01\x00') /
+    L2CAP_CmdHdr(code=10, id=2, len=2) /L2CAP_InfoReq(type=2)
+    >>> pkt
+    <HCI_Hdr  type=ACL Data |<HCI_ACL_Hdr  handle=2 PB=0 BC=2 len=10 |<L2CAP_Hdr
+    len=6 cid=control |<L2CAP_CmdHdr  code=info_req id=2 len=2 |<L2CAP_InfoReq
+    type=FEAT_MASK |>>>>>
+    >>> pkt = HCI_Hdr(type="ACL Data") / HCI_ACL_Hdr(handle=2, PB=0, BC=2,
+    len=10) / L2CAP_Hdr(len=6, cid="control") / L2CAP_CmdHdr(code="info_req",
+    id=2, len=2) / L2CAP_InfoReq(type="FEAT_MASK")
+    >>> raw(pkt)
+    '\x02\x02 \n\x00\x06\x00\x01\x00\n\x02\x02\x00\x02\x00'
+    >>> hexdump(pkt)
+    0000  0202200A00060001000A0202000200   .. ............
+
+
+"""
+
+#!/usr/bin/env python
+
+import binascii
+import cmd
+import random
+import socket
+import string
+import struct
+import sys
+from scapy.all import *
+""" Add some more SCAPY stuff"""
+
+
+class HCI_Cmd_Connect(Packet):
+  name = "Connect"
+  fields_desc = [
+      ByteEnumField("filter", 0, {0: "address"}),
+      LEShortField("packet_type", 8),
+      ByteEnumField("page_scan_repetition_mode", 0, {
+          0: "R0",
+          1: "R1",
+          2: "R2"
+      }),
+      ByteEnumField("page_scan_repetition_mode", 0, {0: "Reserved"}),
+      LEShortField("clock_offset", 0),
+      ByteEnumField("allow_role_switch", 0, {
+          0: "false",
+          1: "true"
+      }),
+  ]
+
+
+class HCI_Cmd_Inquiry(Packet):
+  name = "Inquiry"
+  fields_desc = [
+      XByteField("LAP0", 0),
+      XByteField("LAP1", 0x8B),
+      XByteField("LAP2", 0x9E),
+      ByteField("length", 1),
+      ByteField("max_responses", 0),
+  ]
+
+
+""" END SCAPY stuff"""
+
+
+class Connection(object):
+  """Simple wrapper class for a socket object.
+
+  Attributes:
+    socket: The underlying socket created for the specified address and port.
+  """
+
+  def __init__(self, port):
+    self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    self._socket.connect(("localhost", port))
+
+  def close(self):
+    self._socket.close()
+
+  def send(self, data):
+    self._socket.sendall(data)
+
+  def receive(self, size):
+    return self._socket.recv(size)
+
+
+class RawPort(object):
+  """Converts outgoing packets to binary and sends them.
+
+  Attributes:
+    connection: The connection to the HCI port.
+  """
+
+  def __init__(self, port):
+    self._connection = Connection(port)
+
+  def close(self):
+    self._connection.close()
+
+  def send_binary(self, args):
+    joined_args = "".join(arg for arg in args)
+    print(joined_args)
+    packet = binascii.a2b_hex(joined_args)
+    self._connection.send(packet)
+
+  def receive_response(self):
+    ready_to_read, ready_to_write, in_error = \
+               select.select(
+                  [ self._connection._socket ],
+                  [ ],
+                  [ self._connection._socket ],
+                  1.5)
+    if len(in_error) > 0:
+      print("Error")
+      return False
+    if len(ready_to_read) > 0:
+      print("Ready to Read")
+      type_str = self._connection.receive(512)
+      print(len(type_str))
+      print(type_str)
+      return type_str
+    print("Returning false at the end")
+    return False
+
+
+class RawPortShell(cmd.Cmd):
+  """Shell for sending binary data to a port.
+
+  """
+
+  def __init__(self, raw_port):
+    cmd.Cmd.__init__(self)
+    self._raw_port = raw_port
+
+  def do_send(self, args):
+    """Arguments: dev_type_str Add a new device of type dev_type_str.
+
+    """
+    self._raw_port.send_binary(args.split())
+
+  def do_scan(self, args):
+    """Arguments: timeout (seconds) Print the scan responses from reachable devices
+
+    """
+    self._raw_port.send_binary(args.split())
+
+  def do_quit(self, args):
+    """Arguments: None.
+
+    Exits.
+    """
+    self._raw_port.close()
+    print("Goodbye.")
+    return True
+
+  def do_help(self, args):
+    """Arguments: [dev_num [attr]] List the commands available, optionally filtered by device and attr.
+
+    """
+    if (len(args) == 0):
+      cmd.Cmd.do_help(self, args)
+
+  def postcmd(self, stop, line):
+    """Called after each command stop : whether we will stop after this command line : the previous input line Return True to stop, False to continue
+
+    """
+    if stop:
+      return True
+    response = self._raw_port.receive_response()
+    print(response)
+    return False
+
+
+def main(argv):
+  if len(argv) != 2:
+    print("Usage: python raw_port.py [port]")
+    return
+  try:
+    port = int(argv[1])
+  except ValueError:
+    print("Error parsing port.")
+  else:
+    try:
+      raw_port = RawPort(port)
+    except (socket.error, e):
+      print("Error connecting to socket: %s" % e)
+    except:
+      print("Error creating (check arguments).")
+    else:
+      raw_port_shell = RawPortShell(raw_port)
+      raw_port_shell.prompt = "$ "
+      raw_port_shell.cmdloop("Welcome to the RootCanal Console \n" +
+                             'Type \'help\' for more information.')
+
+
+if __name__ == "__main__":
+  main(sys.argv)
diff --git a/vendor_libs/test_vendor_lib/scripts/test_channel.py b/vendor_libs/test_vendor_lib/scripts/test_channel.py
index 06b0410..15f5f1f 100644
--- a/vendor_libs/test_vendor_lib/scripts/test_channel.py
+++ b/vendor_libs/test_vendor_lib/scripts/test_channel.py
@@ -13,7 +13,6 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 #
-
 """Script for sending testing parameters and commands to a Bluetooth device.
 
 This script provides a simple shell interface for sending data at run-time to a
@@ -47,15 +46,18 @@
 DEVICE_NAME_LENGTH = 6
 DEVICE_ADDRESS_LENGTH = 6
 
+
 # Used to generate fake device names and addresses during discovery.
 def generate_random_name():
   return ''.join(random.SystemRandom().choice(string.ascii_uppercase + \
     string.digits) for _ in range(DEVICE_NAME_LENGTH))
 
+
 def generate_random_address():
   return ''.join(random.SystemRandom().choice(string.digits) for _ in \
     range(DEVICE_ADDRESS_LENGTH))
 
+
 class Connection(object):
   """Simple wrapper class for a socket object.
 
@@ -73,25 +75,25 @@
   def send(self, data):
     self._socket.sendall(data)
 
+  def receive(self, size):
+    return self._socket.recv(size)
+
+
 class TestChannel(object):
   """Checks outgoing commands and sends them once verified.
 
   Attributes:
     connection: The connection to the test vendor library that commands are sent
-    on.
+      on.
   """
 
   def __init__(self, port):
     self._connection = Connection(port)
-    self._discovered_devices = DeviceManager()
-
-  def discover_new_device(self, name=None, address=None):
-    device = Device(name, address)
-    self._discovered_devices.add_device(device)
-    return device
+    self._closed = False
 
   def close(self):
     self._connection.close()
+    self._closed = True
 
   def send_command(self, name, args):
     name_size = len(name)
@@ -100,7 +102,25 @@
     encoded_name = chr(name_size) + name
     encoded_args = chr(args_size) + ''.join(chr(len(arg)) + arg for arg in args)
     command = encoded_name + encoded_args
+    if self._closed:
+      return
     self._connection.send(command)
+    if name != 'CLOSE_TEST_CHANNEL':
+      print self.receive_response()
+
+  def receive_response(self):
+    if self._closed:
+      return
+    size_chars = self._connection.receive(4)
+    size_bytes = bytearray(size_chars)
+    if not size_chars:
+      print 'No response, assuming that the connection is broken'
+      return False
+    response_size = 0
+    for i in range(0, len(size_chars) - 1):
+      response_size |= ord(size_chars[i]) << (8 * i)
+    response = self._connection.receive(response_size)
+    return response
 
   def lint_command(self, name, args, name_size, args_size):
     assert name_size == len(name) and args_size == len(args)
@@ -117,39 +137,6 @@
       if len(arg) > 255:
         raise ValueError  # Size must be encodable in one octet.
 
-class DeviceManager(object):
-  """Maintains the active fake devices that have been "discovered".
-
-  Attributes:
-    device_list: Maps device addresses (keys) to devices (values).
-  """
-
-  def __init__(self):
-    self.device_list = {}
-
-  def add_device(self, device):
-    self.device_list[device.get_address()] = device
-
-class Device(object):
-  """A fake device to be returned in inquiry and scan results. Note that if an
-  explicit name or address is not provided, a random string of characters
-  is used.
-
-  Attributes:
-    name: The device name for use in extended results.
-    address: The BD address of the device.
-  """
-
-  def __init__(self, name=None, address=None):
-    # TODO(dennischeng): Generate device properties more robustly.
-    self._name = generate_random_name() if name is None else name
-    self._address = generate_random_address() if address is None else address
-
-  def get_name(self):
-    return self._name
-
-  def get_address(self):
-    return self._address
 
 class TestChannelShell(cmd.Cmd):
   """Shell for sending test channel data to controller.
@@ -164,48 +151,72 @@
   """
 
   def __init__(self, test_channel):
-    print 'Type \'help\' for more information.'
     cmd.Cmd.__init__(self)
     self._test_channel = test_channel
 
   def do_add(self, args):
-    """
-    Arguments: dev_type_str
-    Add a new device of type dev_type_str.
+    """Arguments: dev_type_str Add a new device of type dev_type_str.
+
     """
     self._test_channel.send_command('add', args.split())
 
   def do_del(self, args):
-    """
-    Arguments: device index
-    Delete the device with the specified index.
+    """Arguments: device index Delete the device with the specified index.
+
     """
     self._test_channel.send_command('del', args.split())
 
-  def do_get(self, args):
+  def do_add_phy(self, args):
+    """Arguments: dev_type_str Add a new device of type dev_type_str.
+
     """
-    Arguments: dev_num attr_str
-    Get the value of the attribute attr_str from device dev_num.
+    self._test_channel.send_command('add_phy', args.split())
+
+  def do_del_phy(self, args):
+    """Arguments: phy index Delete the phy with the specified index.
+
+    """
+    self._test_channel.send_command('del_phy', args.split())
+
+  def do_add_device_to_phy(self, args):
+    """Arguments: device index phy index Add a new device of type dev_type_str.
+
+    """
+    self._test_channel.send_command('add_device_to_phy', args.split())
+
+  def do_del_device_from_phy(self, args):
+    """Arguments: phy index Delete the phy with the specified index.
+
+    """
+    self._test_channel.send_command('del_device_from_phy', args.split())
+
+  def do_add_remote(self, args):
+    """Arguments: dev_type_str Connect to a remote device at arg1@arg2.
+
+    """
+    self._test_channel.send_command('add_remote', args.split())
+
+  def do_get(self, args):
+    """Arguments: dev_num attr_str Get the value of the attribute attr_str from device dev_num.
+
     """
     self._test_channel.send_command('get', args.split())
 
   def do_set(self, args):
-    """
-    Arguments: dev_num attr_str val
-    Set the value of the attribute attr_str from device dev_num equal to val.
+    """Arguments: dev_num attr_str val Set the value of the attribute attr_str from device dev_num equal to val.
+
     """
     self._test_channel.send_command('set', args.split())
 
   def do_list(self, args):
-    """
-    Arguments: [dev_num [attr]]
-    List the devices from the controller, optionally filtered by device and attr.
+    """Arguments: [dev_num [attr]] List the devices from the controller, optionally filtered by device and attr.
+
     """
     self._test_channel.send_command('list', args.split())
 
   def do_quit(self, args):
-    """
-    Arguments: None.
+    """Arguments: None.
+
     Exits the test channel.
     """
     self._test_channel.send_command('CLOSE_TEST_CHANNEL', [])
@@ -214,13 +225,35 @@
     return True
 
   def do_help(self, args):
+    """Arguments: [dev_num [attr]] List the commands available, optionally filtered by device and attr.
+
     """
-    Arguments: [dev_num [attr]]
-    List the commands available, optionally filtered by device and attr.
-    """
-    self._test_channel.send_command('help', args.split())
     if (len(args) == 0):
       cmd.Cmd.do_help(self, args)
+    else:
+      self._test_channel.send_command('help', args.split())
+
+  def preloop(self):
+    """Clear out the buffer
+
+    """
+    response = self._test_channel.receive_response()
+
+  #def postcmd(self, stop, line):
+  #"""
+  #Called after each command
+  #stop : whether we will stop after this command
+  #line : the previous input line
+  #Return True to stop, False to continue
+  #"""
+  #if stop:
+  #return True
+  #response = self._test_channel.receive_response()
+  #if not response:
+  #return True
+  #print response
+  #return False
+
 
 def main(argv):
   if len(argv) != 2:
@@ -240,7 +273,9 @@
     else:
       test_channel_shell = TestChannelShell(test_channel)
       test_channel_shell.prompt = '$ '
-      test_channel_shell.cmdloop()
+      test_channel_shell.cmdloop('Welcome to the RootCanal Console \n' +
+                                 'Type \'help\' for more information.')
+
 
 if __name__ == '__main__':
   main(sys.argv)
diff --git a/vendor_libs/test_vendor_lib/src/acl_packet.cc b/vendor_libs/test_vendor_lib/src/acl_packet.cc
deleted file mode 100644
index 47aa8be..0000000
--- a/vendor_libs/test_vendor_lib/src/acl_packet.cc
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "acl_packet"
-
-#include "acl_packet.h"
-
-#include "base/logging.h"
-#include "osi/include/log.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-AclPacket::AclPacket(uint16_t channel,
-                     AclPacket::PacketBoundaryFlags packet_boundary,
-                     AclPacket::BroadcastFlags broadcast)
-    : raw_packet_({static_cast<uint8_t>(channel & 0xff),
-                   static_cast<uint8_t>(((channel >> 8) & 0x0f) |
-                                        ((packet_boundary & 0x3) << 4) |
-                                        (broadcast & 0x3) << 6),
-                   0x00, 0x00}) {}
-
-void AclPacket::AddPayloadOctets(size_t octets, const vector<uint8_t>& bytes) {
-  CHECK(bytes.size() == octets);
-
-  raw_packet_.insert(raw_packet_.end(), bytes.begin(), bytes.end());
-
-  raw_packet_[2] =
-      static_cast<uint8_t>((raw_packet_.size() - kHeaderSize) & 0xff);
-  raw_packet_[3] =
-      static_cast<uint8_t>(((raw_packet_.size() - kHeaderSize) >> 8) & 0xff);
-}
-
-void AclPacket::AddPayloadOctets(size_t octets, uint64_t value) {
-  vector<uint8_t> val_vector;
-
-  uint64_t v = value;
-
-  CHECK(octets <= sizeof(uint64_t));
-
-  for (size_t i = 0; i < octets; i++) {
-    val_vector.push_back(v & 0xff);
-    v = v >> 8;
-  }
-
-  CHECK(v == 0);
-
-  AddPayloadOctets(octets, val_vector);
-}
-
-size_t AclPacket::GetPacketSize() const { return raw_packet_.size(); }
-
-const std::vector<uint8_t>& AclPacket::GetPacket() const { return raw_packet_; }
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/beacon.cc b/vendor_libs/test_vendor_lib/src/beacon.cc
deleted file mode 100644
index 0ca4507..0000000
--- a/vendor_libs/test_vendor_lib/src/beacon.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "beacon"
-
-#include "beacon.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-Beacon::Beacon() {
-  advertising_interval_ms_ = std::chrono::milliseconds(1280);
-  advertising_type_ = BTM_BLE_NON_CONNECT_EVT;
-  adv_data_ = {0x0F,  // Length
-               BTM_BLE_AD_TYPE_NAME_CMPL,
-               'g',
-               'D',
-               'e',
-               'v',
-               'i',
-               'c',
-               'e',
-               '-',
-               'b',
-               'e',
-               'a',
-               'c',
-               'o',
-               'n',
-               0x02,  // Length
-               BTM_BLE_AD_TYPE_FLAG,
-               BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG};
-
-  scan_data_ = {0x05,  // Length
-                BTM_BLE_AD_TYPE_NAME_SHORT,
-                'b',
-                'e',
-                'a',
-                'c'};
-}
-
-void Beacon::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  BtAddress addr;
-  if (addr.FromString(args[1])) SetBtAddress(addr);
-
-  if (args.size() < 3) return;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/beacon_swarm.cc b/vendor_libs/test_vendor_lib/src/beacon_swarm.cc
deleted file mode 100644
index 2f4eed1..0000000
--- a/vendor_libs/test_vendor_lib/src/beacon_swarm.cc
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "beacon_swarm"
-
-#include "beacon_swarm.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-BeaconSwarm::BeaconSwarm() {
-  advertising_interval_ms_ = std::chrono::milliseconds(1280);
-  advertising_type_ = BTM_BLE_NON_CONNECT_EVT;
-  adv_data_ = {0x02,  // Length
-               BTM_BLE_AD_TYPE_FLAG,
-               BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG,
-               0x15,
-               BTM_BLE_AD_TYPE_NAME_CMPL,
-               'g',
-               'D',
-               'e',
-               'v',
-               'i',
-               'c',
-               'e',
-               '-',
-               'b',
-               'e',
-               'a',
-               'c',
-               'o',
-               'n',
-               '_',
-               's',
-               'w',
-               'a',
-               'r',
-               'm'};
-
-  scan_response_present_ = true;
-  scan_data_ = {0x06,  // Length
-                BTM_BLE_AD_TYPE_NAME_SHORT,
-                'c',
-                'b',
-                'e',
-                'a',
-                'c'};
-}
-
-void BeaconSwarm::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  BtAddress addr;
-  if (addr.FromString(args[1])) SetBtAddress(addr);
-
-  if (args.size() < 3) return;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
-void BeaconSwarm::TimerTick() {
-  std::vector<uint8_t> beacon_addr;
-  GetBtAddress().ToVector(beacon_addr);
-  beacon_addr[0]++;
-  BtAddress next_addr;
-  next_addr.FromVector(beacon_addr);
-
-  SetBtAddress(next_addr);
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/bt_address.cc b/vendor_libs/test_vendor_lib/src/bt_address.cc
deleted file mode 100644
index e9d6790..0000000
--- a/vendor_libs/test_vendor_lib/src/bt_address.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "bt_address.h"
-#include <iomanip>
-#include <vector>
-using std::vector;
-
-#include <base/logging.h>
-
-namespace test_vendor_lib {
-
-bool BtAddress::IsValid(const std::string& addr) {
-  if (addr.length() < kStringLength) return false;
-
-  for (size_t i = 0; i < kStringLength; i++) {
-    if (i % 3 == 2) {  // Every third character must be ':'
-      if (addr[i] != ':') return false;
-    } else {  // The rest must be hexadecimal digits
-      if (!isxdigit(addr[i])) return false;
-    }
-  }
-  return true;
-}
-
-bool BtAddress::FromString(const std::string& str) {
-  std::string tok;
-  std::istringstream iss(str);
-
-  if (!IsValid(str)) return false;
-
-  address_ = 0;
-  for (size_t i = 0; i < kOctets; i++) {
-    getline(iss, tok, ':');
-    uint64_t octet = std::stoi(tok, nullptr, 16);
-    address_ |= (octet << (8 * ((kOctets - 1) - i)));
-  }
-  return true;
-}
-
-bool BtAddress::FromVector(const vector<uint8_t>& octets) {
-  if (octets.size() < kOctets) return false;
-
-  address_ = 0;
-  for (size_t i = 0; i < kOctets; i++) {
-    uint64_t to_shift = octets[i];
-    address_ |= to_shift << (8 * i);
-  }
-  return true;
-}
-
-void BtAddress::ToVector(vector<uint8_t>& octets) const {
-  for (size_t i = 0; i < kOctets; i++) {
-    octets.push_back(address_ >> (8 * i));
-  }
-}
-
-std::string BtAddress::ToString() const {
-  std::stringstream ss;
-
-  ss << std::hex << std::setfill('0') << std::setw(2);
-  for (size_t i = 0; i < kOctets; i++) {
-    uint64_t octet = (address_ >> (8 * ((kOctets - 1) - i))) & 0xff;
-    ss << std::hex << std::setfill('0') << std::setw(2) << octet;
-    if (i != kOctets - 1) ss << std::string(":");
-  }
-
-  return ss.str();
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/classic.cc b/vendor_libs/test_vendor_lib/src/classic.cc
deleted file mode 100644
index b878b5f..0000000
--- a/vendor_libs/test_vendor_lib/src/classic.cc
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "classic"
-
-#include "classic.h"
-#include "osi/include/log.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-Classic::Classic() {
-  advertising_interval_ms_ = std::chrono::milliseconds(0);
-  device_class_ = 0x30201;
-
-  extended_inquiry_data_ = {0x10,  // Length
-                            BT_EIR_COMPLETE_LOCAL_NAME_TYPE,
-                            'g',
-                            'D',
-                            'e',
-                            'v',
-                            'i',
-                            'c',
-                            'e',
-                            '-',
-                            'c',
-                            'l',
-                            'a',
-                            's',
-                            's',
-                            'i',
-                            'c'};
-  page_scan_repetition_mode_ = 0;
-  page_scan_delay_ms_ = std::chrono::milliseconds(600);
-}
-
-void Classic::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  BtAddress addr;
-  if (addr.FromString(args[1])) SetBtAddress(addr);
-
-  if (args.size() < 3) return;
-
-  SetClockOffset(std::stoi(args[2]));
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/command_packet.cc b/vendor_libs/test_vendor_lib/src/command_packet.cc
deleted file mode 100644
index 9b44c98..0000000
--- a/vendor_libs/test_vendor_lib/src/command_packet.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "command_packet"
-
-#include "command_packet.h"
-
-#include "hci/include/hci_hal.h"
-#include "osi/include/log.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-CommandPacket::CommandPacket(vector<uint8_t> header)
-    : Packet(DATA_TYPE_COMMAND, std::move(header)) {}
-
-CommandPacket::CommandPacket(uint16_t opcode)
-    : Packet(DATA_TYPE_COMMAND, {static_cast<uint8_t>(opcode),
-                                 static_cast<uint8_t>(opcode >> 8)}) {}
-
-CommandPacket::CommandPacket(vector<uint8_t> header, vector<uint8_t> payload)
-    : Packet(DATA_TYPE_COMMAND, std::move(header)) {
-  AddPayloadOctets(payload.size(), std::move(payload));
-}
-
-uint16_t CommandPacket::GetOpcode() const {
-  return 0 | (GetHeader()[0] | (GetHeader()[1] << 8));
-}
-
-uint8_t CommandPacket::GetOGF() const { return HCI_OGF(GetOpcode()); }
-
-uint16_t CommandPacket::GetOCF() const { return HCI_OCF(GetOpcode()); }
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/connection.cc b/vendor_libs/test_vendor_lib/src/connection.cc
deleted file mode 100644
index 5bdc20f..0000000
--- a/vendor_libs/test_vendor_lib/src/connection.cc
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "connection"
-
-#include "connection.h"
-
-#include "base/logging.h"
-
-#include "osi/include/log.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-// Add an action from the controller.
-void Connection::AddAction(const TaskCallback& task) { actions_.push(task); }
-
-// Model the quality of the downstream connection
-void Connection::SendToDevice() {
-  while (actions_.size() > 0) {
-    // Execute the first action
-    actions_.front()();
-    actions_.pop();
-  }
-}
-
-// Add a message from the device to the controller.
-void Connection::AddMessage(const vector<uint8_t>& data) {
-  messages_.push(data);
-}
-
-// Model the quality of the upstream connection
-bool Connection::ReceiveFromDevice(vector<uint8_t>& data) {
-  if (messages_.size() > 0) {
-    data = messages_.front();
-    messages_.pop();
-
-    return true;
-  }
-  return false;
-}
-
-const std::string Connection::ToString() {
-  return "connection " + std::to_string(handle_) + " to " + dev_->ToString();
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/device.cc b/vendor_libs/test_vendor_lib/src/device.cc
deleted file mode 100644
index 86d18c0..0000000
--- a/vendor_libs/test_vendor_lib/src/device.cc
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "device"
-
-#include <vector>
-
-#include "device.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-std::string Device::ToString() const {
-  std::string dev = "(" + GetTypeString() + ")" + "@" + address_.ToString();
-
-  return dev;
-}
-
-bool Device::IsAdvertisementAvailable(
-    std::chrono::milliseconds scan_time) const {
-  if (advertising_interval_ms_ == std::chrono::milliseconds(0)) return false;
-
-  std::chrono::steady_clock::time_point now = std::chrono::steady_clock::now();
-
-  std::chrono::steady_clock::time_point last_interval =
-      ((now - time_stamp_) / advertising_interval_ms_) *
-          advertising_interval_ms_ +
-      time_stamp_;
-
-  std::chrono::steady_clock::time_point next_interval =
-      last_interval + advertising_interval_ms_;
-
-  return ((now + scan_time) >= next_interval);
-}
-
-bool Device::IsPageScanAvailable() const { return true; }
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/device_factory.cc b/vendor_libs/test_vendor_lib/src/device_factory.cc
deleted file mode 100644
index 3e23dee..0000000
--- a/vendor_libs/test_vendor_lib/src/device_factory.cc
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "device_factory"
-
-#include "device_factory.h"
-#include "beacon.h"
-#include "beacon_swarm.h"
-#include "broken_adv.h"
-#include "classic.h"
-#include "device.h"
-#include "keyboard.h"
-
-#include "base/logging.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-std::shared_ptr<Device> DeviceFactory::Create(const vector<std::string>& args) {
-  CHECK(!args.empty());
-
-  std::shared_ptr<Device> new_device = nullptr;
-
-  if (args[0] == "beacon") new_device = std::make_shared<Beacon>();
-  if (args[0] == "beacon_swarm") new_device = std::make_shared<BeaconSwarm>();
-  if (args[0] == "broken_adv") new_device = std::make_shared<BrokenAdv>();
-  if (args[0] == "classic") new_device = std::make_shared<Classic>();
-  if (args[0] == "keyboard") new_device = std::make_shared<Keyboard>();
-
-  if (new_device != nullptr) new_device->Initialize(args);
-
-  return new_device;
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc b/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc
deleted file mode 100644
index bc80866..0000000
--- a/vendor_libs/test_vendor_lib/src/dual_mode_controller.cc
+++ /dev/null
@@ -1,921 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "dual_mode_controller"
-
-#include "dual_mode_controller.h"
-#include "device_factory.h"
-
-#include <memory>
-
-#include <base/logging.h>
-#include "base/files/file_util.h"
-#include "base/json/json_reader.h"
-#include "base/values.h"
-
-#include "osi/include/log.h"
-#include "osi/include/osi.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace {
-
-// Included in certain events to indicate success (specific to the event
-// context).
-const uint8_t kSuccessStatus = 0;
-
-const uint8_t kUnknownHciCommand = 1;
-
-// The location of the config file loaded to populate controller attributes.
-const std::string kControllerPropertiesFile =
-    "/etc/bluetooth/controller_properties.json";
-
-void LogCommand(const char* command) {
-  LOG_INFO(LOG_TAG, "Controller performing command: %s", command);
-}
-
-}  // namespace
-
-namespace test_vendor_lib {
-
-void DualModeController::AddControllerEvent(std::chrono::milliseconds delay,
-                                            const TaskCallback& task) {
-  controller_events_.push_back(schedule_task_(delay, task));
-}
-
-void DualModeController::AddConnectionAction(const TaskCallback& task,
-                                             uint16_t handle) {
-  for (size_t i = 0; i < connections_.size(); i++)
-    if (*connections_[i] == handle) connections_[i]->AddAction(task);
-}
-
-void DualModeController::SendCommandCompleteSuccess(
-    uint16_t command_opcode) const {
-  send_event_(EventPacket::CreateCommandCompleteOnlyStatusEvent(
-      command_opcode, kSuccessStatus));
-}
-
-void DualModeController::SendCommandCompleteOnlyStatus(uint16_t command_opcode,
-                                                       uint8_t status) const {
-  send_event_(EventPacket::CreateCommandCompleteOnlyStatusEvent(command_opcode,
-                                                                status));
-}
-
-void DualModeController::SendCommandStatus(uint8_t status,
-                                           uint16_t command_opcode) const {
-  send_event_(EventPacket::CreateCommandStatusEvent(status, command_opcode));
-}
-
-void DualModeController::SendCommandStatusSuccess(
-    uint16_t command_opcode) const {
-  SendCommandStatus(kSuccessStatus, command_opcode);
-}
-
-DualModeController::DualModeController()
-    : state_(kStandby), properties_(kControllerPropertiesFile) {
-  devices_ = {};
-
-  vector<std::string> beacon = {"beacon", "be:ac:10:00:00:01", "1000"};
-  TestChannelAdd(beacon);
-
-  vector<std::string> classic = {std::string("classic"),
-                                 std::string("c1:a5:51:c0:00:01")};
-  TestChannelAdd(classic);
-
-  vector<std::string> keyboard = {std::string("keyboard"),
-                                  std::string("cc:1c:eb:0a:12:d1"),
-                                  std::string("500")};
-  TestChannelAdd(keyboard);
-
-  le_scan_enable_ = 0;
-  le_connect_ = false;
-
-  loopback_mode_ = 0;
-
-#define SET_HANDLER(opcode, method)                                     \
-  active_hci_commands_[opcode] = [this](const vector<uint8_t>& param) { \
-    method(param);                                                      \
-  };
-  SET_HANDLER(HCI_RESET, HciReset);
-  SET_HANDLER(HCI_READ_BUFFER_SIZE, HciReadBufferSize);
-  SET_HANDLER(HCI_HOST_BUFFER_SIZE, HciHostBufferSize);
-  SET_HANDLER(HCI_READ_LOCAL_VERSION_INFO, HciReadLocalVersionInformation);
-  SET_HANDLER(HCI_READ_BD_ADDR, HciReadBdAddr);
-  SET_HANDLER(HCI_READ_LOCAL_SUPPORTED_CMDS, HciReadLocalSupportedCommands);
-  SET_HANDLER(HCI_READ_LOCAL_SUPPORTED_CODECS, HciReadLocalSupportedCodecs);
-  SET_HANDLER(HCI_READ_LOCAL_EXT_FEATURES, HciReadLocalExtendedFeatures);
-  SET_HANDLER(HCI_WRITE_SIMPLE_PAIRING_MODE, HciWriteSimplePairingMode);
-  SET_HANDLER(HCI_WRITE_LE_HOST_SUPPORT, HciWriteLeHostSupport);
-  SET_HANDLER(HCI_SET_EVENT_MASK, HciSetEventMask);
-  SET_HANDLER(HCI_WRITE_INQUIRY_MODE, HciWriteInquiryMode);
-  SET_HANDLER(HCI_WRITE_PAGESCAN_TYPE, HciWritePageScanType);
-  SET_HANDLER(HCI_WRITE_INQSCAN_TYPE, HciWriteInquiryScanType);
-  SET_HANDLER(HCI_WRITE_CLASS_OF_DEVICE, HciWriteClassOfDevice);
-  SET_HANDLER(HCI_WRITE_PAGE_TOUT, HciWritePageTimeout);
-  SET_HANDLER(HCI_WRITE_DEF_POLICY_SETTINGS, HciWriteDefaultLinkPolicySettings);
-  SET_HANDLER(HCI_READ_LOCAL_NAME, HciReadLocalName);
-  SET_HANDLER(HCI_CHANGE_LOCAL_NAME, HciWriteLocalName);
-  SET_HANDLER(HCI_WRITE_EXT_INQ_RESPONSE, HciWriteExtendedInquiryResponse);
-  SET_HANDLER(HCI_WRITE_VOICE_SETTINGS, HciWriteVoiceSetting);
-  SET_HANDLER(HCI_WRITE_CURRENT_IAC_LAP, HciWriteCurrentIacLap);
-  SET_HANDLER(HCI_WRITE_INQUIRYSCAN_CFG, HciWriteInquiryScanActivity);
-  SET_HANDLER(HCI_WRITE_SCAN_ENABLE, HciWriteScanEnable);
-  SET_HANDLER(HCI_SET_EVENT_FILTER, HciSetEventFilter);
-  SET_HANDLER(HCI_INQUIRY, HciInquiry);
-  SET_HANDLER(HCI_INQUIRY_CANCEL, HciInquiryCancel);
-  SET_HANDLER(HCI_DELETE_STORED_LINK_KEY, HciDeleteStoredLinkKey);
-  SET_HANDLER(HCI_RMT_NAME_REQUEST, HciRemoteNameRequest);
-  SET_HANDLER(HCI_BLE_SET_EVENT_MASK, HciLeSetEventMask);
-  SET_HANDLER(HCI_BLE_READ_BUFFER_SIZE, HciLeReadBufferSize);
-  SET_HANDLER(HCI_BLE_READ_LOCAL_SPT_FEAT, HciLeReadLocalSupportedFeatures);
-  SET_HANDLER(HCI_BLE_WRITE_RANDOM_ADDR, HciLeSetRandomAddress);
-  SET_HANDLER(HCI_BLE_WRITE_ADV_DATA, HciLeSetAdvertisingData);
-  SET_HANDLER(HCI_BLE_WRITE_ADV_PARAMS, HciLeSetAdvertisingParameters);
-  SET_HANDLER(HCI_BLE_WRITE_SCAN_PARAMS, HciLeSetScanParameters);
-  SET_HANDLER(HCI_BLE_WRITE_SCAN_ENABLE, HciLeSetScanEnable);
-  SET_HANDLER(HCI_BLE_CREATE_LL_CONN, HciLeCreateConnection);
-  SET_HANDLER(HCI_BLE_CREATE_CONN_CANCEL, HciLeConnectionCancel);
-  SET_HANDLER(HCI_BLE_READ_WHITE_LIST_SIZE, HciLeReadWhiteListSize);
-  SET_HANDLER(HCI_BLE_RAND, HciLeRand);
-  SET_HANDLER(HCI_BLE_READ_SUPPORTED_STATES, HciLeReadSupportedStates);
-  SET_HANDLER((HCI_GRP_VENDOR_SPECIFIC | 0x27), HciBleVendorSleepMode);
-  SET_HANDLER(HCI_BLE_VENDOR_CAP_OCF, HciBleVendorCap);
-  SET_HANDLER(HCI_BLE_MULTI_ADV_OCF, HciBleVendorMultiAdv);
-  SET_HANDLER((HCI_GRP_VENDOR_SPECIFIC | 0x155), HciBleVendor155);
-  SET_HANDLER(HCI_BLE_ADV_FILTER_OCF, HciBleAdvertisingFilter);
-  SET_HANDLER(HCI_BLE_ENERGY_INFO_OCF, HciBleEnergyInfo);
-  SET_HANDLER(HCI_BLE_EXTENDED_SCAN_PARAMS_OCF, HciBleExtendedScanParams);
-  // Testing Commands
-  SET_HANDLER(HCI_READ_LOOPBACK_MODE, HciReadLoopbackMode);
-  SET_HANDLER(HCI_WRITE_LOOPBACK_MODE, HciWriteLoopbackMode);
-#undef SET_HANDLER
-
-#define SET_TEST_HANDLER(command_name, method)  \
-  active_test_channel_commands_[command_name] = \
-      [this](const vector<std::string>& param) { method(param); };
-  SET_TEST_HANDLER("add", TestChannelAdd);
-  SET_TEST_HANDLER("del", TestChannelDel);
-  SET_TEST_HANDLER("list", TestChannelList);
-#undef SET_TEST_HANDLER
-}
-
-void DualModeController::RegisterTaskScheduler(
-    std::function<AsyncTaskId(std::chrono::milliseconds, const TaskCallback&)>
-        oneshotScheduler) {
-  schedule_task_ = oneshotScheduler;
-}
-
-void DualModeController::RegisterPeriodicTaskScheduler(
-    std::function<AsyncTaskId(std::chrono::milliseconds,
-                              std::chrono::milliseconds, const TaskCallback&)>
-        periodicScheduler) {
-  schedule_periodic_task_ = periodicScheduler;
-}
-
-void DualModeController::RegisterTaskCancel(
-    std::function<void(AsyncTaskId)> task_cancel) {
-  cancel_task_ = task_cancel;
-}
-
-void DualModeController::HandleTestChannelCommand(
-    const std::string& name, const vector<std::string>& args) {
-  if (active_test_channel_commands_.count(name) == 0) return;
-  active_test_channel_commands_[name](args);
-}
-
-void DualModeController::HandleAcl(std::unique_ptr<AclPacket> acl_packet) {
-  if (loopback_mode_ == HCI_LOOPBACK_MODE_LOCAL) {
-    uint16_t channel = acl_packet->GetChannel();
-    send_acl_(std::move(acl_packet));
-    send_event_(EventPacket::CreateNumberOfCompletedPacketsEvent(channel, 1));
-    return;
-  }
-}
-
-void DualModeController::HandleSco(std::unique_ptr<ScoPacket> sco_packet) {
-  if (loopback_mode_ == HCI_LOOPBACK_MODE_LOCAL) {
-    uint16_t channel = sco_packet->GetChannel();
-    send_sco_(std::move(sco_packet));
-    send_event_(EventPacket::CreateNumberOfCompletedPacketsEvent(channel, 1));
-    return;
-  }
-}
-
-void DualModeController::HandleCommand(
-    std::unique_ptr<CommandPacket> command_packet) {
-  uint16_t opcode = command_packet->GetOpcode();
-  LOG_INFO(LOG_TAG, "Command opcode: 0x%04X, OGF: 0x%04X, OCF: 0x%04X", opcode,
-           command_packet->GetOGF(), command_packet->GetOCF());
-
-  if (loopback_mode_ == HCI_LOOPBACK_MODE_LOCAL &&
-      // Loopback exceptions.
-      opcode != HCI_RESET && opcode != HCI_SET_HC_TO_HOST_FLOW_CTRL &&
-      opcode != HCI_HOST_BUFFER_SIZE && opcode != HCI_HOST_NUM_PACKETS_DONE &&
-      opcode != HCI_READ_BUFFER_SIZE && opcode != HCI_READ_LOOPBACK_MODE &&
-      opcode != HCI_WRITE_LOOPBACK_MODE) {
-    send_event_(EventPacket::CreateLoopbackCommandEvent(
-        opcode, command_packet->GetPayload()));
-  } else if (active_hci_commands_.count(opcode) > 0) {
-    active_hci_commands_[opcode](command_packet->GetPayload());
-  } else {
-    SendCommandCompleteOnlyStatus(opcode, kUnknownHciCommand);
-  }
-}
-
-void DualModeController::RegisterEventChannel(
-    const std::function<void(std::unique_ptr<EventPacket>)>& callback) {
-  send_event_ = callback;
-}
-
-void DualModeController::RegisterAclChannel(
-    const std::function<void(std::unique_ptr<AclPacket>)>& callback) {
-  send_acl_ = callback;
-}
-
-void DualModeController::RegisterScoChannel(
-    const std::function<void(std::unique_ptr<ScoPacket>)>& callback) {
-  send_sco_ = callback;
-}
-
-void DualModeController::HandleTimerTick() {
-  if (state_ == kInquiry) PageScan();
-  if (le_scan_enable_ || le_connect_) LeScan();
-  Connections();
-  for (size_t dev = 0; dev < devices_.size(); dev++) devices_[dev]->TimerTick();
-}
-
-void DualModeController::SetTimerPeriod(std::chrono::milliseconds new_period) {
-  timer_period_ = new_period;
-
-  if (timer_tick_task_ == kInvalidTaskId) return;
-
-  // Restart the timer with the new period
-  StopTimer();
-  StartTimer();
-}
-
-static uint8_t GetRssi(size_t dev) {
-  // TODO: Model rssi somehow
-  return -((dev * 16) % 127);
-}
-
-static uint8_t LeGetHandle() {
-  static int handle = 0;
-  return handle++;
-}
-
-static uint8_t LeGetConnInterval() { return 1; }
-
-static uint8_t LeGetConnLatency() { return 2; }
-
-static uint8_t LeGetSupervisionTimeout() { return 3; }
-
-void DualModeController::Connections() {
-  for (size_t i = 0; i < connections_.size(); i++) {
-    if (connections_[i]->Connected()) {
-      connections_[i]->SendToDevice();
-      vector<uint8_t> data;
-      connections_[i]->ReceiveFromDevice(data);
-      // HandleConnectionData(data);
-    }
-  }
-}
-
-void DualModeController::LeScan() {
-  std::unique_ptr<EventPacket> le_adverts =
-      EventPacket::CreateLeAdvertisingReportEvent();
-  vector<uint8_t> ad;
-  for (size_t dev = 0; dev < devices_.size(); dev++) {
-    uint8_t adv_type;
-    const BtAddress addr = devices_[dev]->GetBtAddress();
-    uint8_t addr_type = devices_[dev]->GetAddressType();
-    ad.clear();
-
-    // Listen for Advertisements
-    if (devices_[dev]->IsAdvertisementAvailable(
-            std::chrono::milliseconds(le_scan_window_))) {
-      ad = devices_[dev]->GetAdvertisement();
-      adv_type = devices_[dev]->GetAdvertisementType();
-      if (le_scan_enable_ && !le_adverts->AddLeAdvertisingReport(
-                                 adv_type, addr_type, addr, ad, GetRssi(dev))) {
-        send_event_(std::move(le_adverts));
-        le_adverts = EventPacket::CreateLeAdvertisingReportEvent();
-        CHECK(le_adverts->AddLeAdvertisingReport(adv_type, addr_type, addr, ad,
-                                                 GetRssi(dev)));
-      }
-
-      // Connect
-      if (le_connect_ && (adv_type == BTM_BLE_CONNECT_EVT ||
-                          adv_type == BTM_BLE_CONNECT_DIR_EVT)) {
-        LOG_INFO(LOG_TAG, "Connecting to device %d", static_cast<int>(dev));
-        if (peer_address_ == addr && peer_address_type_ == addr_type &&
-            devices_[dev]->LeConnect()) {
-          uint16_t handle = LeGetHandle();
-          std::unique_ptr<EventPacket> event =
-              EventPacket::CreateLeConnectionCompleteEvent(
-                  kSuccessStatus, handle, HCI_ROLE_MASTER, addr_type, addr,
-                  LeGetConnInterval(), LeGetConnLatency(),
-                  LeGetSupervisionTimeout());
-          send_event_(std::move(event));
-          le_connect_ = false;
-
-          connections_.push_back(
-              std::make_shared<Connection>(devices_[dev], handle));
-        }
-
-        // TODO: Handle the white list (if (InWhiteList(dev)))
-      }
-
-      // Active scanning
-      if (le_scan_enable_ && le_scan_type_ == 1) {
-        ad.clear();
-        if (devices_[dev]->HasScanResponse()) {
-          ad = devices_[dev]->GetScanResponse();
-          if (!le_adverts->AddLeAdvertisingReport(
-                  BTM_BLE_SCAN_RSP_EVT, addr_type, addr, ad, GetRssi(dev))) {
-            send_event_(std::move(le_adverts));
-            le_adverts = EventPacket::CreateLeAdvertisingReportEvent();
-            CHECK(le_adverts->AddLeAdvertisingReport(
-                BTM_BLE_SCAN_RSP_EVT, addr_type, addr, ad, GetRssi(dev)));
-          }
-        }
-      }
-    }
-  }
-
-  if (le_scan_enable_) send_event_(std::move(le_adverts));
-}
-
-void DualModeController::PageScan() {
-  // Inquiry modes for specifiying inquiry result formats.
-  static const uint8_t kStandardInquiry = 0x00;
-  static const uint8_t kRssiInquiry = 0x01;
-  static const uint8_t kExtendedOrRssiInquiry = 0x02;
-
-  switch (inquiry_mode_) {
-    case (kStandardInquiry): {
-      std::unique_ptr<EventPacket> inquiry_result =
-          EventPacket::CreateInquiryResultEvent();
-      for (size_t dev = 0; dev < devices_.size(); dev++)
-        // Scan for devices
-        if (devices_[dev]->IsPageScanAvailable()) {
-          bool result_added = inquiry_result->AddInquiryResult(
-              devices_[dev]->GetBtAddress(),
-              devices_[dev]->GetPageScanRepetitionMode(),
-              devices_[dev]->GetDeviceClass(), devices_[dev]->GetClockOffset());
-          if (!result_added) {
-            send_event_(std::move(inquiry_result));
-            inquiry_result = EventPacket::CreateInquiryResultEvent();
-            result_added = inquiry_result->AddInquiryResult(
-                devices_[dev]->GetBtAddress(),
-                devices_[dev]->GetPageScanRepetitionMode(),
-                devices_[dev]->GetDeviceClass(),
-                devices_[dev]->GetClockOffset());
-            CHECK(result_added);
-          }
-        }
-    } break;
-
-    case (kRssiInquiry):
-      LOG_INFO(LOG_TAG, "RSSI Inquiry Mode currently not supported.");
-      break;
-
-    case (kExtendedOrRssiInquiry):
-      for (size_t dev = 0; dev < devices_.size(); dev++)
-        if (devices_[dev]->IsPageScanAvailable()) {
-          send_event_(EventPacket::CreateExtendedInquiryResultEvent(
-              devices_[dev]->GetBtAddress(),
-              devices_[dev]->GetPageScanRepetitionMode(),
-              devices_[dev]->GetDeviceClass(), devices_[dev]->GetClockOffset(),
-              GetRssi(dev), devices_[dev]->GetExtendedInquiryData()));
-        }
-      break;
-  }
-}
-
-void DualModeController::StartTimer() {
-  LOG_ERROR(LOG_TAG, "StartTimer");
-  timer_tick_task_ = schedule_periodic_task_(
-      std::chrono::milliseconds(0), timer_period_,
-      [this]() { DualModeController::HandleTimerTick(); });
-}
-
-void DualModeController::StopTimer() {
-  LOG_ERROR(LOG_TAG, "StopTimer");
-  cancel_task_(timer_tick_task_);
-  timer_tick_task_ = kInvalidTaskId;
-}
-
-void DualModeController::SetEventDelay(int64_t delay) {
-  if (delay < 0) delay = 0;
-}
-
-void DualModeController::TestChannelAdd(const vector<std::string>& args) {
-  LogCommand("TestChannel 'add'");
-
-  std::shared_ptr<Device> new_dev = DeviceFactory::Create(args);
-
-  if (new_dev == NULL) {
-    LOG_ERROR(LOG_TAG, "TestChannel 'add' failed!");
-    return;
-  }
-
-  devices_.push_back(new_dev);
-}
-
-void DualModeController::TestChannelDel(const vector<std::string>& args) {
-  LogCommand("TestChannel 'del'");
-
-  size_t dev_index = std::stoi(args[0]);
-
-  if (dev_index >= devices_.size()) {
-    LOG_INFO(LOG_TAG, "TestChannel 'del': index %d out of range!",
-             static_cast<int>(dev_index));
-  } else {
-    devices_.erase(devices_.begin() + dev_index);
-  }
-}
-
-void DualModeController::TestChannelList(
-    UNUSED_ATTR const vector<std::string>& args) const {
-  LogCommand("TestChannel 'list'");
-  LOG_INFO(LOG_TAG, "Devices:");
-  for (size_t dev = 0; dev < devices_.size(); dev++) {
-    LOG_INFO(LOG_TAG, "%d:", static_cast<int>(dev));
-    devices_[dev]->ToString();
-  }
-}
-
-void DualModeController::HciReset(const vector<uint8_t>& args) {
-  LogCommand("Reset");
-  CHECK(args[0] == 0);  // No arguments
-  state_ = kStandby;
-  if (timer_tick_task_ != kInvalidTaskId) {
-    LOG_INFO(LOG_TAG, "The timer was already running!");
-    StopTimer();
-  }
-  LOG_INFO(LOG_TAG, "Starting timer.");
-  StartTimer();
-
-  SendCommandCompleteSuccess(HCI_RESET);
-}
-
-void DualModeController::HciReadBufferSize(const vector<uint8_t>& args) {
-  LogCommand("Read Buffer Size");
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadBufferSize(
-          kSuccessStatus, properties_.GetAclDataPacketSize(),
-          properties_.GetSynchronousDataPacketSize(),
-          properties_.GetTotalNumAclDataPackets(),
-          properties_.GetTotalNumSynchronousDataPackets());
-
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciHostBufferSize(const vector<uint8_t>& args) {
-  LogCommand("Host Buffer Size");
-  CHECK(args[0] == 7);  // No arguments
-  SendCommandCompleteSuccess(HCI_HOST_BUFFER_SIZE);
-}
-
-void DualModeController::HciReadLocalVersionInformation(
-    const vector<uint8_t>& args) {
-  LogCommand("Read Local Version Information");
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadLocalVersionInformation(
-          kSuccessStatus, properties_.GetVersion(), properties_.GetRevision(),
-          properties_.GetLmpPalVersion(), properties_.GetManufacturerName(),
-          properties_.GetLmpPalSubversion());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciReadBdAddr(const vector<uint8_t>& args) {
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadBdAddr(kSuccessStatus,
-                                                   properties_.GetAddress());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciReadLocalSupportedCommands(
-    const vector<uint8_t>& args) {
-  LogCommand("Read Local Supported Commands");
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadLocalSupportedCommands(
-          kSuccessStatus, properties_.GetLocalSupportedCommands());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciReadLocalSupportedCodecs(
-    const vector<uint8_t>& args) {
-  LogCommand("Read Local Supported Codecs");
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadLocalSupportedCodecs(
-          kSuccessStatus, properties_.GetSupportedCodecs(),
-          properties_.GetVendorSpecificCodecs());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciReadLocalExtendedFeatures(
-    const vector<uint8_t>& args) {
-  LogCommand("Read Local Extended Features");
-  CHECK(args.size() == 2);
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadLocalExtendedFeatures(
-          kSuccessStatus, args[1],
-          properties_.GetLocalExtendedFeaturesMaximumPageNumber(),
-          properties_.GetLocalExtendedFeatures(args[1]));
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciWriteSimplePairingMode(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Simple Pairing Mode");
-  SendCommandCompleteSuccess(HCI_WRITE_SIMPLE_PAIRING_MODE);
-}
-
-void DualModeController::HciWriteLeHostSupport(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Le Host Support");
-  SendCommandCompleteSuccess(HCI_WRITE_LE_HOST_SUPPORT);
-}
-
-void DualModeController::HciSetEventMask(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Set Event Mask");
-  SendCommandCompleteSuccess(HCI_SET_EVENT_MASK);
-}
-
-void DualModeController::HciWriteInquiryMode(const vector<uint8_t>& args) {
-  LogCommand("Write Inquiry Mode");
-  CHECK(args.size() == 2);
-  inquiry_mode_ = args[1];
-  SendCommandCompleteSuccess(HCI_WRITE_INQUIRY_MODE);
-}
-
-void DualModeController::HciWritePageScanType(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Page Scan Type");
-  SendCommandCompleteSuccess(HCI_WRITE_PAGESCAN_TYPE);
-}
-
-void DualModeController::HciWriteInquiryScanType(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Inquiry Scan Type");
-  SendCommandCompleteSuccess(HCI_WRITE_INQSCAN_TYPE);
-}
-
-void DualModeController::HciWriteClassOfDevice(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Class Of Device");
-  SendCommandCompleteSuccess(HCI_WRITE_CLASS_OF_DEVICE);
-}
-
-void DualModeController::HciWritePageTimeout(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Page Timeout");
-  SendCommandCompleteSuccess(HCI_WRITE_PAGE_TOUT);
-}
-
-void DualModeController::HciWriteDefaultLinkPolicySettings(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Default Link Policy Settings");
-  SendCommandCompleteSuccess(HCI_WRITE_DEF_POLICY_SETTINGS);
-}
-
-void DualModeController::HciReadLocalName(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Get Local Name");
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadLocalName(
-          kSuccessStatus, properties_.GetLocalName());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciWriteLocalName(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Local Name");
-  SendCommandCompleteSuccess(HCI_CHANGE_LOCAL_NAME);
-}
-
-void DualModeController::HciWriteExtendedInquiryResponse(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Extended Inquiry Response");
-  SendCommandCompleteSuccess(HCI_WRITE_EXT_INQ_RESPONSE);
-}
-
-void DualModeController::HciWriteVoiceSetting(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Voice Setting");
-  SendCommandCompleteSuccess(HCI_WRITE_VOICE_SETTINGS);
-}
-
-void DualModeController::HciWriteCurrentIacLap(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Current IAC LAP");
-  SendCommandCompleteSuccess(HCI_WRITE_CURRENT_IAC_LAP);
-}
-
-void DualModeController::HciWriteInquiryScanActivity(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Inquiry Scan Activity");
-  SendCommandCompleteSuccess(HCI_WRITE_INQUIRYSCAN_CFG);
-}
-
-void DualModeController::HciWriteScanEnable(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Write Scan Enable");
-  SendCommandCompleteSuccess(HCI_WRITE_SCAN_ENABLE);
-}
-
-void DualModeController::HciSetEventFilter(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Set Event Filter");
-  SendCommandCompleteSuccess(HCI_SET_EVENT_FILTER);
-}
-
-void DualModeController::HciInquiry(const vector<uint8_t>& args) {
-  LogCommand("Inquiry");
-  CHECK(args.size() == 6);
-  state_ = kInquiry;
-  SendCommandStatusSuccess(HCI_INQUIRY);
-  inquiry_lap_[0] = args[1];
-  inquiry_lap_[1] = args[2];
-  inquiry_lap_[2] = args[3];
-
-  AddControllerEvent(std::chrono::milliseconds(args[4] * 1280),
-                     [this]() { DualModeController::InquiryTimeout(); });
-
-  if (args[5] > 0) {
-    inquiry_responses_limited_ = true;
-    inquiry_num_responses_ = args[5];
-  }
-}
-
-void DualModeController::HciInquiryCancel(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Inquiry Cancel");
-  CHECK(state_ == kInquiry);
-  state_ = kStandby;
-  SendCommandCompleteSuccess(HCI_INQUIRY_CANCEL);
-}
-
-void DualModeController::InquiryTimeout() {
-  LOG_INFO(LOG_TAG, "InquiryTimer fired");
-  if (state_ == kInquiry) {
-    state_ = kStandby;
-    inquiry_responses_limited_ = false;
-    send_event_(EventPacket::CreateInquiryCompleteEvent(kSuccessStatus));
-  }
-}
-
-void DualModeController::HciDeleteStoredLinkKey(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Delete Stored Link Key");
-  /* Check the last octect in |args|. If it is 0, delete only the link key for
-   * the given BD_ADDR. If is is 1, delete all stored link keys. */
-  uint16_t deleted_keys = 1;
-
-  send_event_(EventPacket::CreateCommandCompleteDeleteStoredLinkKey(
-      kSuccessStatus, deleted_keys));
-}
-
-void DualModeController::HciRemoteNameRequest(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("Remote Name Request");
-  SendCommandStatusSuccess(HCI_RMT_NAME_REQUEST);
-}
-
-void DualModeController::HciLeSetEventMask(const vector<uint8_t>& args) {
-  LogCommand("LE SetEventMask");
-  le_event_mask_ = args;
-  SendCommandCompleteSuccess(HCI_BLE_SET_EVENT_MASK);
-}
-
-void DualModeController::HciLeReadBufferSize(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteLeReadBufferSize(
-          kSuccessStatus, properties_.GetLeDataPacketLength(),
-          properties_.GetTotalNumLeDataPackets());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciLeReadLocalSupportedFeatures(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteLeReadLocalSupportedFeatures(
-          kSuccessStatus, properties_.GetLeLocalSupportedFeatures());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciLeSetRandomAddress(const vector<uint8_t>& args) {
-  LogCommand("LE SetRandomAddress");
-  CHECK(args.size() == 7);
-  vector<uint8_t> new_addr = {args[1], args[2], args[3],
-                              args[4], args[5], args[6]};
-  CHECK(le_random_address_.FromVector(new_addr));
-  SendCommandCompleteSuccess(HCI_BLE_WRITE_RANDOM_ADDR);
-}
-
-void DualModeController::HciLeSetAdvertisingParameters(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("LE SetAdvertisingParameters");
-  SendCommandCompleteSuccess(HCI_BLE_WRITE_ADV_PARAMS);
-}
-
-void DualModeController::HciLeSetAdvertisingData(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  LogCommand("LE SetAdvertisingData");
-  SendCommandCompleteSuccess(HCI_BLE_WRITE_ADV_DATA);
-}
-
-void DualModeController::HciLeSetScanParameters(const vector<uint8_t>& args) {
-  LogCommand("LE SetScanParameters");
-  CHECK(args.size() == 8);
-  le_scan_type_ = args[1];
-  le_scan_interval_ = args[2] | (args[3] << 8);
-  le_scan_window_ = args[4] | (args[5] << 8);
-  own_address_type_ = args[6];
-  scanning_filter_policy_ = args[7];
-  SendCommandCompleteSuccess(HCI_BLE_WRITE_SCAN_PARAMS);
-}
-
-void DualModeController::HciLeSetScanEnable(const vector<uint8_t>& args) {
-  LogCommand("LE SetScanEnable");
-  CHECK(args.size() == 3);
-  le_scan_enable_ = args[1];
-  filter_duplicates_ = args[2];
-  SendCommandCompleteSuccess(HCI_BLE_WRITE_SCAN_ENABLE);
-}
-
-void DualModeController::HciLeCreateConnection(const vector<uint8_t>& args) {
-  LogCommand("LE CreateConnection");
-  le_connect_ = true;
-  le_scan_interval_ = args[1] | (args[2] << 8);
-  le_scan_window_ = args[3] | (args[4] << 8);
-  initiator_filter_policy_ = args[5];
-
-  if (initiator_filter_policy_ == 0) {  // White list not used
-    peer_address_type_ = args[6];
-    vector<uint8_t> peer_addr = {args[7],  args[8],  args[9],
-                                 args[10], args[11], args[12]};
-    peer_address_.FromVector(peer_addr);
-  }
-
-  SendCommandStatusSuccess(HCI_BLE_CREATE_LL_CONN);
-}
-
-void DualModeController::HciLeConnectionCancel(const vector<uint8_t>& args) {
-  LogCommand("LE ConnectionCancel");
-  CHECK(args[0] == 0);  // No arguments
-  le_connect_ = false;
-  SendCommandStatusSuccess(HCI_BLE_CREATE_CONN_CANCEL);
-}
-
-void DualModeController::HciLeReadWhiteListSize(const vector<uint8_t>& args) {
-  LogCommand("LE ReadWhiteListSize");
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteLeReadWhiteListSize(
-          kSuccessStatus, properties_.GetLeWhiteListSize());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciLeReadRemoteUsedFeaturesB(uint16_t handle) {
-  uint64_t features;
-  LogCommand("LE ReadRemoteUsedFeatures Bottom half");
-
-  for (size_t i = 0; i < connections_.size(); i++)
-    if (*connections_[i] == handle)
-      // TODO:
-      // features = connections_[i]->GetDevice()->GetUsedFeatures();
-      features = 0xffffffffffffffff;
-
-  std::unique_ptr<EventPacket> event =
-      EventPacket::CreateLeRemoteUsedFeaturesEvent(kSuccessStatus, handle,
-                                                   features);
-  send_event_(std::move(event));
-}
-
-void DualModeController::HciLeReadRemoteUsedFeatures(
-    const vector<uint8_t>& args) {
-  LogCommand("LE ReadRemoteUsedFeatures");
-  CHECK(args.size() == 3);
-
-  uint16_t handle = args[1] | (args[2] << 8);
-
-  AddConnectionAction(
-      [this, handle]() {
-        DualModeController::HciLeReadRemoteUsedFeaturesB(handle);
-      },
-      handle);
-
-  SendCommandStatusSuccess(HCI_BLE_READ_REMOTE_FEAT);
-}
-
-void DualModeController::HciLeRand(UNUSED_ATTR const vector<uint8_t>& args) {
-  uint64_t random_val = rand();
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteLeRand(kSuccessStatus, random_val);
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciLeReadSupportedStates(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteLeReadSupportedStates(
-          kSuccessStatus, properties_.GetLeSupportedStates());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciBleVendorSleepMode(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  SendCommandCompleteOnlyStatus(HCI_GRP_VENDOR_SPECIFIC | 0x27,
-                                kUnknownHciCommand);
-}
-
-void DualModeController::HciBleVendorCap(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  vector<uint8_t> caps = properties_.GetLeVendorCap();
-  if (caps.size() == 0) {
-    SendCommandCompleteOnlyStatus(HCI_BLE_VENDOR_CAP_OCF, kUnknownHciCommand);
-    return;
-  }
-
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteLeVendorCap(
-          kSuccessStatus, properties_.GetLeVendorCap());
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciBleVendorMultiAdv(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  SendCommandCompleteOnlyStatus(HCI_BLE_MULTI_ADV_OCF, kUnknownHciCommand);
-}
-
-void DualModeController::HciBleVendor155(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  SendCommandCompleteOnlyStatus(HCI_GRP_VENDOR_SPECIFIC | 0x155,
-                                kUnknownHciCommand);
-}
-
-void DualModeController::HciBleAdvertisingFilter(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  SendCommandCompleteOnlyStatus(HCI_BLE_ADV_FILTER_OCF, kUnknownHciCommand);
-}
-
-void DualModeController::HciBleEnergyInfo(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  SendCommandCompleteOnlyStatus(HCI_BLE_ENERGY_INFO_OCF, kUnknownHciCommand);
-}
-
-void DualModeController::HciBleExtendedScanParams(
-    UNUSED_ATTR const vector<uint8_t>& args) {
-  SendCommandCompleteOnlyStatus(HCI_BLE_EXTENDED_SCAN_PARAMS_OCF,
-                                kUnknownHciCommand);
-}
-
-void DualModeController::HciReadLoopbackMode(const vector<uint8_t>& args) {
-  CHECK(args[0] == 0);  // No arguments
-  std::unique_ptr<EventPacket> command_complete =
-      EventPacket::CreateCommandCompleteReadLoopbackMode(kSuccessStatus,
-                                                         loopback_mode_);
-  send_event_(std::move(command_complete));
-}
-
-void DualModeController::HciWriteLoopbackMode(const vector<uint8_t>& args) {
-  CHECK(args[0] == 1);
-  loopback_mode_ = args[1];
-  // ACL channel
-  uint16_t acl_handle = 0x123;
-  send_event_(EventPacket::CreateConnectionCompleteEvent(
-      kSuccessStatus, acl_handle, properties_.GetAddress(), HCI_LINK_TYPE_ACL,
-      false));
-  // SCO channel
-  uint16_t sco_handle = 0x345;
-  send_event_(EventPacket::CreateConnectionCompleteEvent(
-      kSuccessStatus, sco_handle, properties_.GetAddress(), HCI_LINK_TYPE_SCO,
-      false));
-  SendCommandCompleteSuccess(HCI_WRITE_LOOPBACK_MODE);
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/event_packet.cc b/vendor_libs/test_vendor_lib/src/event_packet.cc
deleted file mode 100644
index 482b47f..0000000
--- a/vendor_libs/test_vendor_lib/src/event_packet.cc
+++ /dev/null
@@ -1,461 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "event_packet"
-
-#include "event_packet.h"
-
-#include "osi/include/log.h"
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-EventPacket::EventPacket(uint8_t event_code)
-    : Packet(DATA_TYPE_EVENT, {event_code}) {}
-
-uint8_t EventPacket::GetEventCode() const { return GetHeader()[0]; }
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.1
-std::unique_ptr<EventPacket> EventPacket::CreateInquiryCompleteEvent(
-    uint8_t status) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_INQUIRY_COMP_EVT));
-  CHECK(evt_ptr->AddPayloadOctets1(status));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.14
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteEvent(
-    uint16_t command_opcode, const vector<uint8_t>& event_return_parameters) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_COMMAND_COMPLETE_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
-  CHECK(evt_ptr->AddPayloadOctets2(command_opcode));
-  CHECK(evt_ptr->AddPayloadOctets(event_return_parameters.size(),
-                                  event_return_parameters));
-
-  return evt_ptr;
-}
-
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteOnlyStatusEvent(
-    uint16_t command_opcode, uint8_t status) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_COMMAND_COMPLETE_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
-  CHECK(evt_ptr->AddPayloadOctets2(command_opcode));
-  CHECK(evt_ptr->AddPayloadOctets1(status));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.15
-std::unique_ptr<EventPacket> EventPacket::CreateCommandStatusEvent(
-    uint8_t status, uint16_t command_opcode) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_COMMAND_STATUS_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(status));
-  CHECK(evt_ptr->AddPayloadOctets1(1));  // num_hci_command_packets
-  CHECK(evt_ptr->AddPayloadOctets2(command_opcode));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.19
-std::unique_ptr<EventPacket> EventPacket::CreateNumberOfCompletedPacketsEvent(
-    uint16_t handle, uint16_t num_completed_packets) {
-  std::unique_ptr<EventPacket> evt_ptr = std::unique_ptr<EventPacket>(
-      new EventPacket(HCI_NUM_COMPL_DATA_PKTS_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(0));  // Number of handles.
-  evt_ptr->AddCompletedPackets(handle, num_completed_packets);
-
-  return evt_ptr;
-}
-
-void EventPacket::AddCompletedPackets(uint16_t handle,
-                                      uint16_t num_completed_packets) {
-  CHECK(AddPayloadOctets2(handle));
-  CHECK(AddPayloadOctets2(num_completed_packets));
-  CHECK(IncrementPayloadCounter(1));  // Increment the number of handles.
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.10
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteDeleteStoredLinkKey(
-    uint8_t status, uint16_t num_keys_deleted) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_DELETE_STORED_LINK_KEY, status);
-
-  CHECK(evt_ptr->AddPayloadOctets2(num_keys_deleted));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.3.12
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteReadLocalName(
-    uint8_t status, const std::string& local_name) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_READ_LOCAL_NAME,
-                                                        status);
-
-  for (size_t i = 0; i < local_name.length(); i++)
-    CHECK(evt_ptr->AddPayloadOctets1(local_name[i]));
-  CHECK(evt_ptr->AddPayloadOctets1(0));  // Null terminated
-  for (size_t i = 0; i < 248 - local_name.length() - 1; i++)
-    CHECK(evt_ptr->AddPayloadOctets1(0xFF));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.1
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteReadLocalVersionInformation(
-    uint8_t status, uint8_t hci_version, uint16_t hci_revision,
-    uint8_t lmp_pal_version, uint16_t manufacturer_name,
-    uint16_t lmp_pal_subversion) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_READ_LOCAL_VERSION_INFO, status);
-
-  CHECK(evt_ptr->AddPayloadOctets1(hci_version));
-  CHECK(evt_ptr->AddPayloadOctets2(hci_revision));
-  CHECK(evt_ptr->AddPayloadOctets1(lmp_pal_version));
-  CHECK(evt_ptr->AddPayloadOctets2(manufacturer_name));
-  CHECK(evt_ptr->AddPayloadOctets2(lmp_pal_subversion));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.2
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteReadLocalSupportedCommands(
-    uint8_t status, const vector<uint8_t>& supported_commands) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_READ_LOCAL_SUPPORTED_CMDS, status);
-
-  CHECK(evt_ptr->AddPayloadOctets(64, supported_commands));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.4
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteReadLocalExtendedFeatures(
-    uint8_t status, uint8_t page_number, uint8_t maximum_page_number,
-    uint64_t extended_lmp_features) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_READ_LOCAL_EXT_FEATURES, status);
-
-  CHECK(evt_ptr->AddPayloadOctets1(page_number));
-  CHECK(evt_ptr->AddPayloadOctets1(maximum_page_number));
-  CHECK(evt_ptr->AddPayloadOctets8(extended_lmp_features));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.5
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteReadBufferSize(
-    uint8_t status, uint16_t hc_acl_data_packet_length,
-    uint8_t hc_synchronous_data_packet_length,
-    uint16_t hc_total_num_acl_data_packets,
-    uint16_t hc_total_synchronous_data_packets) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_READ_BUFFER_SIZE,
-                                                        status);
-
-  CHECK(evt_ptr->AddPayloadOctets2(hc_acl_data_packet_length));
-  CHECK(evt_ptr->AddPayloadOctets1(hc_synchronous_data_packet_length));
-  CHECK(evt_ptr->AddPayloadOctets2(hc_total_num_acl_data_packets));
-  CHECK(evt_ptr->AddPayloadOctets2(hc_total_synchronous_data_packets));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.6
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteReadBdAddr(
-    uint8_t status, const BtAddress& address) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_READ_BD_ADDR,
-                                                        status);
-
-  CHECK(evt_ptr->AddPayloadBtAddress(address));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.4.8
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteReadLocalSupportedCodecs(
-    uint8_t status, const vector<uint8_t>& supported_codecs,
-    const vector<uint32_t>& vendor_specific_codecs) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_READ_LOCAL_SUPPORTED_CODECS, status);
-
-  CHECK(evt_ptr->AddPayloadOctets(supported_codecs.size(), supported_codecs));
-  for (size_t i = 0; i < vendor_specific_codecs.size(); i++)
-    CHECK(evt_ptr->AddPayloadOctets4(vendor_specific_codecs[i]));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.6.1
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteReadLoopbackMode(
-    uint8_t status, uint8_t mode) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_READ_LOOPBACK_MODE,
-                                                        status);
-  CHECK(evt_ptr->AddPayloadOctets1(mode));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.2
-std::unique_ptr<EventPacket> EventPacket::CreateInquiryResultEvent() {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_INQUIRY_RESULT_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(0));  // Start with no responses
-  return evt_ptr;
-}
-
-bool EventPacket::AddInquiryResult(const BtAddress& address,
-                                   uint8_t page_scan_repetition_mode,
-                                   uint32_t class_of_device,
-                                   uint16_t clock_offset) {
-  CHECK(GetEventCode() == HCI_INQUIRY_RESULT_EVT);
-
-  if (!CanAddPayloadOctets(14)) return false;
-
-  CHECK(IncrementPayloadCounter(1));  // Increment the number of responses
-
-  CHECK(AddPayloadBtAddress(address));
-  CHECK(AddPayloadOctets1(page_scan_repetition_mode));
-  CHECK(AddPayloadOctets2(kReservedZero));
-  CHECK(AddPayloadOctets3(class_of_device));
-  CHECK(!(clock_offset & 0x8000));
-  CHECK(AddPayloadOctets2(clock_offset));
-  return true;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.3
-std::unique_ptr<EventPacket> EventPacket::CreateConnectionCompleteEvent(
-    uint8_t status, uint16_t handle, const BtAddress& address,
-    uint8_t link_type, bool encryption_enabled) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_CONNECTION_COMP_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(status));
-  CHECK((handle & 0xf000) == 0);  // Handles are 12-bit values.
-  CHECK(evt_ptr->AddPayloadOctets2(handle));
-  CHECK(evt_ptr->AddPayloadBtAddress(address));
-  CHECK(evt_ptr->AddPayloadOctets1(link_type));
-  CHECK(evt_ptr->AddPayloadOctets1(encryption_enabled ? 1 : 0));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.25
-std::unique_ptr<EventPacket> EventPacket::CreateLoopbackCommandEvent(
-    uint16_t opcode, const vector<uint8_t>& payload) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_LOOPBACK_COMMAND_EVT));
-  CHECK(evt_ptr->AddPayloadOctets2(opcode));
-  for (const auto& payload_byte : payload)  // Fill the packet.
-    evt_ptr->AddPayloadOctets1(payload_byte);
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.38
-std::unique_ptr<EventPacket> EventPacket::CreateExtendedInquiryResultEvent(
-    const BtAddress& address, uint8_t page_scan_repetition_mode,
-    uint32_t class_of_device, uint16_t clock_offset, uint8_t rssi,
-    const vector<uint8_t>& extended_inquiry_response) {
-  std::unique_ptr<EventPacket> evt_ptr = std::unique_ptr<EventPacket>(
-      new EventPacket(HCI_EXTENDED_INQUIRY_RESULT_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(1));  // Always contains a single response
-
-  CHECK(evt_ptr->AddPayloadBtAddress(address));
-  CHECK(evt_ptr->AddPayloadOctets1(page_scan_repetition_mode));
-  CHECK(evt_ptr->AddPayloadOctets1(kReservedZero));
-  CHECK(evt_ptr->AddPayloadOctets3(class_of_device));
-  CHECK(!(clock_offset & 0x8000));
-  CHECK(evt_ptr->AddPayloadOctets2(clock_offset));
-  CHECK(evt_ptr->AddPayloadOctets1(rssi));
-  CHECK(evt_ptr->AddPayloadOctets(extended_inquiry_response.size(),
-                                  extended_inquiry_response));
-  while (evt_ptr->AddPayloadOctets1(0xff))
-    ;  // Fill packet
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.1
-std::unique_ptr<EventPacket> EventPacket::CreateLeConnectionCompleteEvent(
-    uint8_t status, uint16_t handle, uint8_t role, uint8_t peer_address_type,
-    const BtAddress& peer, uint16_t interval, uint16_t latency,
-    uint16_t supervision_timeout) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_BLE_EVENT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(HCI_BLE_CONN_COMPLETE_EVT));
-  CHECK(evt_ptr->AddPayloadOctets1(status));
-  CHECK(evt_ptr->AddPayloadOctets2(handle));
-  CHECK(evt_ptr->AddPayloadOctets1(role));
-  CHECK(evt_ptr->AddPayloadOctets1(peer_address_type));
-  CHECK(evt_ptr->AddPayloadBtAddress(peer));
-  CHECK(evt_ptr->AddPayloadOctets2(interval));
-  CHECK(evt_ptr->AddPayloadOctets2(latency));
-  CHECK(evt_ptr->AddPayloadOctets2(supervision_timeout));
-  CHECK(evt_ptr->AddPayloadOctets1(
-      0x00));  // Master Clock Accuracy (unused for master)
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.2
-std::unique_ptr<EventPacket> EventPacket::CreateLeAdvertisingReportEvent() {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_BLE_EVENT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(HCI_BLE_ADV_PKT_RPT_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(0));  // Start with an empty report
-
-  return evt_ptr;
-}
-
-bool EventPacket::AddLeAdvertisingReport(uint8_t event_type, uint8_t addr_type,
-                                         const BtAddress& addr,
-                                         const vector<uint8_t>& data,
-                                         uint8_t rssi) {
-  if (!CanAddPayloadOctets(10 + data.size())) return false;
-
-  CHECK(GetEventCode() == HCI_BLE_EVENT);
-
-  CHECK(IncrementPayloadCounter(2));  // Increment the number of responses
-
-  CHECK(AddPayloadOctets1(event_type));
-  CHECK(AddPayloadOctets1(addr_type));
-  CHECK(AddPayloadBtAddress(addr));
-  CHECK(AddPayloadOctets1(data.size()));
-  CHECK(AddPayloadOctets(data.size(), data));
-  CHECK(AddPayloadOctets1(rssi));
-  return true;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.7.65.4
-std::unique_ptr<EventPacket> EventPacket::CreateLeRemoteUsedFeaturesEvent(
-    uint8_t status, uint16_t handle, uint64_t features) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      std::unique_ptr<EventPacket>(new EventPacket(HCI_BLE_EVENT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(HCI_BLE_READ_REMOTE_FEAT_CMPL_EVT));
-
-  CHECK(evt_ptr->AddPayloadOctets1(status));
-  CHECK(evt_ptr->AddPayloadOctets2(handle));
-  CHECK(evt_ptr->AddPayloadOctets8(features));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.2
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteLeReadBufferSize(
-    uint8_t status, uint16_t hc_le_data_packet_length,
-    uint8_t hc_total_num_le_data_packets) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_BLE_READ_BUFFER_SIZE, status);
-
-  CHECK(evt_ptr->AddPayloadOctets2(hc_le_data_packet_length));
-  CHECK(evt_ptr->AddPayloadOctets1(hc_total_num_le_data_packets));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.3
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteLeReadLocalSupportedFeatures(
-    uint8_t status, uint64_t le_features) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_BLE_READ_LOCAL_SPT_FEAT, status);
-
-  CHECK(evt_ptr->AddPayloadOctets8(le_features));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.14
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteLeReadWhiteListSize(uint8_t status,
-                                                      uint8_t white_list_size) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_BLE_READ_WHITE_LIST_SIZE, status);
-
-  CHECK(evt_ptr->AddPayloadOctets8(white_list_size));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.23
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteLeRand(
-    uint8_t status, uint64_t random_val) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_BLE_RAND, status);
-
-  CHECK(evt_ptr->AddPayloadOctets8(random_val));
-
-  return evt_ptr;
-}
-
-// Bluetooth Core Specification Version 4.2, Volume 2, Part E, Section 7.8.27
-std::unique_ptr<EventPacket>
-EventPacket::CreateCommandCompleteLeReadSupportedStates(uint8_t status,
-                                                        uint64_t le_states) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(
-          HCI_BLE_READ_SUPPORTED_STATES, status);
-
-  CHECK(evt_ptr->AddPayloadOctets8(le_states));
-
-  return evt_ptr;
-}
-
-// Vendor-specific commands (see hcidefs.h)
-
-std::unique_ptr<EventPacket> EventPacket::CreateCommandCompleteLeVendorCap(
-    uint8_t status, const vector<uint8_t>& vendor_cap) {
-  std::unique_ptr<EventPacket> evt_ptr =
-      EventPacket::CreateCommandCompleteOnlyStatusEvent(HCI_BLE_VENDOR_CAP_OCF,
-                                                        status);
-
-  CHECK(evt_ptr->AddPayloadOctets(vendor_cap.size(), vendor_cap));
-
-  return evt_ptr;
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/hci_packet.cc b/vendor_libs/test_vendor_lib/src/hci_packet.cc
deleted file mode 100644
index 219c187..0000000
--- a/vendor_libs/test_vendor_lib/src/hci_packet.cc
+++ /dev/null
@@ -1,125 +0,0 @@
-#include "hci_packet.h"
-
-namespace test_vendor_lib {
-
-// Iterator Functions
-Iterator::Iterator(std::shared_ptr<HciPacket> packet, size_t i) {
-  hci_packet_ = packet;
-  index_ = i;
-}
-
-Iterator::Iterator(const Iterator& itr) { *this = itr; }
-
-Iterator::operator bool() const { return hci_packet_ != nullptr; }
-
-Iterator Iterator::operator+(size_t offset) {
-  auto itr(*this);
-
-  return itr += offset;
-}
-
-Iterator& Iterator::operator+=(size_t offset) {
-  size_t new_offset = index_ + offset;
-  index_ = new_offset >= hci_packet_->get_length() ? hci_packet_->get_length()
-                                                   : new_offset;
-  return *this;
-}
-
-Iterator Iterator::operator++(int) {
-  auto itr(*this);
-  index_++;
-
-  if (index_ >= hci_packet_->get_length()) index_ = hci_packet_->get_length();
-
-  return itr;
-}
-
-Iterator& Iterator::operator++() {
-  index_++;
-
-  if (index_ >= hci_packet_->get_length()) index_ = hci_packet_->get_length();
-
-  return *this;
-}
-
-Iterator Iterator::operator-(size_t offset) {
-  auto itr(*this);
-
-  return itr -= offset;
-}
-
-int Iterator::operator-(Iterator& itr) { return index_ - itr.index_; }
-
-Iterator& Iterator::operator-=(size_t offset) {
-  index_ = offset > index_ ? 0 : index_ - offset;
-
-  return *this;
-}
-
-Iterator Iterator::operator--(int) {
-  auto itr(*this);
-  if (index_ != 0) index_--;
-
-  return itr;
-}
-
-Iterator& Iterator::operator--() {
-  if (index_ != 0) index_--;
-
-  return *this;
-}
-
-Iterator& Iterator::operator=(const Iterator& itr) {
-  hci_packet_ = itr.hci_packet_;
-  index_ = itr.index_;
-
-  return *this;
-}
-
-bool Iterator::operator==(Iterator& itr) {
-  return ((hci_packet_ == itr.hci_packet_) && (index_ == itr.index_));
-}
-
-bool Iterator::operator!=(Iterator& itr) { return !(*this == itr); }
-
-bool Iterator::operator<(Iterator& itr) {
-  return ((hci_packet_ == itr.hci_packet_) && (index_ < itr.index_));
-}
-
-bool Iterator::operator>(Iterator& itr) {
-  return ((hci_packet_ == itr.hci_packet_) && (index_ > itr.index_));
-}
-
-bool Iterator::operator<=(Iterator& itr) {
-  return ((hci_packet_ == itr.hci_packet_) && (index_ <= itr.index_));
-}
-
-bool Iterator::operator>=(Iterator& itr) {
-  return ((hci_packet_ == itr.hci_packet_) && (index_ >= itr.index_));
-}
-
-uint8_t& Iterator::operator*() const {
-  CHECK(index_ != hci_packet_->get_length());
-
-  return hci_packet_->get_at_index(index_);
-}
-
-uint8_t* Iterator::operator->() const {
-  return &hci_packet_->get_at_index(index_);
-}
-
-// BtPacket Functions
-Iterator HciPacket::get_begin() {
-  Iterator itr(shared_from_this(), 0);
-
-  return itr;
-}
-
-Iterator HciPacket::get_end() {
-  Iterator itr(shared_from_this(), get_length());
-
-  return itr;
-}
-
-uint8_t HciPacket::operator[](size_t i) { return get_at_index(i); }
-};  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/keyboard.cc b/vendor_libs/test_vendor_lib/src/keyboard.cc
deleted file mode 100644
index 74caf41..0000000
--- a/vendor_libs/test_vendor_lib/src/keyboard.cc
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "keyboard"
-
-#include "keyboard.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-Keyboard::Keyboard() {
-  advertising_type_ = BTM_BLE_CONNECT_EVT;
-  adv_data_ = {0x11,  // Length
-               BTM_BLE_AD_TYPE_NAME_CMPL,
-               'g',
-               'D',
-               'e',
-               'v',
-               'i',
-               'c',
-               'e',
-               '-',
-               'k',
-               'e',
-               'y',
-               'b',
-               'o',
-               'a',
-               'r',
-               'd',
-               0x03,  // Length
-               0x19,
-               0xC1,
-               0x03,
-               0x03,  // Length
-               0x03,
-               0x12,
-               0x18,
-               0x02,  // Length
-               BTM_BLE_AD_TYPE_FLAG,
-               BTM_BLE_BREDR_NOT_SPT | BTM_BLE_GEN_DISC_FLAG};
-
-  scan_data_ = {0x04,  // Length
-                BTM_BLE_AD_TYPE_NAME_SHORT, 'k', 'e', 'y'};
-}
-
-std::string Keyboard::GetTypeString() const { return "keyboard"; }
-
-void Keyboard::Initialize(const vector<std::string>& args) {
-  if (args.size() < 2) return;
-
-  BtAddress addr;
-  if (addr.FromString(args[1])) SetBtAddress(addr);
-
-  if (args.size() < 3) return;
-
-  SetAdvertisementInterval(std::chrono::milliseconds(std::stoi(args[2])));
-}
-
-bool Keyboard::LeConnect() { return true; }
-
-bool Keyboard::IsPageScanAvailable() const { return false; }
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/l2cap_packet.cc b/vendor_libs/test_vendor_lib/src/l2cap_packet.cc
deleted file mode 100644
index ad17b48..0000000
--- a/vendor_libs/test_vendor_lib/src/l2cap_packet.cc
+++ /dev/null
@@ -1,300 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "l2cap_packet"
-
-#include "l2cap_packet.h"
-
-#include <algorithm>
-
-#include "osi/include/log.h"
-
-namespace test_vendor_lib {
-
-const size_t kL2capHeaderLength = 4;
-const size_t kSduFirstHeaderLength = 8;
-const size_t kSduStandardHeaderLength = 6;
-const size_t kFcsBytes = 2;
-const uint16_t kSduTxSeqBits = 0x007E;
-const uint8_t kSduFirstReqseq = 0x40;
-const uint8_t kSduContinuationReqseq = 0xC0;
-const uint8_t kSduEndReqseq = 0x80;
-
-std::shared_ptr<L2capPacket> L2capPacket::assemble(
-    const std::vector<std::shared_ptr<L2capSdu> >& sdu_packets) {
-  std::shared_ptr<L2capPacket> built_l2cap_packet(new L2capPacket());
-  uint16_t l2cap_payload_length = 0;
-  uint16_t first_packet_channel_id = 0;
-  uint16_t total_expected_l2cap_length;
-  uint8_t txseq_start;
-
-  if (sdu_packets.size() == 0) {
-    LOG_DEBUG(LOG_TAG, "%s: No SDU received.", __func__);
-    return nullptr;
-  }
-  if (sdu_packets.size() == 1 &&
-      !L2capSdu::is_complete_l2cap(*sdu_packets[0])) {
-    LOG_DEBUG(LOG_TAG, "%s: Unsegmented SDU has incorrect SAR bits.", __func__);
-    return nullptr;
-  }
-
-  first_packet_channel_id = sdu_packets[0]->get_channel_id();
-
-  built_l2cap_packet->l2cap_packet_.resize(kL2capHeaderLength);
-
-  for (size_t i = 0; i < sdu_packets.size(); i++) {
-    uint16_t payload_length = sdu_packets[i]->get_payload_length();
-
-    // TODO(jruthe): Remove these checks when ACL packets have been
-    // implemented. Once those are done, that will be the only way to create
-    // L2capSdu objects and these checks will be moved there instead.
-    //
-    // Check the integrity of the packet length, if it is zero, it is invalid.
-    // The maximum size of a single, segmented L2CAP payload is 1016 bytes.
-    if ((payload_length <= 0) ||
-        (payload_length != sdu_packets[i]->get_vector_size() - 4)) {
-      LOG_DEBUG(LOG_TAG, "%s: SDU payload length incorrect.", __func__);
-      return nullptr;
-    }
-
-    uint16_t fcs_check = sdu_packets[i]->get_fcs();
-
-    if (sdu_packets[i]->calculate_fcs() != fcs_check) {
-      LOG_DEBUG(LOG_TAG, "%s: SDU fcs is incorrect.", __func__);
-      return nullptr;
-    }
-
-    uint16_t controls = sdu_packets[i]->get_controls();
-
-    if (sdu_packets[i]->get_channel_id() != first_packet_channel_id) {
-      LOG_DEBUG(LOG_TAG, "%s: SDU CID does not match expected.", __func__);
-      return nullptr;
-    }
-
-    if (i == 0) txseq_start = controls & kSduTxSeqBits;
-
-    // Bluetooth Specification version 4.2 volume 3 part A 3.3.2:
-    // If there is only a single SDU, the first two bits of the control must be
-    // set to 00b, representing an unsegmented SDU. If the SDU is segmented,
-    // there is a begin and an end. The first segment must have the first two
-    // control bits set to 01b and the ending segment must have them set to 10b.
-    // Meanwhile all segments in between the start and end must have the bits
-    // set to 11b.
-    size_t starting_index;
-    uint8_t txseq = controls & kSduTxSeqBits;
-    if (sdu_packets.size() > 1 && i == 0 &&
-        !L2capSdu::is_starting_sdu(*sdu_packets[i])) {
-      LOG_DEBUG(LOG_TAG, "%s: First segmented SDU has incorrect SAR bits.",
-                __func__);
-      return nullptr;
-    }
-    if (i != 0 && L2capSdu::is_starting_sdu(*sdu_packets[i])) {
-      LOG_DEBUG(LOG_TAG,
-                "%s: SAR bits set to first segmented SDU on "
-                "non-starting SDU.",
-                __func__);
-      return nullptr;
-    }
-    if (txseq != (txseq_start + (static_cast<uint8_t>(i) << 1))) {
-      LOG_DEBUG(LOG_TAG, "%s: TxSeq incorrect.", __func__);
-      return nullptr;
-    }
-    if (sdu_packets.size() > 1 && i == sdu_packets.size() - 1 &&
-        !L2capSdu::is_ending_sdu(*sdu_packets[i])) {
-      LOG_DEBUG(LOG_TAG, "%s: Final segmented SDU has incorrect SAR bits.",
-                __func__);
-      return nullptr;
-    }
-
-    // Subtract the control and fcs from every SDU payload length.
-    l2cap_payload_length += (payload_length - 4);
-
-    if (L2capSdu::is_starting_sdu(*sdu_packets[i])) {
-      starting_index = kSduFirstHeaderLength;
-      total_expected_l2cap_length = sdu_packets[i]->get_total_l2cap_length();
-
-      // Subtract the additional two bytes from the first packet of a segmented
-      // SDU.
-      l2cap_payload_length -= 2;
-    } else {
-      starting_index = kSduStandardHeaderLength;
-    }
-
-    Iterator payload_begin = sdu_packets[i]->get_begin() + starting_index;
-    Iterator payload_end = sdu_packets[i]->get_end() - kFcsBytes;
-
-    built_l2cap_packet->l2cap_packet_.insert(
-        built_l2cap_packet->l2cap_packet_.end(), payload_begin, payload_end);
-  }
-
-  if (l2cap_payload_length != total_expected_l2cap_length &&
-      sdu_packets.size() > 1) {
-    LOG_DEBUG(LOG_TAG, "%s: Total expected L2CAP payload length incorrect.",
-              __func__);
-    return nullptr;
-  }
-
-  built_l2cap_packet->l2cap_packet_[0] = l2cap_payload_length & 0xFF;
-  built_l2cap_packet->l2cap_packet_[1] = (l2cap_payload_length & 0xFF00) >> 8;
-  built_l2cap_packet->l2cap_packet_[2] = first_packet_channel_id & 0xFF;
-  built_l2cap_packet->l2cap_packet_[3] =
-      (first_packet_channel_id & 0xFF00) >> 8;
-
-  return built_l2cap_packet;
-}  // Assemble
-
-uint16_t L2capPacket::get_l2cap_cid() const {
-  return ((l2cap_packet_[3] << 8) | l2cap_packet_[2]);
-}
-
-std::vector<std::shared_ptr<L2capSdu> > L2capPacket::fragment(
-    uint16_t maximum_sdu_size, uint8_t txseq, uint8_t reqseq) {
-  std::vector<std::shared_ptr<L2capSdu> > sdu;
-  if (!check_l2cap_packet()) return sdu;
-
-  std::vector<uint8_t> current_sdu;
-
-  Iterator current_iter = get_begin() + kL2capHeaderLength;
-  Iterator end_iter = get_end();
-
-  size_t number_of_packets = ceil((l2cap_packet_.size() - kL2capHeaderLength) /
-                                  static_cast<float>(maximum_sdu_size));
-
-  if (number_of_packets == 0) {
-    current_sdu.resize(kSduStandardHeaderLength);
-
-    set_sdu_header_length(current_sdu, kL2capHeaderLength);
-
-    set_sdu_cid(current_sdu, get_l2cap_cid());
-
-    reqseq = (reqseq & 0xF0) >> 4;
-    set_sdu_control_bytes(current_sdu, txseq, reqseq);
-
-    sdu.push_back(L2capSdu::L2capSduBuilder(current_sdu));
-
-    return sdu;
-  }
-
-  uint16_t header_length = 0x0000;
-
-  if (number_of_packets == 1) {
-    current_sdu.clear();
-    current_sdu.resize(kSduStandardHeaderLength);
-
-    header_length = ((l2cap_packet_[1] & 0xFF) << 8) | l2cap_packet_[0];
-    header_length += kL2capHeaderLength;
-    set_sdu_header_length(current_sdu, header_length);
-
-    set_sdu_cid(current_sdu, get_l2cap_cid());
-
-    set_sdu_control_bytes(current_sdu, txseq, 0x00);
-
-    current_sdu.insert(current_sdu.end(), current_iter, end_iter);
-
-    sdu.push_back(L2capSdu::L2capSduBuilder(current_sdu));
-
-    return sdu;
-  }
-
-  Iterator next_iter =
-      current_iter + (maximum_sdu_size - (kSduFirstHeaderLength + 2));
-
-  sdu.reserve(number_of_packets);
-  sdu.clear();
-
-  for (size_t i = 0; i <= number_of_packets; i++) {
-    if (i == 0) {
-      current_sdu.resize(kSduFirstHeaderLength);
-
-      header_length = maximum_sdu_size - kL2capHeaderLength;
-
-      reqseq = reqseq | kSduFirstReqseq;
-
-      set_total_sdu_length(current_sdu, l2cap_packet_.size() - 4);
-    } else {
-      current_sdu.resize(kSduStandardHeaderLength);
-
-      header_length = (next_iter - current_iter) + kL2capHeaderLength;
-
-      reqseq = reqseq & 0x0F;
-
-      if (i < number_of_packets) {
-        reqseq |= kSduContinuationReqseq;
-      } else {
-        reqseq |= kSduEndReqseq;
-      }
-    }
-    set_sdu_header_length(current_sdu, header_length);
-
-    set_sdu_cid(current_sdu, get_l2cap_cid());
-
-    set_sdu_control_bytes(current_sdu, txseq, reqseq);
-    txseq += 2;
-
-    // Txseq has a maximum of 0x3F. If it exceeds that, it restarts at 0x00.
-    if (txseq > 0x3F) txseq = 0x00;
-
-    current_sdu.insert(current_sdu.end(), current_iter, next_iter);
-    current_iter = next_iter;
-
-    next_iter = current_iter + (maximum_sdu_size - kSduFirstHeaderLength);
-
-    sdu.push_back(L2capSdu::L2capSduBuilder(std::move(current_sdu)));
-  }
-
-  return sdu;
-}  // fragment
-
-void L2capPacket::set_sdu_header_length(std::vector<uint8_t>& sdu,
-                                        uint16_t length) {
-  sdu[0] = length & 0xFF;
-  sdu[1] = (length & 0xFF00) >> 8;
-}
-
-void L2capPacket::set_total_sdu_length(std::vector<uint8_t>& sdu,
-                                       uint16_t total_sdu_length) {
-  sdu[6] = total_sdu_length & 0xFF;
-  sdu[7] = (total_sdu_length & 0xFF00) >> 8;
-}
-
-void L2capPacket::set_sdu_cid(std::vector<uint8_t>& sdu, uint16_t cid) {
-  sdu[2] = cid & 0xFF;
-  sdu[3] = (cid & 0xFF00) >> 8;
-}
-
-void L2capPacket::set_sdu_control_bytes(std::vector<uint8_t>& sdu,
-                                        uint8_t txseq, uint8_t reqseq) {
-  sdu[4] = txseq;
-  sdu[5] = reqseq;
-}
-
-bool L2capPacket::check_l2cap_packet() const {
-  uint16_t payload_length = ((l2cap_packet_[1] & 0xFF) << 8) | l2cap_packet_[0];
-
-  if (l2cap_packet_.size() < 4) return false;
-  if (payload_length != (l2cap_packet_.size() - 4)) return false;
-
-  return true;
-}
-
-// HciPacket Functions
-size_t L2capPacket::get_length() { return l2cap_packet_.size(); }
-
-uint8_t& L2capPacket::get_at_index(size_t index) {
-  return l2cap_packet_[index];
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc b/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc
deleted file mode 100644
index a93c1ad..0000000
--- a/vendor_libs/test_vendor_lib/src/l2cap_sdu.cc
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "l2cap_sdu.h"
-
-#include <base/logging.h>
-
-namespace test_vendor_lib {
-
-const uint16_t kSduSarBits = 0xe000;
-
-// Define the LFSR table of precalculated values defined by the
-// Bluetooth specification version 4.2 volume 3 part A section 3.3.5.
-const uint16_t L2capSdu::lfsr_table_[256] = {
-    0x0000, 0xc0c1, 0xc181, 0x0140, 0xc301, 0x03c0, 0x0280, 0xc241, 0xc601,
-    0x06c0, 0x0780, 0xc741, 0x0500, 0xc5c1, 0xc481, 0x0440, 0xcc01, 0x0cc0,
-    0x0d80, 0xcd41, 0x0f00, 0xcfc1, 0xce81, 0x0e40, 0x0a00, 0xcac1, 0xcb81,
-    0x0b40, 0xc901, 0x09c0, 0x0880, 0xc841, 0xd801, 0x18c0, 0x1980, 0xd941,
-    0x1b00, 0xdbc1, 0xda81, 0x1a40, 0x1e00, 0xdec1, 0xdf81, 0x1f40, 0xdd01,
-    0x1dc0, 0x1c80, 0xdc41, 0x1400, 0xd4c1, 0xd581, 0x1540, 0xd701, 0x17c0,
-    0x1680, 0xd641, 0xd201, 0x12c0, 0x1380, 0xd341, 0x1100, 0xd1c1, 0xd081,
-    0x1040, 0xf001, 0x30c0, 0x3180, 0xf141, 0x3300, 0xf3c1, 0xf281, 0x3240,
-    0x3600, 0xf6c1, 0xf781, 0x3740, 0xf501, 0x35c0, 0x3480, 0xf441, 0x3c00,
-    0xfcc1, 0xfd81, 0x3d40, 0xff01, 0x3fc0, 0x3e80, 0xfe41, 0xfa01, 0x3ac0,
-    0x3b80, 0xfb41, 0x3900, 0xf9c1, 0xf881, 0x3840, 0x2800, 0xe8c1, 0xe981,
-    0x2940, 0xeb01, 0x2bc0, 0x2a80, 0xea41, 0xee01, 0x2ec0, 0x2f80, 0xef41,
-    0x2d00, 0xedc1, 0xec81, 0x2c40, 0xe401, 0x24c0, 0x2580, 0xe541, 0x2700,
-    0xe7c1, 0xe681, 0x2640, 0x2200, 0xe2c1, 0xe381, 0x2340, 0xe101, 0x21c0,
-    0x2080, 0xe041, 0xa001, 0x60c0, 0x6180, 0xa141, 0x6300, 0xa3c1, 0xa281,
-    0x6240, 0x6600, 0xa6c1, 0xa781, 0x6740, 0xa501, 0x65c0, 0x6480, 0xa441,
-    0x6c00, 0xacc1, 0xad81, 0x6d40, 0xaf01, 0x6fc0, 0x6e80, 0xae41, 0xaa01,
-    0x6ac0, 0x6b80, 0xab41, 0x6900, 0xa9c1, 0xa881, 0x6840, 0x7800, 0xb8c1,
-    0xb981, 0x7940, 0xbb01, 0x7bc0, 0x7a80, 0xba41, 0xbe01, 0x7ec0, 0x7f80,
-    0xbf41, 0x7d00, 0xbdc1, 0xbc81, 0x7c40, 0xb401, 0x74c0, 0x7580, 0xb541,
-    0x7700, 0xb7c1, 0xb681, 0x7640, 0x7200, 0xb2c1, 0xb381, 0x7340, 0xb101,
-    0x71c0, 0x7080, 0xb041, 0x5000, 0x90c1, 0x9181, 0x5140, 0x9301, 0x53c0,
-    0x5280, 0x9241, 0x9601, 0x56c0, 0x5780, 0x9741, 0x5500, 0x95c1, 0x9481,
-    0x5440, 0x9c01, 0x5cc0, 0x5d80, 0x9d41, 0x5f00, 0x9fc1, 0x9e81, 0x5e40,
-    0x5a00, 0x9ac1, 0x9b81, 0x5b40, 0x9901, 0x59c0, 0x5880, 0x9841, 0x8801,
-    0x48c0, 0x4980, 0x8941, 0x4b00, 0x8bc1, 0x8a81, 0x4a40, 0x4e00, 0x8ec1,
-    0x8f81, 0x4f40, 0x8d01, 0x4dc0, 0x4c80, 0x8c41, 0x4400, 0x84c1, 0x8581,
-    0x4540, 0x8701, 0x47c0, 0x4680, 0x8641, 0x8201, 0x42c0, 0x4380, 0x8341,
-    0x4100, 0x81c1, 0x8081, 0x4040,
-};  // lfsr_table
-
-L2capSdu::L2capSdu(std::vector<uint8_t>&& create_from) {
-  sdu_data_ = create_from;
-}
-
-std::shared_ptr<L2capSdu> L2capSdu::L2capSduConstructor(
-    std::vector<uint8_t> create_from) {
-  L2capSdu packet(std::move(create_from));
-
-  return std::make_shared<L2capSdu>(packet);
-}
-
-std::shared_ptr<L2capSdu> L2capSdu::L2capSduBuilder(
-    std::vector<uint8_t> create_from) {
-  L2capSdu packet(std::move(create_from));
-
-  packet.sdu_data_.resize(packet.sdu_data_.size() + 2, 0x00);
-
-  uint16_t fcs = packet.calculate_fcs();
-
-  packet.sdu_data_[packet.sdu_data_.size() - 2] = fcs & 0xFF;
-  packet.sdu_data_[packet.sdu_data_.size() - 1] = (fcs & 0xFF00) >> 8;
-
-  return std::make_shared<L2capSdu>(packet);
-}
-
-uint16_t L2capSdu::convert_from_little_endian(
-    const unsigned int starting_index) const {
-  uint16_t convert = sdu_data_[starting_index + 1];
-  convert = convert << 8;
-  convert = convert | sdu_data_[starting_index];
-
-  return convert;
-}
-
-uint16_t L2capSdu::calculate_fcs() const {
-  // Starting state as directed by Bluetooth specification version 4.2 volume 3
-  // part A 3.3.5.
-  uint16_t lfsr = 0x0000;
-
-  for (size_t i = 0; i < sdu_data_.size() - 2; i++) {
-    uint8_t current_byte = sdu_data_[i];
-    lfsr = ((lfsr >> 8) & 0xff) ^ lfsr_table_[(lfsr & 0xff) ^ current_byte];
-  }
-  return lfsr;
-}
-
-uint16_t L2capSdu::get_payload_length() const {
-  return convert_from_little_endian(0);
-}
-
-uint16_t L2capSdu::get_fcs() const {
-  return convert_from_little_endian(sdu_data_.size() - 2);
-}
-
-uint16_t L2capSdu::get_controls() const {
-  return convert_from_little_endian(4);
-}
-
-uint16_t L2capSdu::get_total_l2cap_length() const {
-  return convert_from_little_endian(6);
-}
-
-uint16_t L2capSdu::get_channel_id() const {
-  return convert_from_little_endian(2);
-}
-
-size_t L2capSdu::get_vector_size() const { return sdu_data_.size(); }
-
-bool L2capSdu::is_complete_l2cap(const L2capSdu& sdu) {
-  uint16_t sar_bits = (sdu.get_controls() & kSduSarBits);
-
-  return (sar_bits == 0x0000);
-}
-
-bool L2capSdu::is_starting_sdu(const L2capSdu& sdu) {
-  uint16_t sar_bits = (sdu.get_controls() & kSduSarBits);
-
-  return (sar_bits == 0x4000);
-}
-
-bool L2capSdu::is_ending_sdu(const L2capSdu& sdu) {
-  uint16_t sar_bits = (sdu.get_controls() & kSduSarBits);
-
-  return (sar_bits == 0x8000);
-}
-
-// HciPacket functions.
-size_t L2capSdu::get_length() { return sdu_data_.size(); }
-uint8_t& L2capSdu::get_at_index(size_t index) { return sdu_data_[index]; }
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/packet.cc b/vendor_libs/test_vendor_lib/src/packet.cc
deleted file mode 100644
index 49f7272..0000000
--- a/vendor_libs/test_vendor_lib/src/packet.cc
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright 2015 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "packet"
-
-#include "packet.h"
-
-#include <algorithm>
-
-#include <base/logging.h>
-#include "osi/include/log.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-Packet::Packet(serial_data_type_t type, vector<uint8_t> header)
-    : type_(type), header_(std::move(header)) {
-  payload_ = {0};
-}
-
-bool Packet::AddPayloadOctets(size_t octets, const vector<uint8_t>& bytes) {
-  if (GetPayloadSize() + octets > kMaxPayloadOctets) return false;
-
-  if (octets != bytes.size()) return false;
-
-  payload_.insert(payload_.end(), bytes.begin(), bytes.end());
-  payload_[0] = payload_.size() - 1;
-
-  return true;
-}
-
-bool Packet::AddPayloadOctets(size_t octets, uint64_t value) {
-  vector<uint8_t> val_vector;
-
-  uint64_t v = value;
-
-  if (octets > sizeof(uint64_t)) return false;
-
-  for (size_t i = 0; i < octets; i++) {
-    val_vector.push_back(v & 0xff);
-    v = v >> 8;
-  }
-
-  if (v != 0) return false;
-
-  return AddPayloadOctets(octets, val_vector);
-}
-
-bool Packet::AddPayloadBtAddress(const BtAddress& address) {
-  if (GetPayloadSize() + BtAddress::kOctets > kMaxPayloadOctets) return false;
-
-  address.ToVector(payload_);
-
-  payload_[0] = payload_.size() - 1;
-
-  return true;
-}
-
-bool Packet::IncrementPayloadCounter(size_t index) {
-  if (payload_.size() < index - 1) return false;
-
-  payload_[index]++;
-  return true;
-}
-
-bool Packet::IncrementPayloadCounter(size_t index, uint8_t max_val) {
-  if (payload_.size() < index - 1) return false;
-
-  if (payload_[index] + 1 > max_val) return false;
-
-  payload_[index]++;
-  return true;
-}
-
-const vector<uint8_t>& Packet::GetHeader() const {
-  // Every packet must have a header.
-  CHECK(GetHeaderSize() > 0);
-  return header_;
-}
-
-uint8_t Packet::GetHeaderSize() const { return header_.size(); }
-
-size_t Packet::GetPacketSize() const {
-  // Add one for the type octet.
-  return 1 + header_.size() + payload_.size();
-}
-
-const vector<uint8_t>& Packet::GetPayload() const { return payload_; }
-
-size_t Packet::GetPayloadSize() const { return payload_.size(); }
-
-serial_data_type_t Packet::GetType() const { return type_; }
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/packet_stream.cc b/vendor_libs/test_vendor_lib/src/packet_stream.cc
deleted file mode 100644
index 224283c..0000000
--- a/vendor_libs/test_vendor_lib/src/packet_stream.cc
+++ /dev/null
@@ -1,129 +0,0 @@
-//
-// Copyright 2015 The Android Open Source Project
-//
-// 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.
-//
-
-#define LOG_TAG "packet_stream"
-
-#include "packet_stream.h"
-
-#include <base/logging.h>
-
-#include <errno.h>
-#include <unistd.h>
-
-#include "osi/include/log.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-std::unique_ptr<CommandPacket> PacketStream::ReceiveCommand(int fd) const {
-  vector<uint8_t> header;
-  vector<uint8_t> params_size;
-  vector<uint8_t> payload;
-
-  if (!ReceiveAll(header, CommandPacket::kCommandHeaderSize, fd)) {
-    LOG_ERROR(LOG_TAG, "Error: receiving command header.");
-    return std::unique_ptr<CommandPacket>(nullptr);
-  }
-
-  if (!ReceiveAll(params_size, 1, fd)) {
-    LOG_ERROR(LOG_TAG, "Error: receiving params size.");
-    return std::unique_ptr<CommandPacket>(nullptr);
-  }
-
-  if (!ReceiveAll(payload, params_size[0], fd)) {
-    LOG_ERROR(LOG_TAG, "Error: receiving command payload.");
-    return std::unique_ptr<CommandPacket>(nullptr);
-  }
-  return std::unique_ptr<CommandPacket>(new CommandPacket(header, payload));
-}
-
-serial_data_type_t PacketStream::ReceivePacketType(int fd) const {
-  vector<uint8_t> raw_type_octet;
-
-  if (!ReceiveAll(raw_type_octet, 1, fd)) {
-    // TODO(dennischeng): Proper error handling.
-    LOG_ERROR(LOG_TAG, "Error: Could not receive packet type.");
-  }
-
-  // Check that the type octet received is in the valid range, i.e. the packet
-  // must be a command or data packet.
-  const serial_data_type_t type =
-      static_cast<serial_data_type_t>(raw_type_octet[0]);
-  if (!ValidateTypeOctet(type)) {
-    // TODO(dennischeng): Proper error handling.
-    LOG_ERROR(LOG_TAG, "Error: Received invalid packet type.");
-  }
-  return type;
-}
-
-bool PacketStream::SendEvent(std::unique_ptr<EventPacket> event, int fd) const {
-  if (event->GetPayload()[0] != event->GetPayloadSize() - 1)
-    LOG_WARN(LOG_TAG, "Malformed event: 0x%04X, payload size %zu, reported %u",
-             event->GetEventCode(), event->GetPacketSize(),
-             event->GetPayload()[0]);
-
-  if (!SendAll({static_cast<uint8_t>(event->GetType())}, 1, fd)) {
-    LOG_ERROR(LOG_TAG, "Error: Could not send event type.");
-    return false;
-  }
-
-  if (!SendAll(event->GetHeader(), event->GetHeaderSize(), fd)) {
-    LOG_ERROR(LOG_TAG, "Error: Could not send event header.");
-    return false;
-  }
-
-  if (!SendAll(event->GetPayload(), event->GetPayloadSize(), fd)) {
-    LOG_ERROR(LOG_TAG, "Error: Could not send event payload.");
-    return false;
-  }
-  return true;
-}
-
-bool PacketStream::ValidateTypeOctet(serial_data_type_t type) const {
-  // The only types of packets that should be received from the HCI are command
-  // packets and data packets.
-  return (type >= DATA_TYPE_COMMAND) && (type <= DATA_TYPE_SCO);
-}
-
-bool PacketStream::ReceiveAll(vector<uint8_t>& destination,
-                              size_t num_octets_to_receive, int fd) const {
-  destination.resize(num_octets_to_receive);
-  size_t octets_remaining = num_octets_to_receive;
-  while (octets_remaining > 0) {
-    const int num_octets_received =
-        read(fd, &destination[num_octets_to_receive - octets_remaining],
-             octets_remaining);
-    if (num_octets_received < 0) return false;
-    octets_remaining -= num_octets_received;
-  }
-  return true;
-}
-
-bool PacketStream::SendAll(const vector<uint8_t>& source,
-                           size_t num_octets_to_send, int fd) const {
-  CHECK(source.size() >= num_octets_to_send);
-  size_t octets_remaining = num_octets_to_send;
-  while (octets_remaining > 0) {
-    const int num_octets_sent = write(
-        fd, &source[num_octets_to_send - octets_remaining], octets_remaining);
-    if (num_octets_sent < 0) return false;
-    octets_remaining -= num_octets_sent;
-  }
-  return true;
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/src/sco_packet.cc b/vendor_libs/test_vendor_lib/src/sco_packet.cc
deleted file mode 100644
index 465d8ff..0000000
--- a/vendor_libs/test_vendor_lib/src/sco_packet.cc
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright 2017 The Android Open Source Project
- *
- * 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.
- */
-
-#define LOG_TAG "sco_packet"
-
-#include "sco_packet.h"
-
-#include "stack/include/hcidefs.h"
-
-using std::vector;
-
-namespace test_vendor_lib {
-
-ScoPacket::ScoPacket(uint16_t channel,
-                     ScoPacket::PacketStatusFlags packet_status)
-    : Packet(DATA_TYPE_SCO,
-             {static_cast<uint8_t>(channel & 0xff),
-              static_cast<uint8_t>(((channel >> 8) & 0x0f) |
-                                   (packet_status & 0x3 << 4))}) {}
-
-uint16_t ScoPacket::GetChannel() const {
-  return (GetHeader()[0] | (GetHeader()[1] << 8)) & 0xfff;
-}
-
-ScoPacket::PacketStatusFlags ScoPacket::GetPacketStatusFlags() const {
-  return static_cast<ScoPacket::PacketStatusFlags>((GetHeader()[1] >> 4) & 0x3);
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc b/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc
index 97b7331..fe2b95a 100644
--- a/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc
+++ b/vendor_libs/test_vendor_lib/test/async_manager_unittest.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "async_manager.h"
+#include "model/setup/async_manager.h"
 #include <gtest/gtest.h>
 #include <cstdint>
 #include <cstring>
@@ -48,8 +48,7 @@
     serv_addr.sin_addr.s_addr = INADDR_ANY;
     serv_addr.sin_port = htons(kPort);
     int reuse_flag = 1;
-    EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag,
-                            sizeof(reuse_flag)) < 0);
+    EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag, sizeof(reuse_flag)) < 0);
     EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0);
 
     listen(fd, 1);
@@ -87,8 +86,7 @@
     async_manager_.WatchFdForNonBlockingReads(socket_fd_, [this](int fd) {
       int connection_fd = AcceptConnection(fd);
 
-      async_manager_.WatchFdForNonBlockingReads(
-          connection_fd, [this](int fd) { ReadIncomingMessage(fd); });
+      async_manager_.WatchFdForNonBlockingReads(connection_fd, [this](int fd) { ReadIncomingMessage(fd); });
     });
   }
 
@@ -112,8 +110,7 @@
     serv_addr.sin_addr.s_addr = *(reinterpret_cast<in_addr_t*>(server->h_addr));
     serv_addr.sin_port = htons(kPort);
 
-    int result =
-        connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
+    int result = connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
     EXPECT_FALSE(result < 0);
 
     return socket_cli_fd;
diff --git a/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc b/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc
deleted file mode 100644
index 0cf3760..0000000
--- a/vendor_libs/test_vendor_lib/test/bt_address_unittest.cc
+++ /dev/null
@@ -1,194 +0,0 @@
-/******************************************************************************
- *
- *  Copyright 2016 Google, Inc.
- *
- *  Licensed under the Apache License, Version 2.0 (the "License");
- *  you may not use this file except in compliance with the License.
- *  You may obtain a copy of the License at:
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *  Unless required by applicable law or agreed to in writing, software
- *  distributed under the License is distributed on an "AS IS" BASIS,
- *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- *  See the License for the specific language governing permissions and
- *  limitations under the License.
- *
- ******************************************************************************/
-
-#include <gtest/gtest.h>
-#include <string>
-#include <vector>
-using std::vector;
-
-#include "bt_address.h"
-
-namespace {
-const std::string kTestAddr1 = "12:34:56:78:9a:bc";
-const std::string kTestAddr2 = "cb:a9:87:65:43:21";
-const std::string kTestAddr3 = "cb:a9:56:78:9a:bc";
-const std::string kUpperMask = "ff:ff:00:00:00:00";
-const std::string kLowerMask = "00:00:ff:ff:ff:ff";
-const std::string kZeros = "00:00:00:00:00:00";
-const vector<uint8_t> kZeros_octets = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-const vector<uint8_t> kTestAddr1_octets = {0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12};
-}  // namespace
-
-namespace test_vendor_lib {
-
-class BtAddressTest : public ::testing::Test {
- public:
-  BtAddressTest() {}
-  ~BtAddressTest() {}
-};
-
-TEST_F(BtAddressTest, IsValid) {
-  EXPECT_FALSE(BtAddress::IsValid(""));
-  EXPECT_FALSE(BtAddress::IsValid("000000000000"));
-  EXPECT_FALSE(BtAddress::IsValid("00:00:00:00:0000"));
-  EXPECT_FALSE(BtAddress::IsValid("00:00:00:00:00:0"));
-  EXPECT_FALSE(BtAddress::IsValid("00:00:00:00:00:0;"));
-  EXPECT_FALSE(BtAddress::IsValid("00:00:000:00:00:0;"));
-  EXPECT_TRUE(BtAddress::IsValid("00:00:00:00:00:00"));
-  EXPECT_FALSE(BtAddress::IsValid("aB:cD:eF:Gh:iJ:Kl"));
-  EXPECT_TRUE(BtAddress::IsValid(kTestAddr1));
-  EXPECT_TRUE(BtAddress::IsValid(kTestAddr2));
-  EXPECT_TRUE(BtAddress::IsValid(kTestAddr3));
-}
-
-TEST_F(BtAddressTest, test_comparisons) {
-  BtAddress btaddr1;
-  BtAddress btaddr1_copy;
-  BtAddress btaddr2;
-
-  EXPECT_TRUE(btaddr1.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr1_copy.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr2.FromString(kTestAddr2));
-
-  EXPECT_TRUE(btaddr1 == btaddr1_copy);
-  EXPECT_FALSE(btaddr1 == btaddr2);
-
-  EXPECT_FALSE(btaddr1 != btaddr1_copy);
-  EXPECT_TRUE(btaddr1 != btaddr2);
-
-  EXPECT_FALSE(btaddr1 < btaddr1_copy);
-  EXPECT_TRUE(btaddr1 < btaddr2);
-  EXPECT_FALSE(btaddr2 < btaddr1);
-
-  EXPECT_FALSE(btaddr1 > btaddr1_copy);
-  EXPECT_FALSE(btaddr1 > btaddr2);
-  EXPECT_TRUE(btaddr2 > btaddr1);
-
-  EXPECT_TRUE(btaddr1 <= btaddr1_copy);
-  EXPECT_TRUE(btaddr1 <= btaddr2);
-  EXPECT_FALSE(btaddr2 <= btaddr1);
-
-  EXPECT_TRUE(btaddr1 >= btaddr1_copy);
-  EXPECT_FALSE(btaddr1 >= btaddr2);
-  EXPECT_TRUE(btaddr2 >= btaddr1);
-}
-
-TEST_F(BtAddressTest, test_assignment) {
-  BtAddress btaddr1;
-  BtAddress btaddr2;
-  BtAddress btaddr3;
-
-  EXPECT_TRUE(btaddr1.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr2.FromString(kTestAddr2));
-  EXPECT_TRUE(btaddr3.FromString(kTestAddr3));
-
-  EXPECT_TRUE(btaddr1 != btaddr2);
-  EXPECT_TRUE(btaddr2 != btaddr3);
-  EXPECT_TRUE(btaddr1 != btaddr3);
-
-  btaddr1 = btaddr2;
-  EXPECT_TRUE(btaddr1 == btaddr2);
-  EXPECT_TRUE(btaddr2 != btaddr3);
-  EXPECT_TRUE(btaddr1 != btaddr3);
-
-  btaddr3 = btaddr2;
-  EXPECT_TRUE(btaddr1 == btaddr2);
-  EXPECT_TRUE(btaddr2 == btaddr3);
-  EXPECT_TRUE(btaddr1 == btaddr3);
-}
-
-TEST_F(BtAddressTest, test_bitoperations) {
-  BtAddress btaddr1;
-  BtAddress btaddr2;
-  BtAddress btaddr3;
-  BtAddress btaddr_lowmask;
-  BtAddress btaddr_upmask;
-
-  EXPECT_TRUE(btaddr1.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr2.FromString(kTestAddr2));
-  EXPECT_TRUE(btaddr3.FromString(kTestAddr3));
-  EXPECT_TRUE(btaddr_lowmask.FromString(kLowerMask));
-  EXPECT_TRUE(btaddr_upmask.FromString(kUpperMask));
-
-  EXPECT_TRUE(btaddr1 != btaddr2);
-  EXPECT_TRUE(btaddr2 != btaddr3);
-  btaddr1 &= btaddr_lowmask;
-  btaddr2 &= btaddr_upmask;
-  btaddr1 |= btaddr2;
-  EXPECT_TRUE(btaddr1 == btaddr3);
-}
-
-TEST_F(BtAddressTest, FromString) {
-  BtAddress btaddrA;
-  BtAddress btaddrB;
-  BtAddress btaddrC;
-  EXPECT_TRUE(btaddrA.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddrA != btaddrB);
-  EXPECT_TRUE(btaddrC == btaddrB);
-  EXPECT_TRUE(btaddrB.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddrC.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddrA == btaddrB);
-  EXPECT_TRUE(btaddrC == btaddrB);
-}
-
-TEST_F(BtAddressTest, FromVector) {
-  BtAddress btaddr1;
-  EXPECT_TRUE(btaddr1.FromString(kTestAddr1));
-  BtAddress btaddrA;
-  BtAddress btaddrB;
-  EXPECT_TRUE(btaddrA.FromVector(kTestAddr1_octets));
-  EXPECT_TRUE(btaddrA != btaddrB);
-  EXPECT_TRUE(btaddrB.FromVector(kTestAddr1_octets));
-  EXPECT_TRUE(btaddrA == btaddrB);
-  EXPECT_TRUE(btaddr1 == btaddrB);
-}
-
-TEST_F(BtAddressTest, ToVector) {
-  BtAddress btaddr1;
-  BtAddress btaddr1_copy;
-  BtAddress btaddr2;
-  vector<uint8_t> octets1;
-  vector<uint8_t> octets1_copy;
-  vector<uint8_t> octets2;
-  EXPECT_TRUE(btaddr1.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr1_copy.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr2.FromString(kTestAddr2));
-  EXPECT_TRUE(btaddr1 == btaddr1_copy);
-  EXPECT_TRUE(btaddr1 != btaddr2);
-  btaddr1.ToVector(octets1);
-  btaddr2.ToVector(octets2);
-  btaddr1_copy.ToVector(octets1_copy);
-  EXPECT_TRUE(octets1 != octets2);
-  EXPECT_TRUE(octets1 == octets1_copy);
-  EXPECT_TRUE(octets1.size() == BtAddress::kOctets);
-  btaddr1.ToVector(octets1);
-  EXPECT_TRUE(octets1.size() == (2 * BtAddress::kOctets));
-}
-
-TEST_F(BtAddressTest, ToString) {
-  BtAddress btaddr_zeros;
-  BtAddress btaddr1;
-  EXPECT_TRUE(btaddr_zeros.FromString(kZeros));
-  EXPECT_TRUE(btaddr1.FromString(kTestAddr1));
-  EXPECT_TRUE(btaddr_zeros.ToString() == kZeros);
-  EXPECT_TRUE(btaddr1.ToString() == kTestAddr1);
-  EXPECT_TRUE(btaddr_zeros.ToString() != kTestAddr1);
-  EXPECT_TRUE(btaddr1.ToString() != kZeros);
-}
-
-}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/iterator_test.cc b/vendor_libs/test_vendor_lib/test/iterator_test.cc
index 92a6d70..4a85068 100644
--- a/vendor_libs/test_vendor_lib/test/iterator_test.cc
+++ b/vendor_libs/test_vendor_lib/test/iterator_test.cc
@@ -29,11 +29,17 @@
   static std::shared_ptr<TestPacket> make_new_packet(vector<uint8_t> v) {
     return std::shared_ptr<TestPacket>(new TestPacket(v));
   }
-  size_t get_length() { return test_vector_.size(); }
-  uint8_t& get_at_index(size_t index) { return test_vector_[index]; }
+  size_t get_length() {
+    return test_vector_.size();
+  }
+  uint8_t& get_at_index(size_t index) {
+    return test_vector_[index];
+  }
 
  private:
-  TestPacket(vector<uint8_t> v) { test_vector_ = v; }
+  TestPacket(vector<uint8_t> v) {
+    test_vector_ = v;
+  }
   vector<uint8_t> test_vector_;
 };
 
@@ -42,9 +48,13 @@
   IteratorTest() = default;
   ~IteratorTest() = default;
 
-  void SetUp() { packet = TestPacket::make_new_packet(complete_l2cap_packet); }
+  void SetUp() {
+    packet = TestPacket::make_new_packet(complete_l2cap_packet);
+  }
 
-  void TearDown() { packet.reset(); }
+  void TearDown() {
+    packet.reset();
+  }
 
   std::shared_ptr<TestPacket> packet;
 };
@@ -77,8 +87,7 @@
   Iterator plus_eq = packet->get_begin();
   for (size_t i = 0; i < complete_l2cap_packet.size(); i += 2) {
     ASSERT_EQ(complete_l2cap_packet[i], *plus_eq)
-        << "+= test: Dereferenced iterator does not equal expected at index "
-        << i;
+        << "+= test: Dereferenced iterator does not equal expected at index " << i;
     plus_eq += 2;
   }
 }
@@ -105,8 +114,7 @@
   Iterator plus = packet->get_begin();
   for (size_t i = 0; i < complete_l2cap_packet.size(); i++) {
     ASSERT_EQ(complete_l2cap_packet[i], *plus)
-        << "+ test: Dereferenced iterator does not equal expected at index "
-        << i;
+        << "+ test: Dereferenced iterator does not equal expected at index " << i;
     plus = plus + static_cast<size_t>(1);
   }
 }
@@ -116,8 +124,7 @@
   minus_eq -= 1;
   for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i -= 2) {
     ASSERT_EQ(complete_l2cap_packet[i], *minus_eq)
-        << "-= test: Dereferenced iterator does not equal expected at index "
-        << i;
+        << "-= test: Dereferenced iterator does not equal expected at index " << i;
     minus_eq -= 2;
   }
 }
@@ -146,8 +153,7 @@
   minus = minus - static_cast<size_t>(1);
   for (size_t i = complete_l2cap_packet.size() - 1; i > 0; i--) {
     ASSERT_EQ(complete_l2cap_packet[i], *minus)
-        << "- test: Dereferenced iterator does not equal expected at index "
-        << i;
+        << "- test: Dereferenced iterator does not equal expected at index " << i;
     minus = minus - static_cast<size_t>(1);
   }
 }
@@ -157,8 +163,7 @@
   plus_eq--;
   for (size_t i = 0; i < 100; i++) {
     plus_eq += i;
-    ASSERT_EQ(packet->get_end(), plus_eq)
-        << "+= test: Iterator exceeded the upper bound set by get_length()";
+    ASSERT_EQ(packet->get_end(), plus_eq) << "+= test: Iterator exceeded the upper bound set by get_length()";
   }
 }
 
@@ -166,9 +171,8 @@
   Iterator plus_plus = packet->get_end();
   plus_plus--;
   for (size_t i = 0; i < 100; i++) {
-    ASSERT_EQ(packet->get_end(), ++plus_plus)
-        << "Pre-increment test: Iterator exceeded the upper bound set "
-           "by get_length()";
+    ASSERT_EQ(packet->get_end(), ++plus_plus) << "Pre-increment test: Iterator exceeded the upper bound set "
+                                                 "by get_length()";
   }
 }
 
@@ -176,9 +180,8 @@
   Iterator plus_plus = packet->get_end();
   plus_plus--;
   for (size_t i = 0; i < 100; i++) {
-    ASSERT_EQ(packet->get_end(), plus_plus++)
-        << "Post-increment test: Iterator exceeded the upper bound set "
-           "by get_length()";
+    ASSERT_EQ(packet->get_end(), plus_plus++) << "Post-increment test: Iterator exceeded the upper bound set "
+                                                 "by get_length()";
   }
 }
 
@@ -187,8 +190,7 @@
   plus--;
   for (size_t i = 0; i < 100; i++) {
     plus = plus + static_cast<size_t>(i);
-    ASSERT_EQ(packet->get_end(), plus)
-        << "+ test: Iterator exceeded the upper bound set by get_length()";
+    ASSERT_EQ(packet->get_end(), plus) << "+ test: Iterator exceeded the upper bound set by get_length()";
   }
 }
 
@@ -196,9 +198,8 @@
   Iterator minus_eq = packet->get_begin();
   for (size_t i = 0; i < 100; i++) {
     minus_eq -= i;
-    ASSERT_EQ(complete_l2cap_packet[0], *minus_eq)
-        << "-= test: Iterator is less than the lower bound set by "
-           "packet->get_begin()";
+    ASSERT_EQ(complete_l2cap_packet[0], *minus_eq) << "-= test: Iterator is less than the lower bound set by "
+                                                      "packet->get_begin()";
   }
 }
 
@@ -224,9 +225,8 @@
   Iterator minus = packet->get_begin();
   for (size_t i = 0; i < 100; i++) {
     minus = minus - static_cast<size_t>(i);
-    ASSERT_EQ(complete_l2cap_packet[0], *minus)
-        << "- test: Iterator is less than the lower bound set "
-           "by packet->get_begin()";
+    ASSERT_EQ(complete_l2cap_packet[0], *minus) << "- test: Iterator is less than the lower bound set "
+                                                   "by packet->get_begin()";
   }
 }
 };  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc b/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc
index 2e6df2c..3a1cd5c 100644
--- a/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc
+++ b/vendor_libs/test_vendor_lib/test/l2cap_sdu_test.cc
@@ -25,24 +25,15 @@
 
 namespace test_vendor_lib {
 
-std::shared_ptr<L2capSdu> packet_1 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_1);
-std::shared_ptr<L2capSdu> packet_2 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_2);
-std::shared_ptr<L2capSdu> packet_3 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_3);
-std::shared_ptr<L2capSdu> packet_4 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_4);
-std::shared_ptr<L2capSdu> packet_5 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_5);
-std::shared_ptr<L2capSdu> packet_6 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_6);
-std::shared_ptr<L2capSdu> packet_7 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_7);
-std::shared_ptr<L2capSdu> packet_8 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_8);
-std::shared_ptr<L2capSdu> packet_9 =
-    L2capSdu::L2capSduConstructor(l2cap_test_packet_9);
+std::shared_ptr<L2capSdu> packet_1 = L2capSdu::L2capSduConstructor(l2cap_test_packet_1);
+std::shared_ptr<L2capSdu> packet_2 = L2capSdu::L2capSduConstructor(l2cap_test_packet_2);
+std::shared_ptr<L2capSdu> packet_3 = L2capSdu::L2capSduConstructor(l2cap_test_packet_3);
+std::shared_ptr<L2capSdu> packet_4 = L2capSdu::L2capSduConstructor(l2cap_test_packet_4);
+std::shared_ptr<L2capSdu> packet_5 = L2capSdu::L2capSduConstructor(l2cap_test_packet_5);
+std::shared_ptr<L2capSdu> packet_6 = L2capSdu::L2capSduConstructor(l2cap_test_packet_6);
+std::shared_ptr<L2capSdu> packet_7 = L2capSdu::L2capSduConstructor(l2cap_test_packet_7);
+std::shared_ptr<L2capSdu> packet_8 = L2capSdu::L2capSduConstructor(l2cap_test_packet_8);
+std::shared_ptr<L2capSdu> packet_9 = L2capSdu::L2capSduConstructor(l2cap_test_packet_9);
 
 class L2capSduTest : public ::testing::Test {
  public:
diff --git a/vendor_libs/test_vendor_lib/test/l2cap_test.cc b/vendor_libs/test_vendor_lib/test/l2cap_test.cc
index f4eea71..b218287 100644
--- a/vendor_libs/test_vendor_lib/test/l2cap_test.cc
+++ b/vendor_libs/test_vendor_lib/test/l2cap_test.cc
@@ -30,13 +30,19 @@
 
 class TestPacket : public HciPacket {
  public:
-  TestPacket(const std::vector<uint8_t>& packet) { complete_packet_ = packet; }
+  TestPacket(const std::vector<uint8_t>& packet) {
+    complete_packet_ = packet;
+  }
   TestPacket() = default;
 
  private:
   std::vector<uint8_t> complete_packet_;
-  size_t get_length() { return complete_packet_.size(); }
-  uint8_t& get_at_index(size_t index) { return complete_packet_[index]; }
+  size_t get_length() {
+    return complete_packet_.size();
+  }
+  uint8_t& get_at_index(size_t index) {
+    return complete_packet_[index];
+  }
 };
 
 class L2capTest : public ::testing::Test {
@@ -47,8 +53,7 @@
     return L2capSdu::L2capSduBuilder(sdu);
   }
 
-  void compare_packets(shared_ptr<HciPacket> expected,
-                       shared_ptr<HciPacket> received) {
+  void compare_packets(shared_ptr<HciPacket> expected, shared_ptr<HciPacket> received) {
     Iterator expected_begin = expected->get_begin();
     Iterator expected_end = expected->get_end();
 
@@ -337,11 +342,10 @@
   sdu = l2cap_expected->fragment(16, 0x02, 0x41);
 
   l2cap_received = L2capPacket::assemble(sdu);
-  ASSERT_NE(l2cap_received, nullptr)
-      << "packet reassembly failed after fragment" << std::endl
-      << "Test1: Small Segment request" << std::endl
-      << "sdu used: good_sdu" << std::endl
-      << "function call: fragment(16, 0x02, 0x41)" << std::endl;
+  ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl
+                                     << "Test1: Small Segment request" << std::endl
+                                     << "sdu used: good_sdu" << std::endl
+                                     << "function call: fragment(16, 0x02, 0x41)" << std::endl;
 
   compare_packets(l2cap_expected, l2cap_received);
 
@@ -374,11 +378,10 @@
   sdu = l2cap_expected->fragment(1024, 0x02, 0x41);
 
   l2cap_received = L2capPacket::assemble(sdu);
-  ASSERT_NE(l2cap_received, nullptr)
-      << "packet reassembly failed after fragment" << std::endl
-      << "Test2: Large Segment request" << std::endl
-      << "sdu used: l2cap_test_packet[1-9]" << std::endl
-      << "function call: fragment(1024, 0x02, 0x41)" << std::endl;
+  ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl
+                                     << "Test2: Large Segment request" << std::endl
+                                     << "sdu used: l2cap_test_packet[1-9]" << std::endl
+                                     << "function call: fragment(1024, 0x02, 0x41)" << std::endl;
 
   compare_packets(l2cap_expected, l2cap_received);
 
@@ -405,11 +408,10 @@
   sdu = l2cap_expected->fragment(24, 0x08, 0x41);
 
   l2cap_received = L2capPacket::assemble(sdu);
-  ASSERT_NE(l2cap_received, nullptr)
-      << "packet reassembly failed after fragment" << std::endl
-      << "Test3: Non-zero starting TxSeq" << std::endl
-      << "sdu used: good_sdu" << std::endl
-      << "function call: fragment(24, 0x08, 0x41)" << std::endl;
+  ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl
+                                     << "Test3: Non-zero starting TxSeq" << std::endl
+                                     << "sdu used: good_sdu" << std::endl
+                                     << "function call: fragment(24, 0x08, 0x41)" << std::endl;
 
   compare_packets(l2cap_expected, l2cap_received);
 
@@ -435,11 +437,10 @@
   sdu = l2cap_expected->fragment(16, 0x02, 0x41);
 
   l2cap_received = L2capPacket::assemble(sdu);
-  ASSERT_NE(l2cap_received, nullptr)
-      << "packet reassembly failed after fragment" << std::endl
-      << "Test4: Packet with no payload" << std::endl
-      << "sdu used: empty_sdu_payload" << std::endl
-      << "function call: fragment(16, 0x02, 0x41)" << std::endl;
+  ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl
+                                     << "Test4: Packet with no payload" << std::endl
+                                     << "sdu used: empty_sdu_payload" << std::endl
+                                     << "function call: fragment(16, 0x02, 0x41)" << std::endl;
 
   compare_packets(l2cap_expected, l2cap_received);
 
@@ -466,11 +467,10 @@
   sdu = l2cap_expected->fragment(256, 0x02, 0x41);
 
   l2cap_received = L2capPacket::assemble(sdu);
-  ASSERT_NE(l2cap_received, nullptr)
-      << "packet reassembly failed after fragment" << std::endl
-      << "Test5: Segment size > Payload" << std::endl
-      << "sdu used: good_sdu" << std::endl
-      << "function call: fragment(256, 0x02, 0x41)" << std::endl;
+  ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl
+                                     << "Test5: Segment size > Payload" << std::endl
+                                     << "sdu used: good_sdu" << std::endl
+                                     << "function call: fragment(256, 0x02, 0x41)" << std::endl;
 
   compare_packets(l2cap_expected, l2cap_received);
 
@@ -502,11 +502,10 @@
   sdu = l2cap_expected->fragment(512, 0x02, 0x41);
 
   l2cap_received = L2capPacket::assemble(sdu);
-  ASSERT_NE(l2cap_received, nullptr)
-      << "packet reassembly failed after fragment" << std::endl
-      << "Test6: Small Segment request on large packet" << std::endl
-      << "sdu used: l2cap_test_packet_[1-9]" << std::endl
-      << "function call: fragment(64, 0x02, 0x41)" << std::endl;
+  ASSERT_NE(l2cap_received, nullptr) << "packet reassembly failed after fragment" << std::endl
+                                     << "Test6: Small Segment request on large packet" << std::endl
+                                     << "sdu used: l2cap_test_packet_[1-9]" << std::endl
+                                     << "function call: fragment(64, 0x02, 0x41)" << std::endl;
 
   compare_packets(l2cap_expected, l2cap_received);
 
diff --git a/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc b/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc
new file mode 100644
index 0000000..f24bf0e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/test/link_layer_socket_device_test.cc
@@ -0,0 +1,306 @@
+/*
+ * Copyright 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "model/devices/link_layer_socket_device.h"
+
+#include <gtest/gtest.h>
+#include <cstdint>
+#include <cstring>
+#include <vector>
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include "include/link.h"
+#include "model/setup/async_manager.h"
+#include "packets/link_layer/command_view.h"
+#include "packets/link_layer/link_layer_packet_builder.h"
+#include "packets/link_layer/link_layer_packet_view.h"
+
+std::vector<uint8_t> count = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+    0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+    0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+};
+
+using test_vendor_lib::packets::CommandBuilder;
+using test_vendor_lib::packets::CommandView;
+using test_vendor_lib::packets::LinkLayerPacketBuilder;
+using test_vendor_lib::packets::LinkLayerPacketView;
+using test_vendor_lib::packets::PacketView;
+using test_vendor_lib::packets::View;
+
+static const size_t kMaxConnections = 300;
+
+namespace test_vendor_lib {
+
+class LinkLayerSocketDeviceTest : public ::testing::Test {
+ public:
+  static const uint16_t kPort = 6123;
+
+ protected:
+  class MockPhyLayer : public PhyLayer {
+   public:
+    MockPhyLayer(const std::function<void(std::shared_ptr<LinkLayerPacketBuilder>)>& on_receive)
+        : PhyLayer(Phy::Type::LOW_ENERGY, 0, [](LinkLayerPacketView) {}), on_receive_(on_receive) {}
+    virtual void Send(const std::shared_ptr<LinkLayerPacketBuilder> packet) override {
+      on_receive_(packet);
+    }
+    virtual void Receive(LinkLayerPacketView) override {}
+    virtual void TimerTick() override {}
+
+   private:
+    std::function<void(std::shared_ptr<LinkLayerPacketBuilder>)> on_receive_;
+  };
+
+  int StartServer() {
+    struct sockaddr_in serv_addr;
+    int fd = socket(AF_INET, SOCK_STREAM, 0);
+    EXPECT_FALSE(fd < 0);
+
+    memset(&serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_addr.s_addr = INADDR_ANY;
+    serv_addr.sin_port = htons(kPort);
+    int reuse_flag = 1;
+    EXPECT_FALSE(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse_flag, sizeof(reuse_flag)) < 0);
+    EXPECT_FALSE(bind(fd, (sockaddr*)&serv_addr, sizeof(serv_addr)) < 0);
+
+    listen(fd, 1);
+    return fd;
+  }
+
+  int AcceptConnection(int fd) {
+    return accept(fd, NULL, NULL);
+  }
+
+  void ValidatePacket(size_t index, bool at_server, std::shared_ptr<LinkLayerPacketBuilder> received) {
+    /* Convert the Builder into a View */
+    std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+    received->Serialize(it);
+    LinkLayerPacketView received_view = LinkLayerPacketView::Create(packet_ptr);
+
+    /* Validate received packet */
+    ASSERT_EQ(received_view.GetSourceAddress(), source_);
+    ASSERT_EQ(received_view.GetDestinationAddress(), dest_);
+    ASSERT_EQ(Link::PacketType::COMMAND, received_view.GetType());
+    CommandView command_view = CommandView::GetCommand(received_view);
+    if (at_server) {
+      ASSERT_EQ(client_opcodes_[index], command_view.GetOpcode());
+    } else {
+      ASSERT_EQ(server_opcodes_[index], command_view.GetOpcode());
+    }
+    auto args_itr = command_view.GetData();
+    ASSERT_EQ(args_itr.NumBytesRemaining(), count.size());
+    for (size_t i = 0; i < count.size(); i++) {
+      ASSERT_EQ(*args_itr++, count[i]);
+    }
+    if (at_server) {
+      validated_client_packets_[index]++;
+    } else {
+      validated_server_packets_[index]++;
+    }
+  }
+
+  void SetUp() override {
+    servers_.reserve(kMaxConnections);
+    clients_.reserve(kMaxConnections);
+    socket_fd_ = StartServer();
+
+    async_manager_.WatchFdForNonBlockingReads(socket_fd_, [this](int fd) {
+      int connection_fd = AcceptConnection(fd);
+      ASSERT_GE(connection_fd, 0);
+      size_t index = servers_.size();
+      servers_.emplace_back(connection_fd, Phy::Type::LOW_ENERGY);
+      ASSERT_EQ(servers_.size() - 1, index) << "Race condition";
+      std::shared_ptr<MockPhyLayer> mock_phy = std::make_shared<MockPhyLayer>(
+          [this, index](std::shared_ptr<LinkLayerPacketBuilder> received) { ValidatePacket(index, true, received); });
+      servers_[index].RegisterPhyLayer(mock_phy);
+    });
+  }
+
+  void TearDown() override {
+    async_manager_.StopWatchingFileDescriptor(socket_fd_);
+    close(socket_fd_);
+  }
+
+  int ConnectClient() {
+    int socket_cli_fd = socket(AF_INET, SOCK_STREAM, 0);
+    EXPECT_FALSE(socket_cli_fd < 0);
+
+    struct hostent* server;
+    server = gethostbyname("localhost");
+    EXPECT_FALSE(server == NULL);
+
+    struct sockaddr_in serv_addr;
+    memset((void*)&serv_addr, 0, sizeof(serv_addr));
+    serv_addr.sin_family = AF_INET;
+    serv_addr.sin_addr.s_addr = INADDR_ANY;
+    serv_addr.sin_port = htons(kPort);
+
+    int result = connect(socket_cli_fd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
+    EXPECT_FALSE(result < 0);
+
+    EXPECT_GE(socket_cli_fd, 0);
+
+    return socket_cli_fd;
+  }
+
+  void ValidateConnection(size_t pair_id) {
+    ASSERT_GT(clients_.size(), pair_id);
+    ASSERT_GT(servers_.size(), pair_id);
+  }
+
+  size_t CreateConnection() {
+    int fd = ConnectClient();
+    size_t index = clients_.size();
+    clients_.emplace_back(fd, Phy::Type::LOW_ENERGY);
+    std::shared_ptr<MockPhyLayer> mock_phy = std::make_shared<MockPhyLayer>(
+        [this, index](std::shared_ptr<LinkLayerPacketBuilder> received) { ValidatePacket(index, false, received); });
+    clients_[index].RegisterPhyLayer(mock_phy);
+    for (size_t timeout = 10; timeout > 0 && clients_.size() > servers_.size(); timeout--) {
+      sleep(0);  // Wait for server to be created
+    }
+    ValidateConnection(index);
+    return index;
+  }
+
+  LinkLayerPacketView NextPacket() {
+    std::shared_ptr<std::vector<uint8_t>> count_shared = std::make_shared<std::vector<uint8_t>>(count);
+    View count_view(count_shared, 0, count_shared->size());
+    PacketView<true> args({count_view});
+    auto builder = CommandBuilder::Create(packet_id_++, args);
+    auto wrapped_command = LinkLayerPacketBuilder::WrapCommand(std::move(builder), source_, dest_);
+    std::shared_ptr<std::vector<uint8_t>> packet_ptr = std::make_shared<std::vector<uint8_t>>();
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet_ptr);
+    wrapped_command->Serialize(it);
+    LinkLayerPacketView view = LinkLayerPacketView::Create(packet_ptr);
+    return view;
+  }
+
+  void SendFromClient(size_t pair_id) {
+    ASSERT_GT(clients_.size(), pair_id);
+    LinkLayerPacketView view = NextPacket();
+    client_opcodes_[pair_id] = CommandView::GetCommand(view).GetOpcode();
+    clients_[pair_id].IncomingPacket(view);
+  }
+
+  void SendFromServer(size_t pair_id) {
+    ASSERT_GT(servers_.size(), pair_id);
+    LinkLayerPacketView view = NextPacket();
+    server_opcodes_[pair_id] = CommandView::GetCommand(view).GetOpcode();
+    servers_[pair_id].IncomingPacket(view);
+  }
+
+  void ReadFromClient(size_t pair_id) {
+    ASSERT_GT(clients_.size(), pair_id);
+    size_t validated_packets = validated_server_packets_[pair_id];
+    for (size_t tries = 0; tries < 10 && validated_server_packets_[pair_id] == validated_packets; tries++) {
+      clients_[pair_id].TimerTick();
+    }
+    ASSERT_EQ(validated_server_packets_[pair_id], validated_packets + 1);
+  }
+
+  void ReadFromServer(size_t pair_id) {
+    ASSERT_GT(servers_.size(), pair_id);
+    size_t validated_packets = validated_client_packets_[pair_id];
+    for (size_t tries = 0; tries < 10 && validated_client_packets_[pair_id] == validated_packets; tries++) {
+      servers_[pair_id].TimerTick();
+    }
+    ASSERT_EQ(validated_client_packets_[pair_id], validated_packets + 1);
+  }
+
+ private:
+  uint16_t packet_id_{1};
+  AsyncManager async_manager_;
+  int socket_fd_;
+  std::vector<LinkLayerSocketDevice> servers_;
+  std::vector<LinkLayerSocketDevice> clients_;
+  uint16_t server_opcodes_[kMaxConnections]{0};
+  uint16_t client_opcodes_[kMaxConnections]{0};
+  size_t validated_server_packets_[kMaxConnections]{0};
+  size_t validated_client_packets_[kMaxConnections]{0};
+  Address source_{{1, 2, 3, 4, 5, 6}};
+  Address dest_{{6, 5, 4, 3, 2, 1}};
+};
+
+TEST_F(LinkLayerSocketDeviceTest, TestClientFirst) {
+  size_t pair_id = CreateConnection();
+  ASSERT_EQ(pair_id, 0u);
+  ValidateConnection(pair_id);
+
+  SendFromClient(pair_id);
+  ReadFromServer(pair_id);
+}
+
+TEST_F(LinkLayerSocketDeviceTest, TestServerFirst) {
+  size_t pair_id = CreateConnection();
+  ASSERT_EQ(pair_id, 0u);
+
+  SendFromServer(pair_id);
+  ReadFromClient(pair_id);
+}
+
+TEST_F(LinkLayerSocketDeviceTest, TestMultiplePackets) {
+  static const int num_packets = 30;
+  size_t pair_id = CreateConnection();
+  ASSERT_EQ(pair_id, 0u);
+  for (int i = 0; i < num_packets; i++) {
+    SendFromClient(pair_id);
+    SendFromServer(pair_id);
+    ReadFromServer(pair_id);
+    ReadFromClient(pair_id);
+  }
+}
+
+TEST_F(LinkLayerSocketDeviceTest, TestMultipleConnectionsFromServer) {
+  static size_t last_pair_id = -1;
+  size_t pair_id;
+  for (size_t i = 0; i < kMaxConnections; i++) {
+    pair_id = CreateConnection();
+    ASSERT_EQ(pair_id, last_pair_id + 1);
+    last_pair_id = pair_id;
+    SendFromServer(pair_id);
+    ReadFromClient(pair_id);
+  }
+}
+
+TEST_F(LinkLayerSocketDeviceTest, TestMultipleConnectionsFromClient) {
+  for (size_t i = 0; i < kMaxConnections; i++) {
+    size_t pair_id = CreateConnection();
+    ASSERT_EQ(pair_id, i);
+    SendFromClient(pair_id);
+    ReadFromServer(pair_id);
+  }
+}
+
+TEST_F(LinkLayerSocketDeviceTest, TestMultipleConnections) {
+  for (size_t i = 0; i < kMaxConnections; i++) {
+    size_t pair_id = CreateConnection();
+    ASSERT_EQ(pair_id, i);
+    SendFromClient(pair_id);
+    SendFromServer(pair_id);
+    ReadFromClient(pair_id);
+    ReadFromServer(pair_id);
+  }
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/packet_builder_test.cc b/vendor_libs/test_vendor_lib/test/packet_builder_test.cc
new file mode 100644
index 0000000..60e5d95
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/test/packet_builder_test.cc
@@ -0,0 +1,244 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "packets/packet_builder.h"
+
+#include <gtest/gtest.h>
+#include <forward_list>
+#include <memory>
+
+using std::vector;
+
+namespace {
+vector<uint8_t> count_all = {
+    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+    0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+
+vector<uint8_t> count_1 = {
+    0x00,
+    0x01,
+    0x02,
+};
+
+vector<uint8_t> count_2 = {
+    0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c,
+};
+
+vector<uint8_t> count_3 = {
+    0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+};
+}  // namespace
+
+namespace test_vendor_lib {
+namespace packets {
+
+template <bool little_endian>
+class EndianBuilder : public PacketBuilder<little_endian> {
+ public:
+  EndianBuilder(uint8_t byte, uint16_t two_bytes, uint32_t four_bytes, uint64_t eight_bytes)
+      : byte_(byte), two_bytes_(two_bytes), four_bytes_(four_bytes), eight_bytes_(eight_bytes) {}
+  ~EndianBuilder() = default;
+
+  virtual size_t size() const override {
+    return sizeof(signature_) + sizeof(byte_) + sizeof(two_bytes_) + sizeof(four_bytes_) + sizeof(eight_bytes_);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    PacketBuilder<little_endian>::insert(signature_, it);
+    PacketBuilder<little_endian>::insert(byte_, it);
+    PacketBuilder<little_endian>::insert(two_bytes_, it);
+    PacketBuilder<little_endian>::insert(four_bytes_, it);
+    PacketBuilder<little_endian>::insert(eight_bytes_, it);
+  }
+
+ private:
+  uint32_t signature_{(little_endian ? 0x03020100 : 0x00010203)};
+  uint8_t byte_;
+  uint16_t two_bytes_;
+  uint32_t four_bytes_;
+  uint64_t eight_bytes_;
+};
+
+class PacketBuilderEndianTest : public ::testing::Test {
+ public:
+  PacketBuilderEndianTest() = default;
+  ~PacketBuilderEndianTest() = default;
+};
+
+TEST(PacketBuilderEndianTest, insertTest) {
+  EndianBuilder<true> little(0x04, 0x0605, 0x0a090807, 0x1211100f0e0d0c0b);
+  EndianBuilder<false> big(0x04, 0x0506, 0x0708090a, 0x0b0c0d0e0f101112);
+  ASSERT_EQ(*big.FinalPacket(), *little.FinalPacket());
+}
+
+template <typename T>
+class VectorBuilder : public PacketBuilder<true> {
+ public:
+  VectorBuilder(std::vector<uint64_t> vect) {
+    for (uint64_t element : vect) {
+      vect.push_back(static_cast<T>(element));
+    }
+  }
+  ~VectorBuilder() = default;
+
+  virtual size_t size() const override {
+    return vect_.size() * sizeof(T);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    PacketBuilder<true>::insert_vector(vect_, it);
+  }
+
+ private:
+  std::vector<T> vect_;
+};
+
+template <typename T>
+class InsertElementsBuilder : public PacketBuilder<true> {
+ public:
+  InsertElementsBuilder(std::vector<uint64_t> vect) {
+    for (uint64_t element : vect) {
+      vect.push_back(static_cast<T>(element));
+    }
+  }
+  virtual ~InsertElementsBuilder() = default;
+
+  virtual size_t size() const override {
+    return vect_.size() * sizeof(T);
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    for (T elem : vect_) {
+      PacketBuilder<true>::insert(elem, it);
+    }
+  }
+
+ private:
+  std::vector<T> vect_;
+};
+
+std::vector<uint64_t> vector_data{
+    0x7060504030201000, 0x7161514131211101, 0x7262524232221202, 0x7363534333231303, 0x7464544434241404,
+    0x7565554535251505, 0x7666564636261606, 0x7767574737271707, 0x7868584838281808,
+};
+
+template <typename T>
+class VectorBuilderTest : public ::testing::Test {
+ public:
+  VectorBuilderTest() = default;
+  ~VectorBuilderTest() = default;
+
+  void SetUp() {
+    packet_1_ = std::shared_ptr<VectorBuilder<T>>(new VectorBuilder<T>(vector_data));
+    packet_2_ = std::shared_ptr<InsertElementsBuilder<T>>(new InsertElementsBuilder<T>(vector_data));
+  }
+
+  void TearDown() {
+    packet_1_.reset();
+    packet_2_.reset();
+  }
+
+  std::shared_ptr<VectorBuilder<T>> packet_1_;
+  std::shared_ptr<InsertElementsBuilder<T>> packet_2_;
+};
+
+using VectorBaseTypes = ::testing::Types<uint8_t, uint16_t, uint32_t, uint64_t, int8_t, int16_t, int32_t, int64_t>;
+TYPED_TEST_CASE(VectorBuilderTest, VectorBaseTypes);
+
+TYPED_TEST(VectorBuilderTest, insertVectorTest) {
+  ASSERT_EQ(*(this->packet_1_->FinalPacket()), *(this->packet_2_->FinalPacket()));
+}
+
+class NestedBuilder : public PacketBuilder<true> {
+ public:
+  ~NestedBuilder() = default;
+
+  virtual size_t size() const override {
+    size_t payload_size = (payload_ ? payload_->size() : 0);
+    return 1 + payload_size;
+  }
+
+  static std::unique_ptr<NestedBuilder> Create(uint8_t level) {
+    return std::unique_ptr<NestedBuilder>(new NestedBuilder(level));
+  }
+
+  static std::unique_ptr<NestedBuilder> CreateNested(std::unique_ptr<BasePacketBuilder> payload, uint8_t level) {
+    return std::unique_ptr<NestedBuilder>(new NestedBuilder(std::move(payload), level));
+  }
+
+  virtual const std::unique_ptr<std::vector<uint8_t>> FinalPacket() {
+    std::unique_ptr<std::vector<uint8_t>> packet = std::make_unique<std::vector<uint8_t>>();
+    packet->reserve(size());
+    std::back_insert_iterator<std::vector<uint8_t>> it(*packet);
+    Serialize(it);
+    return packet;
+  }
+
+  virtual void Serialize(std::back_insert_iterator<std::vector<uint8_t>> it) const override {
+    PacketBuilder<true>::insert(level_, it);
+    if (payload_) {
+      payload_->Serialize(it);
+    }
+  }
+
+ private:
+  std::unique_ptr<BasePacketBuilder> payload_;
+  uint8_t level_;
+
+  NestedBuilder(std::unique_ptr<BasePacketBuilder> inner, uint8_t level) : payload_(std::move(inner)), level_(level) {}
+  NestedBuilder(uint8_t level) : level_(level) {}
+};
+
+class BuilderBuilderTest : public ::testing::Test {};
+
+TEST(BuilderBuilderTest, nestingTest) {
+  std::unique_ptr<BasePacketBuilder> innermost = NestedBuilder::Create(0);
+  std::unique_ptr<BasePacketBuilder> number_1 = NestedBuilder::CreateNested(std::move(innermost), 1);
+  std::unique_ptr<BasePacketBuilder> number_2 = NestedBuilder::CreateNested(std::move(number_1), 2);
+  std::unique_ptr<BasePacketBuilder> number_3 = NestedBuilder::CreateNested(std::move(number_2), 3);
+  std::unique_ptr<BasePacketBuilder> number_4 = NestedBuilder::CreateNested(std::move(number_3), 4);
+  std::unique_ptr<NestedBuilder> number_5 = NestedBuilder::CreateNested(std::move(number_4), 5);
+
+  std::vector<uint8_t> count_down{5, 4, 3, 2, 1, 0};
+  ASSERT_EQ(*number_5->FinalPacket(), count_down);
+}
+}  // namespace packets
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc b/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc
index 3908b9e..375c090 100644
--- a/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc
+++ b/vendor_libs/test_vendor_lib/test/packet_stream_unittest.cc
@@ -69,8 +69,7 @@
     write(socketpair_fds_[1], &packet[1], packet.size());
 
     // Read the command packet.
-    std::unique_ptr<CommandPacket> command =
-        packet_stream_.ReceiveCommand(socketpair_fds_[0]);
+    std::unique_ptr<CommandPacket> command = packet_stream_.ReceiveCommand(socketpair_fds_[0]);
 
     const vector<uint8_t> received_payload = command->GetPayload();
 
@@ -81,8 +80,7 @@
     EXPECT_EQ(opcode, command->GetOpcode());
     EXPECT_EQ(static_cast<size_t>(payload_size + 1), command->GetPayloadSize());
     EXPECT_EQ(payload_size, received_payload[0]);
-    for (int i = 0; i < payload_size; ++i)
-      EXPECT_EQ(packet[4 + i], received_payload[i + 1]);
+    for (int i = 0; i < payload_size; ++i) EXPECT_EQ(packet[4 + i], received_payload[i + 1]);
   }
 
   void CheckedSendEvent(std::unique_ptr<EventPacket> event) {
@@ -108,10 +106,8 @@
     EXPECT_EQ(expected_size, sizeof(event_header) + return_parameters_size + 1);
     EXPECT_EQ(DATA_TYPE_EVENT, event_header[0]);
     EXPECT_EQ(expected_code, event_header[1]);
-    EXPECT_EQ(expected_payload_size,
-              static_cast<size_t>(return_parameters_size) + 1);
-    for (int i = 0; i < return_parameters_size; ++i)
-      EXPECT_EQ(expected_payload[i + 1], return_parameters[i]);
+    EXPECT_EQ(expected_payload_size, static_cast<size_t>(return_parameters_size) + 1);
+    for (int i = 0; i < return_parameters_size; ++i) EXPECT_EQ(expected_payload[i + 1], return_parameters[i]);
   }
 
  protected:
@@ -147,8 +143,7 @@
 
 TEST_F(PacketStreamTest, SendEvent) {
   const vector<uint8_t> return_parameters = {0};
-  CheckedSendEvent(
-      EventPacket::CreateCommandCompleteEvent(HCI_RESET, return_parameters));
+  CheckedSendEvent(EventPacket::CreateCommandCompleteEvent(HCI_RESET, return_parameters));
 }
 
 }  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/polled_socket_test.cc b/vendor_libs/test_vendor_lib/test/polled_socket_test.cc
new file mode 100644
index 0000000..268093e
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/test/polled_socket_test.cc
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "polled_socket.h"
+
+#include <gtest/gtest.h>
+#include <cstdint>
+#include <cstring>
+#include <vector>
+
+#include <netdb.h>
+#include <netinet/in.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+namespace test_vendor_lib {
+namespace net {
+
+class PolledSocketTest : public ::testing::Test {
+ public:
+  static const uint16_t kPort = 6124;
+  static const size_t kBufferSize = 16;
+
+ protected:
+  void SetUp() override {
+    server_.Initialize(kPort);
+    client_.SetServerName("localhost");
+    client_.Initialize(kPort);
+  }
+
+  void TearDown() override {}
+
+  void ConnectClient() {}
+
+  PolledSocketServer server_;
+  PolledSocketClient client_;
+
+ private:
+  std::vector<uint8_t> server_buffer_;
+  std::vector<uint8_t> client_buffer_;
+};
+
+TEST_F(PolledSocketTest, SetUpTearDown) {}
+
+TEST_F(PolledSocketTest, TestOneConnection) {
+  std::vector<uint8_t> tx_buf = {'1', '2', '3'};
+  std::vector<uint8_t> rx_buf(10);
+
+  client_.Send(tx_buf);
+  server_.Receive(3, rx_buf.data());
+  client_.Send(tx_buf);
+  server_.Receive(3, rx_buf.data());
+  EXPECT_EQ(rx_buf.size(), tx_buf.size());
+}
+
+#if 0
+TEST_F(PolledSocketTest, TestRepeatedConnections) {
+  static const int num_connections = 300;
+  for (int i = 0; i < num_connections; i++) {
+    int socket_cli_fd = ConnectClient();
+    WriteFromClient(socket_cli_fd);
+    AwaitServerResponse(socket_cli_fd);
+    close(socket_cli_fd);
+  }
+}
+
+TEST_F(PolledSocketTest, TestMultipleConnections) {
+  static const int num_connections = 300;
+  int socket_cli_fd[num_connections];
+  for (int i = 0; i < num_connections; i++) {
+    socket_cli_fd[i] = ConnectClient();
+    EXPECT_TRUE(socket_cli_fd[i] > 0);
+    WriteFromClient(socket_cli_fd[i]);
+  }
+  for (int i = 0; i < num_connections; i++) {
+    AwaitServerResponse(socket_cli_fd[i]);
+    close(socket_cli_fd[i]);
+  }
+}
+
+#endif
+}  // namespace net
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc b/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc
new file mode 100644
index 0000000..8fa3a03
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/test/security_manager_unittest.cc
@@ -0,0 +1,166 @@
+/******************************************************************************
+ *
+ *  Copyright 2017 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+#include <string>
+#include <vector>
+using std::vector;
+
+#include "model/controller/security_manager.h"
+
+namespace {
+const std::string kTestAddr1 = "12:34:56:78:9a:bc";
+const std::string kTestAddr2 = "cb:a9:87:65:43:21";
+const std::string kTestAddr3 = "cb:a9:56:78:9a:bc";
+const std::string kTestAddr4 = "12:34:56:78:9a:bc";
+const vector<uint8_t> kZeros_octets = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+const vector<uint8_t> kTestAddr1_octets = {0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12};
+const vector<uint8_t> kTestKey = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
+                                  0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10};
+}  // namespace
+
+namespace test_vendor_lib {
+
+class SecurityManagerTest : public ::testing::Test {
+ public:
+  SecurityManagerTest() {}
+  ~SecurityManagerTest() {}
+};
+
+TEST_F(SecurityManagerTest, WriteKey) {
+  Address btaddr1;
+  Address btaddr2;
+  Address btaddr3;
+  Address btaddr4;
+  SecurityManager sm(3);
+
+  Address::FromString(kTestAddr1, btaddr1);
+  Address::FromString(kTestAddr2, btaddr2);
+  Address::FromString(kTestAddr3, btaddr3);
+  Address::FromString(kTestAddr4, btaddr4);
+
+  EXPECT_EQ(1, sm.WriteKey(btaddr1, kTestKey));
+  EXPECT_EQ(1, sm.WriteKey(btaddr2, kTestKey));
+  EXPECT_EQ(1, sm.WriteKey(btaddr3, kTestKey));
+  // Key storage is full.
+  EXPECT_EQ(0, sm.WriteKey(btaddr4, kTestKey));
+}
+
+TEST_F(SecurityManagerTest, ReadKey) {
+  Address btaddr1;
+  Address btaddr2;
+  Address btaddr3;
+  SecurityManager sm(3);
+
+  Address::FromString(kTestAddr1, btaddr1);
+  Address::FromString(kTestAddr2, btaddr2);
+  Address::FromString(kTestAddr3, btaddr3);
+
+  sm.WriteKey(btaddr1, kTestKey);
+  sm.WriteKey(btaddr2, kTestKey);
+
+  EXPECT_EQ(1, sm.ReadKey(btaddr1));
+  EXPECT_EQ(1, sm.ReadKey(btaddr2));
+  EXPECT_EQ(0, sm.ReadKey(btaddr3));
+}
+
+TEST_F(SecurityManagerTest, ReadAllKeys) {
+  Address btaddr1;
+  Address btaddr2;
+  SecurityManager sm(3);
+
+  EXPECT_EQ(0, sm.ReadAllKeys());
+
+  Address::FromString(kTestAddr1, btaddr1);
+  Address::FromString(kTestAddr2, btaddr1);
+  Address::FromString(kTestAddr3, btaddr1);
+
+  sm.WriteKey(btaddr1, kTestKey);
+
+  EXPECT_EQ(1, sm.ReadAllKeys());
+
+  sm.WriteKey(btaddr2, kTestKey);
+
+  EXPECT_EQ(2, sm.ReadAllKeys());
+}
+
+TEST_F(SecurityManagerTest, DeleteKey) {
+  Address btaddr1;
+  Address btaddr2;
+  Address btaddr3;
+  SecurityManager sm(3);
+
+  Address::FromString(kTestAddr1, btaddr1);
+  Address::FromString(kTestAddr2, btaddr2);
+  Address::FromString(kTestAddr3, btaddr3);
+
+  EXPECT_EQ(0, sm.DeleteKey(btaddr2));
+
+  sm.WriteKey(btaddr1, kTestKey);
+
+  EXPECT_EQ(1, sm.ReadAllKeys());
+
+  EXPECT_EQ(1, sm.DeleteKey(btaddr1));
+
+  EXPECT_EQ(0, sm.ReadAllKeys());
+
+  sm.WriteKey(btaddr1, kTestKey);
+  sm.WriteKey(btaddr2, kTestKey);
+
+  EXPECT_EQ(2, sm.ReadAllKeys());
+
+  EXPECT_EQ(1, sm.DeleteKey(btaddr2));
+
+  EXPECT_EQ(1, sm.ReadAllKeys());
+
+  EXPECT_EQ(0, sm.DeleteKey(btaddr2));
+
+  EXPECT_EQ(1, sm.ReadAllKeys());
+}
+
+TEST_F(SecurityManagerTest, DeleteAllKeys) {
+  Address btaddr1;
+  Address btaddr2;
+  Address btaddr3;
+  SecurityManager sm(3);
+
+  Address::FromString(kTestAddr1, btaddr1);
+  Address::FromString(kTestAddr2, btaddr2);
+  Address::FromString(kTestAddr3, btaddr3);
+
+  EXPECT_EQ(0, sm.DeleteAllKeys());
+
+  sm.WriteKey(btaddr1, kTestKey);
+
+  EXPECT_EQ(1, sm.ReadAllKeys());
+
+  EXPECT_EQ(1, sm.DeleteAllKeys());
+
+  EXPECT_EQ(0, sm.ReadAllKeys());
+
+  sm.WriteKey(btaddr1, kTestKey);
+  sm.WriteKey(btaddr2, kTestKey);
+
+  EXPECT_EQ(2, sm.ReadAllKeys());
+
+  EXPECT_EQ(2, sm.DeleteAllKeys());
+
+  EXPECT_EQ(0, sm.ReadAllKeys());
+}
+
+}  // namespace test_vendor_lib
diff --git a/vendor_libs/test_vendor_lib/types/Android.bp b/vendor_libs/test_vendor_lib/types/Android.bp
new file mode 100644
index 0000000..07198e9
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/Android.bp
@@ -0,0 +1,41 @@
+// Bluetooth types
+cc_library_headers {
+    name: "libbt-rootcanal-types-header",
+    export_include_dirs: ["./"],
+    vendor_available: true,
+    host_supported: true,
+}
+
+cc_library_static {
+    name: "libbt-rootcanal-types",
+    vendor_available: true,
+    defaults: ["fluoride_types_defaults"],
+    cflags: [
+        /* we export all classes, so change default visibility, instead of having EXPORT_SYMBOL on each class*/
+        "-fvisibility=default",
+    ],
+    host_supported: true,
+    srcs: [
+        "class_of_device.cc",
+        "address.cc",
+        "bluetooth/uuid.cc",
+    ],
+    header_libs: ["libbt-rootcanal-types-header"],
+    export_header_lib_headers: ["libbt-rootcanal-types-header"],
+}
+
+// ========================================================
+cc_test {
+    name: "rootcanal-test_types",
+    test_suites: ["device-tests"],
+    defaults: ["fluoride_defaults"],
+    host_supported: true,
+    srcs: [
+        "test/class_of_device_unittest.cc",
+        "test/address_unittest.cc",
+        "test/bluetooth/uuid_unittest.cc",
+    ],
+    static_libs: [
+        "libbt-rootcanal-types",
+    ],
+}
diff --git a/tools/mcap_tool/BUILD.gn b/vendor_libs/test_vendor_lib/types/BUILD.gn
similarity index 60%
copy from tools/mcap_tool/BUILD.gn
copy to vendor_libs/test_vendor_lib/types/BUILD.gn
index d41ed56..68f76e3 100644
--- a/tools/mcap_tool/BUILD.gn
+++ b/vendor_libs/test_vendor_lib/types/BUILD.gn
@@ -13,32 +13,50 @@
 #  See the License for the specific language governing permissions and
 #  limitations under the License.
 #
-executable("mcap_tool") {
-  testonly = true
-  sources = [
-    "mcap_tool.cc",
-    "mcap_test_app.cc",
-    "mcap_test_mcl.cc",
-    "mcap_test_mdep.cc",
-    "mcap_test_mdl.cc",
+
+static_library("types") {
+  cflags = [
+     "-fvisibility=default",
   ]
+
+  sources = [
+    "bluetooth/uuid.cc",
+    "le_address.cc",
+    "address.cc",
+  ]
+
   include_dirs = [
     "//",
-    "//internal_include",
-    "//stack/include",
-    "//btif/include",
-    "//btcore/include",
-    "//tools/mcap_tool",
   ]
-  libs = [
-    "-lpthread",
-    "-lrt",
-    "-ldl",
-  ]
+
   deps = [
-    "//btcore",
-    "//osi",
     "//third_party/libchrome:base",
+  ]
+}
+
+executable("types_unittests") {
+  testonly = true
+  sources = [
+    "test/address_unittest.cc",
+    "test/bluetooth/uuid_unittest.cc",
+  ]
+
+  include_dirs = [
+    "//",
+  ]
+
+  libs = [
+     "-ldl",
+     "-lpthread",
+     "-lresolv",
+     "-lrt",
+     "-lz",
+     "-latomic",
+  ]
+
+  deps = [
     "//types",
+    "//third_party/googletest:gmock_main",
+    "//third_party/libchrome:base",
   ]
 }
diff --git a/vendor_libs/test_vendor_lib/types/address.cc b/vendor_libs/test_vendor_lib/types/address.cc
new file mode 100644
index 0000000..b3c1db4
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/address.cc
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ *  Copyright 2017 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "address.h"
+
+#include <base/strings/string_split.h>
+#include <base/strings/stringprintf.h>
+#include <stdint.h>
+#include <algorithm>
+#include <vector>
+
+static_assert(sizeof(Address) == 6, "Address must be 6 bytes long!");
+
+const Address Address::kAny{{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}};
+const Address Address::kEmpty{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+
+Address::Address(const uint8_t (&addr)[6]) {
+  std::copy(addr, addr + kLength, address);
+};
+
+std::string Address::ToString() const {
+  return base::StringPrintf("%02x:%02x:%02x:%02x:%02x:%02x", address[5], address[4], address[3], address[2], address[1],
+                            address[0]);
+}
+
+bool Address::FromString(const std::string& from, Address& to) {
+  Address new_addr;
+  if (from.length() != 17) return false;
+
+  std::vector<std::string> byte_tokens = base::SplitString(from, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (byte_tokens.size() != 6) return false;
+
+  for (int i = 0; i < 6; i++) {
+    const auto& token = byte_tokens[i];
+
+    if (token.length() != 2) return false;
+
+    char* temp = nullptr;
+    new_addr.address[5 - i] = strtol(token.c_str(), &temp, 16);
+    if (*temp != '\0') return false;
+  }
+
+  to = new_addr;
+  return true;
+}
+
+size_t Address::FromOctets(const uint8_t* from) {
+  std::copy(from, from + kLength, address);
+  return kLength;
+};
+
+bool Address::IsValidAddress(const std::string& address) {
+  Address tmp;
+  return Address::FromString(address, tmp);
+}
diff --git a/vendor_libs/test_vendor_lib/types/address.h b/vendor_libs/test_vendor_lib/types/address.h
new file mode 100644
index 0000000..1aa8c97
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/address.h
@@ -0,0 +1,76 @@
+/******************************************************************************
+ *
+ *  Copyright 2017 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <string>
+
+/** Bluetooth Address */
+class Address final {
+ public:
+  static constexpr unsigned int kLength = 6;
+
+  uint8_t address[kLength];
+
+  Address() = default;
+  Address(const uint8_t (&addr)[6]);
+
+  bool operator<(const Address& rhs) const {
+    return (std::memcmp(address, rhs.address, sizeof(address)) < 0);
+  }
+  bool operator==(const Address& rhs) const {
+    return (std::memcmp(address, rhs.address, sizeof(address)) == 0);
+  }
+  bool operator>(const Address& rhs) const {
+    return (rhs < *this);
+  }
+  bool operator<=(const Address& rhs) const {
+    return !(*this > rhs);
+  }
+  bool operator>=(const Address& rhs) const {
+    return !(*this < rhs);
+  }
+  bool operator!=(const Address& rhs) const {
+    return !(*this == rhs);
+  }
+
+  bool IsEmpty() const {
+    return *this == kEmpty;
+  }
+
+  std::string ToString() const;
+
+  // Converts |string| to Address and places it in |to|. If |from| does
+  // not represent a Bluetooth address, |to| is not modified and this function
+  // returns false. Otherwise, it returns true.
+  static bool FromString(const std::string& from, Address& to);
+
+  // Copies |from| raw Bluetooth address octets to the local object.
+  // Returns the number of copied octets - should be always Address::kLength
+  size_t FromOctets(const uint8_t* from);
+
+  static bool IsValidAddress(const std::string& address);
+
+  static const Address kEmpty;  // 00:00:00:00:00:00
+  static const Address kAny;    // FF:FF:FF:FF:FF:FF
+};
+
+inline std::ostream& operator<<(std::ostream& os, const Address& a) {
+  os << a.ToString();
+  return os;
+}
diff --git a/vendor_libs/test_vendor_lib/types/bluetooth/uuid.cc b/vendor_libs/test_vendor_lib/types/bluetooth/uuid.cc
new file mode 100644
index 0000000..7739f41
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/bluetooth/uuid.cc
@@ -0,0 +1,174 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "uuid.h"
+
+#include <base/rand_util.h>
+#include <base/strings/stringprintf.h>
+#include <algorithm>
+
+namespace bluetooth {
+
+static_assert(sizeof(Uuid) == 16, "Uuid must be 16 bytes long!");
+
+using UUID128Bit = Uuid::UUID128Bit;
+
+const Uuid Uuid::kEmpty = Uuid::From128BitBE(UUID128Bit{{0x00}});
+
+namespace {
+constexpr Uuid kBase = Uuid::From128BitBE(
+    UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}});
+}  // namespace
+
+size_t Uuid::GetShortestRepresentationSize() const {
+  if (memcmp(uu.data() + kNumBytes32, kBase.uu.data() + kNumBytes32, kNumBytes128 - kNumBytes32) != 0) {
+    return kNumBytes128;
+  }
+
+  if (uu[0] == 0 && uu[1] == 0) return kNumBytes16;
+
+  return kNumBytes32;
+}
+
+bool Uuid::Is16Bit() const {
+  return GetShortestRepresentationSize() == kNumBytes16;
+}
+
+uint16_t Uuid::As16Bit() const {
+  return (((uint16_t)uu[2]) << 8) + uu[3];
+}
+
+uint32_t Uuid::As32Bit() const {
+  return (((uint32_t)uu[0]) << 24) + (((uint32_t)uu[1]) << 16) + (((uint32_t)uu[2]) << 8) + uu[3];
+}
+
+Uuid Uuid::FromString(const std::string& uuid, bool* is_valid) {
+  if (is_valid) *is_valid = false;
+  Uuid ret = kBase;
+
+  if (uuid.empty()) return ret;
+
+  uint8_t* p = ret.uu.data();
+  if (uuid.size() == kString128BitLen) {
+    if (uuid[8] != '-' || uuid[13] != '-' || uuid[18] != '-' || uuid[23] != '-') {
+      return ret;
+    }
+
+    int c;
+    int rc = sscanf(uuid.c_str(),
+                    "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx"
+                    "-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx%n",
+                    &p[0], &p[1], &p[2], &p[3], &p[4], &p[5], &p[6], &p[7], &p[8], &p[9], &p[10], &p[11], &p[12],
+                    &p[13], &p[14], &p[15], &c);
+    if (rc != 16) return ret;
+    if (c != kString128BitLen) return ret;
+
+    if (is_valid) *is_valid = true;
+  } else if (uuid.size() == 8) {
+    int c;
+    int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%02hhx%02hhx%n", &p[0], &p[1], &p[2], &p[3], &c);
+    if (rc != 4) return ret;
+    if (c != 8) return ret;
+
+    if (is_valid) *is_valid = true;
+  } else if (uuid.size() == 4) {
+    int c;
+    int rc = sscanf(uuid.c_str(), "%02hhx%02hhx%n", &p[2], &p[3], &c);
+    if (rc != 2) return ret;
+    if (c != 4) return ret;
+
+    if (is_valid) *is_valid = true;
+  }
+
+  return ret;
+}
+
+Uuid Uuid::From16Bit(uint16_t uuid16) {
+  Uuid u = kBase;
+
+  u.uu[2] = (uint8_t)((0xFF00 & uuid16) >> 8);
+  u.uu[3] = (uint8_t)(0x00FF & uuid16);
+  return u;
+}
+
+Uuid Uuid::From32Bit(uint32_t uuid32) {
+  Uuid u = kBase;
+
+  u.uu[0] = (uint8_t)((0xFF000000 & uuid32) >> 24);
+  u.uu[1] = (uint8_t)((0x00FF0000 & uuid32) >> 16);
+  u.uu[2] = (uint8_t)((0x0000FF00 & uuid32) >> 8);
+  u.uu[3] = (uint8_t)(0x000000FF & uuid32);
+  return u;
+}
+
+Uuid Uuid::From128BitBE(const uint8_t* uuid) {
+  UUID128Bit tmp;
+  memcpy(tmp.data(), uuid, kNumBytes128);
+  return From128BitBE(tmp);
+}
+
+Uuid Uuid::From128BitLE(const UUID128Bit& uuid) {
+  Uuid u;
+  std::reverse_copy(uuid.data(), uuid.data() + kNumBytes128, u.uu.begin());
+  return u;
+}
+
+Uuid Uuid::From128BitLE(const uint8_t* uuid) {
+  UUID128Bit tmp;
+  memcpy(tmp.data(), uuid, kNumBytes128);
+  return From128BitLE(tmp);
+}
+
+const UUID128Bit Uuid::To128BitLE() const {
+  UUID128Bit le;
+  std::reverse_copy(uu.data(), uu.data() + kNumBytes128, le.begin());
+  return le;
+}
+
+const UUID128Bit& Uuid::To128BitBE() const {
+  return uu;
+}
+
+Uuid Uuid::GetRandom() {
+  Uuid uuid;
+  base::RandBytes(uuid.uu.data(), uuid.uu.size());
+  return uuid;
+}
+
+bool Uuid::IsEmpty() const {
+  return *this == kEmpty;
+}
+
+bool Uuid::operator<(const Uuid& rhs) const {
+  return std::lexicographical_compare(uu.begin(), uu.end(), rhs.uu.begin(), rhs.uu.end());
+}
+
+bool Uuid::operator==(const Uuid& rhs) const {
+  return uu == rhs.uu;
+}
+
+bool Uuid::operator!=(const Uuid& rhs) const {
+  return uu != rhs.uu;
+}
+
+std::string Uuid::ToString() const {
+  return base::StringPrintf("%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", uu[0], uu[1], uu[2],
+                            uu[3], uu[4], uu[5], uu[6], uu[7], uu[8], uu[9], uu[10], uu[11], uu[12], uu[13], uu[14],
+                            uu[15]);
+}
+}  // namespace bluetooth
\ No newline at end of file
diff --git a/vendor_libs/test_vendor_lib/types/bluetooth/uuid.h b/vendor_libs/test_vendor_lib/types/bluetooth/uuid.h
new file mode 100644
index 0000000..58a7da2
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/bluetooth/uuid.h
@@ -0,0 +1,139 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <stdint.h>
+#include <array>
+#include <string>
+
+namespace bluetooth {
+
+// This class is representing Bluetooth UUIDs across whole stack.
+// Here are some general endianness rules:
+// 1. UUID is internally kept as as Big Endian.
+// 2. Bytes representing UUID coming from upper layers, Java or Binder, are Big
+//    Endian.
+// 3. Bytes representing UUID coming from lower layer, HCI packets, are Little
+//    Endian.
+// 4. UUID in storage is always string.
+class Uuid final {
+ public:
+  static constexpr size_t kNumBytes128 = 16;
+  static constexpr size_t kNumBytes32 = 4;
+  static constexpr size_t kNumBytes16 = 2;
+
+  static constexpr size_t kString128BitLen = 36;
+
+  static const Uuid kEmpty;  // 00000000-0000-0000-0000-000000000000
+
+  using UUID128Bit = std::array<uint8_t, kNumBytes128>;
+
+  Uuid() = default;
+
+  // Creates and returns a random 128-bit UUID.
+  static Uuid GetRandom();
+
+  // Returns the shortest possible representation of this UUID in bytes. Either
+  // kNumBytes16, kNumBytes32, or kNumBytes128
+  size_t GetShortestRepresentationSize() const;
+
+  // Returns true if this UUID can be represented as 16 bit.
+  bool Is16Bit() const;
+
+  // Returns 16 bit Little Endian representation of this UUID. Use
+  // GetShortestRepresentationSize() or Is16Bit() before using this method.
+  uint16_t As16Bit() const;
+
+  // Returns 32 bit Little Endian representation of this UUID. Use
+  // GetShortestRepresentationSize() before using this method.
+  uint32_t As32Bit() const;
+
+  // Converts string representing 128, 32, or 16 bit UUID in
+  // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, xxxxxxxx, or xxxx format to UUID. If
+  // set, optional is_valid parameter will be set to true if conversion is
+  // successfull, false otherwise.
+  static Uuid FromString(const std::string& uuid, bool* is_valid = nullptr);
+
+  // Converts 16bit Little Endian representation of UUID to UUID
+  static Uuid From16Bit(uint16_t uuid16bit);
+
+  // Converts 32bit Little Endian representation of UUID to UUID
+  static Uuid From32Bit(uint32_t uuid32bit);
+
+  // Converts 128 bit Big Endian array representing UUID to UUID.
+  static constexpr Uuid From128BitBE(const UUID128Bit& uuid) {
+    Uuid u(uuid);
+    return u;
+  }
+
+  // Converts 128 bit Big Endian array representing UUID to UUID. |uuid| points
+  // to beginning of array.
+  static Uuid From128BitBE(const uint8_t* uuid);
+
+  // Converts 128 bit Little Endian array representing UUID to UUID.
+  static Uuid From128BitLE(const UUID128Bit& uuid);
+
+  // Converts 128 bit Little Endian array representing UUID to UUID. |uuid|
+  // points to beginning of array.
+  static Uuid From128BitLE(const uint8_t* uuid);
+
+  // Returns 128 bit Little Endian representation of this UUID
+  const UUID128Bit To128BitLE() const;
+
+  // Returns 128 bit Big Endian representation of this UUID
+  const UUID128Bit& To128BitBE() const;
+
+  // Returns string representing this UUID in
+  // xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx format, lowercase.
+  std::string ToString() const;
+
+  // Returns true if this UUID is equal to kEmpty
+  bool IsEmpty() const;
+
+  bool operator<(const Uuid& rhs) const;
+  bool operator==(const Uuid& rhs) const;
+  bool operator!=(const Uuid& rhs) const;
+
+ private:
+  constexpr Uuid(const UUID128Bit& val) : uu{val} {};
+
+  // Network-byte-ordered ID (Big Endian).
+  UUID128Bit uu;
+};
+}  // namespace bluetooth
+
+inline std::ostream& operator<<(std::ostream& os, const bluetooth::Uuid& a) {
+  os << a.ToString();
+  return os;
+}
+
+// Custom std::hash specialization so that bluetooth::UUID can be used as a key
+// in std::unordered_map.
+namespace std {
+
+template <>
+struct hash<bluetooth::Uuid> {
+  std::size_t operator()(const bluetooth::Uuid& key) const {
+    const auto& uuid_bytes = key.To128BitBE();
+    std::hash<std::string> hash_fn;
+    return hash_fn(std::string(reinterpret_cast<const char*>(uuid_bytes.data()), uuid_bytes.size()));
+  }
+};
+
+}  // namespace std
diff --git a/vendor_libs/test_vendor_lib/types/class_of_device.cc b/vendor_libs/test_vendor_lib/types/class_of_device.cc
new file mode 100644
index 0000000..c5f1c3f
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/class_of_device.cc
@@ -0,0 +1,75 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include "class_of_device.h"
+
+#include <base/strings/string_split.h>
+#include <base/strings/stringprintf.h>
+#include <stdint.h>
+#include <algorithm>
+#include <vector>
+
+static_assert(sizeof(ClassOfDevice) == ClassOfDevice::kLength, "ClassOfDevice must be 3 bytes long!");
+
+ClassOfDevice::ClassOfDevice(const uint8_t (&class_of_device)[kLength]) {
+  std::copy(class_of_device, class_of_device + kLength, cod);
+};
+
+std::string ClassOfDevice::ToString() const {
+  return base::StringPrintf("%03x-%01x-%02x", (static_cast<uint16_t>(cod[2]) << 4) | cod[1] >> 4, cod[1] & 0x0f,
+                            cod[0]);
+}
+
+bool ClassOfDevice::FromString(const std::string& from, ClassOfDevice& to) {
+  ClassOfDevice new_cod;
+  if (from.length() != 8) return false;
+
+  std::vector<std::string> byte_tokens = base::SplitString(from, "-", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+
+  if (byte_tokens.size() != 3) return false;
+  if (byte_tokens[0].length() != 3) return false;
+  if (byte_tokens[1].length() != 1) return false;
+  if (byte_tokens[2].length() != 2) return false;
+
+  uint16_t values[3];
+
+  for (size_t i = 0; i < kLength; i++) {
+    const auto& token = byte_tokens[i];
+
+    char* temp = nullptr;
+    values[i] = strtol(token.c_str(), &temp, 16);
+    if (*temp != '\0') return false;
+  }
+
+  new_cod.cod[0] = values[2];
+  new_cod.cod[1] = values[1] | ((values[0] & 0xf) << 4);
+  new_cod.cod[2] = values[0] >> 4;
+
+  to = new_cod;
+  return true;
+}
+
+size_t ClassOfDevice::FromOctets(const uint8_t* from) {
+  std::copy(from, from + kLength, cod);
+  return kLength;
+};
+
+bool ClassOfDevice::IsValid(const std::string& cod) {
+  ClassOfDevice tmp;
+  return ClassOfDevice::FromString(cod, tmp);
+}
diff --git a/vendor_libs/test_vendor_lib/types/class_of_device.h b/vendor_libs/test_vendor_lib/types/class_of_device.h
new file mode 100644
index 0000000..8c2ab37
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/class_of_device.h
@@ -0,0 +1,54 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  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.
+ *
+ ******************************************************************************/
+
+#pragma once
+
+#include <string>
+
+/** Bluetooth Class of Device */
+class ClassOfDevice final {
+ public:
+  static constexpr unsigned int kLength = 3;
+
+  uint8_t cod[kLength];
+
+  ClassOfDevice() = default;
+  ClassOfDevice(const uint8_t (&class_of_device)[kLength]);
+
+  bool operator==(const ClassOfDevice& rhs) const {
+    return (std::memcmp(cod, rhs.cod, sizeof(cod)) == 0);
+  }
+
+  std::string ToString() const;
+
+  // Converts |string| to ClassOfDevice and places it in |to|. If |from| does
+  // not represent a Class of Device, |to| is not modified and this function
+  // returns false. Otherwise, it returns true.
+  static bool FromString(const std::string& from, ClassOfDevice& to);
+
+  // Copies |from| raw Class of Device octets to the local object.
+  // Returns the number of copied octets (always ClassOfDevice::kLength)
+  size_t FromOctets(const uint8_t* from);
+
+  static bool IsValid(const std::string& class_of_device);
+};
+
+inline std::ostream& operator<<(std::ostream& os, const ClassOfDevice& c) {
+  os << c.ToString();
+  return os;
+}
diff --git a/vendor_libs/test_vendor_lib/types/test/address_unittest.cc b/vendor_libs/test_vendor_lib/types/test/address_unittest.cc
new file mode 100644
index 0000000..65fd26d
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/test/address_unittest.cc
@@ -0,0 +1,197 @@
+/******************************************************************************
+ *
+ *  Copyright 2017 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "address.h"
+
+static const char* test_addr = "bc:9a:78:56:34:12";
+static const char* test_addr2 = "21:43:65:87:a9:cb";
+
+TEST(AddressUnittest, test_constructor_array) {
+  Address bdaddr({0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc});
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(AddressUnittest, test_is_empty) {
+  Address empty;
+  Address::FromString("00:00:00:00:00:00", empty);
+  ASSERT_TRUE(empty.IsEmpty());
+
+  Address not_empty;
+  Address::FromString("00:00:00:00:00:01", not_empty);
+  ASSERT_FALSE(not_empty.IsEmpty());
+}
+
+TEST(AddressUnittest, test_to_from_str) {
+  Address bdaddr;
+  Address::FromString(test_addr, bdaddr);
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(AddressUnittest, test_from_octets) {
+  static const uint8_t test_addr_array[] = {0x12, 0x34, 0x56, 0x78, 0x9a, 0xbc};
+
+  Address bdaddr;
+  size_t expected_result = Address::kLength;
+  ASSERT_EQ(expected_result, bdaddr.FromOctets(test_addr_array));
+
+  ASSERT_EQ(0x12, bdaddr.address[0]);
+  ASSERT_EQ(0x34, bdaddr.address[1]);
+  ASSERT_EQ(0x56, bdaddr.address[2]);
+  ASSERT_EQ(0x78, bdaddr.address[3]);
+  ASSERT_EQ(0x9A, bdaddr.address[4]);
+  ASSERT_EQ(0xBC, bdaddr.address[5]);
+
+  std::string ret = bdaddr.ToString();
+
+  ASSERT_STREQ(test_addr, ret.c_str());
+}
+
+TEST(AddressTest, test_equals) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 == bdaddr2);
+  EXPECT_FALSE(bdaddr1 != bdaddr2);
+  EXPECT_TRUE(bdaddr1 == bdaddr1);
+  EXPECT_FALSE(bdaddr1 != bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 == bdaddr3);
+  EXPECT_TRUE(bdaddr2 != bdaddr3);
+}
+
+TEST(AddressTest, test_less_than) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_FALSE(bdaddr1 < bdaddr2);
+  EXPECT_FALSE(bdaddr1 < bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_TRUE(bdaddr2 < bdaddr3);
+  EXPECT_FALSE(bdaddr3 < bdaddr2);
+}
+
+TEST(AddressTest, test_more_than) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_FALSE(bdaddr1 > bdaddr2);
+  EXPECT_FALSE(bdaddr1 > bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 > bdaddr3);
+  EXPECT_TRUE(bdaddr3 > bdaddr2);
+}
+
+TEST(AddressTest, test_less_than_or_equal) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 <= bdaddr2);
+  EXPECT_TRUE(bdaddr1 <= bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_TRUE(bdaddr2 <= bdaddr3);
+  EXPECT_FALSE(bdaddr3 <= bdaddr2);
+}
+
+TEST(AddressTest, test_more_than_or_equal) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address bdaddr3;
+  Address::FromString(test_addr, bdaddr1);
+  Address::FromString(test_addr, bdaddr2);
+  EXPECT_TRUE(bdaddr1 >= bdaddr2);
+  EXPECT_TRUE(bdaddr1 >= bdaddr1);
+
+  Address::FromString(test_addr2, bdaddr3);
+  EXPECT_FALSE(bdaddr2 >= bdaddr3);
+  EXPECT_TRUE(bdaddr3 >= bdaddr2);
+}
+
+TEST(AddressTest, test_copy) {
+  Address bdaddr1;
+  Address bdaddr2;
+  Address::FromString(test_addr, bdaddr1);
+  bdaddr2 = bdaddr1;
+
+  EXPECT_TRUE(bdaddr1 == bdaddr2);
+}
+
+TEST(AddressTest, IsValidAddress) {
+  EXPECT_FALSE(Address::IsValidAddress(""));
+  EXPECT_FALSE(Address::IsValidAddress("000000000000"));
+  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:0000"));
+  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:00:0"));
+  EXPECT_FALSE(Address::IsValidAddress("00:00:00:00:00:0;"));
+  EXPECT_TRUE(Address::IsValidAddress("00:00:00:00:00:00"));
+  EXPECT_TRUE(Address::IsValidAddress("AB:cd:00:00:00:00"));
+  EXPECT_FALSE(Address::IsValidAddress("aB:cD:eF:Gh:iJ:Kl"));
+}
+
+TEST(AddressTest, BdAddrFromString) {
+  Address addr;
+  memset(&addr, 0, sizeof(addr));
+
+  EXPECT_TRUE(Address::FromString("00:00:00:00:00:00", addr));
+  const Address result0 = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};
+  EXPECT_EQ(0, memcmp(&addr, &result0, sizeof(addr)));
+
+  EXPECT_TRUE(Address::FromString("ab:01:4C:d5:21:9f", addr));
+  const Address result1 = {{0x9f, 0x21, 0xd5, 0x4c, 0x01, 0xab}};
+  EXPECT_EQ(0, memcmp(&addr, &result1, sizeof(addr)));
+}
+
+TEST(AddressTest, BdAddrFromStringToStringEquivalent) {
+  std::string address = "c1:c2:c3:d1:d2:d3";
+  Address addr;
+
+  EXPECT_TRUE(Address::FromString(address, addr));
+  EXPECT_EQ(addr.ToString(), address);
+}
diff --git a/vendor_libs/test_vendor_lib/types/test/bluetooth/uuid_unittest.cc b/vendor_libs/test_vendor_lib/types/test/bluetooth/uuid_unittest.cc
new file mode 100644
index 0000000..be2ef10
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/test/bluetooth/uuid_unittest.cc
@@ -0,0 +1,155 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2017 Google, Inc.
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <bluetooth/uuid.h>
+#include <gtest/gtest.h>
+
+using bluetooth::Uuid;
+
+static const Uuid ONES = Uuid::From128BitBE(
+    Uuid::UUID128Bit{{0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11}});
+
+static const Uuid SEQUENTIAL = Uuid::From128BitBE(
+    Uuid::UUID128Bit{{0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67, 0x89}});
+
+constexpr Uuid kBase = Uuid::From128BitBE(
+    Uuid::UUID128Bit{{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb}});
+
+TEST(UuidTest, IsEmpty) {
+  EXPECT_TRUE(Uuid::kEmpty.IsEmpty());
+  EXPECT_FALSE(kBase.IsEmpty());
+}
+
+TEST(UuidTest, GetShortestRepresentationSize) {
+  EXPECT_TRUE(Uuid::kNumBytes16 == kBase.GetShortestRepresentationSize());
+  EXPECT_TRUE(Uuid::kNumBytes32 == Uuid::From32Bit(0x01234567).GetShortestRepresentationSize());
+  EXPECT_TRUE(Uuid::kNumBytes128 == Uuid::kEmpty.GetShortestRepresentationSize());
+}
+
+TEST(UuidTest, As16Bit) {
+  // Even though this is is not 16bit UUID, we should be able to get proper bits
+  EXPECT_EQ((uint16_t)0x1111, ONES.As16Bit());
+  EXPECT_EQ((uint16_t)0x4567, SEQUENTIAL.As16Bit());
+  EXPECT_EQ((uint16_t)0x0000, kBase.As16Bit());
+}
+
+TEST(UuidTest, As32Bit) {
+  // Even though this is is not 32bit UUID, we should be able to get proper bits
+  EXPECT_EQ((uint32_t)0x11111111, ONES.As32Bit());
+  EXPECT_EQ((uint32_t)0x01234567, SEQUENTIAL.As32Bit());
+  EXPECT_EQ((uint32_t)0x00000000, kBase.As32Bit());
+  EXPECT_EQ((uint32_t)0x12345678, Uuid::From32Bit(0x12345678).As32Bit());
+}
+
+TEST(UuidTest, Is16Bit) {
+  EXPECT_FALSE(ONES.Is16Bit());
+  EXPECT_FALSE(SEQUENTIAL.Is16Bit());
+  EXPECT_TRUE(kBase.Is16Bit());
+  EXPECT_TRUE(Uuid::FromString("1ae8").Is16Bit());
+}
+
+TEST(UuidTest, From16Bit) {
+  EXPECT_EQ(Uuid::From16Bit(0x0000), kBase);
+
+  const uint8_t u2[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  Uuid uuid = Uuid::From16Bit(0x0001);
+  EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0);
+
+  const uint8_t u3[] = {0x00, 0x00, 0x55, 0x3e, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  uuid = Uuid::From16Bit(0x553e);
+  EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0);
+
+  const uint8_t u4[] = {0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  uuid = Uuid::From16Bit(0xffff);
+  EXPECT_TRUE(memcmp(&uuid, u4, sizeof(u4)) == 0);
+}
+
+TEST(UuidTest, From32Bit) {
+  EXPECT_EQ(Uuid::From32Bit(0x00000000), kBase);
+
+  const uint8_t u2[] = {0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  Uuid uuid = Uuid::From32Bit(0x00000001);
+  EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0);
+
+  const uint8_t u3[] = {0x33, 0x44, 0x55, 0x3e, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  uuid = Uuid::From32Bit(0x3344553e);
+  EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0);
+
+  const uint8_t u4[] = {0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  uuid = Uuid::From32Bit(0xffffffff);
+  EXPECT_TRUE(memcmp(&uuid, u4, sizeof(u4)) == 0);
+}
+
+TEST(UuidTest, ToString) {
+  const std::string UUID_BASE_STR = "00000000-0000-1000-8000-00805f9b34fb";
+  const std::string UUID_EMP_STR = "00000000-0000-0000-0000-000000000000";
+  const std::string UUID_ONES_STR = "11111111-1111-1111-1111-111111111111";
+  const std::string UUID_SEQ_STR = "01234567-89ab-cdef-abcd-ef0123456789";
+
+  EXPECT_EQ(UUID_BASE_STR, kBase.ToString());
+  EXPECT_EQ(UUID_EMP_STR, Uuid::kEmpty.ToString());
+  EXPECT_EQ(UUID_ONES_STR, ONES.ToString());
+  EXPECT_EQ(UUID_SEQ_STR, SEQUENTIAL.ToString());
+
+  Uuid uuid = Uuid::From32Bit(0x12345678);
+  EXPECT_EQ("12345678-0000-1000-8000-00805f9b34fb", uuid.ToString());
+}
+
+TEST(BtifStorageTest, test_string_to_uuid) {
+  const uint8_t u1[] = {0xe3, 0x9c, 0x62, 0x85, 0x86, 0x7f, 0x4b, 0x1d, 0x9d, 0xb0, 0x35, 0xfb, 0xd9, 0xae, 0xbf, 0x22};
+  bool is_valid = false;
+  Uuid uuid = Uuid::FromString("e39c6285-867f-4b1d-9db0-35fbd9aebf22", &is_valid);
+  EXPECT_TRUE(is_valid);
+  EXPECT_TRUE(memcmp(&uuid, u1, sizeof(u1)) == 0);
+
+  const uint8_t u2[] = {0x00, 0x00, 0x1a, 0xe8, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  is_valid = false;
+  uuid = Uuid::FromString("1Ae8", &is_valid);
+  EXPECT_TRUE(is_valid);
+  EXPECT_TRUE(memcmp(&uuid, u2, sizeof(u2)) == 0);
+
+  const uint8_t u3[] = {0x12, 0x34, 0x11, 0x28, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0x80, 0x5f, 0x9b, 0x34, 0xfb};
+  is_valid = false;
+  uuid = Uuid::FromString("12341128", &is_valid);
+  EXPECT_TRUE(is_valid);
+  EXPECT_TRUE(memcmp(&uuid, u3, sizeof(u3)) == 0);
+}
+
+TEST(BtifStorageTest, test_string_to_uuid_invalid) {
+  bool is_valid = false;
+  Uuid uuid = Uuid::FromString("This is not a UUID", &is_valid);
+  EXPECT_FALSE(is_valid);
+
+  uuid = Uuid::FromString("11212", &is_valid);
+  EXPECT_FALSE(is_valid);
+
+  uuid = Uuid::FromString("1121 ", &is_valid);
+  EXPECT_FALSE(is_valid);
+
+  uuid = Uuid::FromString("AGFE", &is_valid);
+  EXPECT_FALSE(is_valid);
+
+  uuid = Uuid::FromString("ABFG", &is_valid);
+  EXPECT_FALSE(is_valid);
+
+  uuid = Uuid::FromString("e39c6285867f14b1d9db035fbd9aebf22", &is_valid);
+  EXPECT_FALSE(is_valid);
+
+  uuid = Uuid::FromString("12234567-89ab-cdef-abcd-ef01234567ZZ", &is_valid);
+  EXPECT_FALSE(is_valid);
+}
diff --git a/vendor_libs/test_vendor_lib/types/test/class_of_device_unittest.cc b/vendor_libs/test_vendor_lib/types/test/class_of_device_unittest.cc
new file mode 100644
index 0000000..5d652a5
--- /dev/null
+++ b/vendor_libs/test_vendor_lib/types/test/class_of_device_unittest.cc
@@ -0,0 +1,96 @@
+/******************************************************************************
+ *
+ *  Copyright 2018 The Android Open Source Project
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#include <gtest/gtest.h>
+
+#include "class_of_device.h"
+
+static const char* test_class = "efc-d-ab";
+static const uint8_t test_bytes[]{0xab, 0xcd, 0xef};
+
+TEST(ClassOfDeviceUnittest, test_constructor_array) {
+  ClassOfDevice cod(test_bytes);
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceUnittest, test_to_from_str) {
+  ClassOfDevice cod;
+  ClassOfDevice::FromString(test_class, cod);
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceUnittest, test_from_octets) {
+  ClassOfDevice cod;
+  size_t expected_result = ClassOfDevice::kLength;
+  ASSERT_EQ(expected_result, cod.FromOctets(test_bytes));
+
+  ASSERT_EQ(test_bytes[0], cod.cod[0]);
+  ASSERT_EQ(test_bytes[1], cod.cod[1]);
+  ASSERT_EQ(test_bytes[2], cod.cod[2]);
+
+  std::string ret = cod.ToString();
+
+  ASSERT_STREQ(test_class, ret.c_str());
+}
+
+TEST(ClassOfDeviceTest, test_copy) {
+  ClassOfDevice cod1;
+  ClassOfDevice cod2;
+  ClassOfDevice::FromString(test_class, cod1);
+  cod2 = cod1;
+
+  ASSERT_EQ(cod1.cod[0], cod2.cod[0]);
+  ASSERT_EQ(cod1.cod[1], cod2.cod[1]);
+  ASSERT_EQ(cod1.cod[2], cod2.cod[2]);
+}
+
+TEST(ClassOfDeviceTest, IsValid) {
+  EXPECT_FALSE(ClassOfDevice::IsValid(""));
+  EXPECT_FALSE(ClassOfDevice::IsValid("000000"));
+  EXPECT_FALSE(ClassOfDevice::IsValid("00-00-00"));
+  EXPECT_FALSE(ClassOfDevice::IsValid("000-0-0"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("000-0-00"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("ABc-d-00"));
+  EXPECT_TRUE(ClassOfDevice::IsValid("aBc-D-eF"));
+}
+
+TEST(ClassOfDeviceTest, classOfDeviceFromString) {
+  ClassOfDevice cod;
+
+  EXPECT_TRUE(ClassOfDevice::FromString("000-0-00", cod));
+  const ClassOfDevice result0 = {{0x00, 0x00, 0x00}};
+  EXPECT_EQ(0, memcmp(&cod, &result0, sizeof(cod)));
+
+  EXPECT_TRUE(ClassOfDevice::FromString("ab2-1-4C", cod));
+  const ClassOfDevice result1 = {{0x4c, 0x21, 0xab}};
+  EXPECT_EQ(0, memcmp(&cod, &result1, sizeof(cod)));
+}