[bt][gap] HACK: discover services after pairing

bt-host currently initiates pairing as soon as a LE connection is
created. This is temporary until support is added to initiate
pairing in response to a service request.

This patch removes a race between service discovery and pairing by
performing the former only after the pairing procedure concludes.
Services are discovered regardless of the pairing result.

Change-Id: Ia0cb27172ca7e105cb35d9a74c19e348b3e35086
TODO: bug number
TODO: tests
diff --git a/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc b/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc
index ba7682d..093a2bf 100644
--- a/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc
+++ b/drivers/bluetooth/lib/gap/low_energy_connection_manager.cc
@@ -116,16 +116,19 @@
         }
       });
 
-      // TODO(armansito): Don't pair automatically. Do this in response to a
-      // service request instead.
+      // TODO(armansito): We register the connection with GATT but don't perform
+      // service discovery until after pairing has completed. Fix this so that
+      // services are discovered immediately and pairing happens in response to
+      // a service request.
+      gatt->AddConnection(self->id(), std::move(att));
       pairing->UpdateSecurity(
           sm::SecurityLevel::kEncrypted,
-          [](sm::Status status, const auto& props) {
+          [gatt, id = self->id()](sm::Status status, const auto& props) {
             FXL_LOG(INFO) << "gap: Pairing status: " << status.ToString()
                           << ", properties: " << props.ToString();
+            gatt->DiscoverServices(id);
           });
 
-      gatt->AddConnection(self->id(), std::move(att));
       self->pairing_ = std::move(pairing);
     };
 
diff --git a/drivers/bluetooth/lib/gatt/connection.cc b/drivers/bluetooth/lib/gatt/connection.cc
index 7018075..6ecfc87 100644
--- a/drivers/bluetooth/lib/gatt/connection.cc
+++ b/drivers/bluetooth/lib/gatt/connection.cc
@@ -17,25 +17,39 @@
                        fxl::RefPtr<att::Bearer> att_bearer,
                        fxl::RefPtr<att::Database> local_db,
                        RemoteServiceWatcher svc_watcher,
-                       async_t* gatt_dispatcher) {
+                       async_t* gatt_dispatcher)
+    : att_(att_bearer) {
   FXL_DCHECK(att_bearer);
   FXL_DCHECK(local_db);
   FXL_DCHECK(svc_watcher);
   FXL_DCHECK(gatt_dispatcher);
 
-  server_ = std::make_unique<gatt::Server>(peer_id, local_db, att_bearer);
+  server_ = std::make_unique<gatt::Server>(peer_id, local_db, att_);
   remote_service_manager_ = std::make_unique<RemoteServiceManager>(
-      gatt::Client::Create(att_bearer), gatt_dispatcher);
+      gatt::Client::Create(att_), gatt_dispatcher);
 
   remote_service_manager_->set_service_watcher(std::move(svc_watcher));
-  remote_service_manager_->Initialize([att_bearer](att::Status status) {
+  //  remote_service_manager_->Initialize([att_bearer](att::Status status) {
+  //    if (status) {
+  //      FXL_VLOG(1) << "gatt: Primary service discovery complete";
+  //    } else {
+  //      FXL_VLOG(1) << "gatt: Client setup failed - " << status.ToString();
+  //
+  //      // Signal a link error.
+  //      att_bearer->ShutDown();
+  //    }
+  //  });
+}
+
+void Connection::Initialize() {
+  remote_service_manager_->Initialize([att = att_](att::Status status) {
     if (status) {
       FXL_VLOG(1) << "gatt: Primary service discovery complete";
     } else {
       FXL_VLOG(1) << "gatt: Client setup failed - " << status.ToString();
 
       // Signal a link error.
-      att_bearer->ShutDown();
+      att->ShutDown();
     }
   });
 }
diff --git a/drivers/bluetooth/lib/gatt/connection.h b/drivers/bluetooth/lib/gatt/connection.h
index 7e68549..3a684c6 100644
--- a/drivers/bluetooth/lib/gatt/connection.h
+++ b/drivers/bluetooth/lib/gatt/connection.h
@@ -56,7 +56,10 @@
     return remote_service_manager_.get();
   }
 
+  void Initialize();
+
  private:
+  fxl::RefPtr<att::Bearer> att_;
   std::unique_ptr<Server> server_;
   std::unique_ptr<RemoteServiceManager> remote_service_manager_;
 
diff --git a/drivers/bluetooth/lib/gatt/fake_layer.cc b/drivers/bluetooth/lib/gatt/fake_layer.cc
index ff77190..d5ce73e 100644
--- a/drivers/bluetooth/lib/gatt/fake_layer.cc
+++ b/drivers/bluetooth/lib/gatt/fake_layer.cc
@@ -21,6 +21,10 @@
   // TODO: implement
 }
 
+void FakeLayer::DiscoverServices(std::string peer_id) {
+  // TODO: implement
+}
+
 void FakeLayer::RemoveConnection(std::string peer_id) {
   // TODO: implement
 }
diff --git a/drivers/bluetooth/lib/gatt/fake_layer.h b/drivers/bluetooth/lib/gatt/fake_layer.h
index 635abb1..232d4ff 100644
--- a/drivers/bluetooth/lib/gatt/fake_layer.h
+++ b/drivers/bluetooth/lib/gatt/fake_layer.h
@@ -23,6 +23,7 @@
   void ShutDown() override;
   void AddConnection(const std::string& peer_id,
                      fbl::RefPtr<l2cap::Channel> att_chan) override;
+  void DiscoverServices(std::string peer_id) override;
   void RemoveConnection(std::string peer_id) override;
   void RegisterService(ServicePtr service,
                        ServiceIdCallback callback,
diff --git a/drivers/bluetooth/lib/gatt/gatt.cc b/drivers/bluetooth/lib/gatt/gatt.cc
index 8ddd770..a9b6e41 100644
--- a/drivers/bluetooth/lib/gatt/gatt.cc
+++ b/drivers/bluetooth/lib/gatt/gatt.cc
@@ -103,6 +103,20 @@
     });
   }
 
+  void DiscoverServices(std::string peer_id) override {
+    FXL_VLOG(1) << "gatt: Discover services: " << peer_id;
+
+    PostMessage([this, peer_id = std::move(peer_id)] {
+      auto iter = connections_.find(peer_id);
+      if (iter == connections_.end()) {
+        FXL_LOG(WARNING) << "gatt: Unknown peer: " << peer_id;
+        return;
+      }
+
+      iter->second.Initialize();
+    });
+  }
+
   void RemoveConnection(std::string peer_id) override {
     FXL_VLOG(1) << "gatt: Remove connection: " << peer_id;
     PostMessage(
diff --git a/drivers/bluetooth/lib/gatt/gatt.h b/drivers/bluetooth/lib/gatt/gatt.h
index 56a3a3f..a3c0793 100644
--- a/drivers/bluetooth/lib/gatt/gatt.h
+++ b/drivers/bluetooth/lib/gatt/gatt.h
@@ -59,6 +59,9 @@
   virtual void AddConnection(const std::string& peer_id,
                              fbl::RefPtr<l2cap::Channel> att_chan) = 0;
 
+  // HACK HACK HACK
+  virtual void DiscoverServices(std::string peer_id) = 0;
+
   // Unregisters the GATT profile connection to the peer with Id |peer_id|.
   virtual void RemoveConnection(std::string peer_id) = 0;