service: Implement adding a service declaration
This CL implements initiating and starting a GATT service
declaration in GattServer.
Bug: 24245347
Change-Id: I53281d29a052c1890616b6595881108ca0eedec3
diff --git a/service/gatt_server.h b/service/gatt_server.h
index a2db393..98069b0 100644
--- a/service/gatt_server.h
+++ b/service/gatt_server.h
@@ -16,12 +16,15 @@
#pragma once
-#include <map>
+#include <functional>
+#include <queue>
#include <mutex>
+#include <unordered_map>
#include <base/macros.h>
#include "service/bluetooth_client_instance.h"
+#include "service/gatt_identifier.h"
#include "service/hal/bluetooth_gatt_interface.h"
#include "service/uuid.h"
@@ -30,7 +33,8 @@
// A GattServer instance represents an application's handle to perform GATT
// server-role operations. Instances cannot be created directly and should be
// obtained through the factory.
-class GattServer : public BluetoothClientInstance {
+class GattServer : public BluetoothClientInstance,
+ private hal::BluetoothGattInterface::ServerObserver {
public:
// The desctructor automatically unregisters this instance from the stack.
~GattServer() override;
@@ -39,17 +43,90 @@
const UUID& GetAppIdentifier() const override;
int GetClientId() const override;
+ // Callback type used to report the status of an asynchronous GATT server
+ // operation.
+ using ResultCallback =
+ std::function<void(BLEStatus status, const GattIdentifier& id)>;
+
+ // Starts a new GATT service declaration for the service with the given
+ // parameters. In the case of an error, for example If a service declaration
+ // is already in progress, then this method returns a NULL pointer. Otherwise,
+ // this returns an identifier that uniquely identifies the added service.
+ //
+ // TODO(armansito): In the framework code, the "min_handles" parameter is
+ // annotated to be used for "conformance testing only". I don't fully see the
+ // point of this and suggest getting rid of this parameter entirely. For now
+ // this code doesn't declare or use it.
+ std::unique_ptr<GattIdentifier> BeginServiceDeclaration(
+ const UUID& uuid, bool is_primary);
+
+ // Ends a previously started service declaration. This method immediately
+ // returns false if a service declaration hasn't been started. Otherwise,
+ // |callback| will be called asynchronously with the result of the operation.
+ //
+ // TODO(armansito): It is unclear to me what it means for this function to
+ // fail. What is the state that we're in? Is the service declaration over so
+ // we can add other services to this server instance? Do we need to clean up
+ // all the entries or does the upper-layer need to remove the service? Or are
+ // we in a stuck-state where the service declaration hasn't ended?
+ bool EndServiceDeclaration(const ResultCallback& callback);
+
private:
friend class GattServerFactory;
+ // Internal representation of a GATT service declaration before it has been
+ // sent to the stack.
+ struct ServiceDeclaration {
+ ServiceDeclaration() : num_handles(0), service_handle(-1) {}
+
+ size_t num_handles;
+ GattIdentifier service_id;
+ int service_handle;
+ std::queue<GattIdentifier> attributes;
+ };
+
// Constructor shouldn't be called directly as instance are meant to be
// obtained from the factory.
GattServer(const UUID& uuid, int server_if);
+ // hal::BluetoothGattInterface::ServerObserver overrides:
+ void ServiceAddedCallback(
+ hal::BluetoothGattInterface* gatt_iface,
+ int status, int server_if,
+ const btgatt_srvc_id_t& srvc_id,
+ int srvc_handle) override;
+ void ServiceStartedCallback(
+ hal::BluetoothGattInterface* gatt_iface,
+ int status, int server_if,
+ int srvc_handle) override;
+ void ServiceStoppedCallback(
+ hal::BluetoothGattInterface* gatt_iface,
+ int status, int server_if,
+ int srvc_handle) override;
+
+ // Helper function that notifies and clears the pending callback.
+ void NotifyEndCallbackAndClearData(BLEStatus status,
+ const GattIdentifier& id);
+ void CleanUpPendingData();
+
+ // Pops the next GATT ID from the pending service declaration's attribute
+ // list.
+ std::unique_ptr<GattIdentifier> PopNextId();
+
// See getters for documentation.
UUID app_identifier_;
int server_if_;
+ // Mutex that synchronizes access to the entries below.
+ std::mutex mutex_;
+ std::unique_ptr<GattIdentifier> pending_id_;
+ std::unique_ptr<ServiceDeclaration> pending_decl_;
+ ResultCallback pending_end_decl_cb_;
+ std::unordered_map<GattIdentifier, int> pending_handle_map_;
+
+ // Mapping of handles and GATT identifiers for started services.
+ std::unordered_map<GattIdentifier, int> handle_map_;
+
DISALLOW_COPY_AND_ASSIGN(GattServer);
};
@@ -77,7 +154,7 @@
// Map of pending calls to register.
std::mutex pending_calls_lock_;
- std::map<UUID, RegisterCallback> pending_calls_;
+ std::unordered_map<UUID, RegisterCallback> pending_calls_;
DISALLOW_COPY_AND_ASSIGN(GattServerFactory);
};