text: //
  //  Copyright (C) 2015 Google, Inc.
  //
  //  Licensed under the Apache License, Version 2.0 (the "License");
  //  you may not use this file except in compliance with the License.
  //  You may obtain a copy of the License at:
  //
  //  http://www.apache.org/licenses/LICENSE-2.0
  //
  //  Unless required by applicable law or agreed to in writing, software
  //  distributed under the License is distributed on an "AS IS" BASIS,
  //  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  //  See the License for the specific language governing permissions and
  //  limitations under the License.
  //
  
  #include "service/hal/bluetooth_gatt_interface.h"
  
  #include <mutex>
  #include <shared_mutex>
  
  #include <base/logging.h>
  #include <base/observer_list.h>
  
  #include "service/hal/bluetooth_interface.h"
  #include "service/logging_helpers.h"
  
  using std::lock_guard;
  using std::unique_lock;
  using std::shared_lock;
  using std::mutex;
  #if defined(OS_GENERIC) && defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION < 3500)
  using shared_mutex_impl = std::shared_mutex;
  #else
  using shared_mutex_impl = std::shared_timed_mutex;
  #endif
  
  namespace bluetooth {
  namespace hal {
  
  namespace {
  
  // The global BluetoothGattInterface instance.
  BluetoothGattInterface* g_interface = nullptr;
  
  // Mutex used by callbacks to access |g_interface|. If we initialize or clean it
  // use unique_lock. If only accessing |g_interface| use shared lock.
  // TODO(jpawlowski): this should be just shared_mutex, as we currently don't use
  // timed methods. Change to shared_mutex when we upgrade to C++14
  shared_mutex_impl g_instance_lock;
  
  // Helper for obtaining the observer lists. This is forward declared here
  // and defined below since it depends on BluetoothInterfaceImpl.
  base::ObserverList<BluetoothGattInterface::ScannerObserver>*
  GetScannerObservers();
  base::ObserverList<BluetoothGattInterface::ClientObserver>*
  GetClientObservers();
  base::ObserverList<BluetoothGattInterface::ServerObserver>*
  GetServerObservers();
  
  #define FOR_EACH_SCANNER_OBSERVER(func)                      \
    FOR_EACH_OBSERVER(BluetoothGattInterface::ScannerObserver, \
                      *GetScannerObservers(), func)
  
  #define FOR_EACH_CLIENT_OBSERVER(func)                      \
    FOR_EACH_OBSERVER(BluetoothGattInterface::ClientObserver, \
                      *GetClientObservers(), func)
  
  #define FOR_EACH_SERVER_OBSERVER(func)                      \
    FOR_EACH_OBSERVER(BluetoothGattInterface::ServerObserver, \
                      *GetServerObservers(), func)
  
  #define VERIFY_INTERFACE_OR_RETURN()                                   \
    do {                                                                 \
      if (!g_interface) {                                                \
        LOG(WARNING) << "Callback received while |g_interface| is NULL"; \
        return;                                                          \
      }                                                                  \
    } while (0)
  
  void RegisterClientCallback(int status, int client_if, bt_uuid_t* app_uuid) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(app_uuid);
  
    FOR_EACH_CLIENT_OBSERVER(
        RegisterClientCallback(g_interface, status, client_if, *app_uuid));
  }
  
  void ScanResultCallback(
      uint16_t ble_evt_type, uint8_t addr_type, bt_bdaddr_t* bda,
      uint8_t ble_primary_phy, uint8_t ble_secondary_phy,
      uint8_t ble_advertising_sid, int8_t ble_tx_power, int8_t rssi,
      uint16_t ble_periodic_adv_int,
      std::vector<uint8_t> adv_data) {  // NOLINT(pass-by-value)
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    VLOG(2) << __func__ << " - BD_ADDR: " << BtAddrString(bda)
            << " RSSI: " << rssi;
    FOR_EACH_SCANNER_OBSERVER(
        ScanResultCallback(g_interface, *bda, rssi, adv_data));
  }
  
  void ConnectCallback(int conn_id, int status, int client_if, bt_bdaddr_t* bda) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    VLOG(2) << __func__ << " - status: " << status << " client_if: " << client_if
            << " - BD_ADDR: " << BtAddrString(bda) << " - conn_id: " << conn_id;
  
    FOR_EACH_CLIENT_OBSERVER(
        ConnectCallback(g_interface, conn_id, status, client_if, *bda));
  }
  
  void DisconnectCallback(int conn_id, int status, int client_if,
                          bt_bdaddr_t* bda) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status
            << " client_if: " << client_if << " - BD_ADDR: " << BtAddrString(bda);
    FOR_EACH_CLIENT_OBSERVER(
        DisconnectCallback(g_interface, conn_id, status, client_if, *bda));
  }
  
  void SearchCompleteCallback(int conn_id, int status) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
  
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status;
    FOR_EACH_CLIENT_OBSERVER(
        SearchCompleteCallback(g_interface, conn_id, status));
  }
  
  void RegisterForNotificationCallback(int conn_id, int registered, int status,
                                       uint16_t handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
  
    LOG(INFO) << __func__ << " - conn_id: " << conn_id << " - status: " << status
              << " - registered: " << registered << " - handle: " << handle;
    FOR_EACH_CLIENT_OBSERVER(RegisterForNotificationCallback(
        g_interface, conn_id, status, registered, handle));
  }
  
  void NotifyCallback(int conn_id, btgatt_notify_params_t* p_data) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
  
    VLOG(2) << __func__ << " - conn_id: " << conn_id
            << " - address: " << BtAddrString(&p_data->bda)
            << " - handle: " << p_data->handle << " - len: " << p_data->len
            << " - is_notify: " << p_data->is_notify;
  
    FOR_EACH_CLIENT_OBSERVER(NotifyCallback(g_interface, conn_id, p_data));
  }
  
  void WriteCharacteristicCallback(int conn_id, int status, uint16_t handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
  
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status;
  
    FOR_EACH_CLIENT_OBSERVER(
        WriteCharacteristicCallback(g_interface, conn_id, status, handle));
  }
  
  void WriteDescriptorCallback(int conn_id, int status, uint16_t handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
  
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " - status: " << status;
  
    FOR_EACH_CLIENT_OBSERVER(
        WriteDescriptorCallback(g_interface, conn_id, status, handle));
  }
  
  void MtuChangedCallback(int conn_id, int status, int mtu) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VERIFY_INTERFACE_OR_RETURN();
  
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " status: " << status
            << " mtu: " << mtu;
  
    FOR_EACH_CLIENT_OBSERVER(
        MtuChangedCallback(g_interface, conn_id, status, mtu));
  }
  
  void GetGattDbCallback(int conn_id, btgatt_db_element_t* db, int size) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " size: " << size;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_CLIENT_OBSERVER(GetGattDbCallback(g_interface, conn_id, db, size));
  }
  
  void ServicesRemovedCallback(int conn_id, uint16_t start_handle,
                               uint16_t end_handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id
            << " start_handle: " << start_handle << " end_handle: " << end_handle;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_CLIENT_OBSERVER(
        ServicesRemovedCallback(g_interface, conn_id, start_handle, end_handle));
  }
  
  void ServicesAddedCallback(int conn_id, btgatt_db_element_t* added,
                             int added_count) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id
            << " added_count: " << added_count;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_CLIENT_OBSERVER(
        ServicesAddedCallback(g_interface, conn_id, added, added_count));
  }
  
  void RegisterServerCallback(int status, int server_if, bt_uuid_t* app_uuid) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(app_uuid);
  
    FOR_EACH_SERVER_OBSERVER(
        RegisterServerCallback(g_interface, status, server_if, *app_uuid));
  }
  
  void ConnectionCallback(int conn_id, int server_if, int connected,
                          bt_bdaddr_t* bda) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id
            << " server_if: " << server_if << " connected: " << connected;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    FOR_EACH_SERVER_OBSERVER(
        ConnectionCallback(g_interface, conn_id, server_if, connected, *bda));
  }
  
  void ServiceAddedCallback(
      int status, int server_if,
      std::vector<btgatt_db_element_t> service) {  // NOLINT(pass-by-value)
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
            << " count: " << service.size();
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(service.size());
  
    FOR_EACH_SERVER_OBSERVER(
        ServiceAddedCallback(g_interface, status, server_if, service));
  }
  
  void ServiceStoppedCallback(int status, int server_if, int srvc_handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
            << " handle: " << srvc_handle;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_SERVER_OBSERVER(
        ServiceStoppedCallback(g_interface, status, server_if, srvc_handle));
  }
  
  void ServiceDeletedCallback(int status, int server_if, int srvc_handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - status: " << status << " server_if: " << server_if
            << " handle: " << srvc_handle;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_SERVER_OBSERVER(
        ServiceDeletedCallback(g_interface, status, server_if, srvc_handle));
  }
  
  void RequestReadCharacteristicCallback(int conn_id, int trans_id,
                                         bt_bdaddr_t* bda, int attr_handle,
                                         int offset, bool is_long) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
            << " attr_handle: " << attr_handle << " offset: " << offset
            << " is_long: " << is_long;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    FOR_EACH_SERVER_OBSERVER(RequestReadCharacteristicCallback(
        g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
  }
  
  void RequestReadDescriptorCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
                                     int attr_handle, int offset, bool is_long) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
            << " attr_handle: " << attr_handle << " offset: " << offset
            << " is_long: " << is_long;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    FOR_EACH_SERVER_OBSERVER(RequestReadDescriptorCallback(
        g_interface, conn_id, trans_id, *bda, attr_handle, offset, is_long));
  }
  
  void RequestWriteCharacteristicCallback(int conn_id, int trans_id,
                                          bt_bdaddr_t* bda, int attr_handle,
                                          int offset, bool need_rsp, bool is_prep,
                                          std::vector<uint8_t> value) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
            << " attr_handle: " << attr_handle << " offset: " << offset
            << " length: " << value.size() << " need_rsp: " << need_rsp
            << " is_prep: " << is_prep;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    FOR_EACH_SERVER_OBSERVER(RequestWriteCharacteristicCallback(
        g_interface, conn_id, trans_id, *bda, attr_handle, offset, need_rsp,
        is_prep, value));
  }
  
  void RequestWriteDescriptorCallback(
      int conn_id, int trans_id, bt_bdaddr_t* bda, int attr_handle, int offset,
      bool need_rsp, bool is_prep,
      std::vector<uint8_t> value) {  // NOLINT(pass-by-value)
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
            << " attr_handle: " << attr_handle << " offset: " << offset
            << " length: " << value.size() << " need_rsp: " << need_rsp
            << " is_prep: " << is_prep;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    FOR_EACH_SERVER_OBSERVER(RequestWriteDescriptorCallback(
        g_interface, conn_id, trans_id, *bda, attr_handle, offset, need_rsp,
        is_prep, value));
  }
  
  void RequestExecWriteCallback(int conn_id, int trans_id, bt_bdaddr_t* bda,
                                int exec_write) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " trans_id: " << trans_id
            << " exec_write: " << exec_write;
    VERIFY_INTERFACE_OR_RETURN();
    CHECK(bda);
  
    FOR_EACH_SERVER_OBSERVER(RequestExecWriteCallback(
        g_interface, conn_id, trans_id, *bda, exec_write));
  }
  
  void ResponseConfirmationCallback(int status, int handle) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - status: " << status << " handle: " << handle;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_SERVER_OBSERVER(
        ResponseConfirmationCallback(g_interface, status, handle));
  }
  
  void IndicationSentCallback(int conn_id, int status) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " status: " << status;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_SERVER_OBSERVER(
        IndicationSentCallback(g_interface, conn_id, status));
  }
  
  void MtuChangedCallback(int conn_id, int mtu) {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    VLOG(2) << __func__ << " - conn_id: " << conn_id << " mtu: " << mtu;
    VERIFY_INTERFACE_OR_RETURN();
  
    FOR_EACH_SERVER_OBSERVER(MtuChangedCallback(g_interface, conn_id, mtu));
  }
  
  // The HAL Bluetooth GATT client interface callbacks. These signal a mixture of
  // GATT client-role and GAP events.
  
  const btgatt_scanner_callbacks_t gatt_scanner_callbacks = {
      ScanResultCallback,
      nullptr,  // batchscan_reports_cb
      nullptr,  // batchscan_threshold_cb
      nullptr,  // track_adv_event_cb
  };
  
  const btgatt_client_callbacks_t gatt_client_callbacks = {
      RegisterClientCallback,
      ConnectCallback,
      DisconnectCallback,
      SearchCompleteCallback,
      RegisterForNotificationCallback,
      NotifyCallback,
      nullptr,  // read_characteristic_cb
      WriteCharacteristicCallback,
      nullptr,  // read_descriptor_cb
      WriteDescriptorCallback,
      nullptr,  // execute_write_cb
      nullptr,  // read_remote_rssi_cb
      MtuChangedCallback,
      nullptr,  // congestion_cb
      GetGattDbCallback,
      ServicesRemovedCallback,
      ServicesAddedCallback,
      nullptr,
      nullptr,
  };
  
  const btgatt_server_callbacks_t gatt_server_callbacks = {
      RegisterServerCallback,
      ConnectionCallback,
      ServiceAddedCallback,
      ServiceStoppedCallback,
      ServiceDeletedCallback,
      RequestReadCharacteristicCallback,
      RequestReadDescriptorCallback,
      RequestWriteCharacteristicCallback,
      RequestWriteDescriptorCallback,
      RequestExecWriteCallback,
      ResponseConfirmationCallback,
      IndicationSentCallback,
      nullptr,  // congestion_cb
      MtuChangedCallback,
      nullptr,
      nullptr,
  };
  
  const btgatt_callbacks_t gatt_callbacks = {
      sizeof(btgatt_callbacks_t), &gatt_client_callbacks, &gatt_server_callbacks,
      &gatt_scanner_callbacks,
  };
  
  }  // namespace
  
  // BluetoothGattInterface implementation for production.
  class BluetoothGattInterfaceImpl : public BluetoothGattInterface {
   public:
    BluetoothGattInterfaceImpl() : hal_iface_(nullptr) {}
  
    ~BluetoothGattInterfaceImpl() override {
      if (hal_iface_) hal_iface_->cleanup();
    }
  
    void AddScannerObserver(ScannerObserver* observer) override {
      scanner_observers_.AddObserver(observer);
    }
  
    void RemoveScannerObserver(ScannerObserver* observer) override {
      scanner_observers_.RemoveObserver(observer);
    }
  
    void AddClientObserver(ClientObserver* observer) override {
      client_observers_.AddObserver(observer);
    }
  
    void RemoveClientObserver(ClientObserver* observer) override {
      client_observers_.RemoveObserver(observer);
    }
  
    void AddServerObserver(ServerObserver* observer) override {
      server_observers_.AddObserver(observer);
    }
  
    void RemoveServerObserver(ServerObserver* observer) override {
      server_observers_.RemoveObserver(observer);
    }
  
    BleAdvertiserInterface* GetAdvertiserHALInterface() const override {
      return hal_iface_->advertiser;
    }
  
    BleScannerInterface* GetScannerHALInterface() const override {
      return hal_iface_->scanner;
    }
  
    const btgatt_client_interface_t* GetClientHALInterface() const override {
      return hal_iface_->client;
    }
  
    const btgatt_server_interface_t* GetServerHALInterface() const override {
      return hal_iface_->server;
    }
  
    // Initialize the interface.
    bool Initialize() {
      const bt_interface_t* bt_iface =
          BluetoothInterface::Get()->GetHALInterface();
      CHECK(bt_iface);
  
      const btgatt_interface_t* gatt_iface =
          reinterpret_cast<const btgatt_interface_t*>(
              bt_iface->get_profile_interface(BT_PROFILE_GATT_ID));
      if (!gatt_iface) {
        LOG(ERROR) << "Failed to obtain HAL GATT interface handle";
        return false;
      }
  
      bt_status_t status = gatt_iface->init(&gatt_callbacks);
      if (status != BT_STATUS_SUCCESS) {
        LOG(ERROR) << "Failed to initialize HAL GATT interface";
        return false;
      }
  
      hal_iface_ = gatt_iface;
  
      return true;
    }
  
    base::ObserverList<ScannerObserver>* scanner_observers() {
      return &scanner_observers_;
    }
  
    base::ObserverList<ClientObserver>* client_observers() {
      return &client_observers_;
    }
  
    base::ObserverList<ServerObserver>* server_observers() {
      return &server_observers_;
    }
  
   private:
    // List of observers that are interested in notifications from us.
    // We're not using a base::ObserverListThreadSafe, which it posts observer
    // events automatically on the origin threads, as we want to avoid that
    // overhead and simply forward the events to the upper layer.
    base::ObserverList<ScannerObserver> scanner_observers_;
    base::ObserverList<ClientObserver> client_observers_;
    base::ObserverList<ServerObserver> server_observers_;
  
    // The HAL handle obtained from the shared library. We hold a weak reference
    // to this since the actual data resides in the shared Bluetooth library.
    const btgatt_interface_t* hal_iface_;
  
    DISALLOW_COPY_AND_ASSIGN(BluetoothGattInterfaceImpl);
  };
  
  namespace {
  
  base::ObserverList<BluetoothGattInterface::ScannerObserver>*
  GetScannerObservers() {
    CHECK(g_interface);
    return static_cast<BluetoothGattInterfaceImpl*>(g_interface)
        ->scanner_observers();
  }
  
  base::ObserverList<BluetoothGattInterface::ClientObserver>*
  GetClientObservers() {
    CHECK(g_interface);
    return static_cast<BluetoothGattInterfaceImpl*>(g_interface)
        ->client_observers();
  }
  
  base::ObserverList<BluetoothGattInterface::ServerObserver>*
  GetServerObservers() {
    CHECK(g_interface);
    return static_cast<BluetoothGattInterfaceImpl*>(g_interface)
        ->server_observers();
  }
  
  }  // namespace
  
  // Default observer implementations. These are provided so that the methods
  // themselves are optional.
  
  void BluetoothGattInterface::ScannerObserver::ScanResultCallback(
      BluetoothGattInterface* /* gatt_iface */, const bt_bdaddr_t& /* bda */,
      int /* rssi */,
      std::vector<uint8_t> /* adv_data */) {  // NOLINT(pass-by-value)
    // Do Nothing.
  }
  
  void BluetoothGattInterface::ClientObserver::RegisterClientCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* status */,
      int /* client_if */, const bt_uuid_t& /* app_uuid */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ClientObserver::ConnectCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */, int /* client_if */, const bt_bdaddr_t& /* bda */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::DisconnectCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */, int /* client_if */, const bt_bdaddr_t& /* bda */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::SearchCompleteCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::RegisterForNotificationCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */, int /* registered */, uint16_t /* handle */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::NotifyCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      btgatt_notify_params_t* /* p_data */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::WriteCharacteristicCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */, uint16_t /* handle */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::WriteDescriptorCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */, uint16_t /* handle */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ClientObserver::MtuChangedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* statis*/, int /* mtu */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ClientObserver::GetGattDbCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      btgatt_db_element_t* /* gatt_db */, int /* size */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ClientObserver::ServicesRemovedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      uint16_t /* start_handle */, uint16_t /* end_handle */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ClientObserver::ServicesAddedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      btgatt_db_element_t* /* added */, int /* added_count */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::RegisterServerCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* status */,
      int /* server_if */, const bt_uuid_t& /* app_uuid */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::ConnectionCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* server_if */, int /* connected */, const bt_bdaddr_t& /* bda */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::ServiceAddedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* status */,
      int /* server_if */,
      std::vector<btgatt_db_element_t> /* service */) {  // NOLINT(pass-by-value)
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::ServiceStoppedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* status */,
      int /* server_if */, int /* srvc_handle */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::ServiceDeletedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* status */,
      int /* server_if */, int /* srvc_handle */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::RequestReadCharacteristicCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
      int /* offset */, bool /* is_long */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::RequestReadDescriptorCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
      int /* offset */, bool /* is_long */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::RequestWriteCharacteristicCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
      int /* offset */, bool /* need_rsp */, bool /* is_prep */,
      std::vector<uint8_t> /* value */) {  // NOLINT(pass-by-value)
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::RequestWriteDescriptorCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* attr_handle */,
      int /* offset */, bool /* need_rsp */, bool /* is_prep */,
      std::vector<uint8_t> /* value */) {  // NOLINT(pass-by-value)
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::RequestExecWriteCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* trans_id */, const bt_bdaddr_t& /* bda */, int /* exec_write */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::ResponseConfirmationCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* status */,
      int /* handle */) {
    // Do nothing
  }
  
  void BluetoothGattInterface::ServerObserver::IndicationSentCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* status */) {
    // Do nothing.
  }
  
  void BluetoothGattInterface::ServerObserver::MtuChangedCallback(
      BluetoothGattInterface* /* gatt_iface */, int /* conn_id */,
      int /* mtu */) {
    // Do nothing.
  }
  
  // static
  bool BluetoothGattInterface::Initialize() {
    unique_lock<shared_mutex_impl> lock(g_instance_lock);
    CHECK(!g_interface);
  
    std::unique_ptr<BluetoothGattInterfaceImpl> impl(
        new BluetoothGattInterfaceImpl());
    if (!impl->Initialize()) {
      LOG(ERROR) << "Failed to initialize BluetoothGattInterface";
      return false;
    }
  
    g_interface = impl.release();
  
    return true;
  }
  
  // static
  void BluetoothGattInterface::CleanUp() {
    unique_lock<shared_mutex_impl> lock(g_instance_lock);
    CHECK(g_interface);
  
    delete g_interface;
    g_interface = nullptr;
  }
  
  // static
  bool BluetoothGattInterface::IsInitialized() {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
  
    return g_interface != nullptr;
  }
  
  // static
  BluetoothGattInterface* BluetoothGattInterface::Get() {
    shared_lock<shared_mutex_impl> lock(g_instance_lock);
    CHECK(g_interface);
    return g_interface;
  }
  
  // static
  void BluetoothGattInterface::InitializeForTesting(
      BluetoothGattInterface* test_instance) {
    unique_lock<shared_mutex_impl> lock(g_instance_lock);
    CHECK(test_instance);
    CHECK(!g_interface);
  
    g_interface = test_instance;
  }
  
  bt_status_t BluetoothGattInterface::StartScan(int client_id) {
    lock_guard<mutex> lock(scan_clients_lock_);
  
    // Scan already initiated for this client.
    if (scan_client_set_.find(client_id) != scan_client_set_.end()) {
      // Assume starting scan multiple times is not error, but warn user.
      LOG(WARNING) << "Scan already initiated for client";
      return BT_STATUS_SUCCESS;
    }
  
    // If this is the first scan client, then make a call into the stack. We
    // only do this when the reference count changes to or from 0.
    if (scan_client_set_.empty()) {
      GetScannerHALInterface()->Scan(true);
    }
  
    scan_client_set_.insert(client_id);
  
    return BT_STATUS_SUCCESS;
  }
  
  bt_status_t BluetoothGattInterface::StopScan(int client_id) {
    lock_guard<mutex> lock(scan_clients_lock_);
  
    // Scan not initiated for this client.
    auto iter = scan_client_set_.find(client_id);
    if (iter == scan_client_set_.end()) {
      // Assume stopping scan multiple times is not error, but warn user.
      LOG(WARNING) << "Scan already stopped or not initiated for client";
      return BT_STATUS_SUCCESS;
    }
  
    if (scan_client_set_.size() == 1) {
      GetScannerHALInterface()->Scan(false);
    }
  
    scan_client_set_.erase(iter);
    return BT_STATUS_SUCCESS;
  }
  
  }  // namespace hal
  }  // namespace bluetooth
  