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/gap/low_energy_advertising_manager.h"
16 
17 #include <map>
18 
19 #include "pw_bluetooth_sapphire/internal/host/common/advertising_data.h"
20 #include "pw_bluetooth_sapphire/internal/host/common/assert.h"
21 #include "pw_bluetooth_sapphire/internal/host/common/byte_buffer.h"
22 #include "pw_bluetooth_sapphire/internal/host/common/macros.h"
23 #include "pw_bluetooth_sapphire/internal/host/hci/connection.h"
24 #include "pw_bluetooth_sapphire/internal/host/hci/fake_local_address_delegate.h"
25 #include "pw_bluetooth_sapphire/internal/host/hci/fake_low_energy_connection.h"
26 #include "pw_bluetooth_sapphire/internal/host/testing/controller_test.h"
27 #include "pw_bluetooth_sapphire/internal/host/testing/fake_controller.h"
28 #include "pw_bluetooth_sapphire/internal/host/transport/control_packets.h"
29 #include "pw_bluetooth_sapphire/internal/host/transport/error.h"
30 
31 namespace bt {
32 using testing::FakeController;
33 
34 namespace gap {
35 namespace {
36 namespace pwemb = pw::bluetooth::emboss;
37 using TestingBase = bt::testing::FakeDispatcherControllerTest<FakeController>;
38 
39 constexpr size_t kDefaultMaxAdSize = 23;
40 constexpr size_t kDefaultFakeAdSize = 20;
41 constexpr AdvertisingInterval kTestInterval = AdvertisingInterval::FAST1;
42 
43 const DeviceAddress kPublicAddress(DeviceAddress::Type::kLEPublic,
44                                    {0x01, 0, 0, 0, 0, 0});
45 const DeviceAddress kRandomAddress(DeviceAddress::Type::kLERandom,
46                                    {0x55, 0x44, 0x33, 0x22, 0x11, 0x00});
47 
NopConnectCallback(AdvertisementId,std::unique_ptr<hci::Connection>)48 void NopConnectCallback(AdvertisementId, std::unique_ptr<hci::Connection>) {}
49 
50 struct AdvertisementStatus {
51   AdvertisingData data;
52   AdvertisingData scan_rsp;
53   bool anonymous;
54   uint16_t interval_min;
55   uint16_t interval_max;
56   bool extended_pdu;
57   hci::LowEnergyAdvertiser::ConnectionCallback connect_cb;
58 };
59 
60 // LowEnergyAdvertiser for testing purposes:
61 //  - Reports mas_ad_size supported
62 //  - Actually just accepts all ads and stores them in ad_store
63 class FakeLowEnergyAdvertiser final : public hci::LowEnergyAdvertiser {
64  public:
FakeLowEnergyAdvertiser(const hci::Transport::WeakPtr & hci,std::unordered_map<DeviceAddress,AdvertisementStatus> * ad_store)65   FakeLowEnergyAdvertiser(
66       const hci::Transport::WeakPtr& hci,
67       std::unordered_map<DeviceAddress, AdvertisementStatus>* ad_store)
68       : hci::LowEnergyAdvertiser(hci, kDefaultMaxAdSize),
69         ads_(ad_store),
70         hci_(hci) {
71     PW_CHECK(ads_);
72   }
73 
74   ~FakeLowEnergyAdvertiser() override = default;
75 
MaxAdvertisements() const76   size_t MaxAdvertisements() const override { return 1; }
77 
AllowsRandomAddressChange() const78   bool AllowsRandomAddressChange() const override { return true; }
79 
StartAdvertising(const DeviceAddress & address,const AdvertisingData & data,const AdvertisingData & scan_rsp,const AdvertisingOptions & options,ConnectionCallback connect_callback,hci::ResultFunction<> result_callback)80   void StartAdvertising(const DeviceAddress& address,
81                         const AdvertisingData& data,
82                         const AdvertisingData& scan_rsp,
83                         const AdvertisingOptions& options,
84                         ConnectionCallback connect_callback,
85                         hci::ResultFunction<> result_callback) override {
86     if (pending_error_.is_error()) {
87       result_callback(pending_error_);
88       pending_error_ = fit::ok();
89       return;
90     }
91 
92     fit::result<HostError> result =
93         CanStartAdvertising(address, data, scan_rsp, options, connect_callback);
94     if (result.is_error()) {
95       result_callback(ToResult(result.error_value()));
96       return;
97     }
98 
99     AdvertisementStatus new_status;
100     data.Copy(&new_status.data);
101     scan_rsp.Copy(&new_status.scan_rsp);
102     new_status.connect_cb = std::move(connect_callback);
103     new_status.interval_min = options.interval.min();
104     new_status.interval_max = options.interval.max();
105     new_status.anonymous = options.anonymous;
106     new_status.extended_pdu = options.extended_pdu;
107     ads_->emplace(address, std::move(new_status));
108     result_callback(fit::ok());
109   }
110 
StopAdvertising(const DeviceAddress & address,bool)111   void StopAdvertising(const DeviceAddress& address, bool) override {
112     ads_->erase(address);
113   }
114 
OnIncomingConnection(hci_spec::ConnectionHandle handle,pwemb::ConnectionRole role,const DeviceAddress & peer_address,const hci_spec::LEConnectionParameters &)115   void OnIncomingConnection(hci_spec::ConnectionHandle handle,
116                             pwemb::ConnectionRole role,
117                             const DeviceAddress& peer_address,
118                             const hci_spec::LEConnectionParameters&) override {
119     // Right now, we call the first callback, because we can't call any other
120     // ones.
121     // TODO(jamuraa): make this send it to the correct callback once we can
122     // determine which one that is.
123     const auto& cb = ads_->begin()->second.connect_cb;
124     if (cb) {
125       cb(std::make_unique<hci::testing::FakeLowEnergyConnection>(
126           handle, ads_->begin()->first, peer_address, role, hci_));
127     }
128   }
129 
130   // Sets this faker up to send an error back from the next StartAdvertising
131   // call. Set to success to disable a previously called error.
ErrorOnNext(hci::Result<> error_status)132   void ErrorOnNext(hci::Result<> error_status) {
133     pending_error_ = error_status;
134   }
135 
136  private:
BuildEnablePacket(const DeviceAddress &,pw::bluetooth::emboss::GenericEnableParam,bool)137   hci::CommandPacket BuildEnablePacket(
138       const DeviceAddress&,
139       pw::bluetooth::emboss::GenericEnableParam,
140       bool) override {
141     return hci::CommandPacket::New<
142         pwemb::LESetExtendedAdvertisingEnableDataWriter>(
143         hci_spec::kLESetExtendedAdvertisingEnable);
144   }
145 
BuildSetAdvertisingParams(const DeviceAddress &,const AdvertisingEventProperties &,pwemb::LEOwnAddressType,const hci::AdvertisingIntervalRange &,bool)146   std::optional<hci::CommandPacket> BuildSetAdvertisingParams(
147       const DeviceAddress&,
148       const AdvertisingEventProperties&,
149       pwemb::LEOwnAddressType,
150       const hci::AdvertisingIntervalRange&,
151       bool) override {
152     return std::nullopt;
153   }
154 
BuildSetAdvertisingData(const DeviceAddress &,const AdvertisingData &,AdvFlags,bool)155   std::vector<hci::CommandPacket> BuildSetAdvertisingData(
156       const DeviceAddress&, const AdvertisingData&, AdvFlags, bool) override {
157     hci::CommandPacket packet =
158         hci::CommandPacket::New<pwemb::LESetAdvertisingDataCommandWriter>(
159             hci_spec::kLESetAdvertisingData);
160 
161     std::vector<hci::CommandPacket> packets;
162     packets.push_back(std::move(packet));
163     return packets;
164   }
165 
BuildUnsetAdvertisingData(const DeviceAddress &,bool)166   hci::CommandPacket BuildUnsetAdvertisingData(const DeviceAddress&,
167                                                bool) override {
168     return hci::CommandPacket::New<pwemb::LESetAdvertisingDataCommandWriter>(
169         hci_spec::kLESetAdvertisingData);
170   }
171 
BuildSetScanResponse(const DeviceAddress &,const AdvertisingData &,bool)172   std::vector<hci::CommandPacket> BuildSetScanResponse(const DeviceAddress&,
173                                                        const AdvertisingData&,
174                                                        bool) override {
175     hci::CommandPacket packet =
176         hci::CommandPacket::New<pwemb::LESetScanResponseDataCommandWriter>(
177             hci_spec::kLESetScanResponseData);
178 
179     std::vector<hci::CommandPacket> packets;
180     packets.push_back(std::move(packet));
181     return packets;
182   }
183 
BuildUnsetScanResponse(const DeviceAddress &,bool)184   hci::CommandPacket BuildUnsetScanResponse(const DeviceAddress&,
185                                             bool) override {
186     return hci::CommandPacket::New<pwemb::LESetScanResponseDataCommandWriter>(
187         hci_spec::kLESetScanResponseData);
188   }
189 
BuildRemoveAdvertisingSet(const DeviceAddress &,bool)190   hci::CommandPacket BuildRemoveAdvertisingSet(const DeviceAddress&,
191                                                bool) override {
192     return hci::CommandPacket::New<pwemb::LERemoveAdvertisingSetCommandWriter>(
193         hci_spec::kLERemoveAdvertisingSet);
194   }
195 
196   std::unordered_map<DeviceAddress, AdvertisementStatus>* ads_;
197   hci::Result<> pending_error_ = fit::ok();
198   hci::Transport::WeakPtr hci_;
199 
200   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(FakeLowEnergyAdvertiser);
201 };
202 
203 class LowEnergyAdvertisingManagerTest : public TestingBase {
204  public:
205   LowEnergyAdvertisingManagerTest() = default;
206   ~LowEnergyAdvertisingManagerTest() override = default;
207 
208  protected:
SetUp()209   void SetUp() override {
210     TestingBase::SetUp();
211     InitializeACLDataChannel();
212 
213     fake_address_delegate_.EnablePrivacy(true);
214     fake_address_delegate_.set_identity_address(kPublicAddress);
215     fake_address_delegate_.set_local_address(kRandomAddress);
216     MakeFakeAdvertiser();
217     MakeAdvertisingManager();
218   }
219 
TearDown()220   void TearDown() override {
221     adv_mgr_ = nullptr;
222     advertiser_ = nullptr;
223     TestingBase::TearDown();
224   }
225 
226   // Makes some fake advertising data of a specific |packed_size|
CreateFakeAdvertisingData(size_t packed_size=kDefaultFakeAdSize)227   AdvertisingData CreateFakeAdvertisingData(
228       size_t packed_size = kDefaultFakeAdSize) {
229     AdvertisingData result;
230     StaticByteBuffer buffer(
231         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08);
232     size_t bytes_left = packed_size;
233     while (bytes_left > 0) {
234       // Each field to take 10 bytes total, unless the next header (4 bytes)
235       // won't fit. In which case we add enough bytes to finish up.
236       size_t data_bytes = bytes_left < 14 ? (bytes_left - 4) : 6;
237       EXPECT_TRUE(result.SetManufacturerData(0xb000 + bytes_left,
238                                              buffer.view(0, data_bytes)));
239       bytes_left = packed_size - result.CalculateBlockSize();
240     }
241     return result;
242   }
243 
GetErrorCallback()244   LowEnergyAdvertisingManager::AdvertisingStatusCallback GetErrorCallback() {
245     return [this](AdvertisementInstance instance, hci::Result<> status) {
246       EXPECT_EQ(kInvalidAdvertisementId, instance.id());
247       EXPECT_TRUE(status.is_error());
248       last_status_ = status;
249     };
250   }
251 
GetSuccessCallback()252   LowEnergyAdvertisingManager::AdvertisingStatusCallback GetSuccessCallback() {
253     return [this](AdvertisementInstance instance, hci::Result<> status) {
254       EXPECT_NE(kInvalidAdvertisementId, instance.id());
255       EXPECT_EQ(fit::ok(), status);
256       last_instance_ = std::move(instance);
257       last_status_ = status;
258     };
259   }
260 
MakeFakeAdvertiser()261   void MakeFakeAdvertiser() {
262     advertiser_ = std::make_unique<FakeLowEnergyAdvertiser>(
263         transport()->GetWeakPtr(), &ad_store_);
264   }
265 
MakeAdvertisingManager()266   void MakeAdvertisingManager() {
267     adv_mgr_ = std::make_unique<LowEnergyAdvertisingManager>(
268         advertiser(), &fake_address_delegate_);
269   }
270 
adv_mgr() const271   LowEnergyAdvertisingManager* adv_mgr() const { return adv_mgr_.get(); }
ad_store()272   const std::unordered_map<DeviceAddress, AdvertisementStatus>& ad_store() {
273     return ad_store_;
274   }
last_ad_id() const275   AdvertisementId last_ad_id() const { return last_instance_.id(); }
276 
277   // Returns the currently active advertising state. This is useful for tests
278   // that want to verify advertising parameters when there is a single known
279   // advertisement. Returns nullptr if the number of advertisements are not
280   // equal to one.
current_adv() const281   const AdvertisementStatus* current_adv() const {
282     if (ad_store_.size() != 1u) {
283       return nullptr;
284     }
285     return &ad_store_.begin()->second;
286   }
287 
288   // Returns and clears the last callback status. This resets the state to
289   // detect another callback.
last_status()290   std::optional<hci::Result<>> last_status() { return last_status_; }
291 
advertiser() const292   FakeLowEnergyAdvertiser* advertiser() const { return advertiser_.get(); }
293 
294  private:
295   hci::FakeLocalAddressDelegate fake_address_delegate_{dispatcher()};
296 
297   // TODO(armansito): The address mapping is currently broken since the
298   // gap::LEAM always assigns the controller random address. Make this track
299   // each instance by instance ID instead once the layering issues have been
300   // fixed.
301   std::unordered_map<DeviceAddress, AdvertisementStatus> ad_store_;
302   AdvertisementInstance last_instance_;
303   std::optional<hci::Result<>> last_status_;
304   std::unique_ptr<FakeLowEnergyAdvertiser> advertiser_;
305   std::unique_ptr<LowEnergyAdvertisingManager> adv_mgr_;
306 
307   BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyAdvertisingManagerTest);
308 };
309 
310 // Tests:
311 //  - When the advertiser succeeds, the callback is called with the success
TEST_F(LowEnergyAdvertisingManagerTest,Success)312 TEST_F(LowEnergyAdvertisingManagerTest, Success) {
313   EXPECT_FALSE(adv_mgr()->advertising());
314   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
315                               AdvertisingData(),
316                               /*connect_callback=*/nullptr,
317                               kTestInterval,
318                               /*extended_pdu=*/false,
319                               /*anonymous=*/false,
320                               /*include_tx_power_level=*/false,
321                               /*address_type=*/std::nullopt,
322                               GetSuccessCallback());
323 
324   RunUntilIdle();
325 
326   EXPECT_TRUE(last_status());
327   ASSERT_EQ(1u, ad_store().size());
328   EXPECT_TRUE(adv_mgr()->advertising());
329 
330   // Verify that the advertiser uses the requested local address.
331   EXPECT_EQ(kRandomAddress, ad_store().begin()->first);
332 }
333 
TEST_F(LowEnergyAdvertisingManagerTest,DataSize)334 TEST_F(LowEnergyAdvertisingManagerTest, DataSize) {
335   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
336                               AdvertisingData(),
337                               /*connect_callback=*/nullptr,
338                               kTestInterval,
339                               /*extended_pdu=*/true,
340                               /*anonymous=*/false,
341                               /*include_tx_power_level=*/false,
342                               /*address_type=*/std::nullopt,
343                               GetSuccessCallback());
344 
345   RunUntilIdle();
346 
347   EXPECT_TRUE(last_status());
348   EXPECT_EQ(1u, ad_store().size());
349 
350   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(kDefaultMaxAdSize + 1),
351                               AdvertisingData(),
352                               /*connect_callback=*/nullptr,
353                               kTestInterval,
354                               /*extended_pdu=*/true,
355                               /*anonymous=*/false,
356                               /*include_tx_power_level=*/false,
357                               /*address_type=*/std::nullopt,
358                               GetErrorCallback());
359 
360   RunUntilIdle();
361 
362   EXPECT_TRUE(last_status());
363   EXPECT_EQ(1u, ad_store().size());
364 }
365 
366 // TODO: https://fxbug.dev/42083437 - Revise this test to use multiple
367 // advertising instances when multi-advertising is supported.
368 //  - Stopping one that is registered stops it in the advertiser
369 //    (and stops the right address)
370 //  - Stopping an advertisement that isn't registered returns false
TEST_F(LowEnergyAdvertisingManagerTest,RegisterUnregister)371 TEST_F(LowEnergyAdvertisingManagerTest, RegisterUnregister) {
372   EXPECT_FALSE(adv_mgr()->StopAdvertising(kInvalidAdvertisementId));
373 
374   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
375                               AdvertisingData(),
376                               /*connect_callback=*/nullptr,
377                               kTestInterval,
378                               /*extended_pdu=*/false,
379                               /*anonymous=*/false,
380                               /*include_tx_power_level=*/false,
381                               /*address_type=*/std::nullopt,
382                               GetSuccessCallback());
383 
384   RunUntilIdle();
385 
386   EXPECT_TRUE(last_status());
387   EXPECT_EQ(1u, ad_store().size());
388   EXPECT_TRUE(adv_mgr()->advertising());
389 
390   EXPECT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
391   EXPECT_TRUE(ad_store().empty());
392   EXPECT_FALSE(adv_mgr()->advertising());
393 
394   EXPECT_FALSE(adv_mgr()->StopAdvertising(last_ad_id()));
395   EXPECT_TRUE(ad_store().empty());
396 }
397 
398 //  - When the advertiser returns an error, we return an error
TEST_F(LowEnergyAdvertisingManagerTest,AdvertiserError)399 TEST_F(LowEnergyAdvertisingManagerTest, AdvertiserError) {
400   advertiser()->ErrorOnNext(
401       ToResult(pwemb::StatusCode::INVALID_HCI_COMMAND_PARAMETERS));
402 
403   EXPECT_FALSE(adv_mgr()->advertising());
404   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
405                               AdvertisingData(),
406                               /*connect_callback=*/nullptr,
407                               kTestInterval,
408                               /*extended_pdu=*/false,
409                               /*anonymous=*/false,
410                               /*include_tx_power_level=*/false,
411                               /*address_type=*/std::nullopt,
412                               GetErrorCallback());
413   RunUntilIdle();
414 
415   EXPECT_TRUE(last_status());
416   EXPECT_FALSE(adv_mgr()->advertising());
417 }
418 
419 //  - It calls the connectable callback correctly when connected to
TEST_F(LowEnergyAdvertisingManagerTest,ConnectCallback)420 TEST_F(LowEnergyAdvertisingManagerTest, ConnectCallback) {
421   std::unique_ptr<hci::LowEnergyConnection> link;
422   AdvertisementId advertised_id = kInvalidAdvertisementId;
423 
424   auto connect_cb = [&](AdvertisementId connected_id,
425                         std::unique_ptr<hci::LowEnergyConnection> cb_link) {
426     link = std::move(cb_link);
427     EXPECT_EQ(advertised_id, connected_id);
428   };
429   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
430                               AdvertisingData(),
431                               connect_cb,
432                               kTestInterval,
433                               /*extended_pdu=*/false,
434                               /*anonymous=*/false,
435                               /*include_tx_power_level=*/false,
436                               /*address_type=*/std::nullopt,
437                               GetSuccessCallback());
438 
439   RunUntilIdle();
440 
441   EXPECT_TRUE(last_status());
442   advertised_id = last_ad_id();
443 
444   DeviceAddress peer_address(DeviceAddress::Type::kLEPublic,
445                              {3, 2, 1, 1, 2, 3});
446   advertiser()->OnIncomingConnection(1,
447                                      pwemb::ConnectionRole::PERIPHERAL,
448                                      peer_address,
449                                      hci_spec::LEConnectionParameters());
450   RunUntilIdle();
451   ASSERT_TRUE(link);
452 
453   // Make sure that the link has the correct local and peer addresses
454   // assigned.
455   EXPECT_EQ(kRandomAddress, link->local_address());
456   EXPECT_EQ(peer_address, link->peer_address());
457 }
458 
459 //  - Error: Connectable and Anonymous at the same time
TEST_F(LowEnergyAdvertisingManagerTest,ConnectAdvertiseError)460 TEST_F(LowEnergyAdvertisingManagerTest, ConnectAdvertiseError) {
461   auto connect_cb = [](AdvertisementId,
462                        std::unique_ptr<hci::LowEnergyConnection>) {};
463 
464   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
465                               AdvertisingData(),
466                               connect_cb,
467                               kTestInterval,
468                               /*extended_pdu=*/false,
469                               /*anonymous=*/true,
470                               /*include_tx_power_level=*/false,
471                               /*address_type=*/std::nullopt,
472                               GetErrorCallback());
473 
474   EXPECT_TRUE(last_status());
475 }
476 
477 // Passes the values for the data on. (anonymous, data, scan_rsp)
TEST_F(LowEnergyAdvertisingManagerTest,SendsCorrectData)478 TEST_F(LowEnergyAdvertisingManagerTest, SendsCorrectData) {
479   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
480                               CreateFakeAdvertisingData(/*packed_size=*/21),
481                               /*connect_callback=*/nullptr,
482                               kTestInterval,
483                               /*extended_pdu=*/false,
484                               /*anonymous=*/false,
485                               /*include_tx_power_level=*/false,
486                               /*address_type=*/std::nullopt,
487                               GetSuccessCallback());
488 
489   RunUntilIdle();
490 
491   EXPECT_TRUE(last_status());
492   EXPECT_EQ(1u, ad_store().size());
493 
494   auto ad_status = &ad_store().begin()->second;
495 
496   AdvertisingData expected_ad = CreateFakeAdvertisingData();
497   AdvertisingData expected_scan_rsp =
498       CreateFakeAdvertisingData(/*packed_size=*/21);
499   EXPECT_EQ(expected_ad, ad_status->data);
500   EXPECT_EQ(expected_scan_rsp, ad_status->scan_rsp);
501   EXPECT_EQ(false, ad_status->anonymous);
502   EXPECT_EQ(nullptr, ad_status->connect_cb);
503 }
504 
505 // Test that the AdvertisingInterval values map to the spec defined constants
506 // (NOTE: this might change in the future in favor of a more advanced policy
507 // for managing the intervals; for now they get mapped to recommended values
508 // from Vol 3, Part C, Appendix A).
TEST_F(LowEnergyAdvertisingManagerTest,ConnectableAdvertisingIntervals)509 TEST_F(LowEnergyAdvertisingManagerTest, ConnectableAdvertisingIntervals) {
510   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
511                               CreateFakeAdvertisingData(/*packed_size=*/21),
512                               NopConnectCallback,
513                               AdvertisingInterval::FAST1,
514                               /*extended_pdu=*/false,
515                               /*anonymous=*/false,
516                               /*include_tx_power_level=*/false,
517                               /*address_type=*/std::nullopt,
518                               GetSuccessCallback());
519   RunUntilIdle();
520   ASSERT_TRUE(last_status());
521   ASSERT_TRUE(current_adv());
522   EXPECT_EQ(kLEAdvertisingFastIntervalMin1, current_adv()->interval_min);
523   EXPECT_EQ(kLEAdvertisingFastIntervalMax1, current_adv()->interval_max);
524   ASSERT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
525 
526   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
527                               CreateFakeAdvertisingData(/*packed_size=*/21),
528                               NopConnectCallback,
529                               AdvertisingInterval::FAST2,
530                               /*extended_pdu=*/false,
531                               /*anonymous=*/false,
532                               /*include_tx_power_level=*/false,
533                               /*address_type=*/std::nullopt,
534                               GetSuccessCallback());
535   RunUntilIdle();
536   ASSERT_TRUE(last_status());
537   ASSERT_TRUE(current_adv());
538   EXPECT_EQ(kLEAdvertisingFastIntervalMin2, current_adv()->interval_min);
539   EXPECT_EQ(kLEAdvertisingFastIntervalMax2, current_adv()->interval_max);
540   ASSERT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
541 
542   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
543                               CreateFakeAdvertisingData(/*packed_size=*/21),
544                               NopConnectCallback,
545                               AdvertisingInterval::SLOW,
546                               /*extended_pdu=*/false,
547                               /*anonymous=*/false,
548                               /*include_tx_power_level=*/false,
549                               /*address_type=*/std::nullopt,
550                               GetSuccessCallback());
551   RunUntilIdle();
552   ASSERT_TRUE(last_status());
553   ASSERT_TRUE(current_adv());
554   EXPECT_EQ(kLEAdvertisingSlowIntervalMin, current_adv()->interval_min);
555   EXPECT_EQ(kLEAdvertisingSlowIntervalMax, current_adv()->interval_max);
556   ASSERT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
557 }
558 
TEST_F(LowEnergyAdvertisingManagerTest,NonConnectableAdvertisingIntervals)559 TEST_F(LowEnergyAdvertisingManagerTest, NonConnectableAdvertisingIntervals) {
560   AdvertisingData fake_ad = CreateFakeAdvertisingData();
561   AdvertisingData scan_rsp = CreateFakeAdvertisingData(21 /* size of ad */);
562 
563   // We expect FAST1 to fall back to FAST2 due to specification recommendation
564   // (Vol 3, Part C, Appendix A) and lack of support for non-connectable
565   // advertising with FAST1 parameters on certain controllers.
566   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
567                               CreateFakeAdvertisingData(/*packed_size=*/21),
568                               /*connect_callback=*/nullptr,
569                               AdvertisingInterval::FAST1,
570                               /*extended_pdu=*/false,
571                               /*anonymous=*/false,
572                               /*include_tx_power_level=*/false,
573                               /*address_type=*/std::nullopt,
574                               GetSuccessCallback());
575   RunUntilIdle();
576   ASSERT_TRUE(last_status());
577   ASSERT_TRUE(current_adv());
578   EXPECT_EQ(kLEAdvertisingFastIntervalMin2, current_adv()->interval_min);
579   EXPECT_EQ(kLEAdvertisingFastIntervalMax2, current_adv()->interval_max);
580   ASSERT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
581 
582   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
583                               CreateFakeAdvertisingData(/*packed_size=*/21),
584                               /*connect_callback=*/nullptr,
585                               AdvertisingInterval::FAST2,
586                               /*extended_pdu=*/false,
587                               /*anonymous=*/false,
588                               /*include_tx_power_level=*/false,
589                               /*address_type=*/std::nullopt,
590                               GetSuccessCallback());
591   RunUntilIdle();
592   ASSERT_TRUE(last_status());
593   ASSERT_TRUE(current_adv());
594   EXPECT_EQ(kLEAdvertisingFastIntervalMin2, current_adv()->interval_min);
595   EXPECT_EQ(kLEAdvertisingFastIntervalMax2, current_adv()->interval_max);
596   ASSERT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
597 
598   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
599                               CreateFakeAdvertisingData(/*packed_size=*/21),
600                               /*connect_callback=*/nullptr,
601                               AdvertisingInterval::SLOW,
602                               /*extended_pdu=*/false,
603                               /*anonymous=*/false,
604                               /*include_tx_power_level=*/false,
605                               /*address_type=*/std::nullopt,
606                               GetSuccessCallback());
607   RunUntilIdle();
608   ASSERT_TRUE(last_status());
609   ASSERT_TRUE(current_adv());
610   EXPECT_EQ(kLEAdvertisingSlowIntervalMin, current_adv()->interval_min);
611   EXPECT_EQ(kLEAdvertisingSlowIntervalMax, current_adv()->interval_max);
612   ASSERT_TRUE(adv_mgr()->StopAdvertising(last_ad_id()));
613 }
614 
TEST_F(LowEnergyAdvertisingManagerTest,AdvertisePublicAddress)615 TEST_F(LowEnergyAdvertisingManagerTest, AdvertisePublicAddress) {
616   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
617                               CreateFakeAdvertisingData(/*packed_size=*/21),
618                               NopConnectCallback,
619                               AdvertisingInterval::FAST1,
620                               /*extended_pdu=*/false,
621                               /*anonymous=*/false,
622                               /*include_tx_power_level=*/false,
623                               DeviceAddress::Type::kLEPublic,
624                               GetSuccessCallback());
625   RunUntilIdle();
626   ASSERT_TRUE(last_status());
627   ASSERT_EQ(1u, ad_store().size());
628   EXPECT_TRUE(adv_mgr()->advertising());
629 
630   // Verify that the advertiser uses the requested local address.
631   EXPECT_EQ(kPublicAddress, ad_store().begin()->first);
632 }
633 
TEST_F(LowEnergyAdvertisingManagerTest,AdvertiseRandomAddress)634 TEST_F(LowEnergyAdvertisingManagerTest, AdvertiseRandomAddress) {
635   adv_mgr()->StartAdvertising(CreateFakeAdvertisingData(),
636                               CreateFakeAdvertisingData(/*packed_size=*/21),
637                               NopConnectCallback,
638                               AdvertisingInterval::FAST1,
639                               /*extended_pdu=*/false,
640                               /*anonymous=*/false,
641                               /*include_tx_power_level=*/false,
642                               /*address_type=*/std::nullopt,
643                               GetSuccessCallback());
644   RunUntilIdle();
645   ASSERT_TRUE(last_status());
646   ASSERT_EQ(1u, ad_store().size());
647   EXPECT_TRUE(adv_mgr()->advertising());
648 
649   // Verify that the advertiser uses the requested local address.
650   EXPECT_EQ(kRandomAddress, ad_store().begin()->first);
651 }
652 
TEST_F(LowEnergyAdvertisingManagerTest,DestroyingInstanceStopsAdvertisement)653 TEST_F(LowEnergyAdvertisingManagerTest, DestroyingInstanceStopsAdvertisement) {
654   {
655     AdvertisementInstance instance;
656     adv_mgr()->StartAdvertising(AdvertisingData(),
657                                 AdvertisingData(),
658                                 /*connect_callback=*/nullptr,
659                                 AdvertisingInterval::FAST1,
660                                 /*extended_pdu=*/false,
661                                 /*anonymous=*/false,
662                                 /*include_tx_power_level=*/false,
663                                 /*address_type=*/std::nullopt,
664                                 [&](AdvertisementInstance i, auto status) {
665                                   ASSERT_EQ(fit::ok(), status);
666                                   instance = std::move(i);
667                                 });
668     RunUntilIdle();
669     EXPECT_TRUE(adv_mgr()->advertising());
670 
671     // Destroying |instance| should stop the advertisement.
672   }
673 
674   RunUntilIdle();
675   EXPECT_FALSE(adv_mgr()->advertising());
676 }
677 
TEST_F(LowEnergyAdvertisingManagerTest,MovingIntoInstanceStopsAdvertisement)678 TEST_F(LowEnergyAdvertisingManagerTest, MovingIntoInstanceStopsAdvertisement) {
679   AdvertisementInstance instance;
680   adv_mgr()->StartAdvertising(AdvertisingData(),
681                               AdvertisingData(),
682                               /*connect_callback=*/nullptr,
683                               AdvertisingInterval::FAST1,
684                               /*extended_pdu=*/false,
685                               /*anonymous=*/false,
686                               /*include_tx_power_level=*/false,
687                               /*address_type=*/std::nullopt,
688                               [&](AdvertisementInstance i, auto status) {
689                                 ASSERT_EQ(fit::ok(), status);
690                                 instance = std::move(i);
691                               });
692   RunUntilIdle();
693   EXPECT_TRUE(adv_mgr()->advertising());
694 
695   // Destroying |instance| by invoking the move assignment operator should
696   // stop the advertisement.
697   instance = {};
698   RunUntilIdle();
699   EXPECT_FALSE(adv_mgr()->advertising());
700 }
701 
TEST_F(LowEnergyAdvertisingManagerTest,MovingInstanceTransfersOwnershipOfAdvertisement)702 TEST_F(LowEnergyAdvertisingManagerTest,
703        MovingInstanceTransfersOwnershipOfAdvertisement) {
704   auto instance = std::make_unique<AdvertisementInstance>();
705   adv_mgr()->StartAdvertising(AdvertisingData(),
706                               AdvertisingData(),
707                               /*connect_callback=*/nullptr,
708                               AdvertisingInterval::FAST1,
709                               /*extended_pdu=*/false,
710                               /*anonymous=*/false,
711                               /*include_tx_power_level=*/false,
712                               /*address_type=*/std::nullopt,
713                               [&](AdvertisementInstance i, auto status) {
714                                 ASSERT_EQ(fit::ok(), status);
715                                 *instance = std::move(i);
716                               });
717   RunUntilIdle();
718   EXPECT_TRUE(adv_mgr()->advertising());
719 
720   // Moving |instance| should transfer the ownership of the advertisement
721   // (assignment).
722   {
723     AdvertisementInstance move_assigned_instance = std::move(*instance);
724 
725     // Explicitly clearing the old instance should have no effect.
726     *instance = {};
727     RunUntilIdle();
728     EXPECT_TRUE(adv_mgr()->advertising());
729 
730     *instance = std::move(move_assigned_instance);
731   }
732 
733   // Advertisement should not stop when |move_assigned_instance| goes out of
734   // scope as it no longer owns the advertisement.
735   RunUntilIdle();
736   EXPECT_TRUE(adv_mgr()->advertising());
737 
738   // Moving |instance| should transfer the ownership of the advertisement
739   // (move-constructor).
740   {
741     AdvertisementInstance move_constructed_instance(std::move(*instance));
742 
743     // Explicitly destroying the old instance should have no effect.
744     instance.reset();
745     RunUntilIdle();
746     EXPECT_TRUE(adv_mgr()->advertising());
747   }
748 
749   // Advertisement should stop when |move_constructed_instance| goes out of
750   // scope.
751   RunUntilIdle();
752   EXPECT_FALSE(adv_mgr()->advertising());
753 }
754 
755 }  // namespace
756 }  // namespace gap
757 }  // namespace bt
758