• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
25 // LowEnergyAdvertiser has many potential subclasses (e.g.
26 // LegacyLowEnergyAdvertiser, ExtendedLowEnergyAdvertiser,
27 // AndroidExtendedLowEnergyAdvertiser, etc). The unique features of these
28 // subclass are tested individually in their own unittest files. However, there
29 // are some common features that all LowEnergyAdvertisers should follow. This
30 // class implements a type parameterized test to exercise those common features.
31 //
32 // If you add a new subclass of LowEnergyAdvertiser in the future, make sure to
33 // add its type to the list of types below (in the TYPED_TEST_SUITE) so that its
34 // common features are exercised as well.
35 
36 namespace bt::hci {
37 namespace {
38 
39 using bt::testing::FakeController;
40 using bt::testing::FakePeer;
41 
42 using AdvertisingOptions = LowEnergyAdvertiser::AdvertisingOptions;
43 using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
44 
45 constexpr hci_spec::ConnectionHandle kConnectionHandle = 0x0001;
46 constexpr AdvertisingIntervalRange kTestInterval(
47     hci_spec::kLEAdvertisingIntervalMin, hci_spec::kLEAdvertisingIntervalMax);
48 
49 const DeviceAddress kPublicAddress(DeviceAddress::Type::kLEPublic, {1});
50 const DeviceAddress kRandomAddress(DeviceAddress::Type::kLERandom, {2});
51 
52 // Various parts of the Bluetooth Core Spec require that advertising interval
53 // min and max are not the same value. We shouldn't allow it either. For
54 // example, Core Spec Volume 4, Part E, Section 7.8.5: "The
55 // Advertising_Interval_Min and Advertising_Interval_Max should not be the same
56 // value to enable the Controller to determine the best advertising interval
57 // given other activities."
TEST(AdvertisingIntervalRangeDeathTest,MaxMinNotSame)58 TEST(AdvertisingIntervalRangeDeathTest, MaxMinNotSame) {
59   EXPECT_DEATH(AdvertisingIntervalRange(hci_spec::kLEAdvertisingIntervalMin,
60                                         hci_spec::kLEAdvertisingIntervalMin),
61                ".*");
62 }
63 
TEST(AdvertisingIntervalRangeDeathTest,MinLessThanMax)64 TEST(AdvertisingIntervalRangeDeathTest, MinLessThanMax) {
65   EXPECT_DEATH(AdvertisingIntervalRange(hci_spec::kLEAdvertisingIntervalMax,
66                                         hci_spec::kLEAdvertisingIntervalMin),
67                ".*");
68 }
69 
70 template <typename T>
71 class LowEnergyAdvertiserTest : public TestingBase {
72  public:
73   LowEnergyAdvertiserTest() = default;
74   ~LowEnergyAdvertiserTest() override = default;
75 
76  protected:
SetUp()77   void SetUp() override {
78     TestingBase::SetUp();
79 
80     // ACL data channel needs to be present for production hci::Connection
81     // objects.
82     TestingBase::InitializeACLDataChannel(
83         hci::DataBufferInfo(),
84         hci::DataBufferInfo(hci_spec::kMaxACLPayloadSize, 10));
85 
86     FakeController::Settings settings;
87     settings.ApplyLegacyLEConfig();
88     settings.bd_addr = kPublicAddress;
89     test_device()->set_settings(settings);
90 
91     advertiser_ = std::unique_ptr<T>(CreateAdvertiserInternal());
92 
93     test_device()->set_num_supported_advertising_sets(0xEF);
94   }
95 
TearDown()96   void TearDown() override {
97     advertiser_ = nullptr;
98     TestingBase::TearDown();
99   }
100 
101   template <bool same = std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>>
102   std::enable_if_t<same, AndroidExtendedLowEnergyAdvertiser>*
CreateAdvertiserInternal()103   CreateAdvertiserInternal() {
104     return new AndroidExtendedLowEnergyAdvertiser(transport()->GetWeakPtr(), 1);
105   }
106 
107   template <bool same = std::is_same_v<T, ExtendedLowEnergyAdvertiser>>
108   std::enable_if_t<same, ExtendedLowEnergyAdvertiser>*
CreateAdvertiserInternal()109   CreateAdvertiserInternal() {
110     return new ExtendedLowEnergyAdvertiser(transport()->GetWeakPtr());
111   }
112 
113   template <bool same = std::is_same_v<T, LegacyLowEnergyAdvertiser>>
114   std::enable_if_t<same, LegacyLowEnergyAdvertiser>*
CreateAdvertiserInternal()115   CreateAdvertiserInternal() {
116     return new LegacyLowEnergyAdvertiser(transport()->GetWeakPtr());
117   }
118 
advertiser() const119   LowEnergyAdvertiser* advertiser() const { return advertiser_.get(); }
120 
DestroyAdvertiser()121   void DestroyAdvertiser() { advertiser_.reset(); }
122 
MakeExpectSuccessCallback()123   ResultFunction<> MakeExpectSuccessCallback() {
124     return [this](Result<> status) {
125       last_status_ = status;
126       EXPECT_EQ(fit::ok(), status);
127     };
128   }
129 
MakeExpectErrorCallback()130   ResultFunction<> MakeExpectErrorCallback() {
131     return [this](Result<> status) {
132       last_status_ = status;
133       EXPECT_TRUE(status.is_error());
134     };
135   }
136 
GetLastStatus()137   std::optional<Result<>> GetLastStatus() {
138     if (!last_status_) {
139       return std::nullopt;
140     }
141 
142     Result<> status = last_status_.value();
143     last_status_.reset();
144     return status;
145   }
146 
147   // Makes some fake advertising data.
148   // |include_flags| signals whether to include flag encoding size in the data
149   // calculation.
GetExampleData(bool include_flags=true)150   AdvertisingData GetExampleData(bool include_flags = true) {
151     AdvertisingData result;
152 
153     auto name = "fuchsia";
154     EXPECT_TRUE(result.SetLocalName(name));
155 
156     auto appearance = 0x1234;
157     result.SetAppearance(appearance);
158 
159     EXPECT_LE(result.CalculateBlockSize(include_flags),
160               hci_spec::kMaxLEAdvertisingDataLength);
161     return result;
162   }
163 
164   // Makes fake advertising data that is too large.
165   // |include_flags| signals whether to include flag encoding size in the data
166   // calculation.
GetTooLargeExampleData(bool include_flags,std::size_t size=hci_spec::kMaxLEAdvertisingDataLength+1)167   AdvertisingData GetTooLargeExampleData(
168       bool include_flags,
169       std::size_t size = hci_spec::kMaxLEAdvertisingDataLength + 1) {
170     AdvertisingData result;
171 
172     if (include_flags) {
173       size -= kTLVFlagsSize;
174     }
175 
176     std::ostringstream oss;
177     for (unsigned int i = 0; i <= size; i++) {
178       oss << 'a';
179     }
180 
181     EXPECT_TRUE(result.SetLocalName(oss.str()));
182 
183     // The maximum advertisement packet is:
184     // |hci_spec::kMaxLEAdvertisingDataLength| = 31, and |result| = 32 bytes.
185     // |result| should be too large to advertise.
186     EXPECT_GT(result.CalculateBlockSize(include_flags),
187               hci_spec::kMaxLEAdvertisingDataLength);
188     return result;
189   }
190 
CurrentAdvertisingHandle() const191   std::optional<hci_spec::AdvertisingHandle> CurrentAdvertisingHandle() const {
192     if (std::is_same_v<T, ExtendedLowEnergyAdvertiser>) {
193       auto extended = static_cast<ExtendedLowEnergyAdvertiser*>(advertiser());
194       return extended->LastUsedHandleForTesting();
195     }
196 
197     if (std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>) {
198       auto extended =
199           static_cast<AndroidExtendedLowEnergyAdvertiser*>(advertiser());
200       return extended->LastUsedHandleForTesting();
201     }
202 
203     return 0;  // non-extended advertising doesn't use handles, we can return
204                // any value
205   }
206 
GetControllerAdvertisingState() const207   const FakeController::LEAdvertisingState& GetControllerAdvertisingState()
208       const {
209     if (std::is_same_v<T, LegacyLowEnergyAdvertiser>) {
210       return test_device()->legacy_advertising_state();
211     }
212 
213     if (std::is_same_v<T, ExtendedLowEnergyAdvertiser> ||
214         std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>) {
215       std::optional<hci_spec::AdvertisingHandle> handle =
216           CurrentAdvertisingHandle();
217       if (!handle) {
218         static FakeController::LEAdvertisingState empty;
219         return empty;
220       }
221 
222       return test_device()->extended_advertising_state(handle.value());
223     }
224 
225     EXPECT_TRUE(false) << "advertiser is of unknown type";
226 
227     // return something in order to compile, tests will fail if they get here
228     static FakeController::LEAdvertisingState state;
229     return state;
230   }
231 
MaybeSendMultipleAdvertisingPostConnectionEvents(hci_spec::ConnectionHandle conn_handle,hci_spec::AdvertisingHandle adv_handle)232   void MaybeSendMultipleAdvertisingPostConnectionEvents(
233       hci_spec::ConnectionHandle conn_handle,
234       hci_spec::AdvertisingHandle adv_handle) {
235     if (std::is_same_v<T, AndroidExtendedLowEnergyAdvertiser>) {
236       test_device()->SendAndroidLEMultipleAdvertisingStateChangeSubevent(
237           conn_handle, adv_handle);
238       return;
239     }
240 
241     if (std::is_same_v<T, ExtendedLowEnergyAdvertiser>) {
242       test_device()->SendLEAdvertisingSetTerminatedEvent(conn_handle,
243                                                          adv_handle);
244       return;
245     }
246   }
247 
248  private:
249   std::unique_ptr<LowEnergyAdvertiser> advertiser_;
250   std::optional<Result<>> last_status_;
251 
252   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyAdvertiserTest);
253 };
254 
255 using Implementations = ::testing::Types<LegacyLowEnergyAdvertiser,
256                                          ExtendedLowEnergyAdvertiser,
257                                          AndroidExtendedLowEnergyAdvertiser>;
258 TYPED_TEST_SUITE(LowEnergyAdvertiserTest, Implementations);
259 
260 // - Stops the advertisement when an incoming connection comes in
261 // - Possible to restart advertising
262 // - Advertising state cleaned up between calls
TYPED_TEST(LowEnergyAdvertiserTest,ConnectionTest)263 TYPED_TEST(LowEnergyAdvertiserTest, ConnectionTest) {
264   AdvertisingData adv_data = this->GetExampleData();
265   AdvertisingData scan_data = this->GetExampleData();
266   AdvertisingOptions options(kTestInterval,
267                              /*anonymous=*/false,
268                              kDefaultNoAdvFlags,
269                              /*include_tx_power_level=*/false);
270 
271   std::unique_ptr<LowEnergyConnection> link;
272   auto conn_cb = [&link](auto cb_link) { link = std::move(cb_link); };
273 
274   // Start advertising kPublicAddress
275   this->advertiser()->StartAdvertising(kPublicAddress,
276                                        adv_data,
277                                        scan_data,
278                                        options,
279                                        conn_cb,
280                                        this->MakeExpectSuccessCallback());
281   this->RunUntilIdle();
282   EXPECT_TRUE(this->GetLastStatus());
283   EXPECT_TRUE(this->advertiser()->IsAdvertising());
284   EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
285 
286   // Accept a connection and ensure that connection state is set up correctly
287   link.reset();
288   this->advertiser()->OnIncomingConnection(
289       kConnectionHandle,
290       pw::bluetooth::emboss::ConnectionRole::PERIPHERAL,
291       kRandomAddress,
292       hci_spec::LEConnectionParameters());
293   std::optional<hci_spec::AdvertisingHandle> handle =
294       this->CurrentAdvertisingHandle();
295   ASSERT_TRUE(handle);
296   this->MaybeSendMultipleAdvertisingPostConnectionEvents(kConnectionHandle,
297                                                          handle.value());
298   this->RunUntilIdle();
299 
300   ASSERT_TRUE(link);
301   EXPECT_EQ(kConnectionHandle, link->handle());
302   EXPECT_EQ(kPublicAddress, link->local_address());
303   EXPECT_EQ(kRandomAddress, link->peer_address());
304   EXPECT_FALSE(this->advertiser()->IsAdvertising());
305   EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress));
306 
307   // Advertising state should get cleared on a disconnection
308   link->Disconnect(
309       pw::bluetooth::emboss::StatusCode::REMOTE_USER_TERMINATED_CONNECTION);
310   this->test_device()->SendDisconnectionCompleteEvent(link->handle());
311   this->RunUntilIdle();
312   EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
313 
314   // Restart advertising using a different local address
315   this->advertiser()->StartAdvertising(kRandomAddress,
316                                        adv_data,
317                                        scan_data,
318                                        options,
319                                        conn_cb,
320                                        this->MakeExpectSuccessCallback());
321   this->RunUntilIdle();
322   EXPECT_TRUE(this->GetLastStatus());
323   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
324 
325   // Accept a connection from kPublicAddress. The internal advertising state
326   // should get assigned correctly with no remnants of the previous advertise.
327   link.reset();
328   this->advertiser()->OnIncomingConnection(
329       kConnectionHandle,
330       pw::bluetooth::emboss::ConnectionRole::PERIPHERAL,
331       kPublicAddress,
332       hci_spec::LEConnectionParameters());
333   handle = this->CurrentAdvertisingHandle();
334   ASSERT_TRUE(handle);
335   this->MaybeSendMultipleAdvertisingPostConnectionEvents(kConnectionHandle,
336                                                          handle.value());
337   this->RunUntilIdle();
338 
339   ASSERT_TRUE(link);
340   EXPECT_EQ(kRandomAddress, link->local_address());
341   EXPECT_EQ(kPublicAddress, link->peer_address());
342 }
343 
344 // Tests that advertising can be restarted right away in a connection callback.
TYPED_TEST(LowEnergyAdvertiserTest,RestartInConnectionCallback)345 TYPED_TEST(LowEnergyAdvertiserTest, RestartInConnectionCallback) {
346   AdvertisingData ad = this->GetExampleData();
347   AdvertisingData scan_data = this->GetExampleData();
348   AdvertisingOptions options(kTestInterval,
349                              /*anonymous=*/false,
350                              kDefaultNoAdvFlags,
351                              /*include_tx_power_level=*/false);
352 
353   std::unique_ptr<LowEnergyConnection> link;
354   auto conn_cb = [&, this](auto cb_link) {
355     link = std::move(cb_link);
356 
357     this->advertiser()->StartAdvertising(
358         kPublicAddress,
359         ad,
360         scan_data,
361         options,
362         [](auto) { /*noop*/ },
363         this->MakeExpectSuccessCallback());
364   };
365 
366   this->advertiser()->StartAdvertising(kPublicAddress,
367                                        ad,
368                                        scan_data,
369                                        options,
370                                        conn_cb,
371                                        this->MakeExpectSuccessCallback());
372   this->RunUntilIdle();
373   EXPECT_TRUE(this->GetLastStatus());
374   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
375 
376   bool enabled = true;
377   std::vector<bool> adv_states;
378   this->test_device()->set_advertising_state_callback(
379       [this, &adv_states, &enabled] {
380         bool new_enabled = this->GetControllerAdvertisingState().enabled;
381         if (enabled != new_enabled) {
382           adv_states.push_back(new_enabled);
383           enabled = new_enabled;
384         }
385       });
386 
387   this->advertiser()->OnIncomingConnection(
388       kConnectionHandle,
389       pw::bluetooth::emboss::ConnectionRole::PERIPHERAL,
390       kRandomAddress,
391       hci_spec::LEConnectionParameters());
392   std::optional<hci_spec::AdvertisingHandle> handle =
393       this->CurrentAdvertisingHandle();
394   ASSERT_TRUE(handle);
395   this->MaybeSendMultipleAdvertisingPostConnectionEvents(kConnectionHandle,
396                                                          handle.value());
397 
398   // Advertising should get disabled and re-enabled.
399   this->RunUntilIdle();
400   ASSERT_EQ(2u, adv_states.size());
401   EXPECT_FALSE(adv_states[0]);
402   EXPECT_TRUE(adv_states[1]);
403 
404   this->test_device()->set_advertising_state_callback(nullptr);
405 }
406 
407 // An incoming connection when not advertising should get disconnected.
TYPED_TEST(LowEnergyAdvertiserTest,IncomingConnectionWhenNotAdvertising)408 TYPED_TEST(LowEnergyAdvertiserTest, IncomingConnectionWhenNotAdvertising) {
409   std::vector<std::pair<bool, hci_spec::ConnectionHandle>> connection_states;
410   this->test_device()->set_connection_state_callback(
411       [&](const auto& address, auto handle, bool connected, bool canceled) {
412         EXPECT_EQ(kRandomAddress, address);
413         EXPECT_FALSE(canceled);
414         connection_states.push_back(std::make_pair(connected, handle));
415       });
416 
417   auto fake_peer = std::make_unique<FakePeer>(
418       kRandomAddress, TestFixture::dispatcher(), true, true);
419   this->test_device()->AddPeer(std::move(fake_peer));
420   this->test_device()->ConnectLowEnergy(
421       kRandomAddress, pw::bluetooth::emboss::ConnectionRole::PERIPHERAL);
422   this->RunUntilIdle();
423 
424   ASSERT_EQ(1u, connection_states.size());
425   auto [connection_state, handle] = connection_states[0];
426   EXPECT_TRUE(connection_state);
427 
428   // Notify the advertiser of the incoming connection. It should reject it and
429   // the controller should become disconnected.
430   this->advertiser()->OnIncomingConnection(
431       handle,
432       pw::bluetooth::emboss::ConnectionRole::PERIPHERAL,
433       kRandomAddress,
434       hci_spec::LEConnectionParameters());
435   this->MaybeSendMultipleAdvertisingPostConnectionEvents(kConnectionHandle, 0);
436   this->RunUntilIdle();
437   ASSERT_EQ(2u, connection_states.size());
438   auto [connection_state_after_disconnect, disconnected_handle] =
439       connection_states[1];
440   EXPECT_EQ(handle, disconnected_handle);
441   EXPECT_FALSE(connection_state_after_disconnect);
442 }
443 
444 // An incoming connection during non-connectable advertising should get
445 // disconnected.
TYPED_TEST(LowEnergyAdvertiserTest,IncomingConnectionWhenNonConnectableAdvertising)446 TYPED_TEST(LowEnergyAdvertiserTest,
447            IncomingConnectionWhenNonConnectableAdvertising) {
448   AdvertisingData ad = this->GetExampleData();
449   AdvertisingData scan_data = this->GetExampleData();
450   AdvertisingOptions options(kTestInterval,
451                              /*anonymous=*/false,
452                              kDefaultNoAdvFlags,
453                              /*include_tx_power_level=*/false);
454   this->advertiser()->StartAdvertising(kPublicAddress,
455                                        ad,
456                                        scan_data,
457                                        options,
458                                        nullptr,
459                                        this->MakeExpectSuccessCallback());
460   this->RunUntilIdle();
461   ASSERT_TRUE(this->GetLastStatus());
462 
463   std::vector<std::pair<bool, hci_spec::ConnectionHandle>> connection_states;
464   this->test_device()->set_connection_state_callback(
465       [&](const auto& address, auto handle, bool connected, bool canceled) {
466         EXPECT_EQ(kRandomAddress, address);
467         EXPECT_FALSE(canceled);
468         connection_states.push_back(std::make_pair(connected, handle));
469       });
470 
471   auto fake_peer = std::make_unique<FakePeer>(
472       kRandomAddress, TestFixture::dispatcher(), true, true);
473   this->test_device()->AddPeer(std::move(fake_peer));
474   this->test_device()->ConnectLowEnergy(
475       kRandomAddress, pw::bluetooth::emboss::ConnectionRole::PERIPHERAL);
476   this->RunUntilIdle();
477 
478   ASSERT_EQ(1u, connection_states.size());
479   auto [connection_state, handle] = connection_states[0];
480   EXPECT_TRUE(connection_state);
481 
482   // Notify the advertiser of the incoming connection. It should reject it and
483   // the controller should become disconnected.
484   this->advertiser()->OnIncomingConnection(
485       handle,
486       pw::bluetooth::emboss::ConnectionRole::PERIPHERAL,
487       kRandomAddress,
488       hci_spec::LEConnectionParameters());
489   this->MaybeSendMultipleAdvertisingPostConnectionEvents(kConnectionHandle, 0);
490   this->RunUntilIdle();
491   ASSERT_EQ(2u, connection_states.size());
492   auto [connection_state_after_disconnect, disconnected_handle] =
493       connection_states[1];
494   EXPECT_EQ(handle, disconnected_handle);
495   EXPECT_FALSE(connection_state_after_disconnect);
496 }
497 
498 // Tests starting and stopping an advertisement.
TYPED_TEST(LowEnergyAdvertiserTest,StartAndStop)499 TYPED_TEST(LowEnergyAdvertiserTest, StartAndStop) {
500   AdvertisingData ad = this->GetExampleData();
501   AdvertisingData scan_data = this->GetExampleData();
502   AdvertisingOptions options(kTestInterval,
503                              /*anonymous=*/false,
504                              kDefaultNoAdvFlags,
505                              /*include_tx_power_level=*/false);
506 
507   this->advertiser()->StartAdvertising(kRandomAddress,
508                                        ad,
509                                        scan_data,
510                                        options,
511                                        nullptr,
512                                        this->MakeExpectSuccessCallback());
513   this->RunUntilIdle();
514   EXPECT_TRUE(this->GetLastStatus());
515   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
516 
517   this->advertiser()->StopAdvertising(kRandomAddress);
518   this->RunUntilIdle();
519   EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
520 }
521 
522 // Tests that an advertisement is configured with the correct parameters.
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingParameters)523 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingParameters) {
524   AdvertisingData ad = this->GetExampleData();
525   AdvertisingData scan_data = this->GetExampleData();
526   auto flags = AdvFlag::kLEGeneralDiscoverableMode;
527   AdvertisingOptions options(kTestInterval,
528                              /*anonymous=*/false,
529                              flags,
530                              /*include_tx_power_level=*/false);
531 
532   this->advertiser()->StartAdvertising(kRandomAddress,
533                                        ad,
534                                        scan_data,
535                                        options,
536                                        nullptr,
537                                        this->MakeExpectSuccessCallback());
538   this->RunUntilIdle();
539   EXPECT_TRUE(this->GetLastStatus());
540 
541   // The expected advertisement including the Flags.
542   DynamicByteBuffer expected_ad(ad.CalculateBlockSize(/*include_flags=*/true));
543   ad.WriteBlock(&expected_ad, flags);
544 
545   DynamicByteBuffer expected_scan_data(
546       scan_data.CalculateBlockSize(/*include_flags=*/false));
547   scan_data.WriteBlock(&expected_scan_data, std::nullopt);
548 
549   std::optional<FakeController::LEAdvertisingState> state =
550       this->GetControllerAdvertisingState();
551   EXPECT_TRUE(state);
552   EXPECT_TRUE(state->enabled);
553   EXPECT_EQ(kTestInterval.min(), state->interval_min);
554   EXPECT_EQ(kTestInterval.max(), state->interval_max);
555   EXPECT_EQ(expected_ad, state->advertised_view());
556   EXPECT_EQ(expected_scan_data, state->scan_rsp_view());
557   EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::RANDOM,
558             state->own_address_type);
559 
560   // Restart advertising with a public address and verify that the configured
561   // local address type is correct.
562   this->advertiser()->StopAdvertising(kRandomAddress);
563   AdvertisingOptions new_options(kTestInterval,
564                                  /*anonymous=*/false,
565                                  kDefaultNoAdvFlags,
566                                  /*include_tx_power_level=*/false);
567   this->advertiser()->StartAdvertising(kPublicAddress,
568                                        ad,
569                                        scan_data,
570                                        new_options,
571                                        nullptr,
572                                        this->MakeExpectSuccessCallback());
573   this->RunUntilIdle();
574   EXPECT_TRUE(this->GetLastStatus());
575 
576   state = this->GetControllerAdvertisingState();
577   EXPECT_TRUE(state);
578   EXPECT_TRUE(state->enabled);
579   EXPECT_EQ(pw::bluetooth::emboss::LEOwnAddressType::PUBLIC,
580             state->own_address_type);
581 }
582 
583 // Tests that a previous advertisement's advertising data isn't accidentally
584 // kept around. This test was added to address fxbug.dev/42081491.
TYPED_TEST(LowEnergyAdvertiserTest,PreviousAdvertisingParameters)585 TYPED_TEST(LowEnergyAdvertiserTest, PreviousAdvertisingParameters) {
586   AdvertisingData scan_data = this->GetExampleData();
587   auto flags = AdvFlag::kLEGeneralDiscoverableMode;
588   AdvertisingOptions options(kTestInterval,
589                              /*anonymous=*/false,
590                              flags,
591                              /*include_tx_power_level=*/false);
592 
593   // old advertising data: ideally we would fill this completely so that in the
594   // next start advertising call, we can confirm that none of the remnants are
595   // left. However, doing so results in the advertising data being too long.
596   // Instead, we rely on other unit tests within advertising data unittests to
597   // ensure all previous remnants are removed.
598   AdvertisingData ad;
599   ad.SetTxPower(4);
600   ad.SetAppearance(0x4567);
601   EXPECT_TRUE(ad.SetLocalName("fuchsia"));
602 
603   this->advertiser()->StartAdvertising(kRandomAddress,
604                                        ad,
605                                        scan_data,
606                                        options,
607                                        nullptr,
608                                        this->MakeExpectSuccessCallback());
609   this->RunUntilIdle();
610   EXPECT_TRUE(this->GetLastStatus());
611 
612   // new advertising data (with fewer fields filled in)
613   this->advertiser()->StopAdvertising(kRandomAddress);
614   AdvertisingData new_ad = this->GetExampleData();
615   this->advertiser()->StartAdvertising(kRandomAddress,
616                                        new_ad,
617                                        scan_data,
618                                        options,
619                                        nullptr,
620                                        this->MakeExpectSuccessCallback());
621   this->RunUntilIdle();
622   EXPECT_TRUE(this->GetLastStatus());
623 
624   DynamicByteBuffer expected_ad(
625       new_ad.CalculateBlockSize(/*include_flags=*/true));
626   new_ad.WriteBlock(&expected_ad, flags);
627 
628   std::optional<FakeController::LEAdvertisingState> state =
629       this->GetControllerAdvertisingState();
630   EXPECT_EQ(expected_ad, state->advertised_view());
631 }
632 
633 // Tests that advertising interval values are capped within the allowed range.
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingIntervalWithinAllowedRange)634 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingIntervalWithinAllowedRange) {
635   AdvertisingData ad = this->GetExampleData();
636   AdvertisingData scan_data = this->GetExampleData();
637 
638   // Pass min and max values that are outside the allowed range. These should be
639   // capped.
640   constexpr AdvertisingIntervalRange interval(
641       hci_spec::kLEAdvertisingIntervalMin - 1,
642       hci_spec::kLEAdvertisingIntervalMax + 1);
643   AdvertisingOptions options(interval,
644                              /*anonymous=*/false,
645                              kDefaultNoAdvFlags,
646                              /*include_tx_power_level=*/false);
647   this->advertiser()->StartAdvertising(kRandomAddress,
648                                        ad,
649                                        scan_data,
650                                        options,
651                                        nullptr,
652                                        this->MakeExpectSuccessCallback());
653   this->RunUntilIdle();
654   EXPECT_TRUE(this->GetLastStatus());
655 
656   std::optional<FakeController::LEAdvertisingState> state =
657       this->GetControllerAdvertisingState();
658   EXPECT_TRUE(state);
659   EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMin, state->interval_min);
660   EXPECT_EQ(hci_spec::kLEAdvertisingIntervalMax, state->interval_max);
661 
662   // Reconfigure with values that are within the range. These should get passed
663   // down as is.
664   const AdvertisingIntervalRange new_interval(
665       hci_spec::kLEAdvertisingIntervalMin + 1,
666       hci_spec::kLEAdvertisingIntervalMax - 1);
667   AdvertisingOptions new_options(new_interval,
668                                  /*anonymous=*/false,
669                                  kDefaultNoAdvFlags,
670                                  /*include_tx_power_level=*/false);
671   this->advertiser()->StartAdvertising(kRandomAddress,
672                                        ad,
673                                        scan_data,
674                                        new_options,
675                                        nullptr,
676                                        this->MakeExpectSuccessCallback());
677   this->RunUntilIdle();
678   EXPECT_TRUE(this->GetLastStatus());
679 
680   state = this->GetControllerAdvertisingState();
681   EXPECT_TRUE(state);
682   EXPECT_EQ(new_interval.min(), state->interval_min);
683   EXPECT_EQ(new_interval.max(), state->interval_max);
684 }
685 
TYPED_TEST(LowEnergyAdvertiserTest,StartWhileStarting)686 TYPED_TEST(LowEnergyAdvertiserTest, StartWhileStarting) {
687   AdvertisingData ad = this->GetExampleData();
688   AdvertisingData scan_data = this->GetExampleData();
689   DeviceAddress addr = kRandomAddress;
690 
691   const AdvertisingIntervalRange old_interval = kTestInterval;
692   AdvertisingOptions old_options(old_interval,
693                                  /*anonymous=*/false,
694                                  kDefaultNoAdvFlags,
695                                  /*include_tx_power_level=*/false);
696   const AdvertisingIntervalRange new_interval(kTestInterval.min() + 1,
697                                               kTestInterval.max() - 1);
698   AdvertisingOptions new_options(new_interval,
699                                  /*anonymous=*/false,
700                                  kDefaultNoAdvFlags,
701                                  /*include_tx_power_level=*/false);
702 
703   this->advertiser()->StartAdvertising(
704       addr, ad, scan_data, old_options, nullptr, [](auto) {});
705   EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
706 
707   // This call should override the previous call and succeed with the new
708   // parameters.
709   this->advertiser()->StartAdvertising(addr,
710                                        ad,
711                                        scan_data,
712                                        new_options,
713                                        nullptr,
714                                        this->MakeExpectSuccessCallback());
715   this->RunUntilIdle();
716   EXPECT_TRUE(this->GetLastStatus());
717   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
718   EXPECT_EQ(new_interval.max(),
719             this->GetControllerAdvertisingState().interval_max);
720 }
721 
TYPED_TEST(LowEnergyAdvertiserTest,StartWhileStopping)722 TYPED_TEST(LowEnergyAdvertiserTest, StartWhileStopping) {
723   AdvertisingData ad = this->GetExampleData();
724   AdvertisingData scan_data = this->GetExampleData();
725   DeviceAddress addr = kRandomAddress;
726   AdvertisingOptions options(kTestInterval,
727                              /*anonymous=*/false,
728                              kDefaultNoAdvFlags,
729                              /*include_tx_power_level=*/false);
730 
731   // Get to a started state.
732   this->advertiser()->StartAdvertising(
733       addr, ad, scan_data, options, nullptr, this->MakeExpectSuccessCallback());
734   this->RunUntilIdle();
735   EXPECT_TRUE(this->GetLastStatus());
736   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
737 
738   // Initiate a request to Stop and wait until it's partially in progress.
739   bool enabled = true;
740   bool was_disabled = false;
741   auto adv_state_cb = [&] {
742     enabled = this->GetControllerAdvertisingState().enabled;
743     if (!was_disabled && !enabled) {
744       was_disabled = true;
745 
746       // Starting now should cancel the stop sequence and succeed.
747       this->advertiser()->StartAdvertising(addr,
748                                            ad,
749                                            scan_data,
750                                            options,
751                                            nullptr,
752                                            this->MakeExpectSuccessCallback());
753     }
754   };
755   this->test_device()->set_advertising_state_callback(adv_state_cb);
756 
757   this->advertiser()->StopAdvertising(addr);
758 
759   // Advertising should have been momentarily disabled.
760   this->RunUntilIdle();
761   EXPECT_TRUE(was_disabled);
762   EXPECT_TRUE(enabled);
763   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
764 
765   this->test_device()->set_advertising_state_callback(nullptr);
766 }
767 
TYPED_TEST(LowEnergyAdvertiserTest,StopWhileStarting)768 TYPED_TEST(LowEnergyAdvertiserTest, StopWhileStarting) {
769   AdvertisingData ad = this->GetExampleData();
770   AdvertisingData scan_data = this->GetExampleData();
771   AdvertisingOptions options(kTestInterval,
772                              /*anonymous=*/false,
773                              kDefaultNoAdvFlags,
774                              /*include_tx_power_level=*/false);
775 
776   this->advertiser()->StartAdvertising(kPublicAddress,
777                                        ad,
778                                        scan_data,
779                                        options,
780                                        nullptr,
781                                        this->MakeExpectErrorCallback());
782   this->advertiser()->StopAdvertising();
783 
784   this->RunUntilIdle();
785   EXPECT_TRUE(this->GetLastStatus());
786   EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
787 }
788 
789 // - StopAdvertisement noops when the advertisement address is wrong
790 // - Sets the advertisement data to null when stopped to prevent data leakage
791 //   (re-enable advertising without changing data, intercept)
TYPED_TEST(LowEnergyAdvertiserTest,StopAdvertisingConditions)792 TYPED_TEST(LowEnergyAdvertiserTest, StopAdvertisingConditions) {
793   AdvertisingData ad = this->GetExampleData();
794   AdvertisingData scan_data = this->GetExampleData();
795   AdvertisingOptions options(kTestInterval,
796                              /*anonymous=*/false,
797                              kDefaultNoAdvFlags,
798                              /*include_tx_power_level=*/false);
799 
800   this->advertiser()->StartAdvertising(kRandomAddress,
801                                        ad,
802                                        scan_data,
803                                        options,
804                                        nullptr,
805                                        this->MakeExpectSuccessCallback());
806 
807   this->RunUntilIdle();
808 
809   EXPECT_TRUE(this->GetLastStatus());
810 
811   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
812   DynamicByteBuffer expected_ad(ad.CalculateBlockSize(/*include_flags=*/true));
813   ad.WriteBlock(&expected_ad, kDefaultNoAdvFlags);
814   EXPECT_TRUE(ContainersEqual(
815       this->GetControllerAdvertisingState().advertised_view(), expected_ad));
816 
817   this->RunUntilIdle();
818   this->advertiser()->StopAdvertising(kPublicAddress);
819   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
820   EXPECT_TRUE(ContainersEqual(
821       this->GetControllerAdvertisingState().advertised_view(), expected_ad));
822 
823   this->advertiser()->StopAdvertising(kRandomAddress);
824 
825   this->RunUntilIdle();
826   EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
827   EXPECT_EQ(0u, this->GetControllerAdvertisingState().advertised_view().size());
828   EXPECT_EQ(0u, this->GetControllerAdvertisingState().scan_rsp_view().size());
829 }
830 
831 // - Updates data and params for the same address when advertising already
TYPED_TEST(LowEnergyAdvertiserTest,AdvertiseUpdate)832 TYPED_TEST(LowEnergyAdvertiserTest, AdvertiseUpdate) {
833   AdvertisingData ad = this->GetExampleData();
834   AdvertisingData scan_data = this->GetExampleData();
835   AdvertisingOptions options(kTestInterval,
836                              /*anonymous=*/false,
837                              kDefaultNoAdvFlags,
838                              /*include_tx_power_level=*/false);
839 
840   this->advertiser()->StartAdvertising(kRandomAddress,
841                                        ad,
842                                        scan_data,
843                                        options,
844                                        nullptr,
845                                        this->MakeExpectSuccessCallback());
846   this->RunUntilIdle();
847 
848   EXPECT_TRUE(this->GetLastStatus());
849   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
850 
851   // The expected advertising data payload, with the flags.
852   DynamicByteBuffer expected_ad(ad.CalculateBlockSize(/*include_flags=*/true));
853   ad.WriteBlock(&expected_ad, kDefaultNoAdvFlags);
854   EXPECT_TRUE(ContainersEqual(
855       this->GetControllerAdvertisingState().advertised_view(), expected_ad));
856 
857   EXPECT_EQ(kTestInterval.min(),
858             this->GetControllerAdvertisingState().interval_min);
859   EXPECT_EQ(kTestInterval.max(),
860             this->GetControllerAdvertisingState().interval_max);
861 
862   uint16_t new_appearance = 0x6789;
863   ad.SetAppearance(new_appearance);
864 
865   const AdvertisingIntervalRange new_interval(kTestInterval.min() + 1,
866                                               kTestInterval.max() - 1);
867   AdvertisingOptions new_options(new_interval,
868                                  /*anonymous=*/false,
869                                  kDefaultNoAdvFlags,
870                                  /*include_tx_power_level=*/false);
871   this->advertiser()->StartAdvertising(kRandomAddress,
872                                        ad,
873                                        scan_data,
874                                        new_options,
875                                        nullptr,
876                                        this->MakeExpectSuccessCallback());
877   this->RunUntilIdle();
878 
879   EXPECT_TRUE(this->GetLastStatus());
880   EXPECT_TRUE(this->GetControllerAdvertisingState().enabled);
881 
882   DynamicByteBuffer expected_new_ad(
883       ad.CalculateBlockSize(/*include_flags=*/true));
884   ad.WriteBlock(&expected_new_ad, kDefaultNoAdvFlags);
885   EXPECT_TRUE(
886       ContainersEqual(this->GetControllerAdvertisingState().advertised_view(),
887                       expected_new_ad));
888 
889   EXPECT_EQ(new_interval.min(),
890             this->GetControllerAdvertisingState().interval_min);
891   EXPECT_EQ(new_interval.max(),
892             this->GetControllerAdvertisingState().interval_max);
893 }
894 
895 // Ensures advertising set data is removed from controller memory after
896 // advertising is stopped
TYPED_TEST(LowEnergyAdvertiserTest,StopAdvertisingSingleAdvertisement)897 TYPED_TEST(LowEnergyAdvertiserTest, StopAdvertisingSingleAdvertisement) {
898   AdvertisingData ad = this->GetExampleData();
899   AdvertisingData scan_data = this->GetExampleData();
900 
901   // start public address advertising
902   AdvertisingOptions options(kTestInterval,
903                              /*anonymous=*/false,
904                              kDefaultNoAdvFlags,
905                              /*include_tx_power_level=*/false);
906   this->advertiser()->StartAdvertising(kPublicAddress,
907                                        ad,
908                                        scan_data,
909                                        options,
910                                        nullptr,
911                                        this->MakeExpectSuccessCallback());
912   this->RunUntilIdle();
913   EXPECT_TRUE(this->GetLastStatus());
914 
915   constexpr uint8_t blank[hci_spec::kMaxLEAdvertisingDataLength] = {0};
916 
917   // check that advertiser and controller both report the same advertising state
918   EXPECT_TRUE(this->advertiser()->IsAdvertising());
919   EXPECT_TRUE(this->advertiser()->IsAdvertising(kPublicAddress));
920 
921   {
922     const FakeController::LEAdvertisingState& state =
923         this->GetControllerAdvertisingState();
924     EXPECT_TRUE(state.enabled);
925     EXPECT_NE(
926         0,
927         std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
928     EXPECT_NE(0, state.data_length);
929     EXPECT_NE(
930         0,
931         std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
932     EXPECT_NE(0, state.scan_rsp_length);
933   }
934 
935   // stop advertising the random address
936   this->advertiser()->StopAdvertising(kPublicAddress);
937   this->RunUntilIdle();
938 
939   // check that advertiser and controller both report the same advertising state
940   EXPECT_FALSE(this->advertiser()->IsAdvertising());
941   EXPECT_FALSE(this->advertiser()->IsAdvertising(kPublicAddress));
942 
943   {
944     const FakeController::LEAdvertisingState& state =
945         this->GetControllerAdvertisingState();
946     EXPECT_FALSE(state.enabled);
947     EXPECT_EQ(
948         0,
949         std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
950     EXPECT_EQ(0, state.data_length);
951     EXPECT_EQ(
952         0,
953         std::memcmp(blank, state.data, hci_spec::kMaxLEAdvertisingDataLength));
954     EXPECT_EQ(0, state.scan_rsp_length);
955   }
956 }
957 
958 // - Rejects anonymous advertisement (unsupported)
TYPED_TEST(LowEnergyAdvertiserTest,NoAnonymous)959 TYPED_TEST(LowEnergyAdvertiserTest, NoAnonymous) {
960   AdvertisingData ad = this->GetExampleData();
961   AdvertisingData scan_data = this->GetExampleData();
962   AdvertisingOptions options(kTestInterval,
963                              /*anonymous=*/true,
964                              kDefaultNoAdvFlags,
965                              /*include_tx_power_level=*/false);
966 
967   this->advertiser()->StartAdvertising(kRandomAddress,
968                                        ad,
969                                        scan_data,
970                                        options,
971                                        nullptr,
972                                        this->MakeExpectErrorCallback());
973   EXPECT_TRUE(this->GetLastStatus());
974   EXPECT_FALSE(this->GetControllerAdvertisingState().enabled);
975 }
976 
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingDataTooLong)977 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingDataTooLong) {
978   AdvertisingData invalid_ad =
979       this->GetTooLargeExampleData(/*include_flags=*/true);
980   AdvertisingData valid_scan_rsp =
981       this->GetExampleData(/*include_flags=*/false);
982   AdvertisingOptions options(kTestInterval,
983                              /*anonymous=*/false,
984                              kDefaultNoAdvFlags,
985                              /*include_tx_power_level=*/false);
986 
987   // Advertising data too large.
988   this->advertiser()->StartAdvertising(kRandomAddress,
989                                        invalid_ad,
990                                        valid_scan_rsp,
991                                        options,
992                                        nullptr,
993                                        this->MakeExpectErrorCallback());
994   this->RunUntilIdle();
995   auto status = this->GetLastStatus();
996   ASSERT_TRUE(status);
997   EXPECT_EQ(ToResult(HostError::kAdvertisingDataTooLong), *status);
998 }
999 
TYPED_TEST(LowEnergyAdvertiserTest,AdvertisingDataTooLongWithTxPower)1000 TYPED_TEST(LowEnergyAdvertiserTest, AdvertisingDataTooLongWithTxPower) {
1001   AdvertisingData invalid_ad = this->GetTooLargeExampleData(
1002       /*include_flags=*/true,
1003       hci_spec::kMaxLEAdvertisingDataLength - kTLVTxPowerLevelSize + 1);
1004   AdvertisingData valid_scan_rsp =
1005       this->GetExampleData(/*include_flags=*/false);
1006   AdvertisingOptions options(kTestInterval,
1007                              /*anonymous=*/false,
1008                              kDefaultNoAdvFlags,
1009                              /*include_tx_power_level=*/true);
1010 
1011   // Advertising data too large.
1012   this->advertiser()->StartAdvertising(kRandomAddress,
1013                                        invalid_ad,
1014                                        valid_scan_rsp,
1015                                        options,
1016                                        nullptr,
1017                                        this->MakeExpectErrorCallback());
1018   this->RunUntilIdle();
1019   auto status = this->GetLastStatus();
1020   ASSERT_TRUE(status);
1021   EXPECT_EQ(ToResult(HostError::kAdvertisingDataTooLong), *status);
1022 }
1023 
TYPED_TEST(LowEnergyAdvertiserTest,ScanResponseTooLong)1024 TYPED_TEST(LowEnergyAdvertiserTest, ScanResponseTooLong) {
1025   AdvertisingData valid_ad = this->GetExampleData();
1026   AdvertisingData invalid_scan_rsp =
1027       this->GetTooLargeExampleData(/*include_flags=*/false);
1028   AdvertisingOptions options(kTestInterval,
1029                              /*anonymous=*/false,
1030                              kDefaultNoAdvFlags,
1031                              /*include_tx_power_level=*/false);
1032   this->advertiser()->StartAdvertising(kRandomAddress,
1033                                        valid_ad,
1034                                        invalid_scan_rsp,
1035                                        options,
1036                                        nullptr,
1037                                        this->MakeExpectErrorCallback());
1038   this->RunUntilIdle();
1039   auto status = this->GetLastStatus();
1040   ASSERT_TRUE(status);
1041   EXPECT_EQ(ToResult(HostError::kScanResponseTooLong), *status);
1042 }
1043 
TYPED_TEST(LowEnergyAdvertiserTest,ScanResponseTooLongWithTxPower)1044 TYPED_TEST(LowEnergyAdvertiserTest, ScanResponseTooLongWithTxPower) {
1045   AdvertisingData valid_ad = this->GetExampleData();
1046   AdvertisingData invalid_scan_rsp = this->GetTooLargeExampleData(
1047       /*include_flags=*/false,
1048       hci_spec::kMaxLEAdvertisingDataLength - kTLVTxPowerLevelSize + 1);
1049   AdvertisingOptions options(kTestInterval,
1050                              /*anonymous=*/false,
1051                              kDefaultNoAdvFlags,
1052                              /*include_tx_power_level=*/true);
1053   this->advertiser()->StartAdvertising(kRandomAddress,
1054                                        valid_ad,
1055                                        invalid_scan_rsp,
1056                                        options,
1057                                        nullptr,
1058                                        this->MakeExpectErrorCallback());
1059   this->RunUntilIdle();
1060   auto status = this->GetLastStatus();
1061   ASSERT_TRUE(status);
1062   EXPECT_EQ(ToResult(HostError::kScanResponseTooLong), *status);
1063 }
1064 
TYPED_TEST(LowEnergyAdvertiserTest,DestroyingTransportBeforeAdvertiserDoesNotCrash)1065 TYPED_TEST(LowEnergyAdvertiserTest,
1066            DestroyingTransportBeforeAdvertiserDoesNotCrash) {
1067   this->DeleteTransport();
1068   this->DestroyAdvertiser();
1069 }
1070 
1071 }  // namespace
1072 }  // namespace bt::hci
1073