1 // Copyright 2023 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/internal/host/hci/low_energy_advertiser.h"
16
17 #include "pw_bluetooth_sapphire/internal/host/hci/android_extended_low_energy_advertiser.h"
18 #include "pw_bluetooth_sapphire/internal/host/hci/extended_low_energy_advertiser.h"
19 #include "pw_bluetooth_sapphire/internal/host/hci/legacy_low_energy_advertiser.h"
20 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
21 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h"
22 #include "pw_bluetooth_sapphire/internal/host/testing/fake_peer.h"
23 #include "pw_bluetooth_sapphire/internal/host/testing/test_helpers.h"
24 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
25
26 // LowEnergyAdvertiser has many potential subclasses (e.g.
27 // LegacyLowEnergyAdvertiser, ExtendedLowEnergyAdvertiser,
28 // AndroidExtendedLowEnergyAdvertiser, etc). The unique features of these
29 // subclass are tested individually in their own unittest files. However, there
30 // are some common features that all LowEnergyAdvertisers should follow. This
31 // class implements a type parameterized test to exercise those common features.
32 //
33 // If you add a new subclass of LowEnergyAdvertiser in the future, make sure to
34 // add its type to the list of types below (in the TYPED_TEST_SUITE) so that its
35 // common features are exercised as well.
36
37 namespace bt::hci {
38 namespace {
39
40 namespace pwemb = pw::bluetooth::emboss;
41
42 using bt::testing::FakeController;
43 using bt::testing::FakePeer;
44
45 using AdvertisingOptions = LowEnergyAdvertiser::AdvertisingOptions;
46 using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
47
48 constexpr hci_spec::ConnectionHandle kConnectionHandle = 0x0001;
49 constexpr AdvertisingIntervalRange kTestInterval(
50 hci_spec::kLEAdvertisingIntervalMin, hci_spec::kLEAdvertisingIntervalMax);
51
52 const DeviceAddress kPublicAddress(DeviceAddress::Type::kLEPublic, {1});
53 const DeviceAddress kRandomAddress(DeviceAddress::Type::kLERandom, {2});
54
55 // Various parts of the Bluetooth Core Spec require that advertising interval
56 // min and max are not the same value. We shouldn't allow it either. For
57 // example, Core Spec Volume 4, Part E, Section 7.8.5: "The
58 // Advertising_Interval_Min and Advertising_Interval_Max should not be the same
59 // value to enable the Controller to determine the best advertising interval
60 // given other activities."
TEST(AdvertisingIntervalRangeDeathTest,MaxMinNotSame)61 TEST(AdvertisingIntervalRangeDeathTest, MaxMinNotSame) {
62 EXPECT_DEATH(AdvertisingIntervalRange(hci_spec::kLEAdvertisingIntervalMin,
63 hci_spec::kLEAdvertisingIntervalMin),
64 ".*");
65 }
66
TEST(AdvertisingIntervalRangeDeathTest,MinLessThanMax)67 TEST(AdvertisingIntervalRangeDeathTest, MinLessThanMax) {
68 EXPECT_DEATH(AdvertisingIntervalRange(hci_spec::kLEAdvertisingIntervalMax,
69 hci_spec::kLEAdvertisingIntervalMin),
70 ".*");
71 }
72
73 template <typename T>
74 class LowEnergyAdvertiserTest : public TestingBase {
75 public:
76 LowEnergyAdvertiserTest() = default;
77 ~LowEnergyAdvertiserTest() override = default;
78
79 protected:
SetUp()80 void SetUp() override {
81 TestingBase::SetUp();
82
83 // ACL data channel needs to be present for production hci::Connection
84 // objects.
85 TestingBase::InitializeACLDataChannel(
86 hci::DataBufferInfo(),
87 hci::DataBufferInfo(hci_spec::kMaxACLPayloadSize, 10));
88
89 FakeController::Settings settings;
90 settings.ApplyLegacyLEConfig();
91 settings.bd_addr = kPublicAddress;
92 test_device()->set_settings(settings);
93
94 advertiser_ = std::unique_ptr<T>(CreateAdvertiserInternal());
95
96 test_device()->set_num_supported_advertising_sets(0xEF);
97 }
98
TearDown()99 void TearDown() override {
100 advertiser_ = nullptr;
101 TestingBase::TearDown();
102 }
103
104 template <bool same = std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>>
105 std::enable_if_t<same, AndroidExtendedLowEnergyAdvertiser>*
CreateAdvertiserInternal()106 CreateAdvertiserInternal() {
107 return new AndroidExtendedLowEnergyAdvertiser(transport()->GetWeakPtr(), 1);
108 }
109
110 template <bool same = std::is_same_v<T, ExtendedLowEnergyAdvertiser>>
111 std::enable_if_t<same, ExtendedLowEnergyAdvertiser>*
CreateAdvertiserInternal()112 CreateAdvertiserInternal() {
113 return new ExtendedLowEnergyAdvertiser(
114 transport()->GetWeakPtr(),
115 hci_spec::kMaxLEExtendedAdvertisingDataLength);
116 }
117
118 template <bool same = std::is_same_v<T, LegacyLowEnergyAdvertiser>>
119 std::enable_if_t<same, LegacyLowEnergyAdvertiser>*
CreateAdvertiserInternal()120 CreateAdvertiserInternal() {
121 return new LegacyLowEnergyAdvertiser(transport()->GetWeakPtr());
122 }
123
advertiser() const124 LowEnergyAdvertiser* advertiser() const { return advertiser_.get(); }
125
DestroyAdvertiser()126 void DestroyAdvertiser() { advertiser_.reset(); }
127
MakeExpectSuccessCallback()128 ResultFunction<> MakeExpectSuccessCallback() {
129 return [this](Result<> status) {
130 last_status_ = status;
131 EXPECT_EQ(fit::ok(), status);
132 };
133 }
134
MakeExpectErrorCallback()135 ResultFunction<> MakeExpectErrorCallback() {
136 return [this](Result<> status) {
137 last_status_ = status;
138 EXPECT_TRUE(status.is_error());
139 };
140 }
141
GetLastStatus()142 std::optional<Result<>> GetLastStatus() {
143 if (!last_status_) {
144 return std::nullopt;
145 }
146
147 Result<> status = last_status_.value();
148 last_status_.reset();
149 return status;
150 }
151
152 // Makes some fake advertising data.
153 // |include_flags| signals whether to include flag encoding size in the data
154 // calculation.
GetExampleData(bool include_flags=true)155 AdvertisingData GetExampleData(bool include_flags = true) {
156 AdvertisingData result;
157
158 auto name = "fuchsia";
159 EXPECT_TRUE(result.SetLocalName(name));
160
161 uint16_t appearance = 0x1234;
162 result.SetAppearance(appearance);
163
164 EXPECT_LE(result.CalculateBlockSize(include_flags),
165 hci_spec::kMaxLEAdvertisingDataLength);
166 return result;
167 }
168
169 // Makes fake advertising data that is too large.
170 // |include_flags| signals whether to include flag encoding size in the data
171 // calculation.
GetTooLargeExampleData(bool include_flags,std::size_t size=hci_spec::kMaxLEAdvertisingDataLength+1)172 AdvertisingData GetTooLargeExampleData(
173 bool include_flags,
174 std::size_t size = hci_spec::kMaxLEAdvertisingDataLength + 1) {
175 AdvertisingData result;
176
177 if (include_flags) {
178 size -= kTLVFlagsSize;
179 }
180
181 std::string data(size + 1, 'a');
182 EXPECT_TRUE(result.SetLocalName(data));
183
184 // The maximum advertisement packet is:
185 // |hci_spec::kMaxLEAdvertisingDataLength| = 31, and |result| = 32 bytes.
186 // |result| should be too large to advertise.
187 EXPECT_GT(result.CalculateBlockSize(include_flags),
188 hci_spec::kMaxLEAdvertisingDataLength);
189 return result;
190 }
191
CurrentAdvertisingHandle() const192 std::optional<hci_spec::AdvertisingHandle> CurrentAdvertisingHandle() const {
193 if (std::is_same_v<T, ExtendedLowEnergyAdvertiser>) {
194 auto extended = static_cast<ExtendedLowEnergyAdvertiser*>(advertiser());
195 return extended->LastUsedHandleForTesting();
196 }
197
198 if (std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>) {
199 auto extended =
200 static_cast<AndroidExtendedLowEnergyAdvertiser*>(advertiser());
201 return extended->LastUsedHandleForTesting();
202 }
203
204 return 0; // non-extended advertising doesn't use handles, we can return
205 // any value
206 }
207
GetControllerAdvertisingState() const208 const FakeController::LEAdvertisingState& GetControllerAdvertisingState()
209 const {
210 if (std::is_same_v<T, LegacyLowEnergyAdvertiser>) {
211 return test_device()->legacy_advertising_state();
212 }
213
214 if (std::is_same_v<T, ExtendedLowEnergyAdvertiser> ||
215 std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>) {
216 std::optional<hci_spec::AdvertisingHandle> handle =
217 CurrentAdvertisingHandle();
218 if (!handle) {
219 static FakeController::LEAdvertisingState empty;
220 return empty;
221 }
222
223 return test_device()->extended_advertising_state(handle.value());
224 }
225
226 EXPECT_TRUE(false) << "advertiser is of unknown type";
227
228 // return something in order to compile, tests will fail if they get here
229 static FakeController::LEAdvertisingState state;
230 return state;
231 }
232
SendMultipleAdvertisingPostConnectionEvents(hci_spec::ConnectionHandle conn_handle,hci_spec::AdvertisingHandle adv_handle)233 void SendMultipleAdvertisingPostConnectionEvents(
234 hci_spec::ConnectionHandle conn_handle,
235 hci_spec::AdvertisingHandle adv_handle) {
236 if (std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>) {
237 test_device()->SendAndroidLEMultipleAdvertisingStateChangeSubevent(
238 conn_handle, adv_handle);
239 return;
240 }
241
242 if (std::is_same_v<T, ExtendedLowEnergyAdvertiser>) {
243 test_device()->SendLEAdvertisingSetTerminatedEvent(conn_handle,
244 adv_handle);
245 return;
246 }
247 }
248
SetRandomAddress(DeviceAddress random_address)249 void SetRandomAddress(DeviceAddress random_address) {
250 if (std::is_same_v<T, LegacyLowEnergyAdvertiser>) {
251 auto emboss_packet = CommandPacket::New<
252 pw::bluetooth::emboss::LESetRandomAddressCommandWriter>(
253 hci_spec::kLESetRandomAddress);
254 emboss_packet.view_t().random_address().CopyFrom(
255 random_address.value().view());
256
257 test_device()->SendCommand(emboss_packet.data().subspan());
258 RunUntilIdle();
259 }
260
261 // TODO(fxbug.dev/42161900): Support setting a random address
262 // for extended advertisers when proper checks are introduced in
263 // `FakeController::OnLESetExtendedAdvertisingEnable()`.
264 }
265
SupportsExtendedPdus() const266 bool SupportsExtendedPdus() const {
267 return std::is_same_v<T, ExtendedLowEnergyAdvertiser>;
268 }
269
270 private:
271 std::unique_ptr<LowEnergyAdvertiser> advertiser_;
272 std::optional<Result<>> last_status_;
273
274 BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyAdvertiserTest);
275 };
276
277 using Implementations = ::testing::Types<LegacyLowEnergyAdvertiser,
278 ExtendedLowEnergyAdvertiser,
279 AndroidExtendedLowEnergyAdvertiser>;
280 TYPED_TEST_SUITE(LowEnergyAdvertiserTest, Implementations);
281
TYPED_TEST(LowEnergyAdvertiserTest,GetLegacyAdvertisingEventPropertiesAdvInd)282 TYPED_TEST(LowEnergyAdvertiserTest, GetLegacyAdvertisingEventPropertiesAdvInd) {
283 AdvertisingOptions options(kTestInterval,
284 kDefaultNoAdvFlags,
285 /*extended_pdu=*/false,
286 /*anonymous=*/false,
287 /*include_tx_power_level=*/false);
288 LowEnergyAdvertiser::AdvertisingEventProperties properties =
289 LowEnergyAdvertiser::GetAdvertisingEventProperties(
290 this->GetExampleData(), this->GetExampleData(), options, [](auto) {});
291 EXPECT_TRUE(properties.connectable);
292 EXPECT_TRUE(properties.scannable);
293 EXPECT_FALSE(properties.directed);
294 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
295 EXPECT_TRUE(properties.use_legacy_pdus);
296 EXPECT_FALSE(properties.anonymous_advertising);
297 EXPECT_FALSE(properties.include_tx_power);
298 }
299
TYPED_TEST(LowEnergyAdvertiserTest,GetLegacyAdvertisingEventPropertiesAdvScanInd)300 TYPED_TEST(LowEnergyAdvertiserTest,
301 GetLegacyAdvertisingEventPropertiesAdvScanInd) {
302 AdvertisingOptions options(kTestInterval,
303 kDefaultNoAdvFlags,
304 /*extended_pdu=*/false,
305 /*anonymous=*/false,
306 /*include_tx_power_level=*/false);
307 LowEnergyAdvertiser::AdvertisingEventProperties properties =
308 LowEnergyAdvertiser::GetAdvertisingEventProperties(
309 this->GetExampleData(),
310 this->GetExampleData(),
311 options,
312 /*connect_callback=*/nullptr);
313 EXPECT_FALSE(properties.connectable);
314 EXPECT_TRUE(properties.scannable);
315 EXPECT_FALSE(properties.directed);
316 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
317 EXPECT_TRUE(properties.use_legacy_pdus);
318 EXPECT_FALSE(properties.anonymous_advertising);
319 EXPECT_FALSE(properties.include_tx_power);
320 }
321
TYPED_TEST(LowEnergyAdvertiserTest,GetLegacyAdvertisingEventPropertiesAdvNonConnInd)322 TYPED_TEST(LowEnergyAdvertiserTest,
323 GetLegacyAdvertisingEventPropertiesAdvNonConnInd) {
324 AdvertisingData empty;
325 AdvertisingOptions options(kTestInterval,
326 kDefaultNoAdvFlags,
327 /*extended_pdu=*/false,
328 /*anonymous=*/false,
329 /*include_tx_power_level=*/false);
330 LowEnergyAdvertiser::AdvertisingEventProperties properties =
331 LowEnergyAdvertiser::GetAdvertisingEventProperties(
332 this->GetExampleData(),
333 empty,
334 options,
335 /*connect_callback=*/nullptr);
336 EXPECT_FALSE(properties.connectable);
337 EXPECT_FALSE(properties.scannable);
338 EXPECT_FALSE(properties.directed);
339 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
340 EXPECT_TRUE(properties.use_legacy_pdus);
341 EXPECT_FALSE(properties.anonymous_advertising);
342 EXPECT_FALSE(properties.include_tx_power);
343 }
344
345 // Ensure we can't set include anonymous for legacy pdus
TYPED_TEST(LowEnergyAdvertiserTest,GetLegacyAdvertisingEventPropertiesNoAnonymous)346 TYPED_TEST(LowEnergyAdvertiserTest,
347 GetLegacyAdvertisingEventPropertiesNoAnonymous) {
348 AdvertisingData empty;
349 AdvertisingOptions options(kTestInterval,
350 kDefaultNoAdvFlags,
351 /*extended_pdu=*/false,
352 /*anonymous=*/true,
353 /*include_tx_power_level=*/false);
354 LowEnergyAdvertiser::AdvertisingEventProperties properties =
355 LowEnergyAdvertiser::GetAdvertisingEventProperties(
356 empty,
357 empty,
358 options,
359 /*connect_callback=*/nullptr);
360 EXPECT_FALSE(properties.connectable);
361 EXPECT_FALSE(properties.scannable);
362 EXPECT_FALSE(properties.directed);
363 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
364 EXPECT_TRUE(properties.use_legacy_pdus);
365 EXPECT_FALSE(properties.anonymous_advertising);
366 EXPECT_FALSE(properties.include_tx_power);
367 }
368
369 // Ensure we can't set include tx power level for legacy pdus
TYPED_TEST(LowEnergyAdvertiserTest,GetLegacyAdvertisingEventPropertiesNoIncludeTxPower)370 TYPED_TEST(LowEnergyAdvertiserTest,
371 GetLegacyAdvertisingEventPropertiesNoIncludeTxPower) {
372 AdvertisingData empty;
373 AdvertisingOptions options(kTestInterval,
374 kDefaultNoAdvFlags,
375 /*extended_pdu=*/false,
376 /*anonymous=*/false,
377 /*include_tx_power_level=*/true);
378 LowEnergyAdvertiser::AdvertisingEventProperties properties =
379 LowEnergyAdvertiser::GetAdvertisingEventProperties(
380 empty,
381 empty,
382 options,
383 /*connect_callback=*/nullptr);
384 EXPECT_FALSE(properties.connectable);
385 EXPECT_FALSE(properties.scannable);
386 EXPECT_FALSE(properties.directed);
387 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
388 EXPECT_TRUE(properties.use_legacy_pdus);
389 EXPECT_FALSE(properties.anonymous_advertising);
390 EXPECT_FALSE(properties.include_tx_power);
391 }
392
TYPED_TEST(LowEnergyAdvertiserTest,GetExtendedAdvertisingEventPropertiesConnectable)393 TYPED_TEST(LowEnergyAdvertiserTest,
394 GetExtendedAdvertisingEventPropertiesConnectable) {
395 AdvertisingData empty;
396 AdvertisingOptions options(kTestInterval,
397 kDefaultNoAdvFlags,
398 /*extended_pdu=*/true,
399 /*anonymous=*/false,
400 /*include_tx_power_level=*/false);
401 LowEnergyAdvertiser::AdvertisingEventProperties properties =
402 LowEnergyAdvertiser::GetAdvertisingEventProperties(
403 empty, empty, options, [](auto) {});
404 EXPECT_TRUE(properties.connectable);
405 EXPECT_FALSE(properties.scannable);
406 EXPECT_FALSE(properties.directed);
407 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
408 EXPECT_FALSE(properties.use_legacy_pdus);
409 EXPECT_FALSE(properties.anonymous_advertising);
410 EXPECT_FALSE(properties.include_tx_power);
411 }
412
TYPED_TEST(LowEnergyAdvertiserTest,GetExtendedAdvertisingEventPropertiesScannable)413 TYPED_TEST(LowEnergyAdvertiserTest,
414 GetExtendedAdvertisingEventPropertiesScannable) {
415 AdvertisingData empty;
416 AdvertisingOptions options(kTestInterval,
417 kDefaultNoAdvFlags,
418 /*extended_pdu=*/true,
419 /*anonymous=*/false,
420 /*include_tx_power_level=*/false);
421 LowEnergyAdvertiser::AdvertisingEventProperties properties =
422 LowEnergyAdvertiser::GetAdvertisingEventProperties(
423 empty,
424 this->GetExampleData(),
425 options,
426 /*connect_callback=*/nullptr);
427 EXPECT_FALSE(properties.connectable);
428 EXPECT_TRUE(properties.scannable);
429 EXPECT_FALSE(properties.directed);
430 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
431 EXPECT_FALSE(properties.use_legacy_pdus);
432 EXPECT_FALSE(properties.anonymous_advertising);
433 EXPECT_FALSE(properties.include_tx_power);
434 }
435
TYPED_TEST(LowEnergyAdvertiserTest,GetExtendedAdvertisingEventPropertiesAnonymous)436 TYPED_TEST(LowEnergyAdvertiserTest,
437 GetExtendedAdvertisingEventPropertiesAnonymous) {
438 AdvertisingData empty;
439 AdvertisingOptions options(kTestInterval,
440 kDefaultNoAdvFlags,
441 /*extended_pdu=*/true,
442 /*anonymous=*/true,
443 /*include_tx_power_level=*/false);
444 LowEnergyAdvertiser::AdvertisingEventProperties properties =
445 LowEnergyAdvertiser::GetAdvertisingEventProperties(
446 empty,
447 empty,
448 options,
449 /*connect_callback=*/nullptr);
450 EXPECT_FALSE(properties.connectable);
451 EXPECT_FALSE(properties.scannable);
452 EXPECT_FALSE(properties.directed);
453 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
454 EXPECT_FALSE(properties.use_legacy_pdus);
455 EXPECT_TRUE(properties.anonymous_advertising);
456 EXPECT_FALSE(properties.include_tx_power);
457 }
458
TYPED_TEST(LowEnergyAdvertiserTest,GetExtendedAdvertisingEventPropertiesIncludeTxPower)459 TYPED_TEST(LowEnergyAdvertiserTest,
460 GetExtendedAdvertisingEventPropertiesIncludeTxPower) {
461 AdvertisingData empty;
462 AdvertisingOptions options(kTestInterval,
463 kDefaultNoAdvFlags,
464 /*extended_pdu=*/true,
465 /*anonymous=*/false,
466 /*include_tx_power_level=*/true);
467 LowEnergyAdvertiser::AdvertisingEventProperties properties =
468 LowEnergyAdvertiser::GetAdvertisingEventProperties(
469 empty,
470 empty,
471 options,
472 /*connect_callback=*/nullptr);
473 EXPECT_FALSE(properties.connectable);
474 EXPECT_FALSE(properties.scannable);
475 EXPECT_FALSE(properties.directed);
476 EXPECT_FALSE(properties.high_duty_cycle_directed_connectable);
477 EXPECT_FALSE(properties.use_legacy_pdus);
478 EXPECT_FALSE(properties.anonymous_advertising);
479 EXPECT_TRUE(properties.include_tx_power);
480 }
481
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingEventPropertiesToLEAdvertisingType)482 TYPED_TEST(LowEnergyAdvertiserTest,
483 AdvertisingEventPropertiesToLEAdvertisingType) {
484 {
485 LowEnergyAdvertiser::AdvertisingEventProperties properties;
486 properties.scannable = true;
487 properties.connectable = true;
488 pwemb::LEAdvertisingType adv_type =
489 LowEnergyAdvertiser::AdvertisingEventPropertiesToLEAdvertisingType(
490 properties);
491 EXPECT_EQ(adv_type,
492 pwemb::LEAdvertisingType::CONNECTABLE_AND_SCANNABLE_UNDIRECTED);
493 }
494
495 {
496 LowEnergyAdvertiser::AdvertisingEventProperties properties;
497 properties.directed = true;
498 properties.connectable = true;
499 pwemb::LEAdvertisingType adv_type =
500 LowEnergyAdvertiser::AdvertisingEventPropertiesToLEAdvertisingType(
501 properties);
502 EXPECT_EQ(adv_type,
503 pwemb::LEAdvertisingType::CONNECTABLE_LOW_DUTY_CYCLE_DIRECTED);
504 }
505
506 {
507 LowEnergyAdvertiser::AdvertisingEventProperties properties;
508 properties.high_duty_cycle_directed_connectable = true;
509 properties.directed = true;
510 properties.connectable = true;
511 pwemb::LEAdvertisingType adv_type =
512 LowEnergyAdvertiser::AdvertisingEventPropertiesToLEAdvertisingType(
513 properties);
514 EXPECT_EQ(adv_type,
515 pwemb::LEAdvertisingType::CONNECTABLE_HIGH_DUTY_CYCLE_DIRECTED);
516 }
517
518 {
519 LowEnergyAdvertiser::AdvertisingEventProperties properties;
520 properties.scannable = true;
521 pwemb::LEAdvertisingType adv_type =
522 LowEnergyAdvertiser::AdvertisingEventPropertiesToLEAdvertisingType(
523 properties);
524 EXPECT_EQ(adv_type, pwemb::LEAdvertisingType::SCANNABLE_UNDIRECTED);
525 }
526
527 {
528 LowEnergyAdvertiser::AdvertisingEventProperties properties;
529 pwemb::LEAdvertisingType adv_type =
530 LowEnergyAdvertiser::AdvertisingEventPropertiesToLEAdvertisingType(
531 properties);
532 EXPECT_EQ(adv_type, pwemb::LEAdvertisingType::NOT_CONNECTABLE_UNDIRECTED);
533 }
534 }
535
536 // - Stops the advertisement when an incoming connection comes in
537 // - Possible to restart advertising
538 // - Advertising state cleaned up between calls
TYPED_TEST(LowEnergyAdvertiserTest,ConnectionTest)539 TYPED_TEST(LowEnergyAdvertiserTest, ConnectionTest) {
540 AdvertisingData adv_data = this->GetExampleData();
541 AdvertisingData scan_data = this->GetExampleData();
542 AdvertisingOptions options(kTestInterval,
543 kDefaultNoAdvFlags,
544 /*extended_pdu=*/false,
545 /*anonymous=*/false,
546 /*include_tx_power_level=*/false);
547
548 std::unique_ptr<LowEnergyConnection> link;
549 auto conn_cb = [&link](auto cb_link) { link = std::move(cb_link); };
550
551 // Start advertising kPublicAddress
552 this->advertiser()->StartAdvertising(kPublicAddress,
553 adv_data,
554 scan_data,
555 options,
556 conn_cb,
557 this->MakeExpectSuccessCallback());
558 this->RunUntilIdle();
559 EXPECT_TRUE(this->GetLastStatus());
560 EXPECT_TRUE(this->advertiser()->IsAdvertising());
561 EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress,
562 /*extended_pdu=*/false));
563
564 // Accept a connection and ensure that connection state is set up correctly
565 link.reset();
566 this->advertiser()->OnIncomingConnection(kConnectionHandle,
567 pwemb::ConnectionRole::PERIPHERAL,
568 kRandomAddress,
569 hci_spec::LEConnectionParameters());
570 std::optional<hci_spec::AdvertisingHandle> handle =
571 this->CurrentAdvertisingHandle();
572 ASSERT_TRUE(handle);
573 this->SendMultipleAdvertisingPostConnectionEvents(kConnectionHandle,
574 handle.value());
575 this->RunUntilIdle();
576
577 ASSERT_TRUE(link);
578 EXPECT_EQ(kConnectionHandle, link->handle());
579 EXPECT_EQ(kPublicAddress, link->local_address());
580 EXPECT_EQ(kRandomAddress, link->peer_address());
581 EXPECT_FALSE(this->advertiser()->IsAdvertising());
582 EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress,
583 /*extended_pdu=*/false));
584
585 // Advertising state should get cleared on a disconnection
586 link->Disconnect(pwemb::StatusCode::REMOTE_USER_TERMINATED_CONNECTION);
587 this->test_device()->SendDisconnectionCompleteEvent(link->handle());
588 this->RunUntilIdle();
589 EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
590
591 // Restart advertising using a different local address
592 this->SetRandomAddress(kRandomAddress);
593 this->advertiser()->StartAdvertising(kRandomAddress,
594 adv_data,
595 scan_data,
596 options,
597 conn_cb,
598 this->MakeExpectSuccessCallback());
599 this->RunUntilIdle();
600 EXPECT_TRUE(this->GetLastStatus());
601 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
602
603 // Accept a connection from kPublicAddress. The internal advertising state
604 // should get assigned correctly with no remnants of the previous advertise.
605 link.reset();
606 this->advertiser()->OnIncomingConnection(kConnectionHandle,
607 pwemb::ConnectionRole::PERIPHERAL,
608 kPublicAddress,
609 hci_spec::LEConnectionParameters());
610 handle = this->CurrentAdvertisingHandle();
611 ASSERT_TRUE(handle);
612 this->SendMultipleAdvertisingPostConnectionEvents(kConnectionHandle,
613 handle.value());
614 this->RunUntilIdle();
615
616 ASSERT_TRUE(link);
617 EXPECT_EQ(kRandomAddress, link->local_address());
618 EXPECT_EQ(kPublicAddress, link->peer_address());
619 }
620
621 // Tests that advertising can be restarted right away in a connection
622 // callback.
TYPED_TEST(LowEnergyAdvertiserTest,RestartInConnectionCallback)623 TYPED_TEST(LowEnergyAdvertiserTest, RestartInConnectionCallback) {
624 AdvertisingData ad = this->GetExampleData();
625 AdvertisingData scan_data = this->GetExampleData();
626 AdvertisingOptions options(kTestInterval,
627 kDefaultNoAdvFlags,
628 /*extended_pdu=*/false,
629 /*anonymous=*/false,
630 /*include_tx_power_level=*/false);
631
632 std::unique_ptr<LowEnergyConnection> link;
633 auto conn_cb = [&, this](auto cb_link) {
634 link = std::move(cb_link);
635
636 this->advertiser()->StartAdvertising(
637 kPublicAddress,
638 ad,
639 scan_data,
640 options,
641 [](auto) { /*noop*/ },
642 this->MakeExpectSuccessCallback());
643 };
644
645 this->advertiser()->StartAdvertising(kPublicAddress,
646 ad,
647 scan_data,
648 options,
649 conn_cb,
650 this->MakeExpectSuccessCallback());
651 this->RunUntilIdle();
652 EXPECT_TRUE(this->GetLastStatus());
653 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
654
655 bool enabled = true;
656 std::vector<bool> adv_states;
657 this->test_device()->set_advertising_state_callback(
658 [this, &adv_states, &enabled] {
659 bool new_enabled = this->GetControllerAdvertisingState().enabled;
660 if (enabled != new_enabled) {
661 adv_states.push_back(new_enabled);
662 enabled = new_enabled;
663 }
664 });
665
666 this->advertiser()->OnIncomingConnection(kConnectionHandle,
667 pwemb::ConnectionRole::PERIPHERAL,
668 kRandomAddress,
669 hci_spec::LEConnectionParameters());
670 std::optional<hci_spec::AdvertisingHandle> handle =
671 this->CurrentAdvertisingHandle();
672 ASSERT_TRUE(handle);
673 this->SendMultipleAdvertisingPostConnectionEvents(kConnectionHandle,
674 handle.value());
675
676 // Advertising should get disabled and re-enabled.
677 this->RunUntilIdle();
678 ASSERT_EQ(2u, adv_states.size());
679 EXPECT_FALSE(adv_states[0]);
680 EXPECT_TRUE(adv_states[1]);
681
682 this->test_device()->set_advertising_state_callback(nullptr);
683 }
684
685 // An incoming connection when not advertising should get disconnected.
TYPED_TEST(LowEnergyAdvertiserTest,IncomingConnectionWhenNotAdvertising)686 TYPED_TEST(LowEnergyAdvertiserTest, IncomingConnectionWhenNotAdvertising) {
687 std::vector<std::pair<bool, hci_spec::ConnectionHandle>> connection_states;
688 this->test_device()->set_connection_state_callback(
689 [&](const auto& address, auto handle, bool connected, bool canceled) {
690 EXPECT_EQ(kRandomAddress, address);
691 EXPECT_FALSE(canceled);
692 connection_states.push_back(std::make_pair(connected, handle));
693 });
694
695 auto fake_peer = std::make_unique<FakePeer>(
696 kRandomAddress, TestFixture::dispatcher(), true, true);
697 this->test_device()->AddPeer(std::move(fake_peer));
698 this->test_device()->ConnectLowEnergy(kRandomAddress,
699 pwemb::ConnectionRole::PERIPHERAL);
700 this->RunUntilIdle();
701
702 ASSERT_EQ(1u, connection_states.size());
703 auto [connection_state, handle] = connection_states[0];
704 EXPECT_TRUE(connection_state);
705
706 // Notify the advertiser of the incoming connection. It should reject it and
707 // the controller should become disconnected.
708 this->advertiser()->OnIncomingConnection(handle,
709 pwemb::ConnectionRole::PERIPHERAL,
710 kRandomAddress,
711 hci_spec::LEConnectionParameters());
712 this->SendMultipleAdvertisingPostConnectionEvents(kConnectionHandle, 0);
713 this->RunUntilIdle();
714 ASSERT_EQ(2u, connection_states.size());
715 auto [connection_state_after_disconnect, disconnected_handle] =
716 connection_states[1];
717 EXPECT_EQ(handle, disconnected_handle);
718 EXPECT_FALSE(connection_state_after_disconnect);
719 }
720
721 // An incoming connection during non-connectable advertising should get
722 // disconnected.
TYPED_TEST(LowEnergyAdvertiserTest,IncomingConnectionWhenNonConnectableAdvertising)723 TYPED_TEST(LowEnergyAdvertiserTest,
724 IncomingConnectionWhenNonConnectableAdvertising) {
725 AdvertisingData ad = this->GetExampleData();
726 AdvertisingData scan_data = this->GetExampleData();
727 AdvertisingOptions options(kTestInterval,
728 kDefaultNoAdvFlags,
729 /*extended_pdu=*/false,
730 /*anonymous=*/false,
731 /*include_tx_power_level=*/false);
732 this->advertiser()->StartAdvertising(kPublicAddress,
733 ad,
734 scan_data,
735 options,
736 nullptr,
737 this->MakeExpectSuccessCallback());
738 this->RunUntilIdle();
739 ASSERT_TRUE(this->GetLastStatus());
740
741 std::vector<std::pair<bool, hci_spec::ConnectionHandle>> connection_states;
742 this->test_device()->set_connection_state_callback(
743 [&](const auto& address, auto handle, bool connected, bool canceled) {
744 EXPECT_EQ(kRandomAddress, address);
745 EXPECT_FALSE(canceled);
746 connection_states.push_back(std::make_pair(connected, handle));
747 });
748
749 auto fake_peer = std::make_unique<FakePeer>(
750 kRandomAddress, TestFixture::dispatcher(), true, true);
751 this->test_device()->AddPeer(std::move(fake_peer));
752 this->test_device()->ConnectLowEnergy(kRandomAddress,
753 pwemb::ConnectionRole::PERIPHERAL);
754 this->RunUntilIdle();
755
756 ASSERT_EQ(1u, connection_states.size());
757 auto [connection_state, handle] = connection_states[0];
758 EXPECT_TRUE(connection_state);
759
760 // Notify the advertiser of the incoming connection. It should reject it and
761 // the controller should become disconnected.
762 this->advertiser()->OnIncomingConnection(handle,
763 pwemb::ConnectionRole::PERIPHERAL,
764 kRandomAddress,
765 hci_spec::LEConnectionParameters());
766 this->SendMultipleAdvertisingPostConnectionEvents(kConnectionHandle, 0);
767 this->RunUntilIdle();
768 ASSERT_EQ(2u, connection_states.size());
769 auto [connection_state_after_disconnect, disconnected_handle] =
770 connection_states[1];
771 EXPECT_EQ(handle, disconnected_handle);
772 EXPECT_FALSE(connection_state_after_disconnect);
773 }
774
775 // Tests starting and stopping an advertisement.
TYPED_TEST(LowEnergyAdvertiserTest,StartAndStop)776 TYPED_TEST(LowEnergyAdvertiserTest, StartAndStop) {
777 AdvertisingData ad = this->GetExampleData();
778 AdvertisingData scan_data = this->GetExampleData();
779 AdvertisingOptions options(kTestInterval,
780 kDefaultNoAdvFlags,
781 /*extended_pdu=*/false,
782 /*anonymous=*/false,
783 /*include_tx_power_level=*/false);
784 this->SetRandomAddress(kRandomAddress);
785
786 this->advertiser()->StartAdvertising(kRandomAddress,
787 ad,
788 scan_data,
789 options,
790 nullptr,
791 this->MakeExpectSuccessCallback());
792 this->RunUntilIdle();
793 EXPECT_TRUE(this->GetLastStatus());
794 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
795
796 this->advertiser()->StopAdvertising(kRandomAddress, /*extended_pdu=*/false);
797 this->RunUntilIdle();
798 EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
799 }
800
801 // Tests that an advertisement is configured with the correct parameters.
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingParameters)802 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingParameters) {
803 AdvertisingData ad = this->GetExampleData();
804 AdvertisingData scan_data = this->GetExampleData();
805 auto flags = AdvFlag::kLEGeneralDiscoverableMode;
806 AdvertisingOptions options(kTestInterval,
807 flags,
808 /*extended_pdu=*/false,
809 /*anonymous=*/false,
810 /*include_tx_power_level=*/false);
811 this->SetRandomAddress(kRandomAddress);
812
813 this->advertiser()->StartAdvertising(kRandomAddress,
814 ad,
815 scan_data,
816 options,
817 nullptr,
818 this->MakeExpectSuccessCallback());
819 this->RunUntilIdle();
820 EXPECT_TRUE(this->GetLastStatus());
821
822 // The expected advertisement including the Flags.
823 DynamicByteBuffer expected_ad(ad.CalculateBlockSize(/*include_flags=*/true));
824 ad.WriteBlock(&expected_ad, flags);
825
826 DynamicByteBuffer expected_scan_data(
827 scan_data.CalculateBlockSize(/*include_flags=*/false));
828 scan_data.WriteBlock(&expected_scan_data, std::nullopt);
829
830 std::optional<FakeController::LEAdvertisingState> state =
831 this->GetControllerAdvertisingState();
832 EXPECT_TRUE(state);
833 EXPECT_TRUE(state->enabled);
834 EXPECT_EQ(kTestInterval.min(), state->interval_min);
835 EXPECT_EQ(kTestInterval.max(), state->interval_max);
836 EXPECT_EQ(expected_ad, state->advertised_view());
837 EXPECT_EQ(expected_scan_data, state->scan_rsp_view());
838 EXPECT_EQ(pwemb::LEOwnAddressType::RANDOM, state->own_address_type);
839
840 // Restart advertising with a public address and verify that the configured
841 // local address type is correct.
842 this->advertiser()->StopAdvertising(kRandomAddress, /*extended_pdu=*/false);
843 AdvertisingOptions new_options(kTestInterval,
844 kDefaultNoAdvFlags,
845 /*extended_pdu=*/false,
846 /*anonymous=*/false,
847 /*include_tx_power_level=*/false);
848 this->advertiser()->StartAdvertising(kPublicAddress,
849 ad,
850 scan_data,
851 new_options,
852 nullptr,
853 this->MakeExpectSuccessCallback());
854 this->RunUntilIdle();
855 EXPECT_TRUE(this->GetLastStatus());
856
857 state = this->GetControllerAdvertisingState();
858 EXPECT_TRUE(state);
859 EXPECT_TRUE(state->enabled);
860 EXPECT_EQ(pwemb::LEOwnAddressType::PUBLIC, state->own_address_type);
861 }
862
863 // Tests that a previous advertisement's advertising data isn't accidentally
864 // kept around. This test was added to address fxbug.dev/42081491.
TYPED_TEST(LowEnergyAdvertiserTest,PreviousAdvertisingParameters)865 TYPED_TEST(LowEnergyAdvertiserTest, PreviousAdvertisingParameters) {
866 AdvertisingData scan_data = this->GetExampleData();
867 auto flags = AdvFlag::kLEGeneralDiscoverableMode;
868 AdvertisingOptions options(kTestInterval,
869 flags,
870 /*extended_pdu=*/false,
871 /*anonymous=*/false,
872 /*include_tx_power_level=*/false);
873
874 // old advertising data: ideally we would fill this completely so that in
875 // the next start advertising call, we can confirm that none of the remnants
876 // are left. However, doing so results in the advertising data being too
877 // long. Instead, we rely on other unit tests within advertising data
878 // unittests to ensure all previous remnants are removed.
879 AdvertisingData ad;
880 ad.SetTxPower(4);
881 ad.SetAppearance(0x4567);
882 EXPECT_TRUE(ad.SetLocalName("fuchsia"));
883 this->SetRandomAddress(kRandomAddress);
884
885 this->advertiser()->StartAdvertising(kRandomAddress,
886 ad,
887 scan_data,
888 options,
889 nullptr,
890 this->MakeExpectSuccessCallback());
891 this->RunUntilIdle();
892 EXPECT_TRUE(this->GetLastStatus());
893
894 // new advertising data (with fewer fields filled in)
895 this->advertiser()->StopAdvertising(kRandomAddress, /*extended_pdu=*/false);
896 AdvertisingData new_ad = this->GetExampleData();
897 this->advertiser()->StartAdvertising(kRandomAddress,
898 new_ad,
899 scan_data,
900 options,
901 nullptr,
902 this->MakeExpectSuccessCallback());
903 this->RunUntilIdle();
904 EXPECT_TRUE(this->GetLastStatus());
905
906 DynamicByteBuffer expected_ad(
907 new_ad.CalculateBlockSize(/*include_flags=*/true));
908 new_ad.WriteBlock(&expected_ad, flags);
909
910 std::optional<FakeController::LEAdvertisingState> state =
911 this->GetControllerAdvertisingState();
912 EXPECT_EQ(expected_ad, state->advertised_view());
913 }
914
915 // Tests that advertising interval values are capped within the allowed range.
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingIntervalWithinAllowedRange)916 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingIntervalWithinAllowedRange) {
917 AdvertisingData ad = this->GetExampleData();
918 AdvertisingData scan_data = this->GetExampleData();
919
920 // Pass min and max values that are outside the allowed range. These should
921 // be capped.
922 constexpr AdvertisingIntervalRange interval(
923 hci_spec::kLEAdvertisingIntervalMin - 1,
924 hci_spec::kLEAdvertisingIntervalMax + 1);
925 AdvertisingOptions options(interval,
926 kDefaultNoAdvFlags,
927 /*extended_pdu=*/false,
928 /*anonymous=*/false,
929 /*include_tx_power_level=*/false);
930 this->SetRandomAddress(kRandomAddress);
931
932 this->advertiser()->StartAdvertising(kRandomAddress,
933 ad,
934 scan_data,
935 options,
936 nullptr,
937 this->MakeExpectSuccessCallback());
938 this->RunUntilIdle();
939 EXPECT_TRUE(this->GetLastStatus());
940
941 std::optional<FakeController::LEAdvertisingState> state =
942 this->GetControllerAdvertisingState();
943 EXPECT_TRUE(state);
944 EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMin, state->interval_min);
945 EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMax, state->interval_max);
946
947 // Reconfigure with values that are within the range. These should get
948 // passed down as is.
949 const AdvertisingIntervalRange new_interval(
950 hci_spec::kLEAdvertisingIntervalMin + 1,
951 hci_spec::kLEAdvertisingIntervalMax - 1);
952 AdvertisingOptions new_options(new_interval,
953 kDefaultNoAdvFlags,
954 /*extended_pdu=*/false,
955 /*anonymous=*/false,
956 /*include_tx_power_level=*/false);
957 this->advertiser()->StartAdvertising(kRandomAddress,
958 ad,
959 scan_data,
960 new_options,
961 nullptr,
962 this->MakeExpectSuccessCallback());
963 this->RunUntilIdle();
964 EXPECT_TRUE(this->GetLastStatus());
965
966 state = this->GetControllerAdvertisingState();
967 EXPECT_TRUE(state);
968 EXPECT_EQ(new_interval.min(), state->interval_min);
969 EXPECT_EQ(new_interval.max(), state->interval_max);
970 }
971
TYPED_TEST(LowEnergyAdvertiserTest,StartWhileStarting)972 TYPED_TEST(LowEnergyAdvertiserTest, StartWhileStarting) {
973 AdvertisingData ad = this->GetExampleData();
974 AdvertisingData scan_data = this->GetExampleData();
975 DeviceAddress addr = kRandomAddress;
976
977 const AdvertisingIntervalRange old_interval = kTestInterval;
978 AdvertisingOptions old_options(old_interval,
979 kDefaultNoAdvFlags,
980 /*extended_pdu=*/false,
981 /*anonymous=*/false,
982 /*include_tx_power_level=*/false);
983 const AdvertisingIntervalRange new_interval(kTestInterval.min() + 1,
984 kTestInterval.max() - 1);
985 AdvertisingOptions new_options(new_interval,
986 kDefaultNoAdvFlags,
987 /*extended_pdu=*/false,
988 /*anonymous=*/false,
989 /*include_tx_power_level=*/false);
990 this->SetRandomAddress(addr);
991
992 this->advertiser()->StartAdvertising(
993 addr, ad, scan_data, old_options, nullptr, [](auto) {});
994 EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
995
996 // This call should override the previous call and succeed with the new
997 // parameters.
998 this->advertiser()->StartAdvertising(addr,
999 ad,
1000 scan_data,
1001 new_options,
1002 nullptr,
1003 this->MakeExpectSuccessCallback());
1004 this->RunUntilIdle();
1005 EXPECT_TRUE(this->GetLastStatus());
1006 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1007 EXPECT_EQ(new_interval.max(),
1008 this->GetControllerAdvertisingState().interval_max);
1009 }
1010
TYPED_TEST(LowEnergyAdvertiserTest,StartWhileStopping)1011 TYPED_TEST(LowEnergyAdvertiserTest, StartWhileStopping) {
1012 AdvertisingData ad = this->GetExampleData();
1013 AdvertisingData scan_data = this->GetExampleData();
1014 DeviceAddress addr = kRandomAddress;
1015 AdvertisingOptions options(kTestInterval,
1016 kDefaultNoAdvFlags,
1017 /*extended_pdu=*/false,
1018 /*anonymous=*/false,
1019 /*include_tx_power_level=*/false);
1020 this->SetRandomAddress(addr);
1021
1022 // Get to a started state.
1023 this->advertiser()->StartAdvertising(
1024 addr, ad, scan_data, options, nullptr, this->MakeExpectSuccessCallback());
1025 this->RunUntilIdle();
1026 EXPECT_TRUE(this->GetLastStatus());
1027 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1028
1029 // Initiate a request to Stop and wait until it's partially in progress.
1030 bool enabled = true;
1031 bool was_disabled = false;
1032 auto adv_state_cb = [&] {
1033 enabled = this->GetControllerAdvertisingState().enabled;
1034 if (!was_disabled && !enabled) {
1035 was_disabled = true;
1036
1037 // Starting now should cancel the stop sequence and succeed.
1038 this->advertiser()->StartAdvertising(addr,
1039 ad,
1040 scan_data,
1041 options,
1042 nullptr,
1043 this->MakeExpectSuccessCallback());
1044 }
1045 };
1046 this->test_device()->set_advertising_state_callback(adv_state_cb);
1047
1048 this->advertiser()->StopAdvertising(addr, /*extended_pdu=*/false);
1049
1050 // Advertising should have been momentarily disabled.
1051 this->RunUntilIdle();
1052 EXPECT_TRUE(was_disabled);
1053 EXPECT_TRUE(enabled);
1054 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1055
1056 this->test_device()->set_advertising_state_callback(nullptr);
1057 }
1058
TYPED_TEST(LowEnergyAdvertiserTest,StopWhileStarting)1059 TYPED_TEST(LowEnergyAdvertiserTest, StopWhileStarting) {
1060 AdvertisingData ad = this->GetExampleData();
1061 AdvertisingData scan_data = this->GetExampleData();
1062 AdvertisingOptions options(kTestInterval,
1063 kDefaultNoAdvFlags,
1064 /*extended_pdu=*/false,
1065 /*anonymous=*/false,
1066 /*include_tx_power_level=*/false);
1067
1068 this->advertiser()->StartAdvertising(kPublicAddress,
1069 ad,
1070 scan_data,
1071 options,
1072 nullptr,
1073 this->MakeExpectErrorCallback());
1074 this->advertiser()->StopAdvertising();
1075
1076 this->RunUntilIdle();
1077 EXPECT_TRUE(this->GetLastStatus());
1078 EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
1079 }
1080
1081 // - StopAdvertisement noops when the advertisement address is wrong
1082 // - Sets the advertisement data to null when stopped to prevent data leakage
1083 // (re-enable advertising without changing data, intercept)
TYPED_TEST(LowEnergyAdvertiserTest,StopAdvertisingConditions)1084 TYPED_TEST(LowEnergyAdvertiserTest, StopAdvertisingConditions) {
1085 AdvertisingData ad = this->GetExampleData();
1086 AdvertisingData scan_data = this->GetExampleData();
1087 AdvertisingOptions options(kTestInterval,
1088 kDefaultNoAdvFlags,
1089 /*extended_pdu=*/false,
1090 /*anonymous=*/false,
1091 /*include_tx_power_level=*/false);
1092 this->SetRandomAddress(kRandomAddress);
1093
1094 this->advertiser()->StartAdvertising(kRandomAddress,
1095 ad,
1096 scan_data,
1097 options,
1098 nullptr,
1099 this->MakeExpectSuccessCallback());
1100
1101 this->RunUntilIdle();
1102
1103 EXPECT_TRUE(this->GetLastStatus());
1104
1105 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1106 DynamicByteBuffer expected_ad(ad.CalculateBlockSize(/*include_flags=*/true));
1107 ad.WriteBlock(&expected_ad, kDefaultNoAdvFlags);
1108 EXPECT_TRUE(ContainersEqual(
1109 this->GetControllerAdvertisingState().advertised_view(), expected_ad));
1110
1111 this->RunUntilIdle();
1112 this->advertiser()->StopAdvertising(kPublicAddress, /*extended_pdu=*/false);
1113 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1114 EXPECT_TRUE(ContainersEqual(
1115 this->GetControllerAdvertisingState().advertised_view(), expected_ad));
1116
1117 this->advertiser()->StopAdvertising(kRandomAddress, /*extended_pdu=*/false);
1118
1119 this->RunUntilIdle();
1120 EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
1121 EXPECT_EQ(0u, this->GetControllerAdvertisingState().advertised_view().size());
1122 EXPECT_EQ(0u, this->GetControllerAdvertisingState().scan_rsp_view().size());
1123 }
1124
1125 // - Updates data and params for the same address when advertising already
TYPED_TEST(LowEnergyAdvertiserTest,AdvertiseUpdate)1126 TYPED_TEST(LowEnergyAdvertiserTest, AdvertiseUpdate) {
1127 AdvertisingData ad = this->GetExampleData();
1128 AdvertisingData scan_data = this->GetExampleData();
1129 AdvertisingOptions options(kTestInterval,
1130 kDefaultNoAdvFlags,
1131 /*extended_pdu=*/false,
1132 /*anonymous=*/false,
1133 /*include_tx_power_level=*/false);
1134 this->SetRandomAddress(kRandomAddress);
1135
1136 this->advertiser()->StartAdvertising(kRandomAddress,
1137 ad,
1138 scan_data,
1139 options,
1140 nullptr,
1141 this->MakeExpectSuccessCallback());
1142 this->RunUntilIdle();
1143
1144 EXPECT_TRUE(this->GetLastStatus());
1145 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1146
1147 // The expected advertising data payload, with the flags.
1148 DynamicByteBuffer expected_ad(ad.CalculateBlockSize(/*include_flags=*/true));
1149 ad.WriteBlock(&expected_ad, kDefaultNoAdvFlags);
1150 EXPECT_TRUE(ContainersEqual(
1151 this->GetControllerAdvertisingState().advertised_view(), expected_ad));
1152
1153 EXPECT_EQ(kTestInterval.min(),
1154 this->GetControllerAdvertisingState().interval_min);
1155 EXPECT_EQ(kTestInterval.max(),
1156 this->GetControllerAdvertisingState().interval_max);
1157
1158 uint16_t new_appearance = 0x6789;
1159 ad.SetAppearance(new_appearance);
1160
1161 const AdvertisingIntervalRange new_interval(kTestInterval.min() + 1,
1162 kTestInterval.max() - 1);
1163 AdvertisingOptions new_options(new_interval,
1164 kDefaultNoAdvFlags,
1165 /*extended_pdu=*/false,
1166 /*anonymous=*/false,
1167 /*include_tx_power_level=*/false);
1168 this->advertiser()->StartAdvertising(kRandomAddress,
1169 ad,
1170 scan_data,
1171 new_options,
1172 nullptr,
1173 this->MakeExpectSuccessCallback());
1174 this->RunUntilIdle();
1175
1176 EXPECT_TRUE(this->GetLastStatus());
1177 EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
1178
1179 DynamicByteBuffer expected_new_ad(
1180 ad.CalculateBlockSize(/*include_flags=*/true));
1181 ad.WriteBlock(&expected_new_ad, kDefaultNoAdvFlags);
1182 EXPECT_TRUE(
1183 ContainersEqual(this->GetControllerAdvertisingState().advertised_view(),
1184 expected_new_ad));
1185
1186 EXPECT_EQ(new_interval.min(),
1187 this->GetControllerAdvertisingState().interval_min);
1188 EXPECT_EQ(new_interval.max(),
1189 this->GetControllerAdvertisingState().interval_max);
1190 }
1191
1192 // Ensures advertising set data is removed from controller memory after
1193 // advertising is stopped
TYPED_TEST(LowEnergyAdvertiserTest,StopAdvertisingSingleAdvertisement)1194 TYPED_TEST(LowEnergyAdvertiserTest, StopAdvertisingSingleAdvertisement) {
1195 AdvertisingData ad = this->GetExampleData();
1196 AdvertisingData scan_data = this->GetExampleData();
1197
1198 // start public address advertising
1199 AdvertisingOptions options(kTestInterval,
1200 kDefaultNoAdvFlags,
1201 /*extended_pdu=*/false,
1202 /*anonymous=*/false,
1203 /*include_tx_power_level=*/false);
1204 this->advertiser()->StartAdvertising(kPublicAddress,
1205 ad,
1206 scan_data,
1207 options,
1208 nullptr,
1209 this->MakeExpectSuccessCallback());
1210 this->RunUntilIdle();
1211 EXPECT_TRUE(this->GetLastStatus());
1212
1213 constexpr uint8_t blank[hci_spec::kMaxLEAdvertisingDataLength] = {0};
1214
1215 // check that advertiser and controller both report the same advertising
1216 // state
1217 EXPECT_TRUE(this->advertiser()->IsAdvertising());
1218 EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress,
1219 /*extended_pdu=*/false));
1220
1221 {
1222 const FakeController::LEAdvertisingState& state =
1223 this->GetControllerAdvertisingState();
1224 EXPECT_TRUE(state.enabled);
1225 EXPECT_NE(
1226 0,
1227 std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
1228 EXPECT_NE(0, state.data_length);
1229 EXPECT_NE(
1230 0,
1231 std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
1232 EXPECT_NE(0, state.scan_rsp_length);
1233 }
1234
1235 // stop advertising the random address
1236 this->advertiser()->StopAdvertising(kPublicAddress, /*extended_pdu=*/false);
1237 this->RunUntilIdle();
1238
1239 // check that advertiser and controller both report the same advertising
1240 // state
1241 EXPECT_FALSE(this->advertiser()->IsAdvertising());
1242 EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress,
1243 /*extended_pdu=*/false));
1244
1245 {
1246 const FakeController::LEAdvertisingState& state =
1247 this->GetControllerAdvertisingState();
1248 EXPECT_FALSE(state.enabled);
1249 EXPECT_EQ(
1250 0,
1251 std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
1252 EXPECT_EQ(0, state.data_length);
1253 EXPECT_EQ(
1254 0,
1255 std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
1256 EXPECT_EQ(0, state.scan_rsp_length);
1257 }
1258 }
1259
1260 // - Rejects anonymous advertisement (unsupported)
TYPED_TEST(LowEnergyAdvertiserTest,NoAnonymous)1261 TYPED_TEST(LowEnergyAdvertiserTest, NoAnonymous) {
1262 AdvertisingData ad = this->GetExampleData();
1263 AdvertisingData scan_data = this->GetExampleData();
1264 AdvertisingOptions options(kTestInterval,
1265 kDefaultNoAdvFlags,
1266 /*extended_pdu=*/false,
1267 /*anonymous=*/true,
1268 /*include_tx_power_level=*/false);
1269 this->SetRandomAddress(kRandomAddress);
1270
1271 this->advertiser()->StartAdvertising(kRandomAddress,
1272 ad,
1273 scan_data,
1274 options,
1275 nullptr,
1276 this->MakeExpectErrorCallback());
1277 EXPECT_TRUE(this->GetLastStatus());
1278 EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
1279 }
1280
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingDataTooLong)1281 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingDataTooLong) {
1282 AdvertisingData invalid_ad =
1283 this->GetTooLargeExampleData(/*include_flags=*/true);
1284 AdvertisingData valid_scan_rsp =
1285 this->GetExampleData(/*include_flags=*/false);
1286 AdvertisingOptions options(kTestInterval,
1287 kDefaultNoAdvFlags,
1288 /*extended_pdu=*/false,
1289 /*anonymous=*/false,
1290 /*include_tx_power_level=*/false);
1291 this->SetRandomAddress(kRandomAddress);
1292
1293 // Advertising data too large.
1294 this->advertiser()->StartAdvertising(kRandomAddress,
1295 invalid_ad,
1296 valid_scan_rsp,
1297 options,
1298 nullptr,
1299 this->MakeExpectErrorCallback());
1300 this->RunUntilIdle();
1301 auto status = this->GetLastStatus();
1302 ASSERT_TRUE(status);
1303 EXPECT_EQ(ToResult(HostError::kAdvertisingDataTooLong), *status);
1304 }
1305
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingDataTooLongWithTxPower)1306 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingDataTooLongWithTxPower) {
1307 AdvertisingData invalid_ad = this->GetTooLargeExampleData(
1308 /*include_flags=*/true,
1309 hci_spec::kMaxLEAdvertisingDataLength - kTLVTxPowerLevelSize + 1);
1310 AdvertisingData valid_scan_rsp =
1311 this->GetExampleData(/*include_flags=*/false);
1312 AdvertisingOptions options(kTestInterval,
1313 kDefaultNoAdvFlags,
1314 /*extended_pdu=*/false,
1315 /*anonymous=*/false,
1316 /*include_tx_power_level=*/true);
1317 this->SetRandomAddress(kRandomAddress);
1318
1319 // Advertising data too large.
1320 this->advertiser()->StartAdvertising(kRandomAddress,
1321 invalid_ad,
1322 valid_scan_rsp,
1323 options,
1324 nullptr,
1325 this->MakeExpectErrorCallback());
1326 this->RunUntilIdle();
1327 auto status = this->GetLastStatus();
1328 ASSERT_TRUE(status);
1329 EXPECT_EQ(ToResult(HostError::kAdvertisingDataTooLong), *status);
1330 }
1331
TYPED_TEST(LowEnergyAdvertiserTest,ScanResponseTooLong)1332 TYPED_TEST(LowEnergyAdvertiserTest, ScanResponseTooLong) {
1333 AdvertisingData valid_ad = this->GetExampleData();
1334 AdvertisingData invalid_scan_rsp =
1335 this->GetTooLargeExampleData(/*include_flags=*/false);
1336 AdvertisingOptions options(kTestInterval,
1337 kDefaultNoAdvFlags,
1338 /*extended_pdu=*/false,
1339 /*anonymous=*/false,
1340 /*include_tx_power_level=*/false);
1341 this->SetRandomAddress(kRandomAddress);
1342
1343 this->advertiser()->StartAdvertising(kRandomAddress,
1344 valid_ad,
1345 invalid_scan_rsp,
1346 options,
1347 nullptr,
1348 this->MakeExpectErrorCallback());
1349 this->RunUntilIdle();
1350 auto status = this->GetLastStatus();
1351 ASSERT_TRUE(status);
1352 EXPECT_EQ(ToResult(HostError::kScanResponseTooLong), *status);
1353 }
1354
TYPED_TEST(LowEnergyAdvertiserTest,ScanResponseTooLongWithTxPower)1355 TYPED_TEST(LowEnergyAdvertiserTest, ScanResponseTooLongWithTxPower) {
1356 AdvertisingData valid_ad = this->GetExampleData();
1357 AdvertisingData invalid_scan_rsp = this->GetTooLargeExampleData(
1358 /*include_flags=*/false,
1359 hci_spec::kMaxLEAdvertisingDataLength - kTLVTxPowerLevelSize + 1);
1360 AdvertisingOptions options(kTestInterval,
1361 kDefaultNoAdvFlags,
1362 /*extended_pdu=*/false,
1363 /*anonymous=*/false,
1364 /*include_tx_power_level=*/true);
1365 this->SetRandomAddress(kRandomAddress);
1366
1367 this->advertiser()->StartAdvertising(kRandomAddress,
1368 valid_ad,
1369 invalid_scan_rsp,
1370 options,
1371 nullptr,
1372 this->MakeExpectErrorCallback());
1373 this->RunUntilIdle();
1374 auto status = this->GetLastStatus();
1375 ASSERT_TRUE(status);
1376 EXPECT_EQ(ToResult(HostError::kScanResponseTooLong), *status);
1377 }
1378
TYPED_TEST(LowEnergyAdvertiserTest,DestroyingTransportBeforeAdvertiserDoesNotCrash)1379 TYPED_TEST(LowEnergyAdvertiserTest,
1380 DestroyingTransportBeforeAdvertiserDoesNotCrash) {
1381 this->DeleteTransport();
1382 this->DestroyAdvertiser();
1383 }
1384
1385 // Ensure we disallow requesting extended PDUs where we can't use them
TYPED_TEST(LowEnergyAdvertiserTest,ExtendedPdusReturnsErrorWhenNotSupported)1386 TYPED_TEST(LowEnergyAdvertiserTest, ExtendedPdusReturnsErrorWhenNotSupported) {
1387 if (this->SupportsExtendedPdus()) {
1388 return;
1389 }
1390
1391 AdvertisingData ad = this->GetExampleData();
1392 AdvertisingData scan_data = this->GetExampleData();
1393 AdvertisingOptions options(kTestInterval,
1394 kDefaultNoAdvFlags,
1395 /*extended_pdu=*/true,
1396 /*anonymous=*/false,
1397 /*include_tx_power_level=*/false);
1398 this->SetRandomAddress(kRandomAddress);
1399
1400 this->advertiser()->StartAdvertising(kRandomAddress,
1401 ad,
1402 scan_data,
1403 options,
1404 nullptr,
1405 this->MakeExpectErrorCallback());
1406 this->RunUntilIdle();
1407 auto status = this->GetLastStatus();
1408 ASSERT_TRUE(status);
1409 EXPECT_EQ(ToResult(HostError::kNotSupported), *status);
1410 }
1411
1412 } // namespace
1413 } // namespace bt::hci
1414