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