//
//  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 <base/logging.h>
#include <base/observer_list.h>

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

#include "abstract_observer_list.h"
#include "notreached.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"
#include "types/raw_address.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);
          if (hal_name) {
            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,
                                int fail_reason) 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, int transport_link_type,
                               bt_hci_error_code_t hci_reason) 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_;
  btbase::AbstractObserverList<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
