[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;