1 /*
2  * Copyright 2020 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #define LOG_TAG "bt_shim_advertiser"
18 
19 #include "le_advertising_manager.h"
20 
21 #include <bluetooth/log.h>
22 #include <com_android_bluetooth_flags.h>
23 #include <hardware/bluetooth.h>
24 #include <hardware/bt_gatt.h>
25 
26 #include <vector>
27 
28 #include "btif/include/btif_common.h"
29 #include "hci/le_advertising_manager.h"
30 #include "main/shim/entry.h"
31 #include "main/shim/helpers.h"
32 #include "stack/include/btm_log_history.h"
33 #include "stack/include/main_thread.h"
34 #include "types/raw_address.h"
35 #include "utils.h"
36 
37 using bluetooth::hci::Address;
38 using bluetooth::hci::AddressType;
39 using bluetooth::hci::AdvertiserAddressType;
40 using bluetooth::hci::ErrorCode;
41 using bluetooth::hci::GapData;
42 using bluetooth::shim::parse_gap_data;
43 using std::vector;
44 using namespace bluetooth;
45 
46 namespace {
47 constexpr char kBtmLogTag[] = "ADV";
48 }
49 
50 class BleAdvertiserInterfaceImpl : public ::BleAdvertiserInterface,
51                                    public bluetooth::hci::AdvertisingCallback {
52 public:
~BleAdvertiserInterfaceImpl()53   ~BleAdvertiserInterfaceImpl() override {}
54 
Init()55   void Init() {
56     // Register callback
57     bluetooth::shim::GetAdvertising()->RegisterAdvertisingCallback(this);
58   }
59 
60   // ::BleAdvertiserInterface
RegisterAdvertiser(IdStatusCallback cb)61   void RegisterAdvertiser(IdStatusCallback cb) override {
62     log::info("in shim layer");
63 
64     bluetooth::shim::GetAdvertising()->RegisterAdvertiser(
65             bluetooth::shim::GetGdShimHandler()->BindOnce(
66                     [](::BleAdvertiserInterface::IdStatusCallback cb, uint8_t id,
67                        AdvertisingCallback::AdvertisingStatus status) {
68                       do_in_main_thread(base::BindOnce(
69                               [](::BleAdvertiserInterface::IdStatusCallback cb, uint8_t id,
70                                  AdvertisingCallback::AdvertisingStatus status) {
71                                 cb.Run(id, static_cast<uint8_t>(status));
72                               },
73                               cb, id, status));
74                     },
75                     cb));
76   }
77 
78   // ::BleAdvertiserInterface
Unregister(uint8_t advertiser_id)79   void Unregister(uint8_t advertiser_id) override {
80     log::info("in shim layer");
81     bluetooth::shim::GetAdvertising()->RemoveAdvertiser(advertiser_id);
82     int reg_id = bluetooth::shim::GetAdvertising()->GetAdvertiserRegId(advertiser_id);
83     uint8_t client_id = is_native_advertiser(reg_id);
84     // if registered by native client, remove the register id
85     if (client_id != kAdvertiserClientIdJni) {
86       native_reg_id_map[client_id].erase(reg_id);
87     }
88     BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Le advert stopped",
89                    base::StringPrintf("advert_id:%d", advertiser_id));
90   }
91 
92   // ::BleAdvertiserInterface
GetOwnAddress(uint8_t advertiser_id,::BleAdvertiserInterface::GetAddressCallback cb)93   void GetOwnAddress(uint8_t advertiser_id,
94                      ::BleAdvertiserInterface::GetAddressCallback cb) override {
95     log::info("in shim layer");
96     address_callbacks_[advertiser_id] = jni_thread_wrapper(cb);
97     bluetooth::shim::GetAdvertising()->GetOwnAddress(advertiser_id);
98   }
99 
100   // ::BleAdvertiserInterface
SetParameters(uint8_t advertiser_id,::AdvertiseParameters params,::BleAdvertiserInterface::ParametersCallback)101   void SetParameters(uint8_t advertiser_id, ::AdvertiseParameters params,
102                      ::BleAdvertiserInterface::ParametersCallback /* cb */) override {
103     log::info("in shim layer");
104     bluetooth::hci::AdvertisingConfig config{};
105     parse_parameter(config, params);
106     bluetooth::shim::GetAdvertising()->SetParameters(advertiser_id, config);
107   }
108 
109   // ::BleAdvertiserInterface
SetData(int advertiser_id,bool set_scan_rsp,vector<uint8_t> data,::BleAdvertiserInterface::StatusCallback)110   void SetData(int advertiser_id, bool set_scan_rsp, vector<uint8_t> data,
111                ::BleAdvertiserInterface::StatusCallback /* cb */) override {
112     log::info("in shim layer");
113     std::vector<GapData> advertising_data = {};
114     parse_gap_data(data, advertising_data);
115     bluetooth::shim::GetAdvertising()->SetData(advertiser_id, set_scan_rsp, advertising_data);
116   }
117 
118   // ::BleAdvertiserInterface
Enable(uint8_t advertiser_id,bool enable,::BleAdvertiserInterface::StatusCallback,uint16_t duration,uint8_t maxExtAdvEvents,::BleAdvertiserInterface::StatusCallback)119   void Enable(uint8_t advertiser_id, bool enable, ::BleAdvertiserInterface::StatusCallback /* cb */,
120               uint16_t duration, uint8_t maxExtAdvEvents,
121               ::BleAdvertiserInterface::StatusCallback /* timeout_cb */) override {
122     log::info("in shim layer");
123     bluetooth::shim::GetAdvertising()->EnableAdvertiser(advertiser_id, enable, duration,
124                                                         maxExtAdvEvents);
125   }
126 
127   // nobody use this function
128   // ::BleAdvertiserInterface
StartAdvertising(uint8_t advertiser_id,::BleAdvertiserInterface::StatusCallback cb,::AdvertiseParameters params,std::vector<uint8_t> advertise_data,std::vector<uint8_t> scan_response_data,int timeout_s,::BleAdvertiserInterface::StatusCallback timeout_cb)129   void StartAdvertising(uint8_t advertiser_id, ::BleAdvertiserInterface::StatusCallback cb,
130                         ::AdvertiseParameters params, std::vector<uint8_t> advertise_data,
131                         std::vector<uint8_t> scan_response_data, int timeout_s,
132                         ::BleAdvertiserInterface::StatusCallback timeout_cb) override {
133     log::info("in shim layer");
134 
135     bluetooth::hci::AdvertisingConfig config{};
136     parse_parameter(config, params);
137 
138     parse_gap_data(advertise_data, config.advertisement);
139     parse_gap_data(scan_response_data, config.scan_response);
140 
141     bluetooth::shim::GetAdvertising()->StartAdvertising(
142             advertiser_id, config, timeout_s * 100, cb, timeout_cb, scan_callback,
143             set_terminated_callback, bluetooth::shim::GetGdShimHandler());
144   }
145 
146   // ::BleAdvertiserInterface
StartAdvertisingSet(uint8_t client_id,int reg_id,::BleAdvertiserInterface::IdTxPowerStatusCallback,::AdvertiseParameters params,std::vector<uint8_t> advertise_data,std::vector<uint8_t> scan_response_data,::PeriodicAdvertisingParameters periodic_params,std::vector<uint8_t> periodic_data,uint16_t duration,uint8_t maxExtAdvEvents,::BleAdvertiserInterface::IdStatusCallback)147   void StartAdvertisingSet(uint8_t client_id, int reg_id,
148                            ::BleAdvertiserInterface::IdTxPowerStatusCallback /* register_cb */,
149                            ::AdvertiseParameters params, std::vector<uint8_t> advertise_data,
150                            std::vector<uint8_t> scan_response_data,
151                            ::PeriodicAdvertisingParameters periodic_params,
152                            std::vector<uint8_t> periodic_data, uint16_t duration,
153                            uint8_t maxExtAdvEvents,
154                            ::BleAdvertiserInterface::IdStatusCallback /* timeout_cb */) override {
155     log::info("in shim layer");
156 
157     bluetooth::hci::AdvertisingConfig config{};
158     parse_parameter(config, params);
159     parse_periodic_advertising_parameter(config.periodic_advertising_parameters, periodic_params);
160 
161     parse_gap_data(advertise_data, config.advertisement);
162     parse_gap_data(scan_response_data, config.scan_response);
163     parse_gap_data(periodic_data, config.periodic_data);
164 
165     // if registered by native client, add the register id
166     if (client_id != kAdvertiserClientIdJni) {
167       native_reg_id_map[client_id].insert(reg_id);
168     }
169 
170     bluetooth::shim::GetAdvertising()->ExtendedCreateAdvertiser(
171             client_id, reg_id, config, scan_callback, set_terminated_callback, duration,
172             maxExtAdvEvents, bluetooth::shim::GetGdShimHandler());
173 
174     log::info("create advertising set, client_id:{}, reg_id:{}", client_id, reg_id);
175     BTM_LogHistory(kBtmLogTag, RawAddress::kEmpty, "Le advert started",
176                    base::StringPrintf("reg_id:%d", reg_id));
177 
178     return;
179   }
180 
181   // ::BleAdvertiserInterface
SetPeriodicAdvertisingParameters(int advertiser_id,::PeriodicAdvertisingParameters periodic_params,::BleAdvertiserInterface::StatusCallback)182   void SetPeriodicAdvertisingParameters(
183           int advertiser_id, ::PeriodicAdvertisingParameters periodic_params,
184           ::BleAdvertiserInterface::StatusCallback /* cb */) override {
185     log::info("in shim layer");
186     bluetooth::hci::PeriodicAdvertisingParameters parameters;
187     parameters.max_interval = periodic_params.max_interval;
188     parameters.min_interval = periodic_params.min_interval;
189     parameters.properties = periodic_params.periodic_advertising_properties;
190     bluetooth::shim::GetAdvertising()->SetPeriodicParameters(advertiser_id, parameters);
191   }
192 
193   // ::BleAdvertiserInterface
SetPeriodicAdvertisingData(int advertiser_id,std::vector<uint8_t> data,::BleAdvertiserInterface::StatusCallback)194   void SetPeriodicAdvertisingData(int advertiser_id, std::vector<uint8_t> data,
195                                   ::BleAdvertiserInterface::StatusCallback /* cb */) override {
196     log::info("in shim layer");
197     std::vector<GapData> advertising_data = {};
198     parse_gap_data(data, advertising_data);
199     bluetooth::shim::GetAdvertising()->SetPeriodicData(advertiser_id, advertising_data);
200   }
201 
202   // ::BleAdvertiserInterface
SetPeriodicAdvertisingEnable(int advertiser_id,bool enable,bool include_adi,::BleAdvertiserInterface::StatusCallback)203   void SetPeriodicAdvertisingEnable(int advertiser_id, bool enable, bool include_adi,
204                                     ::BleAdvertiserInterface::StatusCallback /* cb */) override {
205     log::info("in shim layer");
206     bluetooth::shim::GetAdvertising()->EnablePeriodicAdvertising(advertiser_id, enable,
207                                                                  include_adi);
208   }
209 
210   // ::BleAdvertiserInterface
RegisterCallbacks(::AdvertisingCallbacks * callbacks)211   void RegisterCallbacks(::AdvertisingCallbacks* callbacks) override {
212     advertising_callbacks_ = callbacks;
213   }
214 
215   // ::BleAdvertiserInterface
RegisterCallbacksNative(::AdvertisingCallbacks * callbacks,uint8_t client_id)216   void RegisterCallbacksNative(::AdvertisingCallbacks* callbacks, uint8_t client_id) override {
217     native_adv_callbacks_map_[client_id] = callbacks;
218   }
219 
on_scan(Address,AddressType)220   void on_scan(Address /* address */, AddressType /* address_type */) {
221     log::info("in shim layer");
222   }
223 
on_set_terminated(ErrorCode,uint8_t,uint8_t)224   void on_set_terminated(ErrorCode /* error_code */, uint8_t, uint8_t) {
225     log::info("in shim layer");
226   }
227 
228   const bluetooth::common::Callback<void(Address, AddressType)> scan_callback =
229           bluetooth::common::Bind(&BleAdvertiserInterfaceImpl::on_scan,
230                                   bluetooth::common::Unretained(this));
231 
232   const bluetooth::common::Callback<void(ErrorCode, uint8_t, uint8_t)> set_terminated_callback =
233           bluetooth::common::Bind(&BleAdvertiserInterfaceImpl::on_set_terminated,
234                                   bluetooth::common::Unretained(this));
235 
236   // bluetooth::hci::AdvertisingCallback
OnAdvertisingSetStarted(int reg_id,uint8_t advertiser_id,int8_t tx_power,AdvertisingCallback::AdvertisingStatus status)237   void OnAdvertisingSetStarted(int reg_id, uint8_t advertiser_id, int8_t tx_power,
238                                AdvertisingCallback::AdvertisingStatus status) override {
239     uint8_t client_id = is_native_advertiser(reg_id);
240     if (client_id != kAdvertiserClientIdJni) {
241       // Invoke callback for native client
242       do_in_main_thread(base::Bind(&::AdvertisingCallbacks::OnAdvertisingSetStarted,
243                                    base::Unretained(native_adv_callbacks_map_[client_id]), reg_id,
244                                    advertiser_id, tx_power, status));
245       return;
246     }
247     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnAdvertisingSetStarted,
248                                     base::Unretained(advertising_callbacks_), reg_id, advertiser_id,
249                                     tx_power, status));
250   }
251 
252   // bluetooth::hci::AdvertisingCallback
OnAdvertisingEnabled(uint8_t advertiser_id,bool enable,AdvertisingCallback::AdvertisingStatus status)253   void OnAdvertisingEnabled(uint8_t advertiser_id, bool enable,
254                             AdvertisingCallback::AdvertisingStatus status) override {
255     int reg_id = bluetooth::shim::GetAdvertising()->GetAdvertiserRegId(advertiser_id);
256     uint8_t client_id = is_native_advertiser(reg_id);
257     if (client_id != kAdvertiserClientIdJni) {
258       // Invoke callback for native client
259       do_in_main_thread(base::Bind(&::AdvertisingCallbacks::OnAdvertisingEnabled,
260                                    base::Unretained(native_adv_callbacks_map_[client_id]),
261                                    advertiser_id, enable, status));
262       return;
263     }
264     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnAdvertisingEnabled,
265                                     base::Unretained(advertising_callbacks_), advertiser_id, enable,
266                                     status));
267   }
268 
269   // bluetooth::hci::AdvertisingCallback
OnAdvertisingDataSet(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)270   void OnAdvertisingDataSet(uint8_t advertiser_id,
271                             AdvertisingCallback::AdvertisingStatus status) override {
272     if (com::android::bluetooth::flags::leaudio_broadcast_update_metadata_callback()) {
273       int reg_id = bluetooth::shim::GetAdvertising()->GetAdvertiserRegId(advertiser_id);
274       uint8_t client_id = is_native_advertiser(reg_id);
275       if (client_id != kAdvertiserClientIdJni) {
276         // Invoke callback for native client
277         do_in_main_thread(base::Bind(&::AdvertisingCallbacks::OnAdvertisingDataSet,
278                                      base::Unretained(native_adv_callbacks_map_[client_id]),
279                                      advertiser_id, status));
280         return;
281       }
282     }
283     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnAdvertisingDataSet,
284                                     base::Unretained(advertising_callbacks_), advertiser_id,
285                                     status));
286   }
287 
288   // bluetooth::hci::AdvertisingCallback
OnScanResponseDataSet(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)289   void OnScanResponseDataSet(uint8_t advertiser_id,
290                              AdvertisingCallback::AdvertisingStatus status) override {
291     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnScanResponseDataSet,
292                                     base::Unretained(advertising_callbacks_), advertiser_id,
293                                     status));
294   }
295 
296   // bluetooth::hci::AdvertisingCallback
OnAdvertisingParametersUpdated(uint8_t advertiser_id,int8_t tx_power,AdvertisingCallback::AdvertisingStatus status)297   void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t tx_power,
298                                       AdvertisingCallback::AdvertisingStatus status) override {
299     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnAdvertisingParametersUpdated,
300                                     base::Unretained(advertising_callbacks_), advertiser_id,
301                                     tx_power, status));
302   }
303 
304   // bluetooth::hci::AdvertisingCallback
OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)305   void OnPeriodicAdvertisingParametersUpdated(
306           uint8_t advertiser_id, AdvertisingCallback::AdvertisingStatus status) override {
307     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnPeriodicAdvertisingParametersUpdated,
308                                     base::Unretained(advertising_callbacks_), advertiser_id,
309                                     status));
310   }
311 
312   // bluetooth::hci::AdvertisingCallback
OnPeriodicAdvertisingDataSet(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)313   void OnPeriodicAdvertisingDataSet(uint8_t advertiser_id,
314                                     AdvertisingCallback::AdvertisingStatus status) override {
315     if (com::android::bluetooth::flags::leaudio_broadcast_update_metadata_callback()) {
316       int reg_id = bluetooth::shim::GetAdvertising()->GetAdvertiserRegId(advertiser_id);
317       uint8_t client_id = is_native_advertiser(reg_id);
318       if (client_id != kAdvertiserClientIdJni) {
319         // Invoke callback for native client
320         do_in_main_thread(base::Bind(&::AdvertisingCallbacks::OnPeriodicAdvertisingDataSet,
321                                      base::Unretained(native_adv_callbacks_map_[client_id]),
322                                      advertiser_id, status));
323         return;
324       }
325     }
326     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnPeriodicAdvertisingDataSet,
327                                     base::Unretained(advertising_callbacks_), advertiser_id,
328                                     status));
329   }
330 
331   // bluetooth::hci::AdvertisingCallback
OnPeriodicAdvertisingEnabled(uint8_t advertiser_id,bool enable,AdvertisingCallback::AdvertisingStatus status)332   void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool enable,
333                                     AdvertisingCallback::AdvertisingStatus status) override {
334     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnPeriodicAdvertisingEnabled,
335                                     base::Unretained(advertising_callbacks_), advertiser_id, enable,
336                                     status));
337   }
338 
339   // bluetooth::hci::AdvertisingCallback
OnOwnAddressRead(uint8_t advertiser_id,uint8_t address_type,Address address)340   void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type, Address address) override {
341     RawAddress raw_address = bluetooth::ToRawAddress(address);
342     if (address_callbacks_.find(advertiser_id) != address_callbacks_.end()) {
343       address_callbacks_[advertiser_id].Run(address_type, raw_address);
344       address_callbacks_.erase(advertiser_id);
345       return;
346     }
347     do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnOwnAddressRead,
348                                     base::Unretained(advertising_callbacks_), advertiser_id,
349                                     address_type, raw_address));
350   }
351 
352   ::AdvertisingCallbacks* advertising_callbacks_;
353   std::map<uint8_t, ::AdvertisingCallbacks*> native_adv_callbacks_map_;
354 
355 private:
356   // Convert ble advertising parameters into implemented configuration parameters
parse_parameter(bluetooth::hci::AdvertisingConfig & config,::AdvertiseParameters params)357   void parse_parameter(bluetooth::hci::AdvertisingConfig& config, ::AdvertiseParameters params) {
358     config.connectable = params.advertising_event_properties & 0x01;
359     config.scannable = params.advertising_event_properties & 0x02;
360     config.directed = params.advertising_event_properties & 0x04;
361     config.high_duty_cycle = params.advertising_event_properties & 0x08;
362     config.legacy_pdus = params.advertising_event_properties & 0x10;
363     config.anonymous = params.advertising_event_properties & 0x20;
364     config.include_tx_power = params.advertising_event_properties & 0x40;
365     config.discoverable = params.discoverable;
366     config.interval_min = params.min_interval;
367     config.interval_max = params.max_interval;
368     config.channel_map = params.channel_map;
369     config.tx_power = params.tx_power;
370     config.use_le_coded_phy = params.primary_advertising_phy == 0x03;
371     config.secondary_advertising_phy =
372             static_cast<bluetooth::hci::SecondaryPhyType>(params.secondary_advertising_phy);
373     config.enable_scan_request_notifications =
374             static_cast<bluetooth::hci::Enable>(params.scan_request_notification_enable);
375     config.peer_address = bluetooth::ToGdAddress(params.peer_address);
376     // Matching the ADDRESS_TYPE_* enums from Java
377     switch (params.own_address_type) {
378       case -1:
379         config.requested_advertiser_address_type = AdvertiserAddressType::RESOLVABLE_RANDOM;
380         break;
381       case 0:
382         config.requested_advertiser_address_type = AdvertiserAddressType::PUBLIC;
383         break;
384       case 1:
385         config.requested_advertiser_address_type = AdvertiserAddressType::RESOLVABLE_RANDOM;
386         break;
387       case 2:
388         config.requested_advertiser_address_type = AdvertiserAddressType::NONRESOLVABLE_RANDOM;
389         break;
390       default:
391         log::error("Received unexpected address type: {}", params.own_address_type);
392         config.requested_advertiser_address_type = AdvertiserAddressType::RESOLVABLE_RANDOM;
393     }
394     switch (params.peer_address_type) {
395       case 0:
396         config.peer_address_type =
397                 bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS;
398         break;
399       case 1:
400         config.peer_address_type =
401                 bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS;
402         break;
403       default:
404         log::error("Received unexpected peer address type: {}", params.peer_address_type);
405     }
406   }
407 
408   // Convert ble periodic advertising parameters into implemented configuration parameters
parse_periodic_advertising_parameter(bluetooth::hci::PeriodicAdvertisingParameters & config,::PeriodicAdvertisingParameters periodic_params)409   void parse_periodic_advertising_parameter(bluetooth::hci::PeriodicAdvertisingParameters& config,
410                                             ::PeriodicAdvertisingParameters periodic_params) {
411     config.max_interval = periodic_params.max_interval;
412     config.min_interval = periodic_params.min_interval;
413     config.properties = periodic_params.periodic_advertising_properties;
414     config.enable = periodic_params.enable;
415     config.include_adi = periodic_params.include_adi;
416   }
417 
is_native_advertiser(int reg_id)418   uint8_t is_native_advertiser(int reg_id) {
419     // Return client id if it's native advertiser, otherwise return jni id as
420     // default
421     for (auto const& entry : native_adv_callbacks_map_) {
422       if (native_reg_id_map[entry.first].count(reg_id)) {
423         return entry.first;
424       }
425     }
426     return kAdvertiserClientIdJni;
427   }
428 
429   std::map<uint8_t, ::BleAdvertiserInterface::GetAddressCallback> address_callbacks_;
430   std::map<uint8_t, std::set<int>> native_reg_id_map;
431 };
432 
433 BleAdvertiserInterfaceImpl* bt_le_advertiser_instance = nullptr;
434 
get_ble_advertiser_instance()435 ::BleAdvertiserInterface* bluetooth::shim::get_ble_advertiser_instance() {
436   if (bt_le_advertiser_instance == nullptr) {
437     bt_le_advertiser_instance = new BleAdvertiserInterfaceImpl();
438   }
439   return bt_le_advertiser_instance;
440 }
441 
init_advertising_manager()442 void bluetooth::shim::init_advertising_manager() {
443   static_cast<BleAdvertiserInterfaceImpl*>(bluetooth::shim::get_ble_advertiser_instance())->Init();
444 }
445