//
//  Copyright 2015 Google, Inc.
//
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at:
//
//  http://www.apache.org/licenses/LICENSE-2.0
//
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
//

#include "service/adapter.h"

#include <atomic>
#include <mutex>
#include <string>
#include <unordered_set>

#include <base/logging.h>
#include <base/observer_list.h>

#include "service/a2dp_sink.h"
#include "service/a2dp_source.h"
#include "service/avrcp_control.h"
#include "service/avrcp_target.h"
#include "service/common/bluetooth/util/atomic_string.h"
#include "service/gatt_client.h"
#include "service/gatt_server.h"
#include "service/hal/bluetooth_interface.h"
#include "service/logging_helpers.h"
#include "service/low_energy_advertiser.h"
#include "service/low_energy_client.h"
#include "service/low_energy_scanner.h"

using std::lock_guard;
using std::mutex;

namespace bluetooth {

namespace {

RemoteDeviceProps ParseRemoteDeviceProps(int num_properties,
                                         bt_property_t* properties) {
  std::string name;
  std::string address;
  std::vector<Uuid> service_uuids;
  int32_t device_class = 0;
  int32_t device_type = 0;
  int32_t rssi = 0;

  for (int i = 0; i < num_properties; ++i) {
    bt_property_t* property = properties + i;
    switch (property->type) {
      case BT_PROPERTY_BDNAME: {
        if (property->len < 0) {
          NOTREACHED() << "Invalid length for BT_PROPERTY_BDNAME";
          break;
        }
        bt_bdname_t* hal_name = reinterpret_cast<bt_bdname_t*>(property->val);
        name = reinterpret_cast<char*>(hal_name->name);
        break;
      }
      case BT_PROPERTY_BDADDR: {
        if (property->len != sizeof(RawAddress)) {
          NOTREACHED() << "Invalid length for BT_PROPERTY_BDADDR";
          break;
        }
        address = BtAddrString(reinterpret_cast<RawAddress*>(property->val));
        break;
      }
      case BT_PROPERTY_UUIDS: {
        if (property->len < 0) {
          NOTREACHED() << "Negative length on BT_PROPERTY_UUIDS:";
          break;
        }
        if (property->len % sizeof(Uuid) != 0) {
          NOTREACHED() << "Trailing bytes on BT_PROPERTY_UUIDS:";
        }
        auto uuids = static_cast<const Uuid*>(property->val);

        for (size_t i = 0; i < property->len / sizeof(Uuid); ++i) {
          service_uuids.push_back(uuids[i]);
        }
        break;
      }
      case BT_PROPERTY_CLASS_OF_DEVICE: {
        if (property->len != sizeof(int32_t)) {
          NOTREACHED() << "Invalid length for BT_PROPERTY_CLASS_OF_DEVICE";
          break;
        }
        device_class = *reinterpret_cast<const int32_t*>(property->val);
        break;
      }
      case BT_PROPERTY_TYPE_OF_DEVICE: {
        if (property->len != sizeof(int32_t)) {
          NOTREACHED() << "Invalid length for BT_PROPERTY_TYPE_OF_DEVICE";
          break;
        }
        device_type = *reinterpret_cast<const int32_t*>(property->val);
        break;
      }
      case BT_PROPERTY_REMOTE_RSSI: {
        if (property->len != sizeof(int8_t)) {
          NOTREACHED() << "Invalid length for BT_PROPERTY_REMOTE_RSSI";
          break;
        }
        rssi = *reinterpret_cast<const int8_t*>(property->val);
        break;
      }
      default:
        VLOG(1) << "Unhandled adapter property: "
                << BtPropertyText(property->type);
        break;
    }
  }

  return RemoteDeviceProps(name, address, service_uuids, device_class,
                           device_type, rssi);
}

}  // namespace

// static
const char Adapter::kDefaultAddress[] = "00:00:00:00:00:00";
// static
const char Adapter::kDefaultName[] = "not-initialized";

// TODO(armansito): The following constants come straight from
// packages/apps/Bluetooth/src/c/a/b/btservice/AdapterService.java. It would be
// nice to know if there were a way to obtain these values from the stack
// instead of hardcoding them here.

// The minimum number of advertising instances required for multi-advertisement
// support.
const int kMinAdvInstancesForMultiAdv = 5;

// Used when determining if offloaded scan filtering is supported.
const int kMinOffloadedFilters = 10;

// Used when determining if offloaded scan batching is supported.
const int kMinOffloadedScanStorageBytes = 1024;

void Adapter::Observer::OnAdapterStateChanged(Adapter* adapter,
                                              AdapterState prev_state,
                                              AdapterState new_state) {
  // Default implementation does nothing
}

void Adapter::Observer::OnDeviceConnectionStateChanged(
    Adapter* adapter, const std::string& device_address, bool connected) {
  // Default implementation does nothing
}

void Adapter::Observer::OnScanEnableChanged(Adapter* adapter,
                                            bool scan_enabled) {
  // Default implementation does nothing
}

void Adapter::Observer::OnSspRequest(Adapter* adapter,
                                     const std::string& device_address,
                                     const std::string& device_name, int cod,
                                     int pairing_variant, int pass_key) {
  // Default implementation does nothing
}

void Adapter::Observer::OnBondStateChanged(Adapter* adapter, int status,
                                           const std::string& device_address,
                                           int state) {
  // Default implementation does nothing
}

void Adapter::Observer::OnGetBondedDevices(
    Adapter* adapter, int status,
    const std::vector<std::string>& bonded_devices) {
  // Default implementation does nothing
}

void Adapter::Observer::OnGetRemoteDeviceProperties(
    Adapter* adapter, int status, const std::string& device_address,
    const RemoteDeviceProps& properties) {
  // Default implementation does nothing
}

void Adapter::Observer::OnDeviceFound(Adapter* adapter,
                                      const RemoteDeviceProps& properties) {
  // Default implementation does nothing
}

// The real Adapter implementation used in production.
class AdapterImpl : public Adapter, public hal::BluetoothInterface::Observer {
 public:
  AdapterImpl()
      : state_(ADAPTER_STATE_OFF),
        address_(kDefaultAddress),
        name_(kDefaultName) {
    memset(&local_le_features_, 0, sizeof(local_le_features_));
    hal::BluetoothInterface::Get()->AddObserver(this);
    a2dp_sink_factory_.reset(new A2dpSinkFactory);
    a2dp_source_factory_.reset(new A2dpSourceFactory);
    avrcp_control_factory_.reset(new AvrcpControlFactory);
    avrcp_target_factory_.reset(new AvrcpTargetFactory);
    ble_client_factory_.reset(new LowEnergyClientFactory(*this));
    ble_advertiser_factory_.reset(new LowEnergyAdvertiserFactory());
    ble_scanner_factory_.reset(new LowEnergyScannerFactory(*this));
    gatt_client_factory_.reset(new GattClientFactory());
    gatt_server_factory_.reset(new GattServerFactory());
    hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
  }

  ~AdapterImpl() override {
    hal::BluetoothInterface::Get()->RemoveObserver(this);
  }

  void AddObserver(Adapter::Observer* observer) override {
    lock_guard<mutex> lock(observers_lock_);
    observers_.AddObserver(observer);
  }

  void RemoveObserver(Adapter::Observer* observer) override {
    lock_guard<mutex> lock(observers_lock_);
    observers_.RemoveObserver(observer);
  }

  AdapterState GetState() const override { return state_.load(); }

  bool IsEnabled() const override { return state_.load() == ADAPTER_STATE_ON; }

  bool Enable() override {
    AdapterState current_state = GetState();
    if (current_state != ADAPTER_STATE_OFF) {
      LOG(INFO) << "Adapter not disabled - state: "
                << AdapterStateToString(current_state);
      return false;
    }

    // Set the state before calling enable() as there might be a race between
    // here and the AdapterStateChangedCallback.
    state_ = ADAPTER_STATE_TURNING_ON;
    NotifyAdapterStateChanged(current_state, state_);

    int status = hal::BluetoothInterface::Get()->GetHALInterface()->enable();
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to enable Bluetooth - status: "
                 << BtStatusText((const bt_status_t)status);
      state_ = ADAPTER_STATE_OFF;
      NotifyAdapterStateChanged(ADAPTER_STATE_TURNING_ON, state_);
      return false;
    }

    return true;
  }

  bool Disable() override {
    if (!IsEnabled()) {
      LOG(INFO) << "Adapter is not enabled";
      return false;
    }

    AdapterState current_state = GetState();

    // Set the state before calling enable() as there might be a race between
    // here and the AdapterStateChangedCallback.
    state_ = ADAPTER_STATE_TURNING_OFF;
    NotifyAdapterStateChanged(current_state, state_);

    int status = hal::BluetoothInterface::Get()->GetHALInterface()->disable();
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to disable Bluetooth - status: "
                 << BtStatusText((const bt_status_t)status);
      state_ = current_state;
      NotifyAdapterStateChanged(ADAPTER_STATE_TURNING_OFF, state_);
      return false;
    }

    return true;
  }

  std::string GetName() const override { return name_.Get(); }

  bool SetName(const std::string& name) override {
    bt_bdname_t hal_name;
    size_t max_name_len = sizeof(hal_name.name);

    // Include the \0 byte in size measurement.
    if (name.length() >= max_name_len) {
      LOG(ERROR) << "Given name \"" << name << "\" is larger than maximum"
                 << " allowed size: " << max_name_len;
      return false;
    }

    strncpy(reinterpret_cast<char*>(hal_name.name), name.c_str(),
            name.length() + 1);

    VLOG(1) << "Setting adapter name: " << name;

    if (!SetAdapterProperty(BT_PROPERTY_BDNAME, &hal_name, sizeof(hal_name))) {
      LOG(ERROR) << "Failed to set adapter name: " << name;
      return false;
    }

    return true;
  }

  std::string GetAddress() const override { return address_.Get(); }

  bool SetScanMode(int scan_mode) override {
    switch (scan_mode) {
      case BT_SCAN_MODE_NONE:
      case BT_SCAN_MODE_CONNECTABLE:
      case BT_SCAN_MODE_CONNECTABLE_DISCOVERABLE:
        break;
      default:
        LOG(ERROR) << "Unknown scan mode: " << scan_mode;
        return false;
    }

    auto bd_scanmode = static_cast<bt_scan_mode_t>(scan_mode);

    if (!SetAdapterProperty(BT_PROPERTY_ADAPTER_SCAN_MODE, &bd_scanmode,
                            sizeof(bd_scanmode))) {
      LOG(ERROR) << "Failed to set scan mode to : " << scan_mode;
      return false;
    }

    return true;
  }

  bool SetScanEnable(bool scan_enable) override {
    if (scan_enable) {
      int status =
          hal::BluetoothInterface::Get()->GetHALInterface()->start_discovery();
      if (status != BT_STATUS_SUCCESS) {
        LOG(ERROR) << "Failed to enable scanning";
        return false;
      }
    } else {
      int status =
          hal::BluetoothInterface::Get()->GetHALInterface()->cancel_discovery();
      if (status != BT_STATUS_SUCCESS) {
        LOG(ERROR) << "Failed to disable scanning";
        return false;
      }
    }
    return true;
  }

  bool SspReply(const std::string& device_address, int variant, bool accept,
                int32_t pass_key) override {
    RawAddress addr;
    if (!RawAddress::FromString(device_address, addr)) {
      LOG(ERROR) << "Invalid device address given: " << device_address;
      return false;
    }

    int status = hal::BluetoothInterface::Get()->GetHALInterface()->ssp_reply(
        &addr, static_cast<bt_ssp_variant_t>(variant), accept, pass_key);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to send SSP response - status: "
                 << BtStatusText((const bt_status_t)status);
      return false;
    }

    return true;
  }

  bool CreateBond(const std::string& device_address, int transport) override {
    RawAddress addr;
    if (!RawAddress::FromString(device_address, addr)) {
      LOG(ERROR) << "Invalid device address given: " << device_address;
      return false;
    }

    int status = hal::BluetoothInterface::Get()->GetHALInterface()->create_bond(
        &addr, transport);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to create bond - status: "
                 << BtStatusText((const bt_status_t)status);
      return false;
    }

    return true;
  }

  bool IsMultiAdvertisementSupported() override {
    lock_guard<mutex> lock(local_le_features_lock_);
    return local_le_features_.max_adv_instance >= kMinAdvInstancesForMultiAdv;
  }

  bool IsDeviceConnected(const std::string& device_address) override {
    lock_guard<mutex> lock(connected_devices_lock_);
    return connected_devices_.find(device_address) != connected_devices_.end();
  }

  int GetTotalNumberOfTrackableAdvertisements() override {
    lock_guard<mutex> lock(local_le_features_lock_);
    return local_le_features_.total_trackable_advertisers;
  }

  bool IsOffloadedFilteringSupported() override {
    lock_guard<mutex> lock(local_le_features_lock_);
    return local_le_features_.max_adv_filter_supported >= kMinOffloadedFilters;
  }

  bool IsOffloadedScanBatchingSupported() override {
    lock_guard<mutex> lock(local_le_features_lock_);
    return local_le_features_.scan_result_storage_size >=
           kMinOffloadedScanStorageBytes;
  }

  bool GetBondedDevices() override {
    int status =
        hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_property(
            BT_PROPERTY_ADAPTER_BONDED_DEVICES);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to get bonded devices. Status: "
                 << BtStatusText(static_cast<bt_status_t>(status));
      return false;
    }

    return true;
  }

  bool RemoveBond(const std::string& device_address) override {
    RawAddress addr;
    if (!RawAddress::FromString(device_address, addr)) {
      LOG(ERROR) << "Invalid device address given: " << device_address;
      return false;
    }

    int status =
        hal::BluetoothInterface::Get()->GetHALInterface()->remove_bond(&addr);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to send remove bond - status: "
                 << BtStatusText(static_cast<bt_status_t>(status));
      return false;
    }

    return true;
  }

  bool GetRemoteDeviceProperties(const std::string& device_address) override {
    RawAddress addr;
    if (!RawAddress::FromString(device_address, addr)) {
      LOG(ERROR) << "Invalid device address given: " << device_address;
      return false;
    }

    int status = hal::BluetoothInterface::Get()
                     ->GetHALInterface()
                     ->get_remote_device_properties(&addr);
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "Failed to send GetRemoteDeviceProperties - status: "
                 << BtStatusText((const bt_status_t)status);
      return false;
    }

    return true;
  }

  A2dpSinkFactory* GetA2dpSinkFactory() const override {
    return a2dp_sink_factory_.get();
  }

  A2dpSourceFactory* GetA2dpSourceFactory() const override {
    return a2dp_source_factory_.get();
  }

  AvrcpControlFactory* GetAvrcpControlFactory() const override {
    return avrcp_control_factory_.get();
  }

  AvrcpTargetFactory* GetAvrcpTargetFactory() const override {
    return avrcp_target_factory_.get();
  }

  LowEnergyClientFactory* GetLowEnergyClientFactory() const override {
    return ble_client_factory_.get();
  }

  LowEnergyAdvertiserFactory* GetLeAdvertiserFactory() const override {
    return ble_advertiser_factory_.get();
  }

  LowEnergyScannerFactory* GetLeScannerFactory() const override {
    return ble_scanner_factory_.get();
  }

  GattClientFactory* GetGattClientFactory() const override {
    return gatt_client_factory_.get();
  }

  GattServerFactory* GetGattServerFactory() const override {
    return gatt_server_factory_.get();
  }

  // hal::BluetoothInterface::Observer overrides.
  void AdapterStateChangedCallback(bt_state_t state) override {
    LOG(INFO) << "Adapter state changed: " << BtStateText(state);

    AdapterState prev_state = GetState();

    switch (state) {
      case BT_STATE_OFF:
        state_ = ADAPTER_STATE_OFF;
        break;

      case BT_STATE_ON:
        state_ = ADAPTER_STATE_ON;
        break;

      default:
        NOTREACHED();
    }

    NotifyAdapterStateChanged(prev_state, GetState());
  }

  void AdapterPropertiesCallback(bt_status_t status, int num_properties,
                                 bt_property_t* properties) override {
    LOG(INFO) << "Adapter properties changed";

    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "status: " << BtStatusText(status);

      for (int i = 0; i < num_properties; ++i) {
        bt_property_t* property = properties + i;
        if (property->type == BT_PROPERTY_ADAPTER_BONDED_DEVICES) {
          lock_guard<mutex> lock(observers_lock_);
          for (auto& observer : observers_) {
            observer.OnGetBondedDevices(this, status, {});
          }
        }
      }
      return;
    }

    for (int i = 0; i < num_properties; i++) {
      bt_property_t* property = properties + i;
      switch (property->type) {
        case BT_PROPERTY_BDADDR: {
          std::string address =
              BtAddrString(reinterpret_cast<RawAddress*>(property->val));
          LOG(INFO) << "Adapter address changed: " << address;
          address_.Set(address);
          break;
        }
        case BT_PROPERTY_BDNAME: {
          bt_bdname_t* hal_name = reinterpret_cast<bt_bdname_t*>(property->val);
          std::string name = reinterpret_cast<char*>(hal_name->name);
          LOG(INFO) << "Adapter name changed: " << name;
          name_.Set(name);
          break;
        }
        case BT_PROPERTY_LOCAL_LE_FEATURES: {
          lock_guard<mutex> lock(local_le_features_lock_);
          if (property->len != sizeof(bt_local_le_features_t)) {
            LOG(WARNING) << "Malformed value received for property: "
                         << "BT_PROPERTY_LOCAL_LE_FEATURES";
            break;
          }
          bt_local_le_features_t* features =
              reinterpret_cast<bt_local_le_features_t*>(property->val);
          memcpy(&local_le_features_, features, sizeof(*features));
          LOG(INFO) << "Supported LE features updated";
          break;
        }
        case BT_PROPERTY_ADAPTER_BONDED_DEVICES: {
          if (property->len < 0) {
            NOTREACHED() << "Negative property length";
            break;
          }
          auto addrs = reinterpret_cast<const RawAddress*>(property->val);
          if (property->len % sizeof(addrs[0]) != 0) {
            LOG(ERROR) << "Invalid property length: " << property->len;
            // TODO(bcf): Seems to be a bug where we hit this somewhat
            // frequently.
            break;
          }
          std::vector<std::string> str_addrs;

          for (size_t i = 0; i < property->len / sizeof(addrs[0]); ++i)
            str_addrs.push_back(BtAddrString(addrs + i));

          lock_guard<mutex> lock(observers_lock_);
          for (auto& observer : observers_) {
            observer.OnGetBondedDevices(this, status, str_addrs);
          }
          break;
        }
        default:
          VLOG(1) << "Unhandled adapter property: "
                  << BtPropertyText(property->type);
          break;
      }

      // TODO(armansito): notify others of the updated properties
    }
  }

  void RemoteDevicePropertiesCallback(bt_status_t status,
                                      RawAddress* remote_bdaddr,
                                      int num_properties,
                                      bt_property_t* properties) override {
    std::string device_address = BtAddrString(remote_bdaddr);
    if (status != BT_STATUS_SUCCESS) {
      lock_guard<mutex> lock(observers_lock_);
      for (auto& observer : observers_) {
        observer.OnGetRemoteDeviceProperties(this, status, device_address,
                                             RemoteDeviceProps());
      }
      return;
    }

    RemoteDeviceProps props =
        ParseRemoteDeviceProps(num_properties, properties);

    std::string address = BtAddrString(remote_bdaddr);
    props.set_address(address);

    lock_guard<mutex> lock(observers_lock_);
    for (auto& observer : observers_) {
      observer.OnGetRemoteDeviceProperties(this, status, device_address, props);
    }
  }

  void DeviceFoundCallback(int num_properties,
                           bt_property_t* properties) override {
    RemoteDeviceProps props =
        ParseRemoteDeviceProps(num_properties, properties);

    lock_guard<mutex> lock(observers_lock_);
    for (auto& observer : observers_) {
      observer.OnDeviceFound(this, props);
    }
  }

  void DiscoveryStateChangedCallback(bt_discovery_state_t state) override {
    bool enabled = false;
    switch (state) {
      case BT_DISCOVERY_STOPPED:
        enabled = false;
        break;
      case BT_DISCOVERY_STARTED:
        enabled = true;
        break;
      default:
        NOTREACHED();
    }

    for (auto& observer : observers_) {
      observer.OnScanEnableChanged(this, enabled);
    }
  }

  void SSPRequestCallback(RawAddress* remote_bdaddr, bt_bdname_t* bd_name,
                          uint32_t cod, bt_ssp_variant_t pairing_variant,
                          uint32_t pass_key) override {
    std::string device_address = BtAddrString(remote_bdaddr);
    std::string name = reinterpret_cast<char*>(bd_name->name);

    lock_guard<mutex> lock(observers_lock_);
    for (auto& observer : observers_) {
      observer.OnSspRequest(this, device_address, name, cod, pairing_variant,
                            pass_key);
    }
  }

  void BondStateChangedCallback(bt_status_t status, RawAddress* remote_bdaddr,
                                bt_bond_state_t state) override {
    std::string device_address = BtAddrString(remote_bdaddr);

    lock_guard<mutex> lock(observers_lock_);
    for (auto& observer : observers_) {
      observer.OnBondStateChanged(this, status, device_address, state);
    }
  }

  void AclStateChangedCallback(bt_status_t status,
                               const RawAddress& remote_bdaddr,
                               bt_acl_state_t state) override {
    std::string device_address = BtAddrString(&remote_bdaddr);
    bool connected = (state == BT_ACL_STATE_CONNECTED);
    LOG(INFO) << "ACL state changed: " << device_address
              << " - connected: " << (connected ? "true" : "false");

    // If this is reported with an error status, I suppose the best thing we can
    // do is to log it and ignore the event.
    if (status != BT_STATUS_SUCCESS) {
      LOG(ERROR) << "status: " << BtStatusText(status);
      return;
    }

    // Introduce a scope to manage |connected_devices_lock_| with RAII.
    {
      lock_guard<mutex> lock(connected_devices_lock_);
      if (connected)
        connected_devices_.insert(device_address);
      else
        connected_devices_.erase(device_address);
    }

    lock_guard<mutex> lock(observers_lock_);
    for (auto& observer : observers_) {
      observer.OnDeviceConnectionStateChanged(this, device_address, connected);
    }
  }

  // Sends a request to set the given HAL adapter property type and value.
  bool SetAdapterProperty(bt_property_type_t type, void* value, int length) {
    CHECK(length > 0);
    CHECK(value);

    bt_property_t property;
    property.len = length;
    property.val = value;
    property.type = type;

    int status =
        hal::BluetoothInterface::Get()->GetHALInterface()->set_adapter_property(
            &property);
    if (status != BT_STATUS_SUCCESS) {
      VLOG(1) << "Failed to set property";
      return false;
    }

    return true;
  }

  // Helper for invoking the AdapterStateChanged observer method.
  void NotifyAdapterStateChanged(AdapterState prev_state,
                                 AdapterState new_state) {
    if (prev_state == new_state) return;

    lock_guard<mutex> lock(observers_lock_);
    for (auto& observer : observers_) {
      observer.OnAdapterStateChanged(this, prev_state, new_state);
    }
  }

 private:
  // The current adapter state.
  std::atomic<AdapterState> state_;

  // The Bluetooth device address of the local adapter in string from
  // (i.e.. XX:XX:XX:XX:XX:XX)
  util::AtomicString address_;

  // The current local adapter name.
  util::AtomicString name_;

  // The current set of supported LE features as obtained from the stack. The
  // values here are all initially set to 0 and updated when the corresponding
  // adapter property has been received from the stack.
  std::mutex local_le_features_lock_;
  bt_local_le_features_t local_le_features_;

  // List of observers that are interested in notifications from us.
  std::mutex observers_lock_;
  base::ObserverList<Adapter::Observer> observers_;

  // List of devices addresses that are currently connected.
  std::mutex connected_devices_lock_;
  std::unordered_set<std::string> connected_devices_;

  // Factory used to create per-app A2dpSink instances.
  std::unique_ptr<A2dpSinkFactory> a2dp_sink_factory_;

  // Factory used to create per-app A2dpSource instances.
  std::unique_ptr<A2dpSourceFactory> a2dp_source_factory_;

  // Factory used to create per-app AvrcpControl instances.
  std::unique_ptr<AvrcpControlFactory> avrcp_control_factory_;

  // Factory used to create per-app AvrcpTarget instances.
  std::unique_ptr<AvrcpTargetFactory> avrcp_target_factory_;

  // Factory used to create per-app LowEnergyClient instances.
  std::unique_ptr<LowEnergyClientFactory> ble_client_factory_;

  // Factory used to create per-app LeAdvertiser instances.
  std::unique_ptr<LowEnergyAdvertiserFactory> ble_advertiser_factory_;

  // Factory used to create per-app LeScanner instances.
  std::unique_ptr<LowEnergyScannerFactory> ble_scanner_factory_;

  // Factory used to create per-app GattClient instances.
  std::unique_ptr<GattClientFactory> gatt_client_factory_;

  // Factory used to create per-app GattServer instances.
  std::unique_ptr<GattServerFactory> gatt_server_factory_;

  DISALLOW_COPY_AND_ASSIGN(AdapterImpl);
};

// static
std::unique_ptr<Adapter> Adapter::Create() {
  return std::unique_ptr<Adapter>(new AdapterImpl());
}

}  // namespace bluetooth
