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 std::format("advert_id:{}", 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 std::format("reg_id:{}", 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 int reg_id = bluetooth::shim::GetAdvertising()->GetAdvertiserRegId(advertiser_id);
273 uint8_t client_id = is_native_advertiser(reg_id);
274 if (client_id != kAdvertiserClientIdJni) {
275 // Invoke callback for native client
276 do_in_main_thread(base::Bind(&::AdvertisingCallbacks::OnAdvertisingDataSet,
277 base::Unretained(native_adv_callbacks_map_[client_id]),
278 advertiser_id, status));
279 return;
280 }
281 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnAdvertisingDataSet,
282 base::Unretained(advertising_callbacks_), advertiser_id,
283 status));
284 }
285
286 // bluetooth::hci::AdvertisingCallback
OnScanResponseDataSet(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)287 void OnScanResponseDataSet(uint8_t advertiser_id,
288 AdvertisingCallback::AdvertisingStatus status) override {
289 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnScanResponseDataSet,
290 base::Unretained(advertising_callbacks_), advertiser_id,
291 status));
292 }
293
294 // bluetooth::hci::AdvertisingCallback
OnAdvertisingParametersUpdated(uint8_t advertiser_id,int8_t tx_power,AdvertisingCallback::AdvertisingStatus status)295 void OnAdvertisingParametersUpdated(uint8_t advertiser_id, int8_t tx_power,
296 AdvertisingCallback::AdvertisingStatus status) override {
297 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnAdvertisingParametersUpdated,
298 base::Unretained(advertising_callbacks_), advertiser_id,
299 tx_power, status));
300 }
301
302 // bluetooth::hci::AdvertisingCallback
OnPeriodicAdvertisingParametersUpdated(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)303 void OnPeriodicAdvertisingParametersUpdated(
304 uint8_t advertiser_id, AdvertisingCallback::AdvertisingStatus status) override {
305 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnPeriodicAdvertisingParametersUpdated,
306 base::Unretained(advertising_callbacks_), advertiser_id,
307 status));
308 }
309
310 // bluetooth::hci::AdvertisingCallback
OnPeriodicAdvertisingDataSet(uint8_t advertiser_id,AdvertisingCallback::AdvertisingStatus status)311 void OnPeriodicAdvertisingDataSet(uint8_t advertiser_id,
312 AdvertisingCallback::AdvertisingStatus status) override {
313 int reg_id = bluetooth::shim::GetAdvertising()->GetAdvertiserRegId(advertiser_id);
314 uint8_t client_id = is_native_advertiser(reg_id);
315 if (client_id != kAdvertiserClientIdJni) {
316 // Invoke callback for native client
317 do_in_main_thread(base::Bind(&::AdvertisingCallbacks::OnPeriodicAdvertisingDataSet,
318 base::Unretained(native_adv_callbacks_map_[client_id]),
319 advertiser_id, status));
320 return;
321 }
322 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnPeriodicAdvertisingDataSet,
323 base::Unretained(advertising_callbacks_), advertiser_id,
324 status));
325 }
326
327 // bluetooth::hci::AdvertisingCallback
OnPeriodicAdvertisingEnabled(uint8_t advertiser_id,bool enable,AdvertisingCallback::AdvertisingStatus status)328 void OnPeriodicAdvertisingEnabled(uint8_t advertiser_id, bool enable,
329 AdvertisingCallback::AdvertisingStatus status) override {
330 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnPeriodicAdvertisingEnabled,
331 base::Unretained(advertising_callbacks_), advertiser_id, enable,
332 status));
333 }
334
335 // bluetooth::hci::AdvertisingCallback
OnOwnAddressRead(uint8_t advertiser_id,uint8_t address_type,Address address)336 void OnOwnAddressRead(uint8_t advertiser_id, uint8_t address_type, Address address) override {
337 RawAddress raw_address = bluetooth::ToRawAddress(address);
338 if (address_callbacks_.find(advertiser_id) != address_callbacks_.end()) {
339 address_callbacks_[advertiser_id].Run(address_type, raw_address);
340 address_callbacks_.erase(advertiser_id);
341 return;
342 }
343 do_in_jni_thread(base::BindOnce(&::AdvertisingCallbacks::OnOwnAddressRead,
344 base::Unretained(advertising_callbacks_), advertiser_id,
345 address_type, raw_address));
346 }
347
348 ::AdvertisingCallbacks* advertising_callbacks_;
349 std::map<uint8_t, ::AdvertisingCallbacks*> native_adv_callbacks_map_;
350
351 private:
352 // Convert ble advertising parameters into implemented configuration parameters
parse_parameter(bluetooth::hci::AdvertisingConfig & config,::AdvertiseParameters params)353 void parse_parameter(bluetooth::hci::AdvertisingConfig& config, ::AdvertiseParameters params) {
354 config.connectable = params.advertising_event_properties & 0x01;
355 config.scannable = params.advertising_event_properties & 0x02;
356 config.directed = params.advertising_event_properties & 0x04;
357 config.high_duty_cycle = params.advertising_event_properties & 0x08;
358 config.legacy_pdus = params.advertising_event_properties & 0x10;
359 config.anonymous = params.advertising_event_properties & 0x20;
360 config.include_tx_power = params.advertising_event_properties & 0x40;
361 config.discoverable = params.discoverable;
362 config.interval_min = params.min_interval;
363 config.interval_max = params.max_interval;
364 config.channel_map = params.channel_map;
365 config.tx_power = params.tx_power;
366 config.use_le_coded_phy = params.primary_advertising_phy == 0x03;
367 config.secondary_advertising_phy =
368 static_cast<bluetooth::hci::SecondaryPhyType>(params.secondary_advertising_phy);
369 config.enable_scan_request_notifications =
370 static_cast<bluetooth::hci::Enable>(params.scan_request_notification_enable);
371 config.peer_address = bluetooth::ToGdAddress(params.peer_address);
372 // Matching the ADDRESS_TYPE_* enums from Java
373 switch (params.own_address_type) {
374 case -1:
375 config.requested_advertiser_address_type = AdvertiserAddressType::RESOLVABLE_RANDOM;
376 break;
377 case 0:
378 config.requested_advertiser_address_type = AdvertiserAddressType::PUBLIC;
379 break;
380 case 1:
381 config.requested_advertiser_address_type = AdvertiserAddressType::RESOLVABLE_RANDOM;
382 break;
383 case 2:
384 config.requested_advertiser_address_type = AdvertiserAddressType::NONRESOLVABLE_RANDOM;
385 break;
386 default:
387 log::error("Received unexpected address type: {}", params.own_address_type);
388 config.requested_advertiser_address_type = AdvertiserAddressType::RESOLVABLE_RANDOM;
389 }
390 switch (params.peer_address_type) {
391 case 0:
392 config.peer_address_type =
393 bluetooth::hci::PeerAddressType::PUBLIC_DEVICE_OR_IDENTITY_ADDRESS;
394 break;
395 case 1:
396 config.peer_address_type =
397 bluetooth::hci::PeerAddressType::RANDOM_DEVICE_OR_IDENTITY_ADDRESS;
398 break;
399 default:
400 log::error("Received unexpected peer address type: {}", params.peer_address_type);
401 }
402 }
403
404 // Convert ble periodic advertising parameters into implemented configuration parameters
parse_periodic_advertising_parameter(bluetooth::hci::PeriodicAdvertisingParameters & config,::PeriodicAdvertisingParameters periodic_params)405 void parse_periodic_advertising_parameter(bluetooth::hci::PeriodicAdvertisingParameters& config,
406 ::PeriodicAdvertisingParameters periodic_params) {
407 config.max_interval = periodic_params.max_interval;
408 config.min_interval = periodic_params.min_interval;
409 config.properties = periodic_params.periodic_advertising_properties;
410 config.enable = periodic_params.enable;
411 config.include_adi = periodic_params.include_adi;
412 }
413
is_native_advertiser(int reg_id)414 uint8_t is_native_advertiser(int reg_id) {
415 // Return client id if it's native advertiser, otherwise return jni id as
416 // default
417 for (auto const& entry : native_adv_callbacks_map_) {
418 if (native_reg_id_map[entry.first].count(reg_id)) {
419 return entry.first;
420 }
421 }
422 return kAdvertiserClientIdJni;
423 }
424
425 std::map<uint8_t, ::BleAdvertiserInterface::GetAddressCallback> address_callbacks_;
426 std::map<uint8_t, std::set<int>> native_reg_id_map;
427 };
428
429 BleAdvertiserInterfaceImpl* bt_le_advertiser_instance = nullptr;
430
get_ble_advertiser_instance()431 ::BleAdvertiserInterface* bluetooth::shim::get_ble_advertiser_instance() {
432 if (bt_le_advertiser_instance == nullptr) {
433 bt_le_advertiser_instance = new BleAdvertiserInterfaceImpl();
434 }
435 return bt_le_advertiser_instance;
436 }
437
init_advertising_manager()438 void bluetooth::shim::init_advertising_manager() {
439 static_cast<BleAdvertiserInterfaceImpl*>(bluetooth::shim::get_ble_advertiser_instance())->Init();
440 }
441