Move mkdir /data/nfc/... to rootdir init.rc
am: 698b291176

Change-Id: I652ce22990ab28e24eaa880b8e65ca34a71f11df
diff --git a/Android.bp b/Android.bp
new file mode 100644
index 0000000..f31b444
--- /dev/null
+++ b/Android.bp
@@ -0,0 +1,18 @@
+//
+// 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.
+
+subdirs = [
+    "bluetooth",
+]
diff --git a/AndroidProducts.mk b/AndroidProducts.mk
index 7bc7d5b..5faaef4 100644
--- a/AndroidProducts.mk
+++ b/AndroidProducts.mk
@@ -15,4 +15,5 @@
 #
 
 PRODUCT_MAKEFILES := \
-	$(LOCAL_DIR)/aosp_dragon.mk
+	$(LOCAL_DIR)/aosp_dragon.mk \
+	$(LOCAL_DIR)/aosp_dragon_car.mk
diff --git a/CleanSpec.mk b/CleanSpec.mk
index 8933ebc..c9e5cf0 100644
--- a/CleanSpec.mk
+++ b/CleanSpec.mk
@@ -49,3 +49,5 @@
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/permissions/android.hardware.location.gps.xml)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/permissions/android.hardware.camera.full.xml)
 $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/etc/permissions/android.hardware.camera.manual_sensor.xml)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib/hw/android.hardware.broadcastradio@1.0-impl.so)
+$(call add-clean-step, rm -f $(PRODUCT_OUT)/system/lib64/hw/android.hardware.broadcastradio@1.0-impl.so)
diff --git a/aosp_dragon_car.mk b/aosp_dragon_car.mk
new file mode 100644
index 0000000..34aa6c7
--- /dev/null
+++ b/aosp_dragon_car.mk
@@ -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.
+
+#
+# This file is the build configuration for an aosp Android
+# build for dragon hardware. This cleanly combines a set of
+# device-specific aspects (drivers) with a device-agnostic
+# product configuration (apps). Except for a few implementation
+# details, it only fundamentally contains two inherit-product
+# lines, aosp and dragon, hence its name.
+#
+
+PRODUCT_COPY_FILES += \
+    device/google/dragon/manifest_dragon_car.xml:vendor/manifest.xml
+
+$(call inherit-product, packages/services/Car/car_product/build/car.mk)
+$(call inherit-product, device/google/dragon/aosp_dragon.mk)
+
+BOARD_SEPOLICY_DIRS += packages/services/Car/car_product/sepolicy
+
+PRODUCT_NAME := aosp_dragon_car
+PRODUCT_DEVICE := dragon
+PRODUCT_BRAND := Android
+PRODUCT_MODEL := Android Auto Embedded on dragon
+PRODUCT_MANUFACTURER := Google
+PRODUCT_RESTRICT_VENDOR_FILES := true
diff --git a/bluetooth/Android.bp b/bluetooth/Android.bp
new file mode 100644
index 0000000..0f38d9b
--- /dev/null
+++ b/bluetooth/Android.bp
@@ -0,0 +1,45 @@
+//
+// 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.
+
+cc_library_shared {
+    name: "android.hardware.bluetooth@1.0-impl-dragon",
+    cflags: [
+        "-Wall",
+        "-Werror",
+    ],
+    vendor: true,
+    relative_install_path: "hw",
+    srcs: [
+        "bluetooth_address.cc",
+        "bluetooth_hci.cc",
+        "vendor_interface.cc",
+    ],
+    shared_libs: [
+        "android.frameworks.schedulerservice@1.0",
+        "android.hardware.bluetooth@1.0",
+        "libbase",
+        "libcutils",
+        "libhardware",
+        "libhidlbase",
+        "libhidltransport",
+        "libhwbinder",
+        "liblog",
+        "libutils",
+    ],
+    static_libs: [
+        "android.hardware.bluetooth-async",
+        "android.hardware.bluetooth-hci",
+    ],
+}
diff --git a/bluetooth/bluetooth_address.cc b/bluetooth/bluetooth_address.cc
new file mode 100644
index 0000000..f3ec963
--- /dev/null
+++ b/bluetooth/bluetooth_address.cc
@@ -0,0 +1,79 @@
+//
+// 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 "bluetooth_address.h"
+
+#include <android-base/logging.h>
+#include <cutils/properties.h>
+#include <fcntl.h>
+#include <utils/Log.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace dragon {
+
+void BluetoothAddress::bytes_to_string(const uint8_t* addr, char* addr_str) {
+  sprintf(addr_str, "%02x:%02x:%02x:%02x:%02x:%02x", addr[0], addr[1], addr[2],
+          addr[3], addr[4], addr[5]);
+}
+
+bool BluetoothAddress::string_to_bytes(const char* addr_str, uint8_t* addr) {
+  if (addr_str == NULL) return false;
+  if (strnlen(addr_str, kStringLength) != kStringLength) return false;
+  unsigned char trailing_char = '\0';
+
+  return (sscanf(addr_str, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx%1c",
+                 &addr[0], &addr[1], &addr[2], &addr[3], &addr[4], &addr[5],
+                 &trailing_char) == kBytes);
+}
+
+bool BluetoothAddress::get_local_address(uint8_t* local_addr) {
+  char property[PROPERTY_VALUE_MAX] = {0};
+
+  // No factory BDADDR found. Look for a previously stored BDA.
+  if (property_get(PERSIST_BDADDR_PROPERTY, property, NULL) &&
+      string_to_bytes(property, local_addr)) {
+    return true;
+  }
+
+  // Look for an the WiFi MAC from an AzureWave module.
+  int wifi_mac_fd = open(AZW_WIFI_MAC_PATH, O_RDONLY);
+  if (wifi_mac_fd != -1) {
+    int bytes_read = read(wifi_mac_fd, property, kStringLength);
+    close(wifi_mac_fd);
+    if (bytes_read != kStringLength) return false;
+
+    // Null terminate the string.
+    property[kStringLength] = '\0';
+
+    // Zero last bit to calculate the Bluetooth address. This works because the
+    // WiFi address is always odd (never ending in 0x0 or 0xa).
+    property[kStringLength - 1] = property[kStringLength - 1] - 1;
+
+    ALOGD("%s: Got BDA from WiFi MAC %s", __func__, property);
+    return string_to_bytes(property, local_addr);
+  }
+
+  return false;
+}
+
+}  // namespace dragon
+}  // namespace V1_0
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/bluetooth_address.h b/bluetooth/bluetooth_address.h
new file mode 100644
index 0000000..40e84d7
--- /dev/null
+++ b/bluetooth/bluetooth_address.h
@@ -0,0 +1,58 @@
+//
+// 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 <fcntl.h>
+
+#include <cstdint>
+#include <string>
+#include <vector>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace dragon {
+
+// Check for a legacy address stored as a property.
+static constexpr char PERSIST_BDADDR_PROPERTY[] =
+    "persist.service.bdroid.bdaddr";
+
+// Use the WiFi MAC with bit 0 cleared for AzureWave modules
+static constexpr char AZW_WIFI_MAC_PATH[] =
+    "/sys/devices/700b0200.sdhci/mmc_host/mmc0/"
+    "mmc0:0001/mmc0:0001:2/net/wlan0/address";
+
+// Encapsulate handling for Bluetooth Addresses:
+class BluetoothAddress {
+ public:
+  // Conversion constants
+  static constexpr size_t kStringLength = sizeof("XX:XX:XX:XX:XX:XX") - 1;
+  static constexpr size_t kBytes = (kStringLength + 1) / 3;
+
+  static void bytes_to_string(const uint8_t* addr, char* addr_str);
+
+  static bool string_to_bytes(const char* addr_str, uint8_t* addr);
+
+  static bool get_local_address(uint8_t* addr);
+};
+
+}  // namespace dragon
+}  // namespace V1_0
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/bluetooth_hci.cc b/bluetooth/bluetooth_hci.cc
new file mode 100644
index 0000000..b5e6fdc
--- /dev/null
+++ b/bluetooth/bluetooth_hci.cc
@@ -0,0 +1,145 @@
+//
+// 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 "android.hardware.bluetooth@1.0-impl-dragon"
+#include "bluetooth_hci.h"
+
+#include <log/log.h>
+
+#include "vendor_interface.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace dragon {
+
+static const uint8_t HCI_DATA_TYPE_COMMAND = 1;
+static const uint8_t HCI_DATA_TYPE_ACL = 2;
+static const uint8_t HCI_DATA_TYPE_SCO = 3;
+
+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*/) {
+    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; }
+
+ private:
+  bool has_died_;
+};
+
+BluetoothHci::BluetoothHci()
+    : death_recipient_(new BluetoothDeathRecipient(this)) {}
+
+Return<void> BluetoothHci::initialize(
+    const ::android::sp<IBluetoothHciCallbacks>& cb) {
+  ALOGI("BluetoothHci::initialize()");
+  if (cb == nullptr) {
+    ALOGE("cb == nullptr! -> Unable to call initializationComplete(ERR)");
+    return Void();
+  }
+
+  death_recipient_->setHasDied(false);
+  cb->linkToDeath(death_recipient_, 0);
+
+  bool rc = VendorInterface::Initialize(
+      [cb](bool status) {
+        auto hidl_status = cb->initializationComplete(
+            status ? Status::SUCCESS : Status::INITIALIZATION_ERROR);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call initializationComplete()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->hciEventReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call hciEventReceived()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->aclDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call aclDataReceived()");
+        }
+      },
+      [cb](const hidl_vec<uint8_t>& packet) {
+        auto hidl_status = cb->scoDataReceived(packet);
+        if (!hidl_status.isOk()) {
+          ALOGE("VendorInterface -> Unable to call scoDataReceived()");
+        }
+      });
+  if (!rc) {
+    auto hidl_status = cb->initializationComplete(Status::INITIALIZATION_ERROR);
+    if (!hidl_status.isOk()) {
+      ALOGE("VendorInterface -> Unable to call initializationComplete(ERR)");
+    }
+  }
+
+  unlink_cb_ = [cb](sp<BluetoothDeathRecipient>& death_recipient) {
+    if (death_recipient->getHasDied())
+      ALOGI("Skipping unlink call, service died.");
+    else
+      cb->unlinkToDeath(death_recipient);
+  };
+
+  return Void();
+}
+
+Return<void> BluetoothHci::close() {
+  ALOGI("BluetoothHci::close()");
+  unlink_cb_(death_recipient_);
+  VendorInterface::Shutdown();
+  return Void();
+}
+
+Return<void> BluetoothHci::sendHciCommand(const hidl_vec<uint8_t>& command) {
+  sendDataToController(HCI_DATA_TYPE_COMMAND, command);
+  return Void();
+}
+
+Return<void> BluetoothHci::sendAclData(const hidl_vec<uint8_t>& data) {
+  sendDataToController(HCI_DATA_TYPE_ACL, data);
+  return Void();
+}
+
+Return<void> BluetoothHci::sendScoData(const hidl_vec<uint8_t>& data) {
+  sendDataToController(HCI_DATA_TYPE_SCO, data);
+  return Void();
+}
+
+void BluetoothHci::sendDataToController(const uint8_t type,
+                                        const hidl_vec<uint8_t>& data) {
+  VendorInterface::get()->Send(type, data.data(), data.size());
+}
+
+IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* /* name */) {
+  return new BluetoothHci();
+}
+
+}  // namespace dragon
+}  // namespace V1_0
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/bluetooth_hci.h b/bluetooth/bluetooth_hci.h
new file mode 100644
index 0000000..4661d92
--- /dev/null
+++ b/bluetooth/bluetooth_hci.h
@@ -0,0 +1,59 @@
+//
+// 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 android_hardware_bluetooth_V1_0_BluetoothHci_H_
+#define android_hardware_bluetooth_V1_0_BluetoothHci_H_
+
+#include <android/hardware/bluetooth/1.0/IBluetoothHci.h>
+
+#include <hidl/MQDescriptor.h>
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace dragon {
+
+using ::android::hardware::Return;
+using ::android::hardware::hidl_vec;
+
+class BluetoothDeathRecipient;
+
+class BluetoothHci : public IBluetoothHci {
+ public:
+  BluetoothHci();
+  Return<void> initialize(
+      const ::android::sp<IBluetoothHciCallbacks>& cb) override;
+  Return<void> sendHciCommand(const hidl_vec<uint8_t>& packet) override;
+  Return<void> sendAclData(const hidl_vec<uint8_t>& data) override;
+  Return<void> sendScoData(const hidl_vec<uint8_t>& data) override;
+  Return<void> close() override;
+
+ private:
+  void sendDataToController(const uint8_t type, const hidl_vec<uint8_t>& data);
+  ::android::sp<BluetoothDeathRecipient> death_recipient_;
+  std::function<void(sp<BluetoothDeathRecipient>&)> unlink_cb_;
+};
+
+extern "C" IBluetoothHci* HIDL_FETCH_IBluetoothHci(const char* name);
+
+}  // namespace dragon
+}  // namespace V1_0
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
+
+#endif  // android_hardware_bluetooth_V1_0_BluetoothHci_H_
diff --git a/bluetooth/bt_vendor_lib.h b/bluetooth/bt_vendor_lib.h
new file mode 100644
index 0000000..c4035b7
--- /dev/null
+++ b/bluetooth/bt_vendor_lib.h
@@ -0,0 +1,434 @@
+/******************************************************************************
+ *
+ *  Copyright (C) 2009-2012 Broadcom Corporation
+ *
+ *  Licensed under the Apache License, Version 2.0 (the "License");
+ *  you may not use this file except in compliance with the License.
+ *  You may obtain a copy of the License at:
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ *
+ ******************************************************************************/
+
+#ifndef BT_VENDOR_LIB_H
+#define BT_VENDOR_LIB_H
+
+#include <stdint.h>
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/** Struct types */
+
+/** Typedefs and defines */
+
+/** Vendor specific operations OPCODE */
+typedef enum {
+  /*  [operation]
+   *      Power on or off the BT Controller.
+   *  [input param]
+   *      A pointer to int type with content of bt_vendor_power_state_t.
+   *      Typecasting conversion: (int *) param.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      None.
+   */
+  BT_VND_OP_POWER_CTRL,
+
+  /*  [operation]
+   *      Perform any vendor specific initialization or configuration
+   *      on the BT Controller. This is called before stack initialization.
+   *  [input param]
+   *      None.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      Must call fwcfg_cb to notify the stack of the completion of vendor
+   *      specific initialization once it has been done.
+   */
+  BT_VND_OP_FW_CFG,
+
+  /*  [operation]
+   *      Perform any vendor specific SCO/PCM configuration on the BT
+   * Controller.
+   *      This is called after stack initialization.
+   *  [input param]
+   *      None.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      Must call scocfg_cb to notify the stack of the completion of vendor
+   *      specific SCO configuration once it has been done.
+   */
+  BT_VND_OP_SCO_CFG,
+
+  /*  [operation]
+   *      Open UART port on where the BT Controller is attached.
+   *      This is called before stack initialization.
+   *  [input param]
+   *      A pointer to int array type for open file descriptors.
+   *      The mapping of HCI channel to fd slot in the int array is given in
+   *      bt_vendor_hci_channels_t.
+   *      And, it requires the vendor lib to fill up the content before
+   * returning
+   *      the call.
+   *      Typecasting conversion: (int (*)[]) param.
+   *  [return]
+   *      Numbers of opened file descriptors.
+   *      Valid number:
+   *          1 - CMD/EVT/ACL-In/ACL-Out via the same fd (e.g. UART)
+   *          2 - CMD/EVT on one fd, and ACL-In/ACL-Out on the other fd
+   *          4 - CMD, EVT, ACL-In, ACL-Out are on their individual fd
+   *  [callback]
+   *      None.
+   */
+  BT_VND_OP_USERIAL_OPEN,
+
+  /*  [operation]
+   *      Close the previously opened UART port.
+   *  [input param]
+   *      None.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      None.
+   */
+  BT_VND_OP_USERIAL_CLOSE,
+
+  /*  [operation]
+   *      Get the LPM idle timeout in milliseconds.
+   *      The stack uses this information to launch a timer delay before it
+   *      attempts to de-assert LPM WAKE signal once downstream HCI packet
+   *      has been delivered.
+   *  [input param]
+   *      A pointer to uint32_t type which is passed in by the stack. And, it
+   *      requires the vendor lib to fill up the content before returning
+   *      the call.
+   *      Typecasting conversion: (uint32_t *) param.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      None.
+   */
+  BT_VND_OP_GET_LPM_IDLE_TIMEOUT,
+
+  /*  [operation]
+   *      Enable or disable LPM mode on BT Controller.
+   *  [input param]
+   *      A pointer to uint8_t type with content of bt_vendor_lpm_mode_t.
+   *      Typecasting conversion: (uint8_t *) param.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      Must call lpm_cb to notify the stack of the completion of LPM
+   *      disable/enable process once it has been done.
+   */
+  BT_VND_OP_LPM_SET_MODE,
+
+  /*  [operation]
+   *      Assert or Deassert LPM WAKE on BT Controller.
+   *  [input param]
+   *      A pointer to uint8_t type with content of bt_vendor_lpm_wake_state_t.
+   *      Typecasting conversion: (uint8_t *) param.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      None.
+   */
+  BT_VND_OP_LPM_WAKE_SET_STATE,
+
+  /*  [operation]
+   *      Perform any vendor specific commands related to audio state changes.
+   *  [input param]
+   *      a pointer to bt_vendor_op_audio_state_t indicating what audio state is
+   *      set.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      None.
+   */
+  BT_VND_OP_SET_AUDIO_STATE,
+
+  /*  [operation]
+   *      The epilog call to the vendor module so that it can perform any
+   *      vendor-specific processes (e.g. send a HCI_RESET to BT Controller)
+   *      before the caller calls for cleanup().
+   *  [input param]
+   *      None.
+   *  [return]
+   *      0 - default, don't care.
+   *  [callback]
+   *      Must call epilog_cb to notify the stack of the completion of vendor
+   *      specific epilog process once it has been done.
+   */
+  BT_VND_OP_EPILOG,
+
+  /*  [operation]
+   *      Call to the vendor module so that it can perform all vendor-specific
+   *      operations to start offloading a2dp media encode & tx.
+   *  [input param]
+   *      pointer to bt_vendor_op_a2dp_offload_start_t containing elements
+   *      required for VND FW to setup a2dp offload.
+   *  [return]
+   *      0  - default, dont care.
+   *  [callback]
+   *      Must call a2dp_offload_start_cb to notify the stack of the
+   *      completion of vendor specific setup process once it has been done.
+   */
+  BT_VND_OP_A2DP_OFFLOAD_START,
+
+  /*  [operation]
+   *      Call to the vendor module so that it can perform all vendor-specific
+   *      operations to suspend offloading a2dp media encode & tx.
+   *  [input param]
+   *      pointer to bt_vendor_op_a2dp_offload_t containing elements
+   *      required for VND FW to setup a2dp offload.
+   *  [return]
+   *      0  - default, dont care.
+   *  [callback]
+   *      Must call a2dp_offload_cb to notify the stack of the
+   *      completion of vendor specific setup process once it has been done.
+   */
+  BT_VND_OP_A2DP_OFFLOAD_STOP,
+
+} bt_vendor_opcode_t;
+
+/** Power on/off control states */
+typedef enum {
+  BT_VND_PWR_OFF,
+  BT_VND_PWR_ON,
+} bt_vendor_power_state_t;
+
+/** Define HCI channel identifier in the file descriptors array
+    used in BT_VND_OP_USERIAL_OPEN operation.
+ */
+typedef enum {
+  CH_CMD,      // HCI Command channel
+  CH_EVT,      // HCI Event channel
+  CH_ACL_OUT,  // HCI ACL downstream channel
+  CH_ACL_IN,   // HCI ACL upstream channel
+
+  CH_MAX  // Total channels
+} bt_vendor_hci_channels_t;
+
+/** LPM disable/enable request */
+typedef enum {
+  BT_VND_LPM_DISABLE,
+  BT_VND_LPM_ENABLE,
+} bt_vendor_lpm_mode_t;
+
+/** LPM WAKE set state request */
+typedef enum {
+  BT_VND_LPM_WAKE_ASSERT,
+  BT_VND_LPM_WAKE_DEASSERT,
+} bt_vendor_lpm_wake_state_t;
+
+/** Callback result values */
+typedef enum {
+  BT_VND_OP_RESULT_SUCCESS,
+  BT_VND_OP_RESULT_FAIL,
+} bt_vendor_op_result_t;
+
+/** audio (SCO) state changes triggering VS commands for configuration */
+typedef struct {
+  uint16_t handle;
+  uint16_t peer_codec;
+  uint16_t state;
+} bt_vendor_op_audio_state_t;
+
+/*
+ * Bluetooth Host/Controller Vendor callback structure.
+ */
+
+/* vendor initialization/configuration callback */
+typedef void (*cfg_result_cb)(bt_vendor_op_result_t result);
+
+/* datapath buffer allocation callback (callout)
+ *
+ *  Vendor lib needs to request a buffer through the alloc callout function
+ *  from HCI lib if the buffer is for constructing a HCI Command packet which
+ *  will be sent through xmit_cb to BT Controller.
+ *
+ *  For each buffer allocation, the requested size needs to be big enough to
+ *  accommodate the below header plus a complete HCI packet --
+ *      typedef struct
+ *      {
+ *          uint16_t          event;
+ *          uint16_t          len;
+ *          uint16_t          offset;
+ *          uint16_t          layer_specific;
+ *      } HC_BT_HDR;
+ *
+ *  HCI lib returns a pointer to the buffer where Vendor lib should use to
+ *  construct a HCI command packet as below format:
+ *
+ *  --------------------------------------------
+ *  |  HC_BT_HDR  |  HCI command               |
+ *  --------------------------------------------
+ *  where
+ *      HC_BT_HDR.event = 0x2000;
+ *      HC_BT_HDR.len = Length of HCI command;
+ *      HC_BT_HDR.offset = 0;
+ *      HC_BT_HDR.layer_specific = 0;
+ *
+ *  For example, a HCI_RESET Command will be formed as
+ *  ------------------------
+ *  |  HC_BT_HDR  |03|0c|00|
+ *  ------------------------
+ *  with
+ *      HC_BT_HDR.event = 0x2000;
+ *      HC_BT_HDR.len = 3;
+ *      HC_BT_HDR.offset = 0;
+ *      HC_BT_HDR.layer_specific = 0;
+ */
+typedef void* (*malloc_cb)(int size);
+
+/* datapath buffer deallocation callback (callout) */
+typedef void (*mdealloc_cb)(void* p_buf);
+
+/* define callback of the cmd_xmit_cb
+ *
+ *  The callback function which HCI lib will call with the return of command
+ *  complete packet. Vendor lib is responsible for releasing the buffer passed
+ *  in at the p_mem parameter by calling dealloc callout function.
+ */
+typedef void (*tINT_CMD_CBACK)(void* p_mem);
+
+/* hci command packet transmit callback (callout)
+ *
+ *  Vendor lib calls xmit_cb callout function in order to send a HCI Command
+ *  packet to BT Controller. The buffer carrying HCI Command packet content
+ *  needs to be first allocated through the alloc callout function.
+ *  HCI lib will release the buffer for Vendor lib once it has delivered the
+ *  packet content to BT Controller.
+ *
+ *  Vendor lib needs also provide a callback function (p_cback) which HCI lib
+ *  will call with the return of command complete packet.
+ *
+ *  The opcode parameter gives the HCI OpCode (combination of OGF and OCF) of
+ *  HCI Command packet. For example, opcode = 0x0c03 for the HCI_RESET command
+ *  packet.
+ */
+typedef uint8_t (*cmd_xmit_cb)(uint16_t opcode, void* p_buf,
+                               tINT_CMD_CBACK p_cback);
+
+typedef void (*cfg_a2dp_cb)(bt_vendor_op_result_t result, bt_vendor_opcode_t op,
+                            uint8_t bta_av_handle);
+
+typedef struct {
+  /** set to sizeof(bt_vendor_callbacks_t) */
+  size_t size;
+
+  /*
+   * Callback and callout functions have implemented in HCI libray
+   * (libbt-hci.so).
+   */
+
+  /* notifies caller result of firmware configuration request */
+  cfg_result_cb fwcfg_cb;
+
+  /* notifies caller result of sco configuration request */
+  cfg_result_cb scocfg_cb;
+
+  /* notifies caller result of lpm enable/disable */
+  cfg_result_cb lpm_cb;
+
+  /* notifies the result of codec setting */
+  cfg_result_cb audio_state_cb;
+
+  /* buffer allocation request */
+  malloc_cb alloc;
+
+  /* buffer deallocation request */
+  mdealloc_cb dealloc;
+
+  /* hci command packet transmit request */
+  cmd_xmit_cb xmit_cb;
+
+  /* notifies caller completion of epilog process */
+  cfg_result_cb epilog_cb;
+
+  /* notifies status of a2dp offload cmd's */
+  cfg_a2dp_cb a2dp_offload_cb;
+} bt_vendor_callbacks_t;
+
+/** A2DP offload request */
+typedef struct {
+  uint8_t bta_av_handle;  /* BTA_AV Handle for callbacks */
+  uint16_t xmit_quota;    /* Total ACL quota for light stack */
+  uint16_t acl_data_size; /* Max ACL data size across HCI transport */
+  uint16_t stream_mtu;
+  uint16_t local_cid;
+  uint16_t remote_cid;
+  uint16_t lm_handle;
+  uint8_t is_flushable; /* true if flushable channel */
+  uint32_t stream_source;
+  uint8_t codec_info[10]; /* Codec capabilities array */
+} bt_vendor_op_a2dp_offload_t;
+
+/*
+ * Bluetooth Host/Controller VENDOR Interface
+ */
+typedef struct {
+  /** Set to sizeof(bt_vndor_interface_t) */
+  size_t size;
+
+  /*
+   * Functions need to be implemented in Vendor libray (libbt-vendor.so).
+   */
+
+  /**
+   * Caller will open the interface and pass in the callback routines
+   * to the implemenation of this interface.
+   */
+  int (*init)(const bt_vendor_callbacks_t* p_cb, unsigned char* local_bdaddr);
+
+  /**  Vendor specific operations */
+  int (*op)(bt_vendor_opcode_t opcode, void* param);
+
+  /** Closes the interface */
+  void (*cleanup)(void);
+} bt_vendor_interface_t;
+
+/*
+ * External shared lib functions/data
+ */
+
+/* Entry point of DLib --
+ *      Vendor library needs to implement the body of bt_vendor_interface_t
+ *      structure and uses the below name as the variable name. HCI library
+ *      will use this symbol name to get address of the object through the
+ *      dlsym call.
+ */
+extern const bt_vendor_interface_t BLUETOOTH_VENDOR_LIB_INTERFACE;
+
+// MODIFICATION FOR NEW HAL/HIDL IMPLEMENTATION:
+// EXPOSE THE BT_HDR STRUCT HERE FOR THE VENDOR INTERFACE
+// ONLY, WITHOUT REQUIRING INCLUDES FROM system/bt OR OTHER
+// DIRECTORIES.
+// ONLY USED INSIDE transmit_cb.
+// DO NOT USE IN NEW HAL IMPLEMENTATIONS GOING FORWARD
+typedef struct {
+  uint16_t event;
+  uint16_t len;
+  uint16_t offset;
+  uint16_t layer_specific;
+  uint8_t data[];
+} HC_BT_HDR;
+// /MODIFICATION
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* BT_VENDOR_LIB_H */
diff --git a/bluetooth/vendor_interface.cc b/bluetooth/vendor_interface.cc
new file mode 100644
index 0000000..d485185
--- /dev/null
+++ b/bluetooth/vendor_interface.cc
@@ -0,0 +1,363 @@
+//
+// 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 "vendor_interface.h"
+
+#define LOG_TAG "android.hardware.bluetooth@1.0-impl-dragon"
+#include <cutils/properties.h>
+#include <utils/Log.h>
+
+#include <dlfcn.h>
+#include <fcntl.h>
+
+#include "bluetooth_address.h"
+#include "h4_protocol.h"
+
+static const char* VENDOR_LIBRARY_NAME = "libbt-vendor.so";
+static const char* VENDOR_LIBRARY_SYMBOL_NAME =
+    "BLUETOOTH_VENDOR_LIB_INTERFACE";
+
+static const int INVALID_FD = -1;
+
+namespace {
+
+using android::hardware::bluetooth::V1_0::dragon::VendorInterface;
+using android::hardware::hidl_vec;
+
+struct {
+  tINT_CMD_CBACK cb;
+  uint16_t opcode;
+} internal_command;
+
+// True when LPM is not enabled yet or wake is not asserted.
+bool lpm_wake_deasserted;
+uint32_t lpm_timeout_ms;
+bool recent_activity_flag;
+
+VendorInterface* g_vendor_interface = nullptr;
+
+HC_BT_HDR* WrapPacketAndCopy(uint16_t event, const hidl_vec<uint8_t>& data) {
+  size_t packet_size = data.size() + sizeof(HC_BT_HDR);
+  HC_BT_HDR* packet = reinterpret_cast<HC_BT_HDR*>(new uint8_t[packet_size]);
+  packet->offset = 0;
+  packet->len = data.size();
+  packet->layer_specific = 0;
+  packet->event = event;
+  // TODO(eisenbach): Avoid copy here; if BT_HDR->data can be ensured to
+  // be the only way the data is accessed, a pointer could be passed here...
+  memcpy(packet->data, data.data(), data.size());
+  return packet;
+}
+
+bool internal_command_event_match(const hidl_vec<uint8_t>& packet) {
+  uint8_t event_code = packet[0];
+  if (event_code != HCI_COMMAND_COMPLETE_EVENT) {
+    ALOGE("%s: Unhandled event type %02X", __func__, event_code);
+    return false;
+  }
+
+  size_t opcode_offset = HCI_EVENT_PREAMBLE_SIZE + 1;  // Skip num packets.
+
+  uint16_t opcode = packet[opcode_offset] | (packet[opcode_offset + 1] << 8);
+
+  ALOGV("%s internal_command.opcode = %04X opcode = %04x", __func__,
+        internal_command.opcode, opcode);
+  return opcode == internal_command.opcode;
+}
+
+uint8_t transmit_cb(uint16_t opcode, void* buffer, tINT_CMD_CBACK callback) {
+  ALOGV("%s opcode: 0x%04x, ptr: %p, cb: %p", __func__, opcode, buffer,
+        callback);
+  internal_command.cb = callback;
+  internal_command.opcode = opcode;
+  uint8_t type = HCI_PACKET_TYPE_COMMAND;
+  HC_BT_HDR* bt_hdr = reinterpret_cast<HC_BT_HDR*>(buffer);
+  VendorInterface::get()->Send(type, bt_hdr->data, bt_hdr->len);
+  delete[] reinterpret_cast<uint8_t*>(buffer);
+  return true;
+}
+
+void firmware_config_cb(bt_vendor_op_result_t result) {
+  ALOGV("%s result: %d", __func__, result);
+  VendorInterface::get()->OnFirmwareConfigured(result);
+}
+
+void sco_config_cb(bt_vendor_op_result_t result) {
+  ALOGD("%s result: %d", __func__, result);
+}
+
+void low_power_mode_cb(bt_vendor_op_result_t result) {
+  ALOGD("%s result: %d", __func__, result);
+}
+
+void sco_audiostate_cb(bt_vendor_op_result_t result) {
+  ALOGD("%s result: %d", __func__, result);
+}
+
+void* buffer_alloc_cb(int size) {
+  void* p = new uint8_t[size];
+  ALOGV("%s pts: %p, size: %d", __func__, p, size);
+  return p;
+}
+
+void buffer_free_cb(void* buffer) {
+  ALOGV("%s ptr: %p", __func__, buffer);
+  delete[] reinterpret_cast<uint8_t*>(buffer);
+}
+
+void epilog_cb(bt_vendor_op_result_t result) {
+  ALOGD("%s result: %d", __func__, result);
+}
+
+void a2dp_offload_cb(bt_vendor_op_result_t result, bt_vendor_opcode_t op,
+                     uint8_t av_handle) {
+  ALOGD("%s result: %d, op: %d, handle: %d", __func__, result, op, av_handle);
+}
+
+const bt_vendor_callbacks_t lib_callbacks = {
+    sizeof(lib_callbacks), firmware_config_cb, sco_config_cb,
+    low_power_mode_cb,     sco_audiostate_cb,  buffer_alloc_cb,
+    buffer_free_cb,        transmit_cb,        epilog_cb,
+    a2dp_offload_cb};
+
+}  // namespace
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace dragon {
+
+class FirmwareStartupTimer {
+ public:
+  FirmwareStartupTimer() : start_time_(std::chrono::steady_clock::now()) {}
+
+  ~FirmwareStartupTimer() {
+    std::chrono::duration<double> duration =
+        std::chrono::steady_clock::now() - start_time_;
+    double s = duration.count();
+    if (s == 0) return;
+    ALOGI("Firmware configured in %.3fs", s);
+  }
+
+ private:
+  std::chrono::steady_clock::time_point start_time_;
+};
+
+bool VendorInterface::Initialize(
+    InitializeCompleteCallback initialize_complete_cb,
+    PacketReadCallback event_cb, PacketReadCallback acl_cb,
+    PacketReadCallback sco_cb) {
+  LOG_ALWAYS_FATAL_IF(g_vendor_interface, "%s: No previous Shutdown()?",
+                      __func__);
+  g_vendor_interface = new VendorInterface();
+  return g_vendor_interface->Open(initialize_complete_cb, event_cb, acl_cb,
+                                  sco_cb);
+}
+
+void VendorInterface::Shutdown() {
+  LOG_ALWAYS_FATAL_IF(!g_vendor_interface, "%s: No Vendor interface!",
+                      __func__);
+  g_vendor_interface->Close();
+  delete g_vendor_interface;
+  g_vendor_interface = nullptr;
+}
+
+VendorInterface* VendorInterface::get() { return g_vendor_interface; }
+
+bool VendorInterface::Open(InitializeCompleteCallback initialize_complete_cb,
+                           PacketReadCallback event_cb,
+                           PacketReadCallback acl_cb,
+                           PacketReadCallback sco_cb) {
+  initialize_complete_cb_ = initialize_complete_cb;
+
+  // Initialize vendor interface
+
+  lib_handle_ = dlopen(VENDOR_LIBRARY_NAME, RTLD_NOW);
+  if (!lib_handle_) {
+    ALOGE("%s unable to open %s (%s)", __func__, VENDOR_LIBRARY_NAME,
+          dlerror());
+    return false;
+  }
+
+  lib_interface_ = reinterpret_cast<bt_vendor_interface_t*>(
+      dlsym(lib_handle_, VENDOR_LIBRARY_SYMBOL_NAME));
+  if (!lib_interface_) {
+    ALOGE("%s unable to find symbol %s in %s (%s)", __func__,
+          VENDOR_LIBRARY_SYMBOL_NAME, VENDOR_LIBRARY_NAME, dlerror());
+    return false;
+  }
+
+  // Get the local BD address
+
+  uint8_t local_bda[BluetoothAddress::kBytes];
+  if (!BluetoothAddress::get_local_address(local_bda)) {
+    LOG_ALWAYS_FATAL("%s: No Bluetooth Address!", __func__);
+  }
+  int status = lib_interface_->init(&lib_callbacks, (unsigned char*)local_bda);
+  if (status) {
+    ALOGE("%s unable to initialize vendor library: %d", __func__, status);
+    return false;
+  }
+
+  ALOGD("%s vendor library loaded", __func__);
+
+  // Power on the controller
+
+  int power_state = BT_VND_PWR_ON;
+  lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+
+  // Get the UART socket(s)
+
+  int fd_list[CH_MAX] = {0};
+  int fd_count = lib_interface_->op(BT_VND_OP_USERIAL_OPEN, &fd_list);
+
+  for (int i = 0; i < fd_count; i++) {
+    if (fd_list[i] == INVALID_FD) {
+      ALOGE("%s: fd %d is invalid!", __func__, fd_list[i]);
+      return false;
+    }
+  }
+
+  event_cb_ = event_cb;
+  PacketReadCallback intercept_events = [this](const hidl_vec<uint8_t>& event) {
+    HandleIncomingEvent(event);
+  };
+
+  if (fd_count == 1) {
+    hci::H4Protocol* h4_hci =
+        new hci::H4Protocol(fd_list[0], intercept_events, acl_cb, sco_cb);
+    fd_watcher_.WatchFdForNonBlockingReads(
+        fd_list[0], [h4_hci](int fd) { h4_hci->OnDataReady(fd); });
+    hci_ = h4_hci;
+  }
+
+  // Initially, the power management is off.
+  lpm_wake_deasserted = true;
+
+  // Start configuring the firmware
+  firmware_startup_timer_ = new FirmwareStartupTimer();
+  lib_interface_->op(BT_VND_OP_FW_CFG, nullptr);
+
+  return true;
+}
+
+void VendorInterface::Close() {
+  // These callbacks may send HCI events (vendor-dependent), so make sure to
+  // StopWatching the file descriptor after this.
+  if (lib_interface_ != nullptr) {
+    bt_vendor_lpm_mode_t mode = BT_VND_LPM_DISABLE;
+    lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
+  }
+
+  fd_watcher_.StopWatchingFileDescriptors();
+
+  if (hci_ != nullptr) {
+    delete hci_;
+    hci_ = nullptr;
+  }
+
+  if (lib_interface_ != nullptr) {
+    lib_interface_->op(BT_VND_OP_USERIAL_CLOSE, nullptr);
+
+    int power_state = BT_VND_PWR_OFF;
+    lib_interface_->op(BT_VND_OP_POWER_CTRL, &power_state);
+  }
+
+  if (lib_handle_ != nullptr) {
+    dlclose(lib_handle_);
+    lib_handle_ = nullptr;
+  }
+
+  if (firmware_startup_timer_ != nullptr) {
+    delete firmware_startup_timer_;
+    firmware_startup_timer_ = nullptr;
+  }
+}
+
+size_t VendorInterface::Send(uint8_t type, const uint8_t* data, size_t length) {
+  recent_activity_flag = true;
+
+  if (lpm_wake_deasserted == true) {
+    // Restart the timer.
+    fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+                                 [this]() { OnTimeout(); });
+    // Assert wake.
+    lpm_wake_deasserted = false;
+    bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_ASSERT;
+    lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
+    ALOGV("%s: Sent wake before (%02x)", __func__, data[0] | (data[1] << 8));
+  }
+
+  return hci_->Send(type, data, length);
+}
+
+void VendorInterface::OnFirmwareConfigured(uint8_t result) {
+  ALOGD("%s result: %d", __func__, result);
+
+  if (firmware_startup_timer_ != nullptr) {
+    delete firmware_startup_timer_;
+    firmware_startup_timer_ = nullptr;
+  }
+
+  if (initialize_complete_cb_ != nullptr) {
+    initialize_complete_cb_(result == 0);
+    initialize_complete_cb_ = nullptr;
+  }
+
+  lib_interface_->op(BT_VND_OP_GET_LPM_IDLE_TIMEOUT, &lpm_timeout_ms);
+  ALOGI("%s: lpm_timeout_ms %d", __func__, lpm_timeout_ms);
+
+  bt_vendor_lpm_mode_t mode = BT_VND_LPM_ENABLE;
+  lib_interface_->op(BT_VND_OP_LPM_SET_MODE, &mode);
+
+  ALOGD("%s Calling StartLowPowerWatchdog()", __func__);
+  fd_watcher_.ConfigureTimeout(std::chrono::milliseconds(lpm_timeout_ms),
+                               [this]() { OnTimeout(); });
+}
+
+void VendorInterface::OnTimeout() {
+  ALOGV("%s", __func__);
+  if (recent_activity_flag == false) {
+    lpm_wake_deasserted = true;
+    bt_vendor_lpm_wake_state_t wakeState = BT_VND_LPM_WAKE_DEASSERT;
+    lib_interface_->op(BT_VND_OP_LPM_WAKE_SET_STATE, &wakeState);
+    fd_watcher_.ConfigureTimeout(std::chrono::seconds(0), []() {
+      ALOGE("Zero timeout! Should never happen.");
+    });
+  }
+  recent_activity_flag = false;
+}
+
+void VendorInterface::HandleIncomingEvent(const hidl_vec<uint8_t>& hci_packet) {
+  if (internal_command.cb != nullptr &&
+      internal_command_event_match(hci_packet)) {
+    HC_BT_HDR* bt_hdr = WrapPacketAndCopy(HCI_PACKET_TYPE_EVENT, hci_packet);
+
+    // The callbacks can send new commands, so don't zero after calling.
+    tINT_CMD_CBACK saved_cb = internal_command.cb;
+    internal_command.cb = nullptr;
+    saved_cb(bt_hdr);
+  } else {
+    event_cb_(hci_packet);
+  }
+}
+
+}  // namespace dragon
+}  // namespace V1_0
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/bluetooth/vendor_interface.h b/bluetooth/vendor_interface.h
new file mode 100644
index 0000000..df7daa1
--- /dev/null
+++ b/bluetooth/vendor_interface.h
@@ -0,0 +1,76 @@
+//
+// 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 <hidl/HidlSupport.h>
+
+#include "async_fd_watcher.h"
+#include "bt_vendor_lib.h"
+#include "hci_protocol.h"
+
+namespace android {
+namespace hardware {
+namespace bluetooth {
+namespace V1_0 {
+namespace dragon {
+
+using ::android::hardware::hidl_vec;
+using InitializeCompleteCallback = std::function<void(bool success)>;
+using PacketReadCallback = std::function<void(const hidl_vec<uint8_t>&)>;
+
+class FirmwareStartupTimer;
+
+class VendorInterface {
+ public:
+  static bool Initialize(InitializeCompleteCallback initialize_complete_cb,
+                         PacketReadCallback event_cb, PacketReadCallback acl_cb,
+                         PacketReadCallback sco_cb);
+  static void Shutdown();
+  static VendorInterface* get();
+
+  size_t Send(uint8_t type, const uint8_t* data, size_t length);
+
+  void OnFirmwareConfigured(uint8_t result);
+
+ private:
+  virtual ~VendorInterface() = default;
+
+  bool Open(InitializeCompleteCallback initialize_complete_cb,
+            PacketReadCallback event_cb, PacketReadCallback acl_cb,
+            PacketReadCallback sco_cb);
+  void Close();
+
+  void OnTimeout();
+
+  void HandleIncomingEvent(const hidl_vec<uint8_t>& hci_packet);
+
+  void* lib_handle_;
+  bt_vendor_interface_t* lib_interface_;
+  async::AsyncFdWatcher fd_watcher_;
+  InitializeCompleteCallback initialize_complete_cb_;
+  hci::HciProtocol* hci_;
+
+  PacketReadCallback event_cb_;
+
+  FirmwareStartupTimer* firmware_startup_timer_;
+};
+
+}  // namespace dragon
+}  // namespace V1_0
+}  // namespace bluetooth
+}  // namespace hardware
+}  // namespace android
diff --git a/device.mk b/device.mk
index 917e755..f1accca 100644
--- a/device.mk
+++ b/device.mk
@@ -127,7 +127,7 @@
 # Bluetooth HAL
 PRODUCT_PACKAGES += \
     libbt-vendor \
-    android.hardware.bluetooth@1.0-impl
+    android.hardware.bluetooth@1.0-impl-dragon
 
 # Copy dsp firmware to the vendor parition so it is available when hotwording
 # starts
@@ -232,7 +232,6 @@
 PRODUCT_PACKAGES += \
     android.hardware.audio@2.0-impl \
     android.hardware.audio.effect@2.0-impl \
-    android.hardware.broadcastradio@1.0-impl \
     android.hardware.soundtrigger@2.0-impl
 
 PRODUCT_PACKAGES += \
diff --git a/manifest_dragon_car.xml b/manifest_dragon_car.xml
new file mode 100644
index 0000000..4d4167f
--- /dev/null
+++ b/manifest_dragon_car.xml
@@ -0,0 +1,39 @@
+<manifest version="1.0" type="device">
+    <hal format="hidl">
+        <name>android.hardware.graphics.allocator</name>
+        <transport>hwbinder</transport>
+        <impl level="generic"></impl>
+        <version>2.0</version>
+        <interface>
+            <name>IAllocator</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>android.hardware.wifi</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>IWifi</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>android.hardware.wifi.supplicant</name>
+        <transport>hwbinder</transport>
+        <version>1.0</version>
+        <interface>
+            <name>ISupplicant</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+    <hal format="hidl">
+        <name>android.hardware.automotive.vehicle</name>
+        <transport>hwbinder</transport>
+        <version>2.1</version>
+        <interface>
+            <name>IVehicle</name>
+            <instance>default</instance>
+        </interface>
+    </hal>
+</manifest>
diff --git a/media_codecs_performance.xml b/media_codecs_performance.xml
index e1f9330..66d5d6b 100644
--- a/media_codecs_performance.xml
+++ b/media_codecs_performance.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="utf-8" ?>
-<!-- Copyright 2016 The Android Open Source Project
+<!-- 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.
@@ -14,111 +14,119 @@
      limitations under the License.
 -->
 
+<!-- Generated file for ryu using measurements between OPR1.170623.019 and OPM1.170911.002 -->
 <MediaCodecs>
+    <!-- Measurements between OPR1.170623.016 and OPM1.170908.002 -->
     <Encoders>
         <MediaCodec name="OMX.Nvidia.h264.encoder" type="video/avc" update="true">
-            <Limit name="measured-frame-rate-320x240" range="280-289" /> <!-- N=38 v93%=1.1 -->
-            <!-- measured 93%:152-276 med:168 SLOW -->
-            <Limit name="measured-frame-rate-720x480" range="168-205" /> <!-- N=38 v93%=1.3 -->
-            <!-- measured 93%:83-139 med:90 SLOW -->
-            <Limit name="measured-frame-rate-1280x720" range="89-108" /> <!-- N=38 v93%=1.3 -->
-            <Limit name="measured-frame-rate-1920x1080" range="88-88" /> <!-- N=38 v93%=1.4 -->
+            <Limit name="measured-frame-rate-320x240" range="333-333" /> <!-- N=118 v98%=1.2 -->
+            <Limit name="measured-frame-rate-720x480" range="197-211" /> <!-- N=118 v98%=1.3 -->
+            <Limit name="measured-frame-rate-1280x720" range="125-125" /> <!-- N=118 v98%=1.3 -->
+            <Limit name="measured-frame-rate-1920x1080" range="73-93" /> <!-- N=118 v98%=1.4 -->
         </MediaCodec>
         <MediaCodec name="OMX.Nvidia.vp8.encoder" type="video/x-vnd.on2.vp8" update="true">
-            <Limit name="measured-frame-rate-320x180" range="265-273" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-640x360" range="196-215" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-1280x720" range="104-114" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-1920x1080" range="67-67" /> <!-- N=38 v93%=1.1 -->
+            <Limit name="measured-frame-rate-320x180" range="304-304" /> <!-- N=118 v98%=1.1 -->
+            <Limit name="measured-frame-rate-640x360" range="216-216" /> <!-- N=118 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1280x720" range="122-123" /> <!-- N=118 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1920x1080" range="70-70" /> <!-- N=118 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.h263.encoder" type="video/3gpp" update="true">
-            <Limit name="measured-frame-rate-176x144" range="646-653" /> <!-- N=38 v93%=1.1 -->
+            <Limit name="measured-frame-rate-176x144" range="684-684" /> <!-- N=118 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.h264.encoder" type="video/avc" update="true">
-            <Limit name="measured-frame-rate-320x240" range="481-481" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-720x480" range="138-138" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-1280x720" range="72-75" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-1920x1080" range="36-36" /> <!-- N=38 v93%=1.1 -->
+            <Limit name="measured-frame-rate-320x240" range="555-555" /> <!-- N=118 v98%=1.2 -->
+            <Limit name="measured-frame-rate-720x480" range="155-156" /> <!-- N=118 v98%=1.1 -->
+            <Limit name="measured-frame-rate-1280x720" range="76-76" /> <!-- N=118 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1920x1080" range="36-36" /> <!-- N=118 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.mpeg4.encoder" type="video/mp4v-es" update="true">
-            <Limit name="measured-frame-rate-176x144" range="744-744" /> <!-- N=38 v93%=1.1 -->
+            <Limit name="measured-frame-rate-176x144" range="780-780" /> <!-- N=118 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.vp8.encoder" type="video/x-vnd.on2.vp8" update="true">
-            <Limit name="measured-frame-rate-320x180" range="139-145" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-640x360" range="85-85" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-1280x720" range="35-35" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-1920x1080" range="18-19" /> <!-- N=38 v93%=1.1 -->
+            <Limit name="measured-frame-rate-320x180" range="161-161" /> <!-- N=118 v98%=1.2 -->
+            <!-- measured 98%:51-114 med:102/102 FLAKY(mn=46.0 < 51 - 204) -->
+            <Limit name="measured-frame-rate-640x360" range="91-102" /> <!-- TWEAKED N=118 v98%=1.5 -->
+            <Limit name="measured-frame-rate-1280x720" range="36-36" /> <!-- N=118 v98%=1.0 -->
+            <Limit name="measured-frame-rate-1920x1080" range="27-27" /> <!-- N=118 v98%=1.1 -->
+        </MediaCodec>
+        <!-- Measurements between OPR1.170208.003 and OPM1.170908.002 -->
+        <MediaCodec name="OMX.google.vp9.encoder" type="video/x-vnd.on2.vp9" update="true">
+            <!-- measured 98%:117-159 med:154/154 N=70 -->
+            <Limit name="measured-frame-rate-320x180" range="154-154" /> <!-- v98%=1.2 -->
+            <!-- measured 98%:34-52 med:50/50 N=72 -->
+            <Limit name="measured-frame-rate-640x360" range="50-50" /> <!-- v98%=1.2 -->
+            <!-- measured 98%:10-13 med:12/12 N=70 -->
+            <Limit name="measured-frame-rate-1280x720" range="12-12" /> <!-- v98%=1.1 -->
         </MediaCodec>
     </Encoders>
     <Decoders>
         <MediaCodec name="OMX.Nvidia.h263.decode" type="video/3gpp" update="true">
-            <Limit name="measured-frame-rate-176x144" range="1967-1967" /> <!-- N=38 v93%=1.5 -->
-            <Limit name="measured-frame-rate-352x288" range="1897-1897" /> <!-- N=38 v93%=1.4 -->
+            <Limit name="measured-frame-rate-176x144" range="2053-2060" /> <!-- N=110 v98%=1.6 -->
+            <Limit name="measured-frame-rate-352x288" range="2033-2062" /> <!-- N=110 v98%=1.7 -->
         </MediaCodec>
         <MediaCodec name="OMX.Nvidia.h264.decode" type="video/avc" update="true">
-            <Limit name="measured-frame-rate-320x240" range="1816-1816" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-720x480" range="994-995" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1280x720" range="471-471" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1920x1088" range="210-210" /> <!-- N=38 v93%=1.0 -->
+            <Limit name="measured-frame-rate-320x240" range="1956-1956" /> <!-- N=110 v98%=1.3 -->
+            <Limit name="measured-frame-rate-720x480" range="995-995" /> <!-- N=110 v98%=1.1 -->
+            <Limit name="measured-frame-rate-1280x720" range="471-471" /> <!-- N=110 v98%=1.1 -->
+            <Limit name="measured-frame-rate-1920x1080" range="212-212" /> <!-- N=110 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.Nvidia.h265.decode" type="video/hevc" update="true">
-            <!-- measured 93%:1355-2968 med:1667 SLOW -->
-            <Limit name="measured-frame-rate-352x288" range="1666-2005" /> <!-- N=38 v93%=1.5 -->
-            <Limit name="measured-frame-rate-640x368" range="1770-1770" /> <!-- N=38 v93%=1.3 -->
-            <Limit name="measured-frame-rate-720x480" range="1526-1526" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-1280x720" range="701-701" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1920x1088" range="355-355" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-3840x2160" range="89-89" /> <!-- N=38 v93%=1.0 -->
+            <!-- measured 98%:1134-3356 med:2208/2204 FLAKY(mn=1019.4 < 1102 - 4408) -->
+            <Limit name="measured-frame-rate-352x288" range="2204-2204" /> <!-- N=110 v98%=1.7 -->
+            <Limit name="measured-frame-rate-640x360" range="1912-1917" /> <!-- N=110 v98%=1.4 -->
+            <Limit name="measured-frame-rate-720x480" range="1555-1556" /> <!-- N=110 v98%=1.3 -->
+            <Limit name="measured-frame-rate-1280x720" range="704-704" /> <!-- N=110 v98%=1.1 -->
+            <Limit name="measured-frame-rate-1920x1080" range="356-356" /> <!-- N=110 v98%=1.1 -->
+            <Limit name="measured-frame-rate-3840x2160" range="89-89" /> <!-- N=110 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.Nvidia.mp4.decode" type="video/mp4v-es" update="true">
-            <!-- measured 93%:1394-3077 med:1761 SLOW -->
-            <Limit name="measured-frame-rate-176x144" range="1760-2072" /> <!-- N=38 v93%=1.5 -->
-            <Limit name="measured-frame-rate-480x368" range="2034-2034" /> <!-- N=38 v93%=1.6 -->
+            <Limit name="measured-frame-rate-176x144" range="2031-2031" /> <!-- N=110 v98%=1.7 -->
+            <Limit name="measured-frame-rate-480x360" range="2056-2056" /> <!-- N=110 v98%=1.6 -->
         </MediaCodec>
         <MediaCodec name="OMX.Nvidia.vp8.decode" type="video/x-vnd.on2.vp8" update="true">
-            <Limit name="measured-frame-rate-320x192" range="1718-1874" /> <!-- N=38 v93%=1.4 -->
-            <Limit name="measured-frame-rate-640x368" range="1364-1364" /> <!-- N=38 v93%=1.4 -->
-            <Limit name="measured-frame-rate-1280x720" range="460-460" /> <!-- N=38 v93%=1.2 -->
-            <Limit name="measured-frame-rate-1920x1088" range="233-233" /> <!-- N=38 v93%=1.1 -->
+            <Limit name="measured-frame-rate-320x180" range="2043-2043" /> <!-- N=110 v98%=1.7 -->
+            <Limit name="measured-frame-rate-640x360" range="1576-1576" /> <!-- N=110 v98%=1.4 -->
+            <Limit name="measured-frame-rate-1280x720" range="462-463" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1920x1080" range="238-238" /> <!-- N=110 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.Nvidia.vp9.decode" type="video/x-vnd.on2.vp9" update="true">
-            <!-- measured 93%:1107-2778 med:1305 SLOW -->
-            <Limit name="measured-frame-rate-320x180" range="1305-1754" /> <!-- N=38 v93%=1.6 -->
-            <Limit name="measured-frame-rate-640x360" range="1253-1284" /> <!-- N=38 v93%=1.4 -->
-            <Limit name="measured-frame-rate-1280x720" range="428-428" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-1920x1080" range="246-246" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-3840x2160" range="63-64" /> <!-- N=38 v93%=1.0 -->
+            <!-- measured 98%:826-3096 med:1876/1856 FLAKY(mn=782.5 < 826 - 3712) -->
+            <Limit name="measured-frame-rate-320x180" range="1564-1856" /> <!-- TWEAKED N=110 v98%=1.9 -->
+            <Limit name="measured-frame-rate-640x360" range="1318-1319" /> <!-- N=110 v98%=1.4 -->
+            <Limit name="measured-frame-rate-1280x720" range="421-421" /> <!-- N=110 v98%=1.3 -->
+            <Limit name="measured-frame-rate-1920x1080" range="243-243" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-3840x2160" range="64-64" /> <!-- N=110 v98%=1.2 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.h263.decoder" type="video/3gpp" update="true">
-            <!-- measured 93%:704-1170 med:792 SLOW -->
-            <Limit name="measured-frame-rate-176x144" range="792-908" /> <!-- N=38 v93%=1.3 -->
+            <Limit name="measured-frame-rate-176x144" range="810-810" /> <!-- N=110 v98%=1.5 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.h264.decoder" type="video/avc" update="true">
-            <Limit name="measured-frame-rate-320x240" range="478-478" /> <!-- N=38 v93%=1.3 -->
-            <Limit name="measured-frame-rate-720x480" range="181-181" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1280x720" range="70-70" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1920x1080" range="31-32" /> <!-- N=38 v93%=1.0 -->
+            <Limit name="measured-frame-rate-320x240" range="493-524" /> <!-- N=110 v98%=1.5 -->
+            <Limit name="measured-frame-rate-720x480" range="181-181" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1280x720" range="67-67" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1920x1080" range="32-32" /> <!-- N=110 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.hevc.decoder" type="video/hevc" update="true">
-            <Limit name="measured-frame-rate-352x288" range="677-685" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-640x360" range="320-320" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-720x480" range="275-275" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-1280x720" range="106-106" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1920x1080" range="49-50" /> <!-- N=38 v93%=1.0 -->
+            <Limit name="measured-frame-rate-352x288" range="635-704" /> <!-- N=110 v98%=1.5 -->
+            <Limit name="measured-frame-rate-640x360" range="344-349" /> <!-- N=110 v98%=1.4 -->
+            <Limit name="measured-frame-rate-720x480" range="293-311" /> <!-- N=110 v98%=1.4 -->
+            <Limit name="measured-frame-rate-1280x720" range="115-115" /> <!-- N=110 v98%=1.3 -->
+            <Limit name="measured-frame-rate-1920x1080" range="56-56" /> <!-- N=110 v98%=1.3 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.mpeg4.decoder" type="video/mp4v-es" update="true">
-            <Limit name="measured-frame-rate-176x144" range="881-930" /> <!-- N=38 v93%=1.4 -->
+            <Limit name="measured-frame-rate-176x144" range="862-906" /> <!-- N=110 v98%=1.5 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.vp8.decoder" type="video/x-vnd.on2.vp8" update="true">
-            <Limit name="measured-frame-rate-320x180" range="900-904" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-640x360" range="314-314" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1280x720" range="67-67" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1920x1080" range="26-27" /> <!-- N=38 v93%=1.0 -->
+            <Limit name="measured-frame-rate-320x180" range="928-928" /> <!-- N=110 v98%=1.3 -->
+            <Limit name="measured-frame-rate-640x360" range="324-325" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1280x720" range="69-69" /> <!-- N=112 v98%=1.1 (OPR1.170623.006-) -->
+            <Limit name="measured-frame-rate-1920x1080" range="27-27" /> <!-- N=110 v98%=1.1 -->
         </MediaCodec>
         <MediaCodec name="OMX.google.vp9.decoder" type="video/x-vnd.on2.vp9" update="true">
-            <Limit name="measured-frame-rate-320x180" range="635-637" /> <!-- N=38 v93%=1.1 -->
-            <Limit name="measured-frame-rate-640x360" range="315-315" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1280x720" range="91-92" /> <!-- N=38 v93%=1.0 -->
-            <Limit name="measured-frame-rate-1920x1080" range="50-51" /> <!-- N=38 v93%=1.0 -->
+            <Limit name="measured-frame-rate-320x180" range="684-686" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-640x360" range="337-337" /> <!-- N=110 v98%=1.2 -->
+            <Limit name="measured-frame-rate-1280x720" range="140-146" /> <!-- N=110 v98%=1.4 -->
+            <Limit name="measured-frame-rate-1920x1080" range="84-84" /> <!-- N=110 v98%=1.3 -->
         </MediaCodec>
     </Decoders>
 </MediaCodecs>
diff --git a/overlay/frameworks/base/core/res/res/values/config.xml b/overlay/frameworks/base/core/res/res/values/config.xml
index 1b13f00..9766de6 100644
--- a/overlay/frameworks/base/core/res/res/values/config.xml
+++ b/overlay/frameworks/base/core/res/res/values/config.xml
@@ -51,6 +51,13 @@
     <!-- Enable device idle mode -->
     <bool name="config_enableAutoPowerModes">true</bool>
 
+    <!-- If true, enables verification of the lockscreen credential in the factory reset protection
+        flow. This should be true if gatekeeper / weaver credentials can still be checked after a
+        factory reset.
+
+        dragon's gatekeeper does not preserve credentials across factory resets. -->
+    <bool name="config_enableCredentialFactoryResetProtection">false</bool>
+
     <!-- Flag indicating whether the we should enable the automatic brightness in Settings.
          Software implementation will be used if config_hardware_auto_brightness_available is not set -->
     <bool name="config_automatic_brightness_available">true</bool>