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