Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[floss] Add FlossAdvertiserClient and BluetoothAdvertisementFloss
BUG=b:233128639 BUG=b:233128814 TEST=Build + deploy chrome TEST=autoninja -C out/Default/ device_unittests LOW_COVERAGE_REASON=unit test will be provided in next change Change-Id: I4ce64727f7cf41c1cc636142c2b0cccc73dbed87 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3886195 Reviewed-by: Sonny Sasaka <sonnysasaka@chromium.org> Commit-Queue: Ying Hsu <yinghsu@chromium.org> Cr-Commit-Position: refs/heads/main@{#1054417}
- Loading branch information
Ying Hsu
authored and
Chromium LUCI CQ
committed
Oct 3, 2022
1 parent
055ae45
commit d6c2264
Showing
13 changed files
with
1,231 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
204 changes: 204 additions & 0 deletions
204
device/bluetooth/floss/bluetooth_advertisement_floss.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
// Copyright 2022 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "device/bluetooth/floss/bluetooth_advertisement_floss.h" | ||
|
||
#include <iomanip> | ||
|
||
#include "base/bind.h" | ||
#include "base/callback.h" | ||
#include "base/callback_helpers.h" | ||
#include "base/guid.h" | ||
#include "base/logging.h" | ||
#include "base/observer_list.h" | ||
#include "base/strings/string_number_conversions.h" | ||
#include "base/strings/string_util.h" | ||
#include "components/device_event_log/device_event_log.h" | ||
#include "device/bluetooth/dbus/bluetooth_le_advertising_manager_client.h" | ||
#include "device/bluetooth/floss/bluetooth_adapter_floss.h" | ||
#include "device/bluetooth/floss/floss_dbus_manager.h" | ||
|
||
namespace floss { | ||
namespace { | ||
|
||
constexpr FlossAdvertiserClient::AdvertiserId kInvalidAdvId = -1; | ||
constexpr uint8_t kServiceData16BitUuid = 0x16; | ||
constexpr int8_t kTxPowerNoPreference = 0x7f; | ||
constexpr int32_t kUnlimitedDuration = 0; | ||
constexpr int32_t kUnlimitedAdvEvents = 0; | ||
|
||
void UnregisterFailure(device::BluetoothAdvertisement::ErrorCode error) { | ||
LOG(ERROR) | ||
<< "BluetoothAdvertisementFloss::Unregister failed with error code = " | ||
<< error; | ||
} | ||
} // namespace | ||
|
||
BluetoothAdvertisementFloss::BluetoothAdvertisementFloss( | ||
std::unique_ptr<device::BluetoothAdvertisement::Data> data, | ||
scoped_refptr<BluetoothAdapterFloss> adapter) { | ||
// Initializing advertising set parameters. | ||
params_.connectable = | ||
(data->type() == | ||
device::BluetoothAdvertisement::ADVERTISEMENT_TYPE_PERIPHERAL); | ||
params_.scannable = adapter->IsDiscoverable(); | ||
params_.is_legacy = true; | ||
params_.is_anonymous = false; | ||
// TODO: check BluetoothAdvertisement::Data. | ||
params_.include_tx_power = false; | ||
params_.primary_phy = | ||
LePhy::kPhy1m; // For Legacy advertisement compatibility. | ||
params_.secondary_phy = LePhy::kPhy1m; | ||
params_.interval = 0x122; // 181.25 ms. | ||
params_.tx_power_level = kTxPowerNoPreference; | ||
params_.own_address_type = | ||
params_.connectable ? OwnAddressType::kPublic : OwnAddressType::kRandom; | ||
|
||
// Initializing advertise data. | ||
absl::optional<UUIDList> service_uuids = data->service_uuids(); | ||
if (service_uuids) { | ||
adv_data_.service_uuids.insert( | ||
adv_data_.service_uuids.end(), | ||
std::make_move_iterator(service_uuids->begin()), | ||
std::make_move_iterator(service_uuids->end())); | ||
} | ||
absl::optional<ManufacturerData> manuf_data = data->manufacturer_data(); | ||
if (manuf_data) { | ||
for (auto& [key, val] : *manuf_data) { | ||
adv_data_.manufacturer_data.emplace(key, std::move(val)); | ||
} | ||
} | ||
absl::optional<UUIDList> solicit_uuids = data->solicit_uuids(); | ||
if (solicit_uuids) { | ||
adv_data_.solicit_uuids.insert( | ||
adv_data_.solicit_uuids.end(), | ||
std::make_move_iterator(solicit_uuids->begin()), | ||
std::make_move_iterator(solicit_uuids->end())); | ||
} | ||
absl::optional<ServiceData> service_data = data->service_data(); | ||
if (service_data) { | ||
for (auto& [key, val] : *service_data) { | ||
adv_data_.service_data.emplace(std::move(key), std::move(val)); | ||
} | ||
} | ||
// TODO: check BluetoothAdvertisement::Data. | ||
adv_data_.include_tx_power_level = false; | ||
adv_data_.include_device_name = false; | ||
|
||
// Initializing scan response data. | ||
absl::optional<ScanResponseData> scan_response_data = | ||
data->scan_response_data(); | ||
if (scan_response_data) { | ||
with_scan_rsp_ = true; | ||
for (auto& [type, val] : *scan_response_data) { | ||
if (type == kServiceData16BitUuid) { | ||
if (val.size() < 2) | ||
continue; | ||
|
||
uint16_t id = (val[1] << 8) | val[0]; | ||
std::stringstream stream; | ||
stream << std::setfill('0') << std::setw(4) << std::hex << id; | ||
std::string uuid_str = stream.str(); | ||
std::vector<uint8_t> bytes(val.begin() + 2, val.end()); | ||
scan_rsp_.service_data.emplace(std::move(uuid_str), std::move(bytes)); | ||
} else { | ||
BLUETOOTH_LOG(ERROR) << "Unsupported type: " << type; | ||
} | ||
} | ||
scan_rsp_.include_tx_power_level = false; | ||
scan_rsp_.include_device_name = false; | ||
} else { | ||
with_scan_rsp_ = false; | ||
} | ||
|
||
adv_id_ = kInvalidAdvId; | ||
} | ||
|
||
BluetoothAdvertisementFloss::~BluetoothAdvertisementFloss() { | ||
Unregister(base::DoNothing(), base::BindOnce(&UnregisterFailure)); | ||
} | ||
|
||
void BluetoothAdvertisementFloss::Unregister(SuccessCallback success_callback, | ||
ErrorCallback error_callback) { | ||
Stop(std::move(success_callback), std::move(error_callback)); | ||
} | ||
|
||
void BluetoothAdvertisementFloss::Start( | ||
SuccessCallback success_callback, | ||
device::BluetoothAdapter::AdvertisementErrorCallback error_callback) { | ||
if (adv_id_ != kInvalidAdvId) { | ||
std::move(error_callback) | ||
.Run( | ||
device::BluetoothAdvertisement::ERROR_ADVERTISEMENT_ALREADY_EXISTS); | ||
return; | ||
} | ||
|
||
FlossDBusManager::Get()->GetAdvertiserClient()->StartAdvertisingSet( | ||
params_, adv_data_, | ||
(with_scan_rsp_ ? absl::optional<AdvertiseData>(scan_rsp_) | ||
: absl::nullopt), | ||
absl::nullopt, absl::nullopt, kUnlimitedDuration, kUnlimitedAdvEvents, | ||
base::BindOnce(&BluetoothAdvertisementFloss::OnStartSuccess, | ||
weak_ptr_factory_.GetWeakPtr(), | ||
std::move(success_callback)), | ||
std::move(error_callback)); | ||
} | ||
|
||
void BluetoothAdvertisementFloss::Stop(SuccessCallback success_callback, | ||
ErrorCallback error_callback) { | ||
if (adv_id_ == kInvalidAdvId) { | ||
std::move(error_callback) | ||
.Run( | ||
device::BluetoothAdvertisement::ERROR_ADVERTISEMENT_DOES_NOT_EXIST); | ||
return; | ||
} | ||
|
||
FlossDBusManager::Get()->GetAdvertiserClient()->StopAdvertisingSet( | ||
adv_id_, | ||
base::BindOnce(&BluetoothAdvertisementFloss::OnStopSuccess, | ||
weak_ptr_factory_.GetWeakPtr(), | ||
std::move(success_callback)), | ||
std::move(error_callback)); | ||
} | ||
|
||
void BluetoothAdvertisementFloss::SetAdvertisingInterval( | ||
const uint16_t interval_ms, | ||
SuccessCallback success_callback, | ||
device::BluetoothAdapter::AdvertisementErrorCallback error_callback) { | ||
if (adv_id_ == kInvalidAdvId) { | ||
std::move(error_callback) | ||
.Run( | ||
device::BluetoothAdvertisement::ERROR_ADVERTISEMENT_DOES_NOT_EXIST); | ||
return; | ||
} | ||
|
||
params_.interval = (interval_ms * 8) / 5; // in 0.625 ms unit. | ||
|
||
FlossDBusManager::Get()->GetAdvertiserClient()->SetAdvertisingParameters( | ||
adv_id_, params_, | ||
base::BindOnce( | ||
&BluetoothAdvertisementFloss::OnSetAdvertisingIntervalSuccess, | ||
weak_ptr_factory_.GetWeakPtr(), std::move(success_callback)), | ||
std::move(error_callback)); | ||
} | ||
|
||
void BluetoothAdvertisementFloss::OnStartSuccess( | ||
SuccessCallback success_callback, | ||
FlossAdvertiserClient::AdvertiserId adv_id) { | ||
adv_id_ = adv_id; | ||
std::move(success_callback).Run(); | ||
} | ||
|
||
void BluetoothAdvertisementFloss::OnStopSuccess( | ||
SuccessCallback success_callback) { | ||
std::move(success_callback).Run(); | ||
adv_id_ = kInvalidAdvId; | ||
} | ||
|
||
void BluetoothAdvertisementFloss::OnSetAdvertisingIntervalSuccess( | ||
SuccessCallback success_callback) { | ||
std::move(success_callback).Run(); | ||
} | ||
|
||
} // namespace floss |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2022 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef DEVICE_BLUETOOTH_FLOSS_BLUETOOTH_ADVERTISEMENT_FLOSS_H_ | ||
#define DEVICE_BLUETOOTH_FLOSS_BLUETOOTH_ADVERTISEMENT_FLOSS_H_ | ||
|
||
#include <memory> | ||
|
||
#include "dbus/object_path.h" | ||
#include "device/bluetooth/bluetooth_adapter.h" | ||
#include "device/bluetooth/bluetooth_advertisement.h" | ||
#include "device/bluetooth/floss/floss_advertiser_client.h" | ||
|
||
namespace floss { | ||
|
||
class BluetoothAdapterFloss; | ||
|
||
// BluetoothAdvertisementFloss represents an BLE advertising set and | ||
// provides methods to start/stop an advertising set and changing its | ||
// parameters. It keeps advertisement data and parameters in the format | ||
// required by Floss. | ||
class DEVICE_BLUETOOTH_EXPORT BluetoothAdvertisementFloss | ||
: public device::BluetoothAdvertisement { | ||
public: | ||
BluetoothAdvertisementFloss( | ||
std::unique_ptr<device::BluetoothAdvertisement::Data> data, | ||
scoped_refptr<BluetoothAdapterFloss> adapter); | ||
|
||
BluetoothAdvertisementFloss(const BluetoothAdvertisementFloss&) = delete; | ||
BluetoothAdvertisementFloss& operator=(const BluetoothAdvertisementFloss&) = | ||
delete; | ||
|
||
// BluetoothAdvertisement overrides: | ||
void Unregister(SuccessCallback success_callback, | ||
ErrorCallback error_callback) override; | ||
|
||
// Starts advertising. | ||
void Start( | ||
SuccessCallback success_callback, | ||
device::BluetoothAdapter::AdvertisementErrorCallback error_callback); | ||
|
||
// Stops advertising. | ||
void Stop( | ||
SuccessCallback success_callback, | ||
device::BluetoothAdapter::AdvertisementErrorCallback error_callback); | ||
|
||
// Changes advertising interval. | ||
void SetAdvertisingInterval( | ||
const uint16_t interval_ms, | ||
SuccessCallback success_callback, | ||
device::BluetoothAdapter::AdvertisementErrorCallback error_callback); | ||
|
||
protected: | ||
void OnStartSuccess(SuccessCallback success_callback, | ||
FlossAdvertiserClient::AdvertiserId adv_id); | ||
|
||
void OnStopSuccess(SuccessCallback success_callback); | ||
|
||
void OnSetAdvertisingIntervalSuccess(SuccessCallback success_callback); | ||
|
||
private: | ||
~BluetoothAdvertisementFloss() override; | ||
|
||
FlossAdvertiserClient::AdvertiserId adv_id_; | ||
AdvertisingSetParameters params_; | ||
AdvertiseData adv_data_; | ||
AdvertiseData scan_rsp_; | ||
bool with_scan_rsp_; | ||
|
||
base::WeakPtrFactory<BluetoothAdvertisementFloss> weak_ptr_factory_{this}; | ||
}; | ||
|
||
} // namespace floss | ||
|
||
#endif // DEVICE_BLUETOOTH_FLOSS_BLUETOOTH_ADVERTISEMENT_FLOSS_H_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.