Implement A2DP source and AVRCP target binder servers

Bug: 64231556
Test: On device.
Change-Id: I57136d5550e8e52626a1e7eb26b7d8c02cd94eb5
diff --git a/service/Android.bp b/service/Android.bp
index 42be835..6d136aa 100644
--- a/service/Android.bp
+++ b/service/Android.bp
@@ -15,8 +15,10 @@
 // ========================================================
 btserviceDaemonSrc = [
     "a2dp_sink.cc",
+    "a2dp_source.cc",
     "adapter.cc",
     "avrcp_control.cc",
+    "avrcp_target.cc",
     "daemon.cc",
     "gatt_client.cc",
     "gatt_server.cc",
@@ -41,7 +43,9 @@
 
 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",
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 2363127..b721ef8 100644
--- a/service/adapter.cc
+++ b/service/adapter.cc
@@ -25,7 +25,9 @@
 #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"
@@ -202,7 +204,9 @@
     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));
@@ -466,10 +470,18 @@
     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();
   }
@@ -764,9 +776,15 @@
   // 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 032f1d9..edb8afe 100644
--- a/service/adapter.h
+++ b/service/adapter.h
@@ -28,7 +28,9 @@
 namespace bluetooth {
 
 class A2dpSinkFactory;
+class A2dpSourceFactory;
 class AvrcpControlFactory;
+class AvrcpTargetFactory;
 class GattClientFactory;
 class GattServerFactory;
 class LowEnergyAdvertiserFactory;
@@ -183,11 +185,21 @@
   // 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_target.cc b/service/avrcp_target.cc
new file mode 100644
index 0000000..f502774
--- /dev/null
+++ b/service/avrcp_target.cc
@@ -0,0 +1,382 @@
+//
+//  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 android::String8;
+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();
+    String8 str(attrs[i].value());
+    size_t to_copy = std::min(sizeof(btrc_attrs[i].text) - 1, str.bytes());
+    if (to_copy < str.bytes()) {
+      LOG(WARNING) << "Value truncated";
+    }
+
+    memcpy(btrc_attrs[i].text, str.string(), 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();
+    String8 str(attrs[i].value());
+    size_t to_copy = std::min(sizeof(btrc_attrs[i].text) - 1, str.bytes());
+    if (to_copy < str.bytes()) {
+      LOG(WARNING) << "Value truncated";
+    }
+
+    memcpy(btrc_attrs[i].text, str.string(), 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/common/Android.bp b/service/common/Android.bp
index b481d19..ef08b21 100644
--- a/service/common/Android.bp
+++ b/service/common/Android.bp
@@ -9,10 +9,14 @@
     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/avrcp_string_value.cc",
         "bluetooth/characteristic.cc",
         "bluetooth/descriptor.cc",
         "bluetooth/remote_device_props.cc",
@@ -42,8 +46,12 @@
         "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",
@@ -57,7 +65,11 @@
         "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",
diff --git a/service/common/android/bluetooth/BluetoothA2dpCodecConfig.aidl b/service/common/android/bluetooth/BluetoothA2dpCodecConfig.aidl
new file mode 100644
index 0000000..083cd75
--- /dev/null
+++ b/service/common/android/bluetooth/BluetoothA2dpCodecConfig.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable BluetoothA2dpCodecConfig cpp_header "android/bluetooth/bluetooth_a2dp_codec_config.h";
diff --git a/service/common/android/bluetooth/BluetoothAvrcpIntValue.aidl b/service/common/android/bluetooth/BluetoothAvrcpIntValue.aidl
new file mode 100644
index 0000000..e126393
--- /dev/null
+++ b/service/common/android/bluetooth/BluetoothAvrcpIntValue.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable BluetoothAvrcpIntValue cpp_header "android/bluetooth/bluetooth_avrcp_int_value.h";
diff --git a/service/common/android/bluetooth/BluetoothAvrcpRegisterNotificationResponse.aidl b/service/common/android/bluetooth/BluetoothAvrcpRegisterNotificationResponse.aidl
new file mode 100644
index 0000000..147a187
--- /dev/null
+++ b/service/common/android/bluetooth/BluetoothAvrcpRegisterNotificationResponse.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable BluetoothAvrcpRegisterNotificationResponse cpp_header "android/bluetooth/bluetooth_avrcp_register_notification_response.h";
diff --git a/service/common/android/bluetooth/BluetoothAvrcpStringValue.aidl b/service/common/android/bluetooth/BluetoothAvrcpStringValue.aidl
new file mode 100644
index 0000000..5bbfbd4
--- /dev/null
+++ b/service/common/android/bluetooth/BluetoothAvrcpStringValue.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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;
+
+parcelable BluetoothAvrcpStringValue cpp_header "android/bluetooth/bluetooth_avrcp_string_value.h";
diff --git a/service/common/android/bluetooth/IBluetooth.aidl b/service/common/android/bluetooth/IBluetooth.aidl
index 9223afb..3986ad7 100644
--- a/service/common/android/bluetooth/IBluetooth.aidl
+++ b/service/common/android/bluetooth/IBluetooth.aidl
@@ -23,7 +23,9 @@
 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;
 
@@ -61,5 +63,7 @@
   IBluetoothGattClient GetGattClientInterface();
   IBluetoothGattServer GetGattServerInterface();
   IBluetoothA2dpSink GetA2dpSinkInterface();
+  IBluetoothA2dpSource GetA2dpSourceInterface();
   IBluetoothAvrcpControl GetAvrcpControlInterface();
+  IBluetoothAvrcpTarget GetAvrcpTargetInterface();
 }
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/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/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/service/common/android/bluetooth/bluetooth_a2dp_codec_config.h b/service/common/android/bluetooth/bluetooth_a2dp_codec_config.h
new file mode 100644
index 0000000..0071d67
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_a2dp_codec_config.h
@@ -0,0 +1,57 @@
+//
+//  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/a2dp_codec_config.h"
+
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothA2dpCodecConfig : public Parcelable,
+                                 public ::bluetooth::A2dpCodecConfig {
+ public:
+  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.
+  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_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/service/common/android/bluetooth/bluetooth_avrcp_int_value.h b/service/common/android/bluetooth/bluetooth_avrcp_int_value.h
new file mode 100644
index 0000000..80eed7c
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_int_value.h
@@ -0,0 +1,57 @@
+//
+//  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_int_value.h"
+
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothAvrcpIntValue : public Parcelable,
+                               public ::bluetooth::AvrcpIntValue {
+ public:
+  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.
+  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_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..72ed179
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_string_value.cc
@@ -0,0 +1,52 @@
+//
+//  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(value_);
+  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;
+
+  status = parcel->readString16(&value_);
+  if (status != OK) return status;
+
+  return status;
+}
+
+}  // namespace bluetooth
+}  // namespace android
diff --git a/service/common/android/bluetooth/bluetooth_avrcp_string_value.h b/service/common/android/bluetooth/bluetooth_avrcp_string_value.h
new file mode 100644
index 0000000..8f7e952
--- /dev/null
+++ b/service/common/android/bluetooth/bluetooth_avrcp_string_value.h
@@ -0,0 +1,57 @@
+//
+//  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_string_value.h"
+
+using android::Parcel;
+using android::Parcelable;
+using android::status_t;
+
+namespace android {
+namespace bluetooth {
+
+class BluetoothAvrcpStringValue : public Parcelable,
+                                  public ::bluetooth::AvrcpStringValue {
+ public:
+  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.
+  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/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_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.cc b/service/common/bluetooth/avrcp_string_value.cc
new file mode 100644
index 0000000..65f7ffa
--- /dev/null
+++ b/service/common/bluetooth/avrcp_string_value.cc
@@ -0,0 +1,29 @@
+//
+//  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_string_value.h"
+
+using android::String16;
+
+namespace bluetooth {
+
+AvrcpStringValue::AvrcpStringValue() = default;
+AvrcpStringValue::AvrcpStringValue(const AvrcpStringValue& other) = default;
+AvrcpStringValue::AvrcpStringValue(int id, const String16& value)
+    : id_(id), value_(value) {}
+AvrcpStringValue::~AvrcpStringValue() = default;
+
+}  // 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..8ba6cb4
--- /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 <utils/String16.h>
+
+namespace bluetooth {
+
+class AvrcpStringValue {
+ public:
+  AvrcpStringValue();
+  AvrcpStringValue(const AvrcpStringValue& other);
+  AvrcpStringValue(int id, const android::String16& value);
+  ~AvrcpStringValue();
+
+  int id() const { return id_; }
+  const android::String16& value() const { return value_; }
+
+ protected:
+  int id_ = 0;
+  android::String16 value_;
+};
+
+}  // namespace bluetooth
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_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 30090ee..ca36019 100644
--- a/service/ipc/binder/bluetooth_binder_server.cc
+++ b/service/ipc/binder/bluetooth_binder_server.cc
@@ -19,7 +19,9 @@
 #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"
@@ -214,6 +216,29 @@
   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__;
@@ -318,6 +343,30 @@
   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;
diff --git a/service/ipc/binder/bluetooth_binder_server.h b/service/ipc/binder/bluetooth_binder_server.h
index 1388626..bfeb589 100644
--- a/service/ipc/binder/bluetooth_binder_server.h
+++ b/service/ipc/binder/bluetooth_binder_server.h
@@ -25,7 +25,9 @@
 
 #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>
@@ -42,7 +44,9 @@
 
 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;
@@ -54,6 +58,8 @@
 namespace binder {
 
 class BluetoothA2dpSinkBinderServer;
+class BluetoothA2dpSourceBinderServer;
+class BluetoothAvrcpTargetBinderServer;
 
 // Implements the server side of the IBluetooth Binder interface.
 class BluetoothBinderServer : public BnBluetooth,
@@ -93,6 +99,8 @@
   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(
@@ -105,6 +113,8 @@
       ::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;
@@ -147,6 +157,10 @@
   // 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_;
@@ -171,6 +185,10 @@
   // 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/test/mock_adapter.h b/service/test/mock_adapter.h
index ff64ab1..2c496b1 100644
--- a/service/test/mock_adapter.h
+++ b/service/test/mock_adapter.h
@@ -52,7 +52,9 @@
   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*());