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);
 };