xref: /aosp_15_r20/external/pigweed/pw_bluetooth_sapphire/host/hci/low_energy_advertiser_test.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
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