xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/fuchsia/host/fidl/host_server_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/host_server.h"
16 
17 #include <fuchsia/bluetooth/cpp/fidl.h>
18 #include <fuchsia/bluetooth/sys/cpp/fidl.h>
19 #include <fuchsia/bluetooth/sys/cpp/fidl_test_base.h>
20 #include <gmock/gmock.h>
21 #include <lib/zx/channel.h>
22 #include <zircon/errors.h>
23 
24 #include "fuchsia/bluetooth/host/cpp/fidl.h"
25 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/adapter_test_fixture.h"
26 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/fake_adapter_test_fixture.h"
27 #include "pw_bluetooth_sapphire/fuchsia/host/fidl/helpers.h"
28 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
29 #include "pw_bluetooth_sapphire/internal/host/common/device_address.h"
30 #include "pw_bluetooth_sapphire/internal/host/gap/gap.h"
31 #include "pw_bluetooth_sapphire/internal/host/gap/low_energy_address_manager.h"
32 #include "pw_bluetooth_sapphire/internal/host/gatt/fake_layer.h"
33 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_channel.h"
34 #include "pw_bluetooth_sapphire/internal/host/l2cap/fake_l2cap.h"
35 #include "pw_bluetooth_sapphire/internal/host/sm/smp.h"
36 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
37 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h"
38 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
39 #include "pw_bluetooth_sapphire/internal/host/testing/test_packets.h"
40 #include "pw_unit_test/framework.h"
41 
42 namespace fuchsia::bluetooth {
43 // Make PeerIds equality comparable for advanced testing matchers. ADL rules
44 // mandate the namespace.
operator ==(const PeerId & a,const PeerId & b)45 bool operator==(const PeerId& a, const PeerId& b) { return fidl::Equals(a, b); }
46 }  // namespace fuchsia::bluetooth
47 
48 namespace bthost {
49 namespace {
50 
51 // Limiting the de-scoped aliases here helps test cases be more specific about
52 // whether they're using FIDL names or bt-host internal names.
53 using bt::LowerBits;
54 using bt::StaticByteBuffer;
55 using bt::UpperBits;
56 using bt::l2cap::testing::FakeChannel;
57 using bt::sm::AuthReq;
58 using bt::sm::KeyDistGen;
59 using bt::testing::FakePeer;
60 
61 namespace fbt = fuchsia::bluetooth;
62 namespace fsys = fuchsia::bluetooth::sys;
63 namespace fhost = fuchsia::bluetooth::host;
64 
65 const bt::PeerId kTestId(1);
66 const bt::DeviceAddress kLeTestAddr(bt::DeviceAddress::Type::kLEPublic,
67                                     {0x01, 0, 0, 0, 0, 0});
68 const bt::DeviceAddress kBredrTestAddr(bt::DeviceAddress::Type::kBREDR,
69                                        {0x01, 0, 0, 0, 0, 0});
70 
71 const fbt::Address kTestFidlAddrPublic{fbt::AddressType::PUBLIC,
72                                        {1, 0, 0, 0, 0, 0}};
73 const fbt::Address kTestFidlAddrRandom{
74     fbt::AddressType::RANDOM, {0x55, 0x44, 0x33, 0x22, 0x11, 0b11000011}};
75 const fbt::Address kTestFidlAddrResolvable{
76     fbt::AddressType::RANDOM, {0x55, 0x44, 0x33, 0x22, 0x11, 0b01000011}};
77 const fbt::Address kTestFidlAddrNonResolvable{
78     fbt::AddressType::RANDOM, {0x55, 0x44, 0x33, 0x22, 0x11, 0x00}};
79 
80 class MockFidlPairingDelegate : public fsys::testing::PairingDelegate_TestBase {
81  public:
82   using PairingRequestCallback = fit::function<void(
83       fsys::Peer, fsys::PairingMethod, uint32_t, OnPairingRequestCallback)>;
84   using PairingCompleteCallback = fit::function<void(fbt::PeerId, bool)>;
85   using RemoteKeypressCallback =
86       fit::function<void(fbt::PeerId, fsys::PairingKeypress)>;
87 
MockFidlPairingDelegate(fidl::InterfaceRequest<PairingDelegate> request,async_dispatcher_t * dispatcher)88   MockFidlPairingDelegate(fidl::InterfaceRequest<PairingDelegate> request,
89                           async_dispatcher_t* dispatcher)
90       : binding_(this, std::move(request), dispatcher) {}
91 
92   ~MockFidlPairingDelegate() override = default;
93 
OnPairingRequest(fsys::Peer device,fsys::PairingMethod method,uint32_t displayed_passkey,OnPairingRequestCallback callback)94   void OnPairingRequest(fsys::Peer device,
95                         fsys::PairingMethod method,
96                         uint32_t displayed_passkey,
97                         OnPairingRequestCallback callback) override {
98     pairing_request_cb_(
99         std::move(device), method, displayed_passkey, std::move(callback));
100   }
101 
OnPairingComplete(fbt::PeerId id,bool success)102   void OnPairingComplete(fbt::PeerId id, bool success) override {
103     pairing_complete_cb_(id, success);
104   }
105 
OnRemoteKeypress(fbt::PeerId id,fsys::PairingKeypress keypress)106   void OnRemoteKeypress(fbt::PeerId id,
107                         fsys::PairingKeypress keypress) override {
108     remote_keypress_cb_(id, keypress);
109   }
110 
set_pairing_request_cb(PairingRequestCallback cb)111   void set_pairing_request_cb(PairingRequestCallback cb) {
112     pairing_request_cb_ = std::move(cb);
113   }
set_pairing_complete_cb(PairingCompleteCallback cb)114   void set_pairing_complete_cb(PairingCompleteCallback cb) {
115     pairing_complete_cb_ = std::move(cb);
116   }
set_remote_keypress_cb(RemoteKeypressCallback cb)117   void set_remote_keypress_cb(RemoteKeypressCallback cb) {
118     remote_keypress_cb_ = std::move(cb);
119   }
120 
121  private:
NotImplemented_(const std::string & name)122   void NotImplemented_(const std::string& name) override {
123     FAIL() << name << " is not implemented";
124   }
125 
126   fidl::Binding<PairingDelegate> binding_;
127   PairingRequestCallback pairing_request_cb_;
128   PairingCompleteCallback pairing_complete_cb_;
129   RemoteKeypressCallback remote_keypress_cb_;
130 };
131 
132 class HostServerTest : public bthost::testing::AdapterTestFixture {
133  public:
134   HostServerTest() = default;
135   ~HostServerTest() override = default;
136 
SetUp()137   void SetUp() override {
138     AdapterTestFixture::SetUp();
139 
140     gatt_ = take_gatt();
141     ResetHostServer();
142   }
143 
ResetHostServer()144   void ResetHostServer() {
145     fidl::InterfaceHandle<fuchsia::bluetooth::host::Host> host_handle;
146     host_server_ =
147         std::make_unique<HostServer>(host_handle.NewRequest().TakeChannel(),
148                                      adapter()->AsWeakPtr(),
149                                      gatt_->GetWeakPtr());
150     host_.Bind(std::move(host_handle));
151   }
152 
TearDown()153   void TearDown() override {
154     RunLoopUntilIdle();
155 
156     host_ = nullptr;
157     host_server_ = nullptr;
158     gatt_ = nullptr;
159 
160     AdapterTestFixture::TearDown();
161   }
162 
163  protected:
host_server() const164   HostServer* host_server() const { return host_server_.get(); }
165 
host_client() const166   fuchsia::bluetooth::host::Host* host_client() const { return host_.get(); }
167 
168   // Mutable reference to the Host client interface pointer.
host_client_ptr()169   fuchsia::bluetooth::host::HostPtr& host_client_ptr() { return host_; }
170 
171   // Create and bind a MockFidlPairingDelegate and attach it to the HostServer
172   // under test. It is heap-allocated to permit its explicit destruction.
173   [[nodiscard]] std::unique_ptr<MockFidlPairingDelegate>
SetMockFidlPairingDelegate(fsys::InputCapability input_capability,fsys::OutputCapability output_capability)174   SetMockFidlPairingDelegate(fsys::InputCapability input_capability,
175                              fsys::OutputCapability output_capability) {
176     using ::testing::StrictMock;
177     fidl::InterfaceHandle<fsys::PairingDelegate> pairing_delegate_handle;
178     auto pairing_delegate = std::make_unique<MockFidlPairingDelegate>(
179         pairing_delegate_handle.NewRequest(), dispatcher());
180     host_client()->SetPairingDelegate(input_capability,
181                                       output_capability,
182                                       std::move(pairing_delegate_handle));
183 
184     // Wait for the Access/SetPairingDelegate message to process.
185     RunLoopUntilIdle();
186     return pairing_delegate;
187   }
188 
AddFakePeer(const bt::DeviceAddress & address)189   bt::gap::Peer* AddFakePeer(const bt::DeviceAddress& address) {
190     bt::gap::Peer* peer =
191         adapter()->peer_cache()->NewPeer(address, /*connectable=*/true);
192     PW_CHECK(peer);
193     PW_CHECK(peer->temporary());
194 
195     test_device()->AddPeer(
196         std::make_unique<FakePeer>(address, pw_dispatcher()));
197 
198     return peer;
199   }
200 
201   using ConnectResult = fhost::Host_Connect_Result;
ConnectFakePeer(bt::PeerId id)202   std::optional<ConnectResult> ConnectFakePeer(bt::PeerId id) {
203     std::optional<ConnectResult> result;
204     host_client()->Connect(fbt::PeerId{id.value()}, [&](ConnectResult _result) {
205       result = std::move(_result);
206     });
207     RunLoopUntilIdle();
208     return result;
209   }
210 
CreateAndConnectFakePeer(bool connect_le=true)211   std::tuple<bt::gap::Peer*, FakeChannel::WeakPtr> CreateAndConnectFakePeer(
212       bool connect_le = true) {
213     auto address = connect_le ? kLeTestAddr : kBredrTestAddr;
214     bt::gap::Peer* peer = AddFakePeer(address);
215 
216     // This is to capture the channel created during the Connection process
217     FakeChannel::WeakPtr fake_chan = FakeChannel::WeakPtr();
218     l2cap()->set_channel_callback(
219         [&fake_chan](FakeChannel::WeakPtr new_fake_chan) {
220           fake_chan = std::move(new_fake_chan);
221         });
222 
223     auto connect_result = ConnectFakePeer(peer->identifier());
224 
225     if (!connect_result || connect_result->is_err()) {
226       peer = nullptr;
227       fake_chan.reset();
228     }
229     return std::make_tuple(peer, fake_chan);
230   }
231 
232   // Calls the RestoreBonds method and verifies that the callback is run with
233   // the expected output.
TestRestoreBonds(fhost::BondingDelegatePtr & delegate,std::vector<fsys::BondingData> bonds,std::vector<fsys::BondingData> expected)234   void TestRestoreBonds(fhost::BondingDelegatePtr& delegate,
235                         std::vector<fsys::BondingData> bonds,
236                         std::vector<fsys::BondingData> expected) {
237     bool called = false;
238     delegate->RestoreBonds(
239         std::move(bonds),
240         [&](fhost::BondingDelegate_RestoreBonds_Result result) {
241           ASSERT_TRUE(result.is_response());
242           called = true;
243           ASSERT_EQ(expected.size(), result.response().errors.size());
244           for (size_t i = 0; i < result.response().errors.size(); i++) {
245             SCOPED_TRACE(i);
246             EXPECT_TRUE(fidl::Equals(result.response().errors[i], expected[i]));
247           }
248         });
249     RunLoopUntilIdle();
250     EXPECT_TRUE(called);
251   }
252 
SetPeerWatcher()253   fidl::InterfacePtr<fhost::PeerWatcher> SetPeerWatcher() {
254     fidl::InterfaceHandle<fhost::PeerWatcher> handle;
255     host_server()->SetPeerWatcher(handle.NewRequest());
256     return handle.Bind();
257   }
258 
259  private:
260   std::unique_ptr<HostServer> host_server_;
261   std::unique_ptr<bt::gatt::GATT> gatt_;
262   fuchsia::bluetooth::host::HostPtr host_;
263 
264   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(HostServerTest);
265 };
266 
267 // The main role of this sub-suite is improved test object lifecycle management
268 // (see TearDown for more details). An additional convenience it provides is
269 // fake peer/channel and mock pairing delegate setup, which all tests of the
270 // full pairing stack need.
271 class HostServerPairingTest : public HostServerTest {
272  public:
SetUp()273   void SetUp() override {
274     HostServerTest::SetUp();
275     NewPairingTest(fsys::InputCapability::NONE, fsys::OutputCapability::NONE);
276   }
277 
NewPairingTest(fsys::InputCapability input_cap,fsys::OutputCapability output_cap,bool is_le=true)278   void NewPairingTest(fsys::InputCapability input_cap,
279                       fsys::OutputCapability output_cap,
280                       bool is_le = true) {
281     pairing_delegate_ = SetMockFidlPairingDelegate(input_cap, output_cap);
282     if (!fake_peer_ || !fake_chan_.is_alive()) {
283       ASSERT_FALSE(fake_peer_);
284       ASSERT_FALSE(fake_chan_.is_alive());
285       std::tie(fake_peer_, fake_chan_) = CreateAndConnectFakePeer(is_le);
286       ASSERT_TRUE(fake_peer_);
287       ASSERT_TRUE(fake_chan_.is_alive());
288       ASSERT_EQ(bt::gap::Peer::ConnectionState::kConnected,
289                 fake_peer_->le()->connection_state());
290     }
291   }
292 
293   // With the base HostServerTest, it is too easy to set up callbacks related to
294   // fake channels or the mock pairing delegate that lead to unexpected failure
295   // callbacks, or worse, use-after- frees. These failures mostly stem from the
296   // Host server notifying the client upon pairing delegate destruction, which
297   // is not important behavior for many tests.
TearDown()298   void TearDown() override {
299     fake_chan_->SetSendCallback(/*callback=*/nullptr);
300     host_client_ptr().Unbind();
301     HostServerTest::TearDown();
302   }
303 
peer()304   bt::gap::Peer* peer() { return fake_peer_; }
fake_chan()305   FakeChannel::WeakPtr fake_chan() { return fake_chan_; }
306 
307  private:
308   std::unique_ptr<MockFidlPairingDelegate> pairing_delegate_;
309   bt::gap::Peer* fake_peer_ = nullptr;
310   FakeChannel::WeakPtr fake_chan_;
311 };
312 
313 // Constructs a vector of a fidl::Clone'able data type that contains a copy of
314 // the input |data|. This allows move-only FIDL types to be re-used in test
315 // cases that need to refer to such data.
316 //
317 // Returns an empty vector if |data| could not be copied, e.g. because it
318 // contains handles that cannot be duplicated.
319 template <typename T>
MakeClonedVector(const T & data)320 std::vector<T> MakeClonedVector(const T& data) {
321   std::vector<T> output;
322   T clone;
323 
324   zx_status_t status = fidl::Clone(data, &clone);
325   EXPECT_EQ(ZX_OK, status);
326   if (status == ZX_OK) {
327     output.push_back(std::move(clone));
328   }
329 
330   return output;
331 }
332 
333 // Construct bonding data structure for testing using the given ID and address
334 // and an empty LE bond structure.
MakeTestBond(bt::PeerId id,fbt::Address address)335 fsys::BondingData MakeTestBond(bt::PeerId id, fbt::Address address) {
336   fsys::BondingData bond;
337   bond.set_identifier(fbt::PeerId{id.value()});
338   bond.set_address(address);
339   bond.set_le_bond(fsys::LeBondData());
340   return bond;
341 }
342 
TEST_F(HostServerTest,FidlIoCapabilitiesMapToHostIoCapability)343 TEST_F(HostServerTest, FidlIoCapabilitiesMapToHostIoCapability) {
344   // Isolate HostServer's private bt::gap::PairingDelegate implementation.
345   auto host_pairing_delegate =
346       static_cast<bt::gap::PairingDelegate*>(host_server());
347 
348   // Getter should be safe to call when no PairingDelegate assigned.
349   EXPECT_EQ(bt::sm::IOCapability::kNoInputNoOutput,
350             host_pairing_delegate->io_capability());
351 
352   auto fidl_pairing_delegate = SetMockFidlPairingDelegate(
353       fsys::InputCapability::KEYBOARD, fsys::OutputCapability::DISPLAY);
354   EXPECT_EQ(bt::sm::IOCapability::kKeyboardDisplay,
355             host_pairing_delegate->io_capability());
356 }
357 
TEST_F(HostServerTest,HostCompletePairingCallsFidlOnPairingComplete)358 TEST_F(HostServerTest, HostCompletePairingCallsFidlOnPairingComplete) {
359   using namespace ::testing;
360 
361   // Isolate HostServer's private bt::gap::PairingDelegate implementation.
362   auto host_pairing_delegate =
363       static_cast<bt::gap::PairingDelegate*>(host_server());
364   auto fidl_pairing_delegate = SetMockFidlPairingDelegate(
365       fsys::InputCapability::KEYBOARD, fsys::OutputCapability::DISPLAY);
366 
367   // fuchsia::bluetooth::PeerId has no equality operator
368   std::optional<fbt::PeerId> actual_id;
369   fidl_pairing_delegate->set_pairing_complete_cb(
370       [&actual_id](fbt::PeerId id, Unused) { actual_id = id; });
371   auto id = bt::PeerId(0xc0decafe);
372   host_pairing_delegate->CompletePairing(
373       id, fit::error(bt::Error(bt::sm::ErrorCode::kConfirmValueFailed)));
374 
375   // Wait for the PairingDelegate/OnPairingComplete message to process.
376   RunLoopUntilIdle();
377 
378   EXPECT_TRUE(actual_id.has_value());
379   EXPECT_EQ(id.value(), actual_id.value().value);
380 }
381 
TEST_F(HostServerTest,HostConfirmPairingRequestsConsentPairingOverFidl)382 TEST_F(HostServerTest, HostConfirmPairingRequestsConsentPairingOverFidl) {
383   using namespace ::testing;
384   auto host_pairing_delegate =
385       static_cast<bt::gap::PairingDelegate*>(host_server());
386   auto fidl_pairing_delegate = SetMockFidlPairingDelegate(
387       fsys::InputCapability::KEYBOARD, fsys::OutputCapability::DISPLAY);
388 
389   auto* const peer =
390       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
391   ASSERT_TRUE(peer);
392 
393   fidl_pairing_delegate->set_pairing_request_cb(
394       [id = peer->identifier()](
395           fsys::Peer peer,
396           fsys::PairingMethod method,
397           uint32_t displayed_passkey,
398           fsys::PairingDelegate::OnPairingRequestCallback callback) {
399         ASSERT_TRUE(peer.has_id());
400         EXPECT_EQ(id.value(), peer.id().value);
401         EXPECT_EQ(method, fsys::PairingMethod::CONSENT);
402         EXPECT_EQ(displayed_passkey, 0u);
403         callback(/*accept=*/true, /*entered_passkey=*/0u);
404       });
405 
406   bool confirm_cb_value = false;
407   bt::gap::PairingDelegate::ConfirmCallback confirm_cb =
408       [&confirm_cb_value](bool confirmed) { confirm_cb_value = confirmed; };
409   host_pairing_delegate->ConfirmPairing(peer->identifier(),
410                                         std::move(confirm_cb));
411 
412   // Wait for the PairingDelegate/OnPairingRequest message to process.
413   RunLoopUntilIdle();
414   EXPECT_TRUE(confirm_cb_value);
415 }
416 
TEST_F(HostServerTest,HostDisplayPasskeyRequestsPasskeyDisplayOrNumericComparisonPairingOverFidl)417 TEST_F(
418     HostServerTest,
419     HostDisplayPasskeyRequestsPasskeyDisplayOrNumericComparisonPairingOverFidl) {
420   using namespace ::testing;
421   auto host_pairing_delegate =
422       static_cast<bt::gap::PairingDelegate*>(host_server());
423   auto fidl_pairing_delegate = SetMockFidlPairingDelegate(
424       fsys::InputCapability::KEYBOARD, fsys::OutputCapability::DISPLAY);
425 
426   auto* const peer =
427       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
428   ASSERT_TRUE(peer);
429 
430   // This call should use PASSKEY_DISPLAY to request that the user perform peer
431   // passkey entry.
432   fidl_pairing_delegate->set_pairing_request_cb(
433       [id = peer->identifier()](
434           fsys::Peer peer,
435           fsys::PairingMethod method,
436           uint32_t displayed_passkey,
437           fsys::PairingDelegate::OnPairingRequestCallback callback) {
438         ASSERT_TRUE(peer.has_id());
439         EXPECT_EQ(id.value(), peer.id().value);
440         EXPECT_EQ(method, fsys::PairingMethod::PASSKEY_DISPLAY);
441         EXPECT_EQ(displayed_passkey, 12345u);
442         callback(/*accept=*/false, /*entered_passkey=*/0u);
443       });
444 
445   bool confirm_cb_called = false;
446   auto confirm_cb = [&confirm_cb_called](bool confirmed) {
447     EXPECT_FALSE(confirmed);
448     confirm_cb_called = true;
449   };
450   using DisplayMethod = bt::gap::PairingDelegate::DisplayMethod;
451   host_pairing_delegate->DisplayPasskey(
452       peer->identifier(), 12345, DisplayMethod::kPeerEntry, confirm_cb);
453 
454   // Wait for the PairingDelegate/OnPairingRequest message to process.
455   RunLoopUntilIdle();
456   EXPECT_TRUE(confirm_cb_called);
457 
458   // This call should use PASSKEY_COMPARISON to request that the user compare
459   // the passkeys shown on the local and peer devices.
460   fidl_pairing_delegate->set_pairing_request_cb(
461       [id = peer->identifier()](
462           fsys::Peer peer,
463           fsys::PairingMethod method,
464           uint32_t displayed_passkey,
465           fsys::PairingDelegate::OnPairingRequestCallback callback) {
466         ASSERT_TRUE(peer.has_id());
467         EXPECT_EQ(id.value(), peer.id().value);
468         EXPECT_EQ(method, fsys::PairingMethod::PASSKEY_COMPARISON);
469         EXPECT_EQ(displayed_passkey, 12345u);
470         callback(/*accept=*/false, /*entered_passkey=*/0u);
471       });
472 
473   confirm_cb_called = false;
474   host_pairing_delegate->DisplayPasskey(
475       peer->identifier(), 12345, DisplayMethod::kComparison, confirm_cb);
476 
477   // Wait for the PairingDelegate/OnPairingRequest message to process.
478   RunLoopUntilIdle();
479   EXPECT_TRUE(confirm_cb_called);
480 }
481 
TEST_F(HostServerTest,HostRequestPasskeyRequestsPasskeyEntryPairingOverFidl)482 TEST_F(HostServerTest, HostRequestPasskeyRequestsPasskeyEntryPairingOverFidl) {
483   using namespace ::testing;
484   auto host_pairing_delegate =
485       static_cast<bt::gap::PairingDelegate*>(host_server());
486   auto fidl_pairing_delegate = SetMockFidlPairingDelegate(
487       fsys::InputCapability::KEYBOARD, fsys::OutputCapability::DISPLAY);
488 
489   auto* const peer =
490       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
491   ASSERT_TRUE(peer);
492 
493   std::optional<int64_t> passkey_response;
494   auto response_cb = [&passkey_response](int64_t passkey) {
495     passkey_response = passkey;
496   };
497 
498   // The first request is rejected and should receive a negative passkey value,
499   // regardless what was passed over FIDL (i.e. 12345).
500   fidl_pairing_delegate->set_pairing_request_cb(
501       [id = peer->identifier()](
502           fsys::Peer peer,
503           fsys::PairingMethod method,
504           uint32_t displayed_passkey,
505           fsys::PairingDelegate::OnPairingRequestCallback callback) {
506         ASSERT_TRUE(peer.has_id());
507         EXPECT_EQ(id.value(), peer.id().value);
508         EXPECT_EQ(method, fsys::PairingMethod::PASSKEY_ENTRY);
509         EXPECT_EQ(displayed_passkey, 0u);
510         callback(/*accept=*/false, /*entered_passkey=*/12345);
511       });
512 
513   host_pairing_delegate->RequestPasskey(peer->identifier(), response_cb);
514   RunLoopUntilIdle();
515   ASSERT_TRUE(passkey_response.has_value());
516   EXPECT_LT(passkey_response.value(), 0);
517 
518   // The second request should be accepted with the passkey set to "0".
519   fidl_pairing_delegate->set_pairing_request_cb(
520       [id = peer->identifier()](
521           fsys::Peer peer,
522           Unused,
523           Unused,
524           fsys::PairingDelegate::OnPairingRequestCallback callback) {
525         ASSERT_TRUE(peer.has_id());
526         EXPECT_EQ(id.value(), peer.id().value);
527         callback(/*accept=*/true, /*entered_passkey=*/0);
528       });
529 
530   passkey_response.reset();
531   host_pairing_delegate->RequestPasskey(peer->identifier(), response_cb);
532   RunLoopUntilIdle();
533   ASSERT_TRUE(passkey_response.has_value());
534   EXPECT_EQ(0, passkey_response.value());
535 
536   // The third request should be accepted with the passkey set to "12345".
537   fidl_pairing_delegate->set_pairing_request_cb(
538       [id = peer->identifier()](
539           fsys::Peer peer,
540           Unused,
541           Unused,
542           fsys::PairingDelegate::OnPairingRequestCallback callback) {
543         ASSERT_TRUE(peer.has_id());
544         EXPECT_EQ(id.value(), peer.id().value);
545         callback(/*accept=*/true, /*entered_passkey=*/12345);
546       });
547 
548   passkey_response.reset();
549   host_pairing_delegate->RequestPasskey(peer->identifier(), response_cb);
550   RunLoopUntilIdle();
551   ASSERT_TRUE(passkey_response.has_value());
552   EXPECT_EQ(12345, passkey_response.value());
553 }
554 
TEST_F(HostServerTest,SysDelegateInvokesCallbackMultipleTimesIgnored)555 TEST_F(HostServerTest, SysDelegateInvokesCallbackMultipleTimesIgnored) {
556   using namespace ::testing;
557   auto host_pairing_delegate =
558       static_cast<bt::gap::PairingDelegate*>(host_server());
559   auto fidl_pairing_delegate = SetMockFidlPairingDelegate(
560       fsys::InputCapability::KEYBOARD, fsys::OutputCapability::DISPLAY);
561 
562   auto* const peer =
563       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
564   ASSERT_TRUE(peer);
565 
566   using OnPairingRequestCallback =
567       fsys::PairingDelegate::OnPairingRequestCallback;
568   OnPairingRequestCallback fidl_passkey_req_cb = nullptr,
569                            fidl_confirm_req_cb = nullptr;
570   fidl_pairing_delegate->set_pairing_request_cb(
571       [id = peer->identifier(), &fidl_passkey_req_cb, &fidl_confirm_req_cb](
572           fsys::Peer peer,
573           fsys::PairingMethod method,
574           auto /*ignore*/,
575           OnPairingRequestCallback callback) {
576         ASSERT_TRUE(peer.has_id());
577         EXPECT_EQ(id.value(), peer.id().value);
578         if (method == fsys::PairingMethod::PASSKEY_ENTRY) {
579           fidl_passkey_req_cb = std::move(callback);
580         } else if (method == fsys::PairingMethod::CONSENT) {
581           fidl_confirm_req_cb = std::move(callback);
582         } else {
583           FAIL() << "unexpected pairing request method!";
584         }
585       });
586 
587   size_t passkey_req_cb_count = 0, confirm_req_cb_count = 0;
588   auto passkey_response_cb = [&passkey_req_cb_count](int64_t /*ignore*/) {
589     passkey_req_cb_count++;
590     ;
591   };
592   auto confirm_req_cb = [&confirm_req_cb_count](bool /*ignore*/) {
593     confirm_req_cb_count++;
594   };
595 
596   host_pairing_delegate->RequestPasskey(peer->identifier(),
597                                         passkey_response_cb);
598   host_pairing_delegate->ConfirmPairing(peer->identifier(), confirm_req_cb);
599   RunLoopUntilIdle();
600   ASSERT_TRUE(fidl_passkey_req_cb);
601   ASSERT_TRUE(fidl_confirm_req_cb);
602 
603   ASSERT_EQ(0u, passkey_req_cb_count);
604   ASSERT_EQ(0u, confirm_req_cb_count);
605 
606   fidl_passkey_req_cb(true, 12345);
607   fidl_confirm_req_cb(true, 0);
608   RunLoopUntilIdle();
609   ASSERT_EQ(1u, passkey_req_cb_count);
610   ASSERT_EQ(1u, confirm_req_cb_count);
611 
612   fidl_passkey_req_cb(true, 456789);
613   fidl_confirm_req_cb(true, 0);
614   RunLoopUntilIdle();
615   ASSERT_EQ(1u, passkey_req_cb_count);
616   ASSERT_EQ(1u, confirm_req_cb_count);
617 }
618 
TEST_F(HostServerTest,WatchState)619 TEST_F(HostServerTest, WatchState) {
620   std::optional<fsys::HostInfo> info;
621   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
622     ASSERT_TRUE(result.is_response());
623     info = std::move(result.response().info);
624   });
625   ASSERT_TRUE(info.has_value());
626   ASSERT_TRUE(info->has_id());
627   ASSERT_TRUE(info->has_technology());
628   ASSERT_TRUE(info->has_local_name());
629   ASSERT_TRUE(info->has_discoverable());
630   ASSERT_TRUE(info->has_discovering());
631   ASSERT_TRUE(info->has_addresses());
632 
633   EXPECT_EQ(adapter()->identifier().value(), info->id().value);
634   EXPECT_EQ(fsys::TechnologyType::DUAL_MODE, info->technology());
635   EXPECT_EQ("fuchsia", info->local_name());
636   EXPECT_FALSE(info->discoverable());
637   EXPECT_FALSE(info->discovering());
638   EXPECT_EQ(fbt::AddressType::PUBLIC, info->addresses()[0].type);
639   EXPECT_TRUE(ContainersEqual(adapter()->state().controller_address.bytes(),
640                               info->addresses()[0].bytes));
641 }
642 
TEST_F(HostServerTest,WatchDiscoveryState)643 TEST_F(HostServerTest, WatchDiscoveryState) {
644   std::optional<fsys::HostInfo> info;
645 
646   // Make initial watch call so that subsequent calls remain pending.
647   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
648     ASSERT_TRUE(result.is_response());
649     info = std::move(result.response().info);
650   });
651   RunLoopUntilIdle();
652   ASSERT_TRUE(info.has_value());
653   ASSERT_TRUE(info->has_discovering());
654   EXPECT_FALSE(info->discovering());
655   info.reset();
656 
657   // Watch for updates.
658   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
659     ASSERT_TRUE(result.is_response());
660     info = std::move(result.response().info);
661   });
662   RunLoopUntilIdle();
663   EXPECT_FALSE(info.has_value());
664 
665   fhost::DiscoverySessionHandle discovery;
666   fhost::HostStartDiscoveryRequest start_request;
667   start_request.set_token(discovery.NewRequest());
668   fidl::InterfacePtr discovery_client = discovery.Bind();
669   std::optional<zx_status_t> discovery_error;
670   discovery_client.set_error_handler(
671       [&](zx_status_t error) { discovery_error = error; });
672   host_client()->StartDiscovery(std::move(start_request));
673   RunLoopUntilIdle();
674   EXPECT_FALSE(discovery_error);
675   ASSERT_TRUE(info.has_value());
676   ASSERT_TRUE(info->has_discovering());
677   EXPECT_TRUE(info->discovering());
678 
679   info.reset();
680   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
681     ASSERT_TRUE(result.is_response());
682     info = std::move(result.response().info);
683   });
684   RunLoopUntilIdle();
685   EXPECT_FALSE(info.has_value());
686   discovery_client->Stop();
687   RunLoopUntilIdle();
688   ASSERT_TRUE(discovery_error);
689   EXPECT_EQ(discovery_error.value(), ZX_ERR_CANCELED);
690   ASSERT_TRUE(info.has_value());
691   ASSERT_TRUE(info->has_discovering());
692   EXPECT_FALSE(info->discovering());
693 }
694 
TEST_F(HostServerTest,StartDiscoveryWithMissingToken)695 TEST_F(HostServerTest, StartDiscoveryWithMissingToken) {
696   fhost::HostStartDiscoveryRequest start_request;
697   host_client()->StartDiscovery(std::move(start_request));
698   RunLoopUntilIdle();
699 }
700 
TEST_F(HostServerTest,StartDiscoveryTwiceAndCloseTwice)701 TEST_F(HostServerTest, StartDiscoveryTwiceAndCloseTwice) {
702   fhost::DiscoverySessionHandle discovery_0;
703   fhost::HostStartDiscoveryRequest start_request_0;
704   start_request_0.set_token(discovery_0.NewRequest());
705   fidl::InterfacePtr discovery_client_0 = discovery_0.Bind();
706   std::optional<zx_status_t> discovery_error_0;
707   discovery_client_0.set_error_handler(
708       [&](zx_status_t error) { discovery_error_0 = error; });
709   host_client()->StartDiscovery(std::move(start_request_0));
710   RunLoopUntilIdle();
711   EXPECT_FALSE(discovery_error_0);
712 
713   fhost::DiscoverySessionHandle discovery_1;
714   fhost::HostStartDiscoveryRequest start_request_1;
715   start_request_1.set_token(discovery_1.NewRequest());
716   fidl::InterfacePtr discovery_client_1 = discovery_1.Bind();
717   std::optional<zx_status_t> discovery_error_1;
718   discovery_client_1.set_error_handler(
719       [&](zx_status_t error) { discovery_error_1 = error; });
720   host_client()->StartDiscovery(std::move(start_request_1));
721   RunLoopUntilIdle();
722   EXPECT_FALSE(discovery_error_0);
723   EXPECT_FALSE(discovery_error_1);
724 
725   std::optional<fsys::HostInfo> info;
726   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
727     info = std::move(result.response().info);
728   });
729   RunLoopUntilIdle();
730   ASSERT_TRUE(info.has_value());
731   EXPECT_TRUE(info->discovering());
732   info.reset();
733 
734   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
735     info = std::move(result.response().info);
736   });
737   RunLoopUntilIdle();
738   EXPECT_FALSE(info.has_value());
739 
740   discovery_client_0.Unbind();
741   RunLoopUntilIdle();
742   // Client 1 is still open, so discovery should still be enabled.
743   EXPECT_FALSE(info.has_value());
744 
745   discovery_client_1.Unbind();
746   RunLoopUntilIdle();
747   ASSERT_TRUE(info.has_value());
748   EXPECT_FALSE(info->discovering());
749 }
750 
TEST_F(HostServerTest,WatchDiscoverableState)751 TEST_F(HostServerTest, WatchDiscoverableState) {
752   std::optional<fsys::HostInfo> info;
753 
754   // Make initial watch call so that subsequent calls remain pending.
755   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
756     ASSERT_TRUE(result.is_response());
757     info = std::move(result.response().info);
758   });
759   ASSERT_TRUE(info.has_value());
760   info.reset();
761 
762   // Watch for updates.
763   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
764     ASSERT_TRUE(result.is_response());
765     info = std::move(result.response().info);
766   });
767   EXPECT_FALSE(info.has_value());
768 
769   host_server()->SetDiscoverable(/*discoverable=*/true, [](auto) {});
770   RunLoopUntilIdle();
771   ASSERT_TRUE(info.has_value());
772   ASSERT_TRUE(info->has_discoverable());
773   EXPECT_TRUE(info->discoverable());
774 
775   info.reset();
776   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
777     ASSERT_TRUE(result.is_response());
778     info = std::move(result.response().info);
779   });
780   EXPECT_FALSE(info.has_value());
781   host_server()->SetDiscoverable(/*discoverable=*/false, [](auto) {});
782   RunLoopUntilIdle();
783   ASSERT_TRUE(info.has_value());
784   ASSERT_TRUE(info->has_discoverable());
785   EXPECT_FALSE(info->discoverable());
786 }
787 
TEST_F(HostServerPairingTest,InitiatePairingLeDefault)788 TEST_F(HostServerPairingTest, InitiatePairingLeDefault) {
789   const StaticByteBuffer kExpected(
790       0x01,  // code: "Pairing Request"
791       0x04,  // IO cap.: KeyboardDisplay
792       0x00,  // OOB: not present
793       // inclusive-language: ignore
794       AuthReq::kBondingFlag | AuthReq::kMITM | AuthReq::kSC | AuthReq::kCT2,
795       0x10,  // encr. key size: 16 (default max)
796       KeyDistGen::kEncKey | KeyDistGen::kLinkKey,  // initiator keys
797       KeyDistGen::kEncKey | KeyDistGen::kIdKey |
798           KeyDistGen::kLinkKey  // responder keys
799   );
800 
801   // inclusive-language: ignore
802   // IOCapabilities must be KeyboardDisplay to support default MITM pairing
803   // request.
804   NewPairingTest(fsys::InputCapability::KEYBOARD,
805                  fsys::OutputCapability::DISPLAY);
806 
807   bool pairing_request_sent = false;
808   // This test only checks that SecureSimplePairingState kicks off an LE pairing
809   // feature exchange correctly, as the call to Pair is only responsible for
810   // starting pairing, not for completing it.
811   auto expect_default_bytebuffer = [&pairing_request_sent,
812                                     kExpected](bt::ByteBufferPtr sent) {
813     ASSERT_TRUE(sent);
814     ASSERT_EQ(*sent, kExpected);
815     pairing_request_sent = true;
816   };
817   fake_chan()->SetSendCallback(expect_default_bytebuffer, pw_dispatcher());
818 
819   std::optional<fhost::Host_Pair_Result> pair_result;
820   fsys::PairingOptions opts;
821   host_client()->Pair(
822       fbt::PeerId{peer()->identifier().value()},
823       std::move(opts),
824       [&](fhost::Host_Pair_Result result) { pair_result = std::move(result); });
825   RunLoopUntilIdle();
826 
827   // TODO(fxbug.dev/42169848): We don't have a good mechanism for driving
828   // pairing to completion without faking the entire SMP exchange. We should add
829   // SMP mocks that allows us to propagate a result up to the FIDL layer. For
830   // now we assert that pairing has started and remains pending.
831   ASSERT_FALSE(pair_result);  // Pairing request is pending
832   ASSERT_TRUE(pairing_request_sent);
833 }
834 
TEST_F(HostServerPairingTest,InitiatePairingLeEncrypted)835 TEST_F(HostServerPairingTest, InitiatePairingLeEncrypted) {
836   const StaticByteBuffer kExpected(
837       0x01,  // code: "Pairing Request"
838       0x03,  // IO cap.: NoInputNoOutput
839       0x00,  // OOB: not present
840       AuthReq::kBondingFlag | AuthReq::kSC | AuthReq::kCT2,
841       0x10,  // encr. key size: 16 (default max)
842       KeyDistGen::kEncKey | KeyDistGen::kLinkKey,  // initiator keys
843       KeyDistGen::kEncKey | KeyDistGen::kIdKey |
844           KeyDistGen::kLinkKey  // responder keys
845   );
846 
847   bool pairing_request_sent = false;
848   // This test only checks that SecureSimplePairingState kicks off an LE pairing
849   // feature exchange correctly, as the call to Pair is only responsible for
850   // starting pairing, not for completing it.
851   auto expect_default_bytebuffer = [&pairing_request_sent,
852                                     kExpected](bt::ByteBufferPtr sent) {
853     ASSERT_TRUE(sent);
854     ASSERT_EQ(*sent, kExpected);
855     pairing_request_sent = true;
856   };
857   fake_chan()->SetSendCallback(expect_default_bytebuffer, pw_dispatcher());
858 
859   std::optional<fhost::Host_Pair_Result> pair_result;
860   fsys::PairingOptions opts;
861   opts.set_le_security_level(fsys::PairingSecurityLevel::ENCRYPTED);
862   host_client()->Pair(fbt::PeerId{peer()->identifier().value()},
863                       std::move(opts),
864                       [&](auto result) { pair_result = std::move(result); });
865   RunLoopUntilIdle();
866 
867   // TODO(fxbug.dev/42169848): We don't have a good mechanism for driving
868   // pairing to completion without faking the entire SMP exchange. We should add
869   // SMP mocks that allows us to propagate a result up to the FIDL layer. For
870   // now we assert that pairing has started and remains pending.
871   ASSERT_FALSE(pair_result);  // Pairing request is pending
872   ASSERT_TRUE(pairing_request_sent);
873 }
874 
TEST_F(HostServerPairingTest,InitiatePairingNonBondableLe)875 TEST_F(HostServerPairingTest, InitiatePairingNonBondableLe) {
876   const StaticByteBuffer kExpected(
877       0x01,  // code: "Pairing Request"
878       0x04,  // IO cap.: KeyboardDisplay
879       0x00,  // OOB: not present
880       // inclusive-language: ignore
881       AuthReq::kMITM | AuthReq::kSC | AuthReq::kCT2,
882       0x10,  // encr. key size: 16 (default max)
883       0x00,  // initiator keys: none
884       0x00   // responder keys: none
885   );
886 
887   // inclusive-language: ignore
888   // IOCapabilities must be KeyboardDisplay to support default MITM pairing
889   // request.
890   NewPairingTest(fsys::InputCapability::KEYBOARD,
891                  fsys::OutputCapability::DISPLAY);
892 
893   bool pairing_request_sent = false;
894   // This test only checks that SecureSimplePairingState kicks off an LE pairing
895   // feature exchange correctly, as the call to Pair is only responsible for
896   // starting pairing, not for completing it.
897   auto expect_default_bytebuffer = [&pairing_request_sent,
898                                     kExpected](bt::ByteBufferPtr sent) {
899     ASSERT_TRUE(sent);
900     ASSERT_EQ(*sent, kExpected);
901     pairing_request_sent = true;
902   };
903   fake_chan()->SetSendCallback(expect_default_bytebuffer, pw_dispatcher());
904 
905   std::optional<fhost::Host_Pair_Result> pair_result;
906   fsys::PairingOptions opts;
907   opts.set_bondable_mode(fsys::BondableMode::NON_BONDABLE);
908   host_client()->Pair(fbt::PeerId{peer()->identifier().value()},
909                       std::move(opts),
910                       [&](auto result) { pair_result = std::move(result); });
911   RunLoopUntilIdle();
912 
913   // TODO(fxbug.dev/42169848): We don't have a good mechanism for driving
914   // pairing to completion without faking the entire SMP exchange. We should add
915   // SMP mocks that allows us to propagate a result up to the FIDL layer. For
916   // now we assert that pairing has started and remains pending.
917   ASSERT_FALSE(pair_result);  // Pairing request is pending
918   ASSERT_TRUE(pairing_request_sent);
919 }
920 
TEST_F(HostServerTest,InitiateBrEdrPairingLePeerFails)921 TEST_F(HostServerTest, InitiateBrEdrPairingLePeerFails) {
922   auto [peer, fake_chan] = CreateAndConnectFakePeer();
923   ASSERT_TRUE(peer);
924   ASSERT_TRUE(fake_chan.is_alive());
925   ASSERT_EQ(bt::gap::Peer::ConnectionState::kConnected,
926             peer->le()->connection_state());
927 
928   std::optional<fhost::Host_Pair_Result> pair_result;
929   fsys::PairingOptions opts;
930   // Set pairing option with classic
931   opts.set_transport(fsys::TechnologyType::CLASSIC);
932   auto pair_cb = [&](auto result) {
933     ASSERT_TRUE(result.is_err());
934     pair_result = std::move(result);
935   };
936   host_client()->Pair(fbt::PeerId{peer->identifier().value()},
937                       std::move(opts),
938                       std::move(pair_cb));
939   RunLoopUntilIdle();
940   ASSERT_TRUE(pair_result);
941   ASSERT_TRUE(pair_result->is_err());
942   ASSERT_EQ(pair_result->err(), fsys::Error::PEER_NOT_FOUND);
943 }
944 
TEST_F(HostServerTest,PeerWatcherGetNextHangsOnFirstCallWithNoExistingPeers)945 TEST_F(HostServerTest, PeerWatcherGetNextHangsOnFirstCallWithNoExistingPeers) {
946   // By default the peer cache contains no entries when HostServer is first
947   // constructed. The first call to GetNext should hang.
948   bool replied = false;
949   fidl::InterfacePtr<fhost::PeerWatcher> client = SetPeerWatcher();
950   client->GetNext([&](auto) { replied = true; });
951   RunLoopUntilIdle();
952   EXPECT_FALSE(replied);
953 }
954 
TEST_F(HostServerTest,PeerWatcherGetNextRepliesOnFirstCallWithExistingPeers)955 TEST_F(HostServerTest, PeerWatcherGetNextRepliesOnFirstCallWithExistingPeers) {
956   [[maybe_unused]] bt::gap::Peer* peer =
957       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
958   ResetHostServer();
959 
960   // The first call to GetNext immediately resolves with the contents of the
961   // peer cache.
962   bool replied = false;
963   fidl::InterfacePtr<fhost::PeerWatcher> client = SetPeerWatcher();
964   client->GetNext([&](fhost::PeerWatcher_GetNext_Result result) {
965     ASSERT_TRUE(result.is_response());
966     ASSERT_TRUE(result.response().is_updated());
967     EXPECT_EQ(1u, result.response().updated().size());
968     replied = true;
969   });
970   RunLoopUntilIdle();
971   EXPECT_TRUE(replied);
972 }
973 
TEST_F(HostServerTest,PeerWatcherHandlesNonEnumeratedAppearanceInPeer)974 TEST_F(HostServerTest, PeerWatcherHandlesNonEnumeratedAppearanceInPeer) {
975   using namespace ::testing;
976   bt::gap::Peer* const peer =
977       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
978   ASSERT_TRUE(peer);
979   bt::AdvertisingData adv_data;
980 
981   // Invalid appearance.
982   adv_data.SetAppearance(0xFFFFu);
983   bt::DynamicByteBuffer write_buf(
984       adv_data.CalculateBlockSize(/*include_flags=*/true));
985   ASSERT_TRUE(
986       adv_data.WriteBlock(&write_buf, bt::AdvFlag::kLEGeneralDiscoverableMode));
987   peer->MutLe().SetAdvertisingData(
988       /*rssi=*/0, write_buf, pw::chrono::SystemClock::time_point());
989 
990   ResetHostServer();
991 
992   bool replied = false;
993   fidl::InterfacePtr<fhost::PeerWatcher> client = SetPeerWatcher();
994   client->GetNext([&](fhost::PeerWatcher_GetNext_Result result) {
995     // Client should still receive updates to this peer.
996     replied = true;
997     const fbt::PeerId id = {peer->identifier().value()};
998     ASSERT_TRUE(result.is_response());
999     ASSERT_THAT(result.response().updated(),
1000                 Contains(Property(&fsys::Peer::id, id)));
1001     EXPECT_FALSE(result.response().updated().front().has_appearance());
1002   });
1003   RunLoopUntilIdle();
1004   EXPECT_TRUE(replied);
1005 }
1006 
TEST_F(HostServerTest,PeerWatcherStateMachine)1007 TEST_F(HostServerTest, PeerWatcherStateMachine) {
1008   std::optional<fhost::PeerWatcher_GetNext_Response> response;
1009 
1010   // Initial watch call hangs as the cache is empty.
1011   fidl::InterfacePtr<fhost::PeerWatcher> client = SetPeerWatcher();
1012   client->GetNext([&](fhost::PeerWatcher_GetNext_Result result) {
1013     ASSERT_TRUE(result.is_response());
1014     response = std::move(result.response());
1015   });
1016   ASSERT_FALSE(response.has_value());
1017 
1018   // Adding a new peer should resolve the hanging get.
1019   bt::gap::Peer* peer =
1020       adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
1021   RunLoopUntilIdle();
1022   ASSERT_TRUE(response.has_value());
1023   ASSERT_TRUE(response->is_updated());
1024   EXPECT_EQ(1u, response->updated().size());
1025   EXPECT_TRUE(
1026       fidl::Equals(fidl_helpers::PeerToFidl(*peer), response->updated()[0]));
1027   response.reset();
1028 
1029   // The next call should hang.
1030   client->GetNext([&](fhost::PeerWatcher_GetNext_Result result) {
1031     ASSERT_TRUE(result.is_response());
1032     response = std::move(result.response());
1033   });
1034   RunLoopUntilIdle();
1035   ASSERT_FALSE(response.has_value());
1036 
1037   // Removing the peer should resolve the hanging get.
1038   auto peer_id = peer->identifier();
1039   [[maybe_unused]] auto result =
1040       adapter()->peer_cache()->RemoveDisconnectedPeer(peer_id);
1041   RunLoopUntilIdle();
1042   ASSERT_TRUE(response.has_value());
1043   ASSERT_TRUE(response->is_removed());
1044   EXPECT_EQ(1u, response->removed().size());
1045   EXPECT_TRUE(
1046       fidl::Equals(fbt::PeerId{peer_id.value()}, response->removed()[0]));
1047 }
1048 
TEST_F(HostServerTest,WatchPeersUpdatedThenRemoved)1049 TEST_F(HostServerTest, WatchPeersUpdatedThenRemoved) {
1050   fidl::InterfacePtr<fhost::PeerWatcher> client = SetPeerWatcher();
1051   RunLoopUntilIdle();
1052 
1053   // Add then remove a peer. The watcher should only report the removal.
1054   bt::PeerId id;
1055   {
1056     bt::gap::Peer* peer =
1057         adapter()->peer_cache()->NewPeer(kLeTestAddr, /*connectable=*/true);
1058     id = peer->identifier();
1059 
1060     // |peer| becomes a dangling pointer after the call to
1061     // RemoveDisconnectedPeer. We scoped the binding of |peer| so that it
1062     // doesn't exist beyond this point.
1063     [[maybe_unused]] auto result =
1064         adapter()->peer_cache()->RemoveDisconnectedPeer(id);
1065   }
1066 
1067   bool replied = false;
1068   client->GetNext([&](fhost::PeerWatcher_GetNext_Result result) {
1069     ASSERT_TRUE(result.is_response());
1070     ASSERT_TRUE(result.response().is_removed());
1071     EXPECT_EQ(1u, result.response().removed().size());
1072     EXPECT_TRUE(
1073         fidl::Equals(fbt::PeerId{id.value()}, result.response().removed()[0]));
1074     replied = true;
1075   });
1076   RunLoopUntilIdle();
1077   EXPECT_TRUE(replied);
1078 }
1079 
TEST_F(HostServerTest,SetBrEdrSecurityMode)1080 TEST_F(HostServerTest, SetBrEdrSecurityMode) {
1081   // Default BR/EDR security mode is Mode 4
1082   ASSERT_EQ(
1083       fidl_helpers::BrEdrSecurityModeFromFidl(fsys::BrEdrSecurityMode::MODE_4),
1084       adapter()->bredr()->security_mode());
1085 
1086   // Set the HostServer to SecureConnectionsOnly mode first
1087   host_client()->SetBrEdrSecurityMode(
1088       fsys::BrEdrSecurityMode::SECURE_CONNECTIONS_ONLY);
1089   RunLoopUntilIdle();
1090   ASSERT_EQ(fidl_helpers::BrEdrSecurityModeFromFidl(
1091                 fsys::BrEdrSecurityMode::SECURE_CONNECTIONS_ONLY),
1092             adapter()->bredr()->security_mode());
1093 
1094   // Set the HostServer back to Mode 4 and verify that the change takes place
1095   host_client()->SetBrEdrSecurityMode(fsys::BrEdrSecurityMode::MODE_4);
1096   RunLoopUntilIdle();
1097   ASSERT_EQ(
1098       fidl_helpers::BrEdrSecurityModeFromFidl(fsys::BrEdrSecurityMode::MODE_4),
1099       adapter()->bredr()->security_mode());
1100 }
1101 
TEST_F(HostServerTest,SetLeSecurityMode)1102 TEST_F(HostServerTest, SetLeSecurityMode) {
1103   // Set the HostServer to SecureConnectionsOnly mode first
1104   host_client()->SetLeSecurityMode(
1105       fsys::LeSecurityMode::SECURE_CONNECTIONS_ONLY);
1106   RunLoopUntilIdle();
1107   ASSERT_EQ(fidl_helpers::LeSecurityModeFromFidl(
1108                 fsys::LeSecurityMode::SECURE_CONNECTIONS_ONLY),
1109             adapter()->le()->security_mode());
1110 
1111   // Set the HostServer back to Mode 1 and verify that the change takes place
1112   host_client()->SetLeSecurityMode(fsys::LeSecurityMode::MODE_1);
1113   RunLoopUntilIdle();
1114   ASSERT_EQ(fidl_helpers::LeSecurityModeFromFidl(fsys::LeSecurityMode::MODE_1),
1115             adapter()->le()->security_mode());
1116 }
1117 
TEST_F(HostServerTest,ConnectLowEnergy)1118 TEST_F(HostServerTest, ConnectLowEnergy) {
1119   bt::gap::Peer* peer = AddFakePeer(kLeTestAddr);
1120   EXPECT_EQ(bt::gap::TechnologyType::kLowEnergy, peer->technology());
1121 
1122   auto result = ConnectFakePeer(peer->identifier());
1123   ASSERT_TRUE(result);
1124   ASSERT_FALSE(result->is_err());
1125 
1126   EXPECT_FALSE(peer->bredr());
1127   ASSERT_TRUE(peer->le());
1128   EXPECT_TRUE(peer->le()->connected());
1129 
1130   // bt-host should only attempt to connect the LE transport.
1131   EXPECT_EQ(1, test_device()->le_create_connection_command_count());
1132   EXPECT_EQ(0, test_device()->acl_create_connection_command_count());
1133 }
1134 
TEST_F(HostServerTest,ConnectBredr)1135 TEST_F(HostServerTest, ConnectBredr) {
1136   bt::gap::Peer* peer = AddFakePeer(kBredrTestAddr);
1137   EXPECT_EQ(bt::gap::TechnologyType::kClassic, peer->technology());
1138 
1139   auto result = ConnectFakePeer(peer->identifier());
1140   ASSERT_TRUE(result);
1141   ASSERT_FALSE(result->is_err());
1142 
1143   EXPECT_FALSE(peer->le());
1144   ASSERT_TRUE(peer->bredr());
1145 
1146   // bt-host should only attempt to connect the BR/EDR transport.
1147   EXPECT_EQ(0, test_device()->le_create_connection_command_count());
1148   EXPECT_EQ(1, test_device()->acl_create_connection_command_count());
1149 }
1150 
TEST_F(HostServerTest,ConnectDualMode)1151 TEST_F(HostServerTest, ConnectDualMode) {
1152   // Initialize the peer with data for both transport types.
1153   bt::gap::Peer* peer = AddFakePeer(kBredrTestAddr);
1154   peer->MutLe();
1155   ASSERT_TRUE(peer->le());
1156   peer->MutBrEdr();
1157   ASSERT_TRUE(peer->bredr());
1158   EXPECT_EQ(bt::gap::TechnologyType::kDualMode, peer->technology());
1159 
1160   auto result = ConnectFakePeer(peer->identifier());
1161   ASSERT_TRUE(result);
1162   ASSERT_FALSE(result->is_err());
1163 
1164   // bt-host should only attempt to connect the BR/EDR transport.
1165   EXPECT_FALSE(peer->le()->connected());
1166   EXPECT_EQ(0, test_device()->le_create_connection_command_count());
1167   EXPECT_EQ(1, test_device()->acl_create_connection_command_count());
1168 }
1169 
TEST_F(HostServerTest,RestoreBondsErrorDataMissing)1170 TEST_F(HostServerTest, RestoreBondsErrorDataMissing) {
1171   fidl::InterfaceHandle<fhost::BondingDelegate> delegate_handle;
1172   host_client()->SetBondingDelegate(delegate_handle.NewRequest());
1173   fhost::BondingDelegatePtr delegate = delegate_handle.Bind();
1174 
1175   fsys::BondingData bond;
1176 
1177   // Empty bond.
1178   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1179 
1180   // ID missing.
1181   bond = MakeTestBond(kTestId, kTestFidlAddrPublic);
1182   bond.clear_identifier();
1183   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1184 
1185   // Address missing.
1186   bond = MakeTestBond(kTestId, kTestFidlAddrPublic);
1187   bond.clear_address();
1188   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1189 
1190   // Transport data missing.
1191   bond = MakeTestBond(kTestId, kTestFidlAddrPublic);
1192   bond.clear_le_bond();
1193   bond.clear_bredr_bond();
1194   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1195 
1196   // Transport data missing keys.
1197   bond = MakeTestBond(kTestId, kTestFidlAddrPublic);
1198   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1199 }
1200 
TEST_F(HostServerTest,RestoreBondsInvalidAddress)1201 TEST_F(HostServerTest, RestoreBondsInvalidAddress) {
1202   fidl::InterfaceHandle<fhost::BondingDelegate> delegate_handle;
1203   host_client()->SetBondingDelegate(delegate_handle.NewRequest());
1204   fhost::BondingDelegatePtr delegate = delegate_handle.Bind();
1205 
1206   // LE Random address on dual-mode or BR/EDR-only bond should not be supported.
1207   fsys::BondingData bond = MakeTestBond(kTestId, kTestFidlAddrRandom);
1208   bond.set_bredr_bond(fsys::BredrBondData());
1209   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1210 
1211   // BR/EDR only
1212   bond.clear_le_bond();
1213   TestRestoreBonds(delegate, MakeClonedVector(bond), MakeClonedVector(bond));
1214 
1215   // Resolvable Private address should not be supported
1216   fsys::BondingData resolvable_bond =
1217       MakeTestBond(kTestId, kTestFidlAddrResolvable);
1218   TestRestoreBonds(delegate,
1219                    MakeClonedVector(resolvable_bond),
1220                    MakeClonedVector(resolvable_bond));
1221 
1222   // Non-resolvable Private address should not be supported
1223   fsys::BondingData non_resolvable_bond =
1224       MakeTestBond(kTestId, kTestFidlAddrNonResolvable);
1225   TestRestoreBonds(delegate,
1226                    MakeClonedVector(non_resolvable_bond),
1227                    MakeClonedVector(non_resolvable_bond));
1228 }
1229 
TEST_F(HostServerTest,RestoreBondsLeOnlySuccess)1230 TEST_F(HostServerTest, RestoreBondsLeOnlySuccess) {
1231   fsys::BondingData bond = MakeTestBond(kTestId, kTestFidlAddrRandom);
1232   auto ltk = fsys::Ltk{.key =
1233                            fsys::PeerKey{
1234                                .security =
1235                                    fsys::SecurityProperties{
1236                                        .authenticated = true,
1237                                        .secure_connections = true,
1238                                        .encryption_key_size = 16,
1239                                    },
1240                                .data =
1241                                    fsys::Key{
1242                                        .value = {1,
1243                                                  2,
1244                                                  3,
1245                                                  4,
1246                                                  5,
1247                                                  6,
1248                                                  7,
1249                                                  8,
1250                                                  9,
1251                                                  10,
1252                                                  11,
1253                                                  12,
1254                                                  13,
1255                                                  14,
1256                                                  15,
1257                                                  16},
1258                                    },
1259                            },
1260                        .ediv = 0,
1261                        .rand = 0};
1262   fsys::LeBondData le;
1263   le.set_peer_ltk(ltk);
1264   le.set_local_ltk(ltk);
1265   bond.set_le_bond(std::move(le));
1266 
1267   fidl::InterfaceHandle<fhost::BondingDelegate> delegate_handle;
1268   host_client()->SetBondingDelegate(delegate_handle.NewRequest());
1269   fhost::BondingDelegatePtr delegate = delegate_handle.Bind();
1270 
1271   // This should succeed.
1272   TestRestoreBonds(
1273       delegate, MakeClonedVector(bond), {} /* no errors expected */);
1274 
1275   auto* peer = adapter()->peer_cache()->FindById(kTestId);
1276   ASSERT_TRUE(peer);
1277   EXPECT_TRUE(peer->le());
1278   EXPECT_FALSE(peer->bredr());
1279   EXPECT_EQ(bt::DeviceAddress::Type::kLERandom, peer->address().type());
1280 }
1281 
TEST_F(HostServerTest,RestoreBondsBredrOnlySuccess)1282 TEST_F(HostServerTest, RestoreBondsBredrOnlySuccess) {
1283   fidl::InterfaceHandle<fhost::BondingDelegate> delegate_handle;
1284   host_client()->SetBondingDelegate(delegate_handle.NewRequest());
1285   fhost::BondingDelegatePtr delegate = delegate_handle.Bind();
1286 
1287   fsys::BondingData bond = MakeTestBond(kTestId, kTestFidlAddrPublic);
1288   bond.clear_le_bond();
1289 
1290   fsys::BredrBondData bredr;
1291   bredr.set_link_key(fsys::PeerKey{
1292       .security =
1293           fsys::SecurityProperties{
1294               .authenticated = true,
1295               .secure_connections = true,
1296               .encryption_key_size = 16,
1297           },
1298       .data =
1299           fsys::Key{
1300               .value = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
1301           },
1302   });
1303   constexpr bt::UUID kServiceId = bt::sdp::profile::kAudioSink;
1304   bredr.set_services({fidl_helpers::UuidToFidl(kServiceId)});
1305   bond.set_bredr_bond(std::move(bredr));
1306 
1307   // This should succeed.
1308   TestRestoreBonds(
1309       delegate, MakeClonedVector(bond), {} /* no errors expected */);
1310 
1311   auto* peer = adapter()->peer_cache()->FindById(kTestId);
1312   ASSERT_TRUE(peer);
1313   ASSERT_TRUE(peer->bredr());
1314   EXPECT_THAT(peer->bredr()->services(), ::testing::ElementsAre(kServiceId));
1315   EXPECT_FALSE(peer->le());
1316   EXPECT_EQ(bt::DeviceAddress::Type::kBREDR, peer->address().type());
1317 }
1318 
TEST_F(HostServerTest,RestoreBondsDualModeSuccess)1319 TEST_F(HostServerTest, RestoreBondsDualModeSuccess) {
1320   fidl::InterfaceHandle<fhost::BondingDelegate> delegate_handle;
1321   host_client()->SetBondingDelegate(delegate_handle.NewRequest());
1322   fhost::BondingDelegatePtr delegate = delegate_handle.Bind();
1323 
1324   fsys::BondingData bond = MakeTestBond(kTestId, kTestFidlAddrPublic);
1325   auto key = fsys::PeerKey{
1326       .security =
1327           fsys::SecurityProperties{
1328               .authenticated = true,
1329               .secure_connections = true,
1330               .encryption_key_size = 16,
1331           },
1332       .data =
1333           fsys::Key{
1334               .value = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16},
1335           },
1336   };
1337   auto ltk = fsys::Ltk{.key = key, .ediv = 0, .rand = 0};
1338   fsys::LeBondData le;
1339   le.set_peer_ltk(ltk);
1340   le.set_local_ltk(ltk);
1341   bond.set_le_bond(std::move(le));
1342 
1343   fsys::BredrBondData bredr;
1344   bredr.set_link_key(key);
1345   constexpr bt::UUID kServiceId = bt::sdp::profile::kAudioSink;
1346   bredr.set_services({fidl_helpers::UuidToFidl(kServiceId)});
1347   bond.set_bredr_bond(std::move(bredr));
1348 
1349   // This should succeed.
1350   TestRestoreBonds(
1351       delegate, MakeClonedVector(bond), {} /* no errors expected */);
1352 
1353   auto* peer = adapter()->peer_cache()->FindById(kTestId);
1354   ASSERT_TRUE(peer);
1355   EXPECT_TRUE(peer->le());
1356   ASSERT_TRUE(peer->bredr());
1357   EXPECT_THAT(peer->bredr()->services(), ::testing::ElementsAre(kServiceId));
1358   EXPECT_EQ(bt::DeviceAddress::Type::kBREDR, peer->address().type());
1359 }
1360 
TEST_F(HostServerTest,SetHostData)1361 TEST_F(HostServerTest, SetHostData) {
1362   EXPECT_FALSE(adapter()->le()->irk());
1363 
1364   fsys::Key irk{{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}};
1365   fsys::HostData data;
1366   data.set_irk(irk);
1367 
1368   host_server()->SetLocalData(std::move(data));
1369   ASSERT_TRUE(adapter()->le()->irk());
1370   EXPECT_EQ(irk.value, adapter()->le()->irk().value());
1371 }
1372 
TEST_F(HostServerTest,OnNewBondingData)1373 TEST_F(HostServerTest, OnNewBondingData) {
1374   const std::string kTestName = "florp";
1375   const bt::UInt128 kTestKeyValue{
1376       1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
1377   const bt::sm::SecurityProperties kTestSecurity(
1378       bt::sm::SecurityLevel::kSecureAuthenticated,
1379       16,
1380       /*secure_connections=*/true);
1381   const bt::sm::LTK kTestLtk(kTestSecurity,
1382                              bt::hci_spec::LinkKey(kTestKeyValue, 0, 0));
1383   const fsys::PeerKey kTestKeyFidl{
1384       .security =
1385           fsys::SecurityProperties{
1386               .authenticated = true,
1387               .secure_connections = true,
1388               .encryption_key_size = 16,
1389           },
1390       .data = fsys::Key{.value = kTestKeyValue},
1391   };
1392   const fsys::Ltk kTestLtkFidl{.key = kTestKeyFidl, .ediv = 0, .rand = 0};
1393 
1394   auto* peer =
1395       adapter()->peer_cache()->NewPeer(kBredrTestAddr, /*connectable=*/true);
1396   peer->RegisterName(kTestName);
1397   adapter()->peer_cache()->StoreLowEnergyBond(
1398       peer->identifier(), bt::sm::PairingData{.peer_ltk = {kTestLtk}});
1399 
1400   // Set the bonding delegate after the bond has already been stored. The
1401   // delegate should still be notified.
1402   fidl::InterfaceHandle<fhost::BondingDelegate> delegate_handle;
1403   host_client_ptr()->SetBondingDelegate(delegate_handle.NewRequest());
1404   fhost::BondingDelegatePtr delegate = delegate_handle.Bind();
1405   std::optional<fsys::BondingData> data;
1406   delegate->WatchBonds(
1407       [&data](fhost::BondingDelegate_WatchBonds_Result result) {
1408         ASSERT_TRUE(result.is_response());
1409         data = std::move(result.response().updated());
1410       });
1411 
1412   RunLoopUntilIdle();
1413   ASSERT_TRUE(data);
1414   ASSERT_TRUE(data->has_identifier());
1415   ASSERT_TRUE(data->has_local_address());
1416   ASSERT_TRUE(data->has_address());
1417   ASSERT_TRUE(data->has_name());
1418 
1419   EXPECT_TRUE(fidl::Equals(
1420       (fbt::Address{fbt::AddressType::PUBLIC, std::array<uint8_t, 6>{0}}),
1421       data->local_address()));
1422   EXPECT_TRUE(fidl::Equals(kTestFidlAddrPublic, data->address()));
1423   EXPECT_EQ(kTestName, data->name());
1424 
1425   ASSERT_TRUE(data->has_le_bond());
1426   EXPECT_FALSE(data->has_bredr_bond());
1427 
1428   ASSERT_TRUE(data->le_bond().has_peer_ltk());
1429   EXPECT_FALSE(data->le_bond().has_local_ltk());
1430   EXPECT_FALSE(data->le_bond().has_irk());
1431   EXPECT_FALSE(data->le_bond().has_csrk());
1432   EXPECT_TRUE(fidl::Equals(kTestLtkFidl, data->le_bond().peer_ltk()));
1433 
1434   // Add BR/EDR data. This time, set WatchBonds callback before storing the
1435   // bond.
1436   data.reset();
1437   delegate->WatchBonds(
1438       [&data](fhost::BondingDelegate_WatchBonds_Result result) {
1439         ASSERT_TRUE(result.is_response());
1440         data = std::move(result.response().updated());
1441       });
1442   RunLoopUntilIdle();
1443 
1444   adapter()->peer_cache()->StoreBrEdrBond(kBredrTestAddr, kTestLtk);
1445   RunLoopUntilIdle();
1446 
1447   ASSERT_TRUE(data);
1448   ASSERT_TRUE(data->has_identifier());
1449   ASSERT_TRUE(data->has_local_address());
1450   ASSERT_TRUE(data->has_address());
1451   ASSERT_TRUE(data->has_name());
1452 
1453   EXPECT_TRUE(fidl::Equals(
1454       (fbt::Address{fbt::AddressType::PUBLIC, std::array<uint8_t, 6>{0}}),
1455       data->local_address()));
1456   EXPECT_TRUE(fidl::Equals(kTestFidlAddrPublic, data->address()));
1457   EXPECT_EQ(kTestName, data->name());
1458 
1459   ASSERT_TRUE(data->has_le_bond());
1460   ASSERT_TRUE(data->le_bond().has_peer_ltk());
1461   EXPECT_FALSE(data->le_bond().has_local_ltk());
1462   EXPECT_FALSE(data->le_bond().has_irk());
1463   EXPECT_FALSE(data->le_bond().has_csrk());
1464   EXPECT_TRUE(fidl::Equals(kTestLtkFidl, data->le_bond().peer_ltk()));
1465 
1466   ASSERT_TRUE(data->has_bredr_bond());
1467   ASSERT_TRUE(data->bredr_bond().has_link_key());
1468   EXPECT_TRUE(fidl::Equals(kTestKeyFidl, data->bredr_bond().link_key()));
1469 }
1470 
TEST_F(HostServerTest,EnableBackgroundScan)1471 TEST_F(HostServerTest, EnableBackgroundScan) {
1472   host_server()->EnableBackgroundScan(true);
1473   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1474 
1475   RunLoopUntilIdle();
1476   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1477   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1478             test_device()->le_scan_state().scan_type);
1479 
1480   host_server()->EnableBackgroundScan(false);
1481   RunLoopUntilIdle();
1482   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1483 }
1484 
TEST_F(HostServerTest,EnableBackgroundScanTwiceAtSameTime)1485 TEST_F(HostServerTest, EnableBackgroundScanTwiceAtSameTime) {
1486   host_server()->EnableBackgroundScan(true);
1487   host_server()->EnableBackgroundScan(true);
1488   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1489 
1490   RunLoopUntilIdle();
1491   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1492   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1493             test_device()->le_scan_state().scan_type);
1494 
1495   host_server()->EnableBackgroundScan(false);
1496   RunLoopUntilIdle();
1497   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1498 }
1499 
TEST_F(HostServerTest,EnableBackgroundScanTwiceSequentially)1500 TEST_F(HostServerTest, EnableBackgroundScanTwiceSequentially) {
1501   host_server()->EnableBackgroundScan(true);
1502   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1503 
1504   RunLoopUntilIdle();
1505   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1506   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1507             test_device()->le_scan_state().scan_type);
1508 
1509   host_server()->EnableBackgroundScan(true);
1510   RunLoopUntilIdle();
1511   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1512   EXPECT_EQ(pw::bluetooth::emboss::LEScanType::PASSIVE,
1513             test_device()->le_scan_state().scan_type);
1514 
1515   host_server()->EnableBackgroundScan(false);
1516   RunLoopUntilIdle();
1517   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1518 }
1519 
TEST_F(HostServerTest,CancelEnableBackgroundScan)1520 TEST_F(HostServerTest, CancelEnableBackgroundScan) {
1521   host_server()->EnableBackgroundScan(true);
1522   host_server()->EnableBackgroundScan(false);
1523 
1524   RunLoopUntilIdle();
1525   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1526 
1527   host_server()->EnableBackgroundScan(true);
1528   RunLoopUntilIdle();
1529   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1530 }
1531 
TEST_F(HostServerTest,DisableBackgroundScan)1532 TEST_F(HostServerTest, DisableBackgroundScan) {
1533   host_server()->EnableBackgroundScan(false);
1534   RunLoopUntilIdle();
1535   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1536 }
1537 
TEST_F(HostServerTest,EnableBackgroundScanFailsToStart)1538 TEST_F(HostServerTest, EnableBackgroundScanFailsToStart) {
1539   test_device()->SetDefaultCommandStatus(
1540       bt::hci_spec::kLESetScanEnable,
1541       pw::bluetooth::emboss::StatusCode::CONTROLLER_BUSY);
1542   host_server()->EnableBackgroundScan(true);
1543   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1544 
1545   RunLoopUntilIdle();
1546   EXPECT_FALSE(test_device()->le_scan_state().enabled);
1547 
1548   test_device()->ClearDefaultCommandStatus(bt::hci_spec::kLESetScanEnable);
1549   host_server()->EnableBackgroundScan(true);
1550   RunLoopUntilIdle();
1551   EXPECT_TRUE(test_device()->le_scan_state().enabled);
1552 }
1553 
1554 class HostServerTestFakeAdapter
1555     : public bt::fidl::testing::FakeAdapterTestFixture {
1556  public:
1557   HostServerTestFakeAdapter() = default;
1558   ~HostServerTestFakeAdapter() override = default;
1559 
SetUp()1560   void SetUp() override {
1561     FakeAdapterTestFixture::SetUp();
1562     gatt_ = std::make_unique<bt::gatt::testing::FakeLayer>(pw_dispatcher());
1563     fidl::InterfaceHandle<fuchsia::bluetooth::host::Host> host_handle;
1564     host_server_ =
1565         std::make_unique<HostServer>(host_handle.NewRequest().TakeChannel(),
1566                                      adapter()->AsWeakPtr(),
1567                                      gatt_->GetWeakPtr());
1568     host_.Bind(std::move(host_handle));
1569   }
1570 
TearDown()1571   void TearDown() override {
1572     RunLoopUntilIdle();
1573     host_ = nullptr;
1574     host_server_ = nullptr;
1575     gatt_ = nullptr;
1576     FakeAdapterTestFixture::TearDown();
1577   }
1578 
1579  protected:
host_server() const1580   HostServer* host_server() const { return host_server_.get(); }
1581 
host_client() const1582   fuchsia::bluetooth::host::Host* host_client() const { return host_.get(); }
1583 
host_client_ptr()1584   fuchsia::bluetooth::host::HostPtr& host_client_ptr() { return host_; }
1585 
1586  private:
1587   std::unique_ptr<HostServer> host_server_;
1588   fuchsia::bluetooth::host::HostPtr host_;
1589   std::unique_ptr<bt::gatt::GATT> gatt_;
1590 
1591   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(HostServerTestFakeAdapter);
1592 };
1593 
TEST_F(HostServerTestFakeAdapter,SetLocalNameNotifiesWatchState)1594 TEST_F(HostServerTestFakeAdapter, SetLocalNameNotifiesWatchState) {
1595   std::vector<fsys::HostInfo> info;
1596   // Consume initial state value.
1597   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
1598     ASSERT_TRUE(result.is_response());
1599     info.push_back(std::move(result.response().info));
1600   });
1601   RunLoopUntilIdle();
1602   EXPECT_EQ(info.size(), 1u);
1603   // Second watch state will hang until state is updated.
1604   host_client()->WatchState([&](fhost::Host_WatchState_Result result) {
1605     ASSERT_TRUE(result.is_response());
1606     info.push_back(std::move(result.response().info));
1607   });
1608   RunLoopUntilIdle();
1609   EXPECT_EQ(info.size(), 1u);
1610 
1611   int cb_count = 0;
1612   host_client()->SetLocalName("test", [&](auto result) {
1613     EXPECT_TRUE(result.is_response());
1614     cb_count++;
1615   });
1616   RunLoopUntilIdle();
1617   EXPECT_EQ(cb_count, 1);
1618   EXPECT_EQ(adapter()->local_name(), "test");
1619   ASSERT_EQ(info.size(), 2u);
1620   ASSERT_TRUE(info.back().has_local_name());
1621   EXPECT_EQ(info.back().local_name(), "test");
1622 }
1623 
TEST_F(HostServerTestFakeAdapter,WatchAddressesState)1624 TEST_F(HostServerTestFakeAdapter, WatchAddressesState) {
1625   std::optional<fsys::HostInfo> info;
1626 
1627   // Make an initial watch call so that subsequent calls remain pending.
1628   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
1629     ASSERT_TRUE(result.is_response());
1630     info = std::move(result.response().info);
1631   });
1632   ASSERT_TRUE(info.has_value());
1633   info.reset();
1634 
1635   // Next request to watch should hang and not produce a result.
1636   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
1637     ASSERT_TRUE(result.is_response());
1638     info = std::move(result.response().info);
1639   });
1640   EXPECT_FALSE(info.has_value());
1641 
1642   host_server()->EnablePrivacy(/*enabled=*/true);
1643   RunLoopUntilIdle();
1644   // The LE address change is an asynchronous operation. The state watcher
1645   // should only update when the address changes.
1646   EXPECT_FALSE(info.has_value());
1647   // Simulate a change in random LE address.
1648   auto resolvable_address = bt::DeviceAddress(
1649       bt::DeviceAddress::Type::kLERandom, {0x55, 0x44, 0x33, 0x22, 0x11, 0x43});
1650   adapter()->fake_le()->UpdateRandomAddress(resolvable_address);
1651   RunLoopUntilIdle();
1652   ASSERT_TRUE(info.has_value());
1653   ASSERT_TRUE(info->has_addresses());
1654   // Both the public and private addresses should be reported.
1655   EXPECT_EQ(info->addresses().size(), 2u);
1656   EXPECT_TRUE(ContainersEqual(adapter()->state().controller_address.bytes(),
1657                               info->addresses()[0].bytes));
1658   EXPECT_EQ(fbt::AddressType::RANDOM, info->addresses()[1].type);
1659   EXPECT_TRUE(ContainersEqual(adapter()->le()->CurrentAddress().value().bytes(),
1660                               info->addresses()[1].bytes));
1661 
1662   info.reset();
1663   host_server()->WatchState([&](fhost::Host_WatchState_Result result) {
1664     ASSERT_TRUE(result.is_response());
1665     info = std::move(result.response().info);
1666   });
1667   EXPECT_FALSE(info.has_value());
1668   // Disabling privacy is a synchronous operation - the random LE address should
1669   // no longer be used.
1670   host_server()->EnablePrivacy(/*enabled=*/false);
1671   RunLoopUntilIdle();
1672 
1673   ASSERT_TRUE(info.has_value());
1674   ASSERT_TRUE(info->has_addresses());
1675   // Only the public address should be reported.
1676   EXPECT_EQ(info->addresses().size(), 1u);
1677   EXPECT_TRUE(ContainersEqual(adapter()->state().controller_address.bytes(),
1678                               info->addresses()[0].bytes));
1679 }
1680 
1681 }  // namespace
1682 }  // namespace bthost
1683