Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0fbcd989 authored by Arman Uguray's avatar Arman Uguray Committed by Gerrit Code Review
Browse files

Merge "service: Introduce bluetooth::GattClient"

parents 40411865 960edc72
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@ btserviceCommonBinderSrc := \
btserviceDaemonSrc := \
	adapter.cpp \
	daemon.cpp \
	gatt_client.cpp \
	gatt_server.cpp \
	gatt_server_old.cpp \
	hal/gatt_helpers.cpp \
@@ -80,6 +81,7 @@ btserviceBaseTestSrc := \
	test/adapter_unittest.cpp \
	test/advertise_data_unittest.cpp \
	test/fake_hal_util.cpp \
	test/gatt_client_unittest.cpp \
	test/gatt_identifier_unittest.cpp \
	test/gatt_server_unittest.cpp \
	test/low_energy_client_unittest.cpp \
+5 −0
Original line number Diff line number Diff line
@@ -49,6 +49,7 @@ Adapter::Adapter()
  memset(&local_le_features_, 0, sizeof(local_le_features_));
  hal::BluetoothInterface::Get()->AddObserver(this);
  ble_client_factory_.reset(new LowEnergyClientFactory());
  gatt_client_factory_.reset(new GattClientFactory());
  gatt_server_factory_.reset(new GattServerFactory());
  hal::BluetoothInterface::Get()->GetHALInterface()->get_adapter_properties();
}
@@ -165,6 +166,10 @@ LowEnergyClientFactory* Adapter::GetLowEnergyClientFactory() const {
  return ble_client_factory_.get();
}

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

GattServerFactory* Adapter::GetGattServerFactory() const {
  return gatt_server_factory_.get();
}
+8 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@

#include "service/common/bluetooth/adapter_state.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/low_energy_client.h"
@@ -95,6 +96,10 @@ class Adapter : public hal::BluetoothInterface::Observer {
  // operations.
  LowEnergyClientFactory* GetLowEnergyClientFactory() const;

  // Returns a pointer to the GattClientFactory. This can be used to register
  // per-application GATT server instances.
  GattClientFactory* GetGattClientFactory() const;

  // Returns a pointer to the GattServerFactory. This can be used to register
  // per-application GATT server instances.
  GattServerFactory* GetGattServerFactory() const;
@@ -135,6 +140,9 @@ class Adapter : public hal::BluetoothInterface::Observer {
  // Factory used to create per-app LowEnergyClient instances.
  std::unique_ptr<LowEnergyClientFactory> ble_client_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_;

+110 −0
Original line number Diff line number Diff line
//
//  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/gatt_client.h"

#include <base/logging.h>

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

namespace bluetooth {

// GattClient implementation
// ========================================================

GattClient::GattClient(const UUID& uuid, int client_id)
    : app_identifier_(uuid),
      client_id_(client_id) {
}

GattClient::~GattClient() {
  // Automatically unregister the client.
  VLOG(1) << "GattClient unregistering client: " << client_id_;

  hal::BluetoothGattInterface::Get()->GetClientHALInterface()->
      unregister_client(client_id_);
}

const UUID& GattClient::GetAppIdentifier() const {
  return app_identifier_;
}

int GattClient::GetClientId() const {
  return client_id_;
}

// GattClientFactory implementation
// ========================================================

GattClientFactory::GattClientFactory() {
  hal::BluetoothGattInterface::Get()->AddClientObserver(this);
}

GattClientFactory::~GattClientFactory() {
  hal::BluetoothGattInterface::Get()->RemoveClientObserver(this);
}

bool GattClientFactory::RegisterClient(const UUID& uuid,
                                       const RegisterCallback& callback) {
  VLOG(1) << __func__ << " - UUID: " << uuid.ToString();
  lock_guard<mutex> lock(pending_calls_lock_);

  if (pending_calls_.find(uuid) != pending_calls_.end()) {
    LOG(ERROR) << "GATT client with given UUID already registered - "
               << "UUID: " << uuid.ToString();
    return false;
  }

  const btgatt_client_interface_t* hal_iface =
      hal::BluetoothGattInterface::Get()->GetClientHALInterface();
  bt_uuid_t app_uuid = uuid.GetBlueDroid();

  if (hal_iface->register_client(&app_uuid) != BT_STATUS_SUCCESS)
    return false;

  pending_calls_[uuid] = callback;

  return true;
}

void GattClientFactory::RegisterClientCallback(
    hal::BluetoothGattInterface* /* gatt_iface */,
    int status, int client_id,
    const bt_uuid_t& app_uuid) {
  UUID uuid(app_uuid);

  auto iter = pending_calls_.find(uuid);
  if (iter == pending_calls_.end()) {
    VLOG(1) << "Ignoring callback for unknown app_id: " << uuid.ToString();
    return;
  }

  bool success = (status == BT_STATUS_SUCCESS);
  BLEStatus result = success ? BLE_STATUS_SUCCESS : BLE_STATUS_FAILURE;

  // No need to construct a client if the call wasn't successful.
  std::unique_ptr<GattClient> client;
  if (success)
    client.reset(new GattClient(uuid, client_id));

  // Notify the result via the result callback.
  iter->second(result, uuid, std::move(client));

  pending_calls_.erase(iter);
}

}  // namespace bluetooth
+84 −0
Original line number Diff line number Diff line
//
//  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.
//

#pragma once

#include <mutex>
#include <unordered_map>

#include <base/macros.h>

#include "service/bluetooth_client_instance.h"
#include "service/common/bluetooth/uuid.h"
#include "service/hal/bluetooth_gatt_interface.h"

namespace bluetooth {

// A GattClient instance represents an application's handle to perform GATT
// client-role operations. Instances cannot be created directly and should be
// obtained through the factory.
class GattClient : public BluetoothClientInstance {
 public:
  ~GattClient() override;

  // BluetoothClientInstace overrides:
  const UUID& GetAppIdentifier() const override;
  int GetClientId() const override;

 private:
  friend class GattClientFactory;

  // Constructor shouldn't be called directly as instances are meant to be
  // obtained from the factory.
  GattClient(const UUID& uuid, int client_id);

  // See getters above for documentation.
  UUID app_identifier_;
  int client_id_;

  DISALLOW_COPY_AND_ASSIGN(GattClient);
};

// GattClientFactory is used to register and obtain a per-application GattClient
// instance. Users should call RegisterClient to obtain their own unique
// GattClient instance that has been registered with the Bluetooth stack.
class GattClientFactory : public BluetoothClientInstanceFactory,
                          private hal::BluetoothGattInterface::ClientObserver {
 public:
  // Don't construct/destruct directly except in tests. Instead, obtain a handle
  // from an Adapter instance.
  GattClientFactory();
  ~GattClientFactory() override;

  // BluetoothClientInstanceFactory override:
  bool RegisterClient(const UUID& uuid,
                      const RegisterCallback& callback) override;

 private:
  // hal::BluetoothGattInterface::ClientObserver override:
  void RegisterClientCallback(
      hal::BluetoothGattInterface* gatt_iface,
      int status, int client_id,
      const bt_uuid_t& app_uuid) override;

  // Map of pending calls to register.
  std::mutex pending_calls_lock_;
  std::unordered_map<UUID, RegisterCallback> pending_calls_;

  DISALLOW_COPY_AND_ASSIGN(GattClientFactory);
};

}  // namespace bluetooth
Loading