blob: 35a54d89f071bcfc7bbdeb4ed52c68e7ab5a8f59 [file] [log] [blame]
Ying Hsud6c22642022-10-03 23:35:371// Copyright 2022 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4#include "device/bluetooth/floss/floss_advertiser_client.h"
5
6#include "components/device_event_log/device_event_log.h"
Sarveshc94e10db2023-01-31 22:05:587#include "device/bluetooth/floss/floss_gatt_manager_client.h"
Ying Hsud6c22642022-10-03 23:35:378
9namespace floss {
10namespace {
11constexpr char kConnectable[] = "connectable";
12constexpr char kScannable[] = "scannable";
13constexpr char kIsLegacy[] = "is_legacy";
14constexpr char kIsAnonymous[] = "is_anonymous";
15constexpr char kIncludeTxPower[] = "include_tx_power";
16constexpr char kPrimaryPhy[] = "primary_phy";
17constexpr char kSecondaryPhy[] = "secondary_phy";
18constexpr char kInterval[] = "interval";
19constexpr char kTxPowerLevel[] = "tx_power_level";
20constexpr char kOwnAddressType[] = "own_address_type";
21
22constexpr char kServiceUuids[] = "service_uuids";
23constexpr char kSolicitUuids[] = "solicit_uuids";
24constexpr char kTransportDiscoveryData[] = "transport_discovery_data";
25constexpr char kManufacturerData[] = "manufacturer_data";
26constexpr char kServiceData[] = "service_data";
27constexpr char kIncludeTxPowerLevel[] = "include_tx_power_level";
28constexpr char kIncludeDeviceName[] = "include_device_name";
29} // namespace
30
31template <>
32void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer,
33 const OwnAddressType& type) {
34 int32_t value = static_cast<int32_t>(type);
35 WriteDBusParam(writer, value);
36}
37
38template <>
39void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer,
40 const AdvertisingSetParameters& params) {
41 dbus::MessageWriter array(nullptr);
42
43 writer->OpenArray("{sv}", &array);
44 WriteDictEntry(&array, kConnectable, params.connectable);
45 WriteDictEntry(&array, kScannable, params.scannable);
46 WriteDictEntry(&array, kIsLegacy, params.is_legacy);
47 WriteDictEntry(&array, kIsAnonymous, params.is_anonymous);
48 WriteDictEntry(&array, kIncludeTxPower, params.include_tx_power);
49 WriteDictEntry(&array, kPrimaryPhy, params.primary_phy);
50 WriteDictEntry(&array, kSecondaryPhy, params.secondary_phy);
51 WriteDictEntry(&array, kInterval, params.interval);
52 WriteDictEntry(&array, kTxPowerLevel, params.tx_power_level);
53 WriteDictEntry(&array, kOwnAddressType, params.own_address_type);
54 writer->CloseContainer(&array);
55}
56
57template <>
58void FlossDBusClient::WriteDBusParam(dbus::MessageWriter* writer,
59 const AdvertiseData& data) {
60 dbus::MessageWriter array(nullptr);
61
62 writer->OpenArray("{sv}", &array);
63 WriteDictEntry(&array, kServiceUuids, data.service_uuids);
64 WriteDictEntry(&array, kSolicitUuids, data.solicit_uuids);
65 WriteDictEntry(&array, kTransportDiscoveryData,
66 data.transport_discovery_data);
67 WriteDictEntry(&array, kManufacturerData, data.manufacturer_data);
68 WriteDictEntry(&array, kServiceData, data.service_data);
69 WriteDictEntry(&array, kIncludeTxPowerLevel, data.include_tx_power_level);
70 WriteDictEntry(&array, kIncludeDeviceName, data.include_device_name);
71 writer->CloseContainer(&array);
72}
73
74template <>
75void FlossDBusClient::WriteDBusParam(
76 dbus::MessageWriter* writer,
77 const PeriodicAdvertisingParameters& params) {
78 dbus::MessageWriter array(nullptr);
79
80 WriteDictEntry(&array, kIncludeTxPowerLevel, params.include_tx_power_level);
81 WriteDictEntry(&array, kInterval, params.interval);
82 writer->CloseContainer(&array);
83}
84
85template <>
86bool FlossDBusClient::ReadDBusParam(dbus::MessageReader* reader,
87 AdvertisingStatus* status) {
88 uint32_t value;
89 if (FlossDBusClient::ReadDBusParam(reader, &value)) {
90 *status = static_cast<AdvertisingStatus>(value);
91 return true;
92 }
93
94 return false;
95}
96
97template <>
98const DBusTypeInfo& GetDBusTypeInfo(const OwnAddressType*) {
99 static DBusTypeInfo info{"i", "OwnAddressType"};
100 return info;
101}
102
103template <>
104const DBusTypeInfo& GetDBusTypeInfo(const AdvertisingSetParameters*) {
105 static DBusTypeInfo info{"a{sv}", "AdvertisingSetParameters"};
106 return info;
107}
108
109template <>
110const DBusTypeInfo& GetDBusTypeInfo(const AdvertiseData*) {
111 static DBusTypeInfo info{"a{sv}", "AdvertiseData"};
112 return info;
113}
114
115template <>
116const DBusTypeInfo& GetDBusTypeInfo(const PeriodicAdvertisingParameters*) {
117 static DBusTypeInfo info{"a{sv}", "PeriodicAdvertisingParameters"};
118 return info;
119}
120
121template <>
122const DBusTypeInfo& GetDBusTypeInfo(const AdvertisingStatus*) {
123 static DBusTypeInfo info{"u", "AdvertisingStatus*"};
124 return info;
125}
126
127// static
Ying Hsud6c22642022-10-03 23:35:37128std::unique_ptr<FlossAdvertiserClient> FlossAdvertiserClient::Create() {
129 return std::make_unique<FlossAdvertiserClient>();
130}
131
132AdvertiseData::AdvertiseData() = default;
133AdvertiseData::AdvertiseData(const AdvertiseData&) = default;
134AdvertiseData::~AdvertiseData() = default;
135
136FlossAdvertiserClient::FlossAdvertiserClient() = default;
137
138FlossAdvertiserClient::~FlossAdvertiserClient() {
139 if (bus_) {
140 exported_callback_manager_.UnexportCallback(
John Laic3f3d5f2022-10-26 08:28:12141 dbus::ObjectPath(kAdvertisingSetCallbackPath));
Ying Hsud6c22642022-10-03 23:35:37142 }
143}
144
145void FlossAdvertiserClient::Init(dbus::Bus* bus,
146 const std::string& service_name,
147 const int adapter_index) {
148 bus_ = bus;
149 service_name_ = service_name;
150 gatt_adapter_path_ = GenerateGattPath(adapter_index);
151
152 dbus::ObjectProxy* object_proxy =
153 bus_->GetObjectProxy(service_name_, gatt_adapter_path_);
154 if (!object_proxy) {
155 LOG(ERROR) << "FlossAdvertiserClient couldn't init. Object proxy was null.";
156 return;
157 }
158
159 exported_callback_manager_.Init(bus_.get());
160 exported_callback_manager_.AddMethod(
161 advertiser::kOnAdvertisingSetStarted,
162 &FlossAdvertiserClientObserver::OnAdvertisingSetStarted);
163 exported_callback_manager_.AddMethod(
164 advertiser::kOnOwnAddressRead,
165 &FlossAdvertiserClientObserver::OnOwnAddressRead);
166 exported_callback_manager_.AddMethod(
167 advertiser::kOnAdvertisingSetStopped,
168 &FlossAdvertiserClientObserver::OnAdvertisingSetStopped);
169 exported_callback_manager_.AddMethod(
170 advertiser::kOnAdvertisingEnabled,
171 &FlossAdvertiserClientObserver::OnAdvertisingEnabled);
172 exported_callback_manager_.AddMethod(
173 advertiser::kOnAdvertisingDataSet,
174 &FlossAdvertiserClientObserver::OnAdvertisingDataSet);
175 exported_callback_manager_.AddMethod(
176 advertiser::kOnScanResponseDataSet,
177 &FlossAdvertiserClientObserver::OnScanResponseDataSet);
178 exported_callback_manager_.AddMethod(
179 advertiser::kOnAdvertisingParametersUpdated,
180 &FlossAdvertiserClientObserver::OnAdvertisingParametersUpdated);
181 exported_callback_manager_.AddMethod(
182 advertiser::kOnPeriodicAdvertisingParametersUpdated,
183 &FlossAdvertiserClientObserver::OnPeriodicAdvertisingParametersUpdated);
184 exported_callback_manager_.AddMethod(
185 advertiser::kOnPeriodicAdvertisingDataSet,
186 &FlossAdvertiserClientObserver::OnPeriodicAdvertisingDataSet);
187 exported_callback_manager_.AddMethod(
188 advertiser::kOnPeriodicAdvertisingEnabled,
189 &FlossAdvertiserClientObserver::OnPeriodicAdvertisingEnabled);
190
191 if (!exported_callback_manager_.ExportCallback(
John Laic3f3d5f2022-10-26 08:28:12192 dbus::ObjectPath(kAdvertisingSetCallbackPath),
Ying Hsud6c22642022-10-03 23:35:37193 weak_ptr_factory_.GetWeakPtr())) {
194 LOG(ERROR)
195 << "Unable to successfully export FlossAdvertiserClientObserver.";
196 return;
197 }
198
199 // Registering callbacks. We will get the callback id in
200 // |CompleteRegisterCallback| for later use.
201 dbus::MethodCall register_callback(kGattInterface,
202 advertiser::kRegisterCallback);
203 dbus::MessageWriter writer(&register_callback);
John Laic3f3d5f2022-10-26 08:28:12204 writer.AppendObjectPath(dbus::ObjectPath(kAdvertisingSetCallbackPath));
Ying Hsud6c22642022-10-03 23:35:37205 object_proxy->CallMethodWithErrorResponse(
206 &register_callback, kDBusTimeoutMs,
207 base::BindOnce(&FlossAdvertiserClient::CompleteRegisterCallback,
208 weak_ptr_factory_.GetWeakPtr()));
209}
210
211void FlossAdvertiserClient::AddObserver(
212 FlossAdvertiserClientObserver* observer) {
213 observers_.AddObserver(observer);
214}
215
216void FlossAdvertiserClient::RemoveObserver(
217 FlossAdvertiserClientObserver* observer) {
218 observers_.RemoveObserver(observer);
219}
220
221void FlossAdvertiserClient::StartAdvertisingSet(
222 const AdvertisingSetParameters& params,
223 const AdvertiseData& adv_data,
224 const absl::optional<AdvertiseData> scan_rsp,
225 const absl::optional<PeriodicAdvertisingParameters> periodic_params,
226 const absl::optional<AdvertiseData> periodic_data,
227 const int32_t duration,
228 const int32_t max_ext_adv_events,
229 StartSuccessCallback success_callback,
230 ErrorCallback error_callback) {
231 CallAdvertisingMethod(
232 base::BindOnce(
233 &FlossAdvertiserClient::CompleteStartAdvertisingSetCallback,
234 weak_ptr_factory_.GetWeakPtr(), std::move(success_callback),
235 std::move(error_callback)),
236 advertiser::kStartAdvertisingSet, params, adv_data, scan_rsp,
237 periodic_params, periodic_data, duration, max_ext_adv_events,
238 callback_id_);
239}
240
241void FlossAdvertiserClient::StopAdvertisingSet(
242 const AdvertiserId adv_id,
243 StopSuccessCallback success_callback,
244 ErrorCallback error_callback) {
245 CallAdvertisingMethod(
246 base::BindOnce(&FlossAdvertiserClient::CompleteStopAdvertisingSetCallback,
247 weak_ptr_factory_.GetWeakPtr(),
248 std::move(success_callback), std::move(error_callback),
249 adv_id),
250 advertiser::kStopAdvertisingSet, adv_id);
251}
252
253void FlossAdvertiserClient::SetAdvertisingParameters(
254 const AdvertiserId adv_id,
255 const AdvertisingSetParameters& params,
256 SetAdvParamsSuccessCallback success_callback,
257 ErrorCallback error_callback) {
258 CallAdvertisingMethod(
259 base::BindOnce(
260 &FlossAdvertiserClient::CompleteSetAdvertisingParametersCallback,
261 weak_ptr_factory_.GetWeakPtr(), std::move(success_callback),
262 std::move(error_callback), adv_id),
263 advertiser::kSetAdvertisingParameters, adv_id, params);
264}
265
266void FlossAdvertiserClient::CompleteRegisterCallback(
267 dbus::Response* response,
268 dbus::ErrorResponse* error_response) {
269 BLUETOOTH_LOG(EVENT) << __func__ << ": error_response=" << error_response;
270 if (error_response) {
271 FlossDBusClient::LogErrorResponse(
272 "AdvertisingManager::RegisterAdvertiserCallback", error_response);
273 } else {
274 dbus::MessageReader reader(response);
275 uint32_t result;
276 if (!reader.PopUint32(&result)) {
277 LOG(ERROR) << "No callback id provided for "
278 "AdvertisingManager::RegisterAdvertiserCallback";
279 return;
280 }
281
282 callback_id_ = result;
283 BLUETOOTH_LOG(EVENT) << __func__ << ": callback_id_ = " << callback_id_;
284 }
285}
286
287void FlossAdvertiserClient::CompleteStartAdvertisingSetCallback(
288 StartSuccessCallback success_callback,
289 ErrorCallback error_callback,
290 DBusResult<RegId> ret) {
291 if (!ret.has_value()) {
292 LOG(ERROR) << "Error on StartAdvertisingSet: " << ret.error();
293 std::move(error_callback)
294 .Run(device::BluetoothAdvertisement::ERROR_STARTING_ADVERTISEMENT);
295 return;
296 }
297
298 RegId reg_id = *ret;
299 start_advertising_set_callbacks_.insert(
300 {reg_id,
301 std::make_pair(std::move(success_callback), std::move(error_callback))});
302}
303
304void FlossAdvertiserClient::CompleteStopAdvertisingSetCallback(
305 StopSuccessCallback success_callback,
306 ErrorCallback error_callback,
307 const AdvertiserId adv_id,
308 DBusResult<Void> ret) {
309 stop_advertising_set_callbacks_.insert(
310 {adv_id,
311 std::make_pair(std::move(success_callback), std::move(error_callback))});
312}
313
314void FlossAdvertiserClient::CompleteSetAdvertisingParametersCallback(
315 SetAdvParamsSuccessCallback success_callback,
316 ErrorCallback error_callback,
317 const AdvertiserId adv_id,
318 DBusResult<Void> ret) {
319 set_advertising_params_callbacks_.insert(
320 {adv_id,
321 std::make_pair(std::move(success_callback), std::move(error_callback))});
322}
323
324void FlossAdvertiserClient::OnAdvertisingSetStarted(RegId reg_id,
325 AdvertiserId adv_id,
326 int32_t tx_power,
327 AdvertisingStatus status) {
328 BLUETOOTH_LOG(EVENT) << __func__ << ": reg_id=" << reg_id
329 << ", adv_id=" << adv_id << ", tx_power=" << tx_power
330 << ", status=" << static_cast<uint32_t>(status);
331
332 auto found = start_advertising_set_callbacks_.find(reg_id);
333 if (found != start_advertising_set_callbacks_.end()) {
334 auto& [success_callback, error_callback] = found->second;
335 if (status == AdvertisingStatus::kSuccess) {
336 std::move(success_callback).Run(adv_id);
337 } else {
338 std::move(error_callback).Run(GetErrorCode(status));
339 }
340 start_advertising_set_callbacks_.erase(found);
341 }
342}
343
344void FlossAdvertiserClient::OnOwnAddressRead(AdvertiserId adv_id,
345 int32_t address_type,
346 std::string address) {
347 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
348 << ", address_type=" << address_type
349 << ", address=" << address;
350}
351
352void FlossAdvertiserClient::OnAdvertisingSetStopped(AdvertiserId adv_id) {
353 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id;
354
355 auto found = stop_advertising_set_callbacks_.find(adv_id);
356 if (found != stop_advertising_set_callbacks_.end()) {
357 auto& [success_callback, error_callback] = found->second;
358 std::move(success_callback).Run();
359 stop_advertising_set_callbacks_.erase(found);
360 }
361}
362
363void FlossAdvertiserClient::OnAdvertisingEnabled(AdvertiserId adv_id,
364 bool enable,
365 AdvertisingStatus status) {
366 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
367 << ", enable=" << enable
368 << ", status=" << static_cast<uint32_t>(status);
369}
370
371void FlossAdvertiserClient::OnAdvertisingDataSet(AdvertiserId adv_id,
372 AdvertisingStatus status) {
373 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
374 << ", status=" << static_cast<uint32_t>(status);
375}
376
377void FlossAdvertiserClient::OnScanResponseDataSet(AdvertiserId adv_id,
378 AdvertisingStatus status) {
379 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
380 << ", status=" << static_cast<uint32_t>(status);
381}
382
383void FlossAdvertiserClient::OnAdvertisingParametersUpdated(
384 AdvertiserId adv_id,
385 int32_t tx_power,
386 AdvertisingStatus status) {
387 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
388 << ", tx_power=" << tx_power
389 << ", status=" << static_cast<uint32_t>(status);
390
391 auto found = set_advertising_params_callbacks_.find(adv_id);
392 if (found != set_advertising_params_callbacks_.end()) {
393 auto& [success_callback, error_callback] = found->second;
394
395 if (status == AdvertisingStatus::kSuccess) {
396 std::move(success_callback).Run();
397 } else {
398 std::move(error_callback).Run(GetErrorCode(status));
399 }
400 set_advertising_params_callbacks_.erase(found);
401 }
402}
403
404void FlossAdvertiserClient::OnPeriodicAdvertisingParametersUpdated(
405 AdvertiserId adv_id,
406 AdvertisingStatus status) {
407 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
408 << ", status=" << static_cast<uint32_t>(status);
409}
410
411void FlossAdvertiserClient::OnPeriodicAdvertisingDataSet(
412 AdvertiserId adv_id,
413 AdvertisingStatus status) {
414 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
415 << ", status=" << static_cast<uint32_t>(status);
416}
417
418void FlossAdvertiserClient::OnPeriodicAdvertisingEnabled(
419 AdvertiserId adv_id,
420 bool enable,
421 AdvertisingStatus status) {
422 BLUETOOTH_LOG(EVENT) << __func__ << ": adv_id=" << adv_id
423 << ", enable=" << enable
424 << ", status=" << static_cast<uint32_t>(status);
425}
426
427device::BluetoothAdvertisement::ErrorCode FlossAdvertiserClient::GetErrorCode(
428 AdvertisingStatus status) {
429 switch (status) {
430 case AdvertisingStatus::kSuccess:
431 return device::BluetoothAdvertisement::INVALID_ADVERTISEMENT_ERROR_CODE;
432 case AdvertisingStatus::kDataTooLarge:
433 return device::BluetoothAdvertisement::ERROR_ADVERTISEMENT_INVALID_LENGTH;
434 case AdvertisingStatus::kAlreadyStarted:
435 return device::BluetoothAdvertisement::ERROR_ADVERTISEMENT_ALREADY_EXISTS;
436 default:
437 return device::BluetoothAdvertisement::
438 ERROR_INVALID_ADVERTISEMENT_INTERVAL;
439 }
440}
441
442} // namespace floss