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