blob: 2f3422f7dd0a3c85adbc186c86eb9f8d8b42c497 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_HOST_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_HOST_H_
#include <fbl/macros.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <fuchsia/bluetooth/gatt/cpp/fidl.h>
#include "lib/fidl/cpp/binding.h"
#include "src/connectivity/bluetooth/core/bt-host/common/task_domain.h"
#include "src/connectivity/bluetooth/core/bt-host/gatt/gatt.h"
#include "src/lib/fxl/memory/weak_ptr.h"
namespace bthost {
class GattClientServer;
class GattServerServer;
// This object is responsible for bridging the GATT profile to the outside
// world.
//
// GattHost represents the GATT TaskDomain. It spawns and manages a thread on
// which all GATT tasks are serialized in an asynchronous event loop.
//
// This domain is responsible for:
//
// * The GATT profile implementation over L2CAP;
// * Creation of child GATT bt-gatt-svc devices and relaying of their
// messages;
// * FIDL message processing
//
// All functions on this object are thread safe. ShutDown() must be called
// at least once to properly clean up this object before destruction (this is
// asserted).
class GattHost final : public fbl::RefCounted<GattHost>, public bt::TaskDomain<GattHost> {
public:
// Type that can be used as a token in some of the functions below. Pointers
// are allowed to be used as tokens.
using Token = uintptr_t;
// Creates a production GattHost that spawns a dispatcher with a dedicated
// thread and constructs a GATT domain attached to that dispatcher. This is
// intended for production use.
static fbl::RefPtr<GattHost> Create(std::string thread_name);
// Creates a GattHost that is intended for testing. This takes the GATT domain
// and the dispatcher as a dependency rather than managing an internal thread.
static fbl::RefPtr<GattHost> CreateForTesting(async_dispatcher_t* dispatcher,
fbl::RefPtr<bt::gatt::GATT> gatt);
// Initialize.
void Initialize();
// This MUST be called to cleanly destroy this object. This method is
// thread-safe.
void ShutDown();
// Closes all open FIDL interface handles.
void CloseServers();
// Binds the given GATT server request to a FIDL server.
void BindGattServer(fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Server> request);
// Binds the given GATT client request to a FIDL server. The binding will be
// associated with the given |token|. The same token can be
// be passed to UnbindGattClient to disconnect a client.
//
// The handle associated with |request| will be closed if |token| is already
// bound to another handle.
void BindGattClient(Token token, bt::gatt::PeerId peer_id,
fidl::InterfaceRequest<fuchsia::bluetooth::gatt::Client> request);
// Unbinds a previously bound GATT client server associated with |token|.
void UnbindGattClient(Token token);
// Returns the GATT profile implementation.
fbl::RefPtr<bt::gatt::GATT> profile() const { return gatt_; }
// Sets a remote service handler to be notified when remote GATT services are
// discovered. These are used by HostDevice to publish bt-gatt-svc devices.
// This method is thread-safe. |callback| will not be called after ShutDown().
void SetRemoteServiceWatcher(bt::gatt::GATT::RemoteServiceWatcher callback);
private:
BT_FRIEND_TASK_DOMAIN(GattHost);
friend class fbl::RefPtr<GattHost>;
// Constructor used in production. This instantiates a real GATT domain object
// and spawns an event loop with a dedicated thread.
explicit GattHost(std::string thread_name);
// Constructor used for testing. This does NOT spawn a thread but takes a
// GATT domain and dispatcher as a dependency.
GattHost(async_dispatcher_t* dispatcher, fbl::RefPtr<bt::gatt::GATT> gatt);
~GattHost() override;
// Called by TaskDomain during shutdown. This must be called on the GATT task
// runner.
void CleanUp();
// Closes the active FIDL servers. This must be called on the GATT thread.
void CloseServersInternal();
std::mutex mtx_;
bt::gatt::GATT::RemoteServiceWatcher remote_service_watcher_ __TA_GUARDED(mtx_);
// NOTE: All members below must be accessed on the GATT thread
// The GATT profile.
fbl::RefPtr<bt::gatt::GATT> gatt_;
// All currently active FIDL connections. These objects are thread hostile and
// must be accessed only via the TaskDomain dispatcher.
std::unordered_map<GattServerServer*, std::unique_ptr<GattServerServer>> server_servers_;
// Mapping from tokens GattClient pointers. The ID is provided by the caller.
std::unordered_map<Token, std::unique_ptr<GattClientServer>> client_servers_;
fxl::WeakPtrFactory<GattHost> weak_ptr_factory_;
DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(GattHost);
};
} // namespace bthost
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GATT_HOST_H_