Skip to content

Commit

Permalink
[floss] Add FlossAdvertiserClient and BluetoothAdvertisementFloss
Browse files Browse the repository at this point in the history
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
Show file tree
Hide file tree
Showing 13 changed files with 1,231 additions and 1 deletion.
6 changes: 6 additions & 0 deletions device/bluetooth/BUILD.gn
Expand Up @@ -434,6 +434,8 @@ component("bluetooth") {
"dbus/dbus_bluez_manager_wrapper_linux.h",
"floss/bluetooth_adapter_floss.cc",
"floss/bluetooth_adapter_floss.h",
"floss/bluetooth_advertisement_floss.cc",
"floss/bluetooth_advertisement_floss.h",
"floss/bluetooth_device_floss.cc",
"floss/bluetooth_device_floss.h",
"floss/bluetooth_gatt_connection_floss.cc",
Expand All @@ -447,6 +449,8 @@ component("bluetooth") {
"floss/exported_callback_manager.h",
"floss/floss_adapter_client.cc",
"floss/floss_adapter_client.h",
"floss/floss_advertiser_client.cc",
"floss/floss_advertiser_client.h",
"floss/floss_dbus_client.cc",
"floss/floss_dbus_client.h",
"floss/floss_dbus_manager.cc",
Expand Down Expand Up @@ -534,6 +538,8 @@ component("bluetooth") {
"dbus/fake_bluetooth_profile_service_provider.h",
"floss/fake_floss_adapter_client.cc",
"floss/fake_floss_adapter_client.h",
"floss/fake_floss_advertiser_client.cc",
"floss/fake_floss_advertiser_client.h",
"floss/fake_floss_lescan_client.cc",
"floss/fake_floss_lescan_client.h",
"floss/fake_floss_manager_client.cc",
Expand Down
204 changes: 204 additions & 0 deletions device/bluetooth/floss/bluetooth_advertisement_floss.cc
@@ -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
76 changes: 76 additions & 0 deletions device/bluetooth/floss/bluetooth_advertisement_floss.h
@@ -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_
7 changes: 7 additions & 0 deletions device/bluetooth/floss/bluetooth_floss_unittest.cc
Expand Up @@ -13,6 +13,7 @@
#include "device/bluetooth/floss/bluetooth_adapter_floss.h"
#include "device/bluetooth/floss/bluetooth_device_floss.h"
#include "device/bluetooth/floss/fake_floss_adapter_client.h"
#include "device/bluetooth/floss/fake_floss_advertiser_client.h"
#include "device/bluetooth/floss/fake_floss_lescan_client.h"
#include "device/bluetooth/floss/fake_floss_manager_client.h"
#include "device/bluetooth/floss/fake_floss_socket_manager.h"
Expand Down Expand Up @@ -89,15 +90,20 @@ class BluetoothFlossTest : public testing::Test {
auto fake_floss_adapter_client = std::make_unique<FakeFlossAdapterClient>();
auto fake_floss_socket_manager = std::make_unique<FakeFlossSocketManager>();
auto fake_floss_lescan_client = std::make_unique<FakeFlossLEScanClient>();
auto fake_floss_advertiser_client =
std::make_unique<FakeFlossAdvertiserClient>();

fake_floss_manager_client_ = fake_floss_manager_client.get();
fake_floss_adapter_client_ = fake_floss_adapter_client.get();
fake_floss_lescan_client_ = fake_floss_lescan_client.get();
fake_floss_advertiser_client_ = fake_floss_advertiser_client.get();

dbus_setter->SetFlossManagerClient(std::move(fake_floss_manager_client));
dbus_setter->SetFlossAdapterClient(std::move(fake_floss_adapter_client));
dbus_setter->SetFlossSocketManager(std::move(fake_floss_socket_manager));
dbus_setter->SetFlossLEScanClient(std::move(fake_floss_lescan_client));
dbus_setter->SetFlossAdvertiserClient(
std::move(fake_floss_advertiser_client));
}

void InitializeAdapter() {
Expand Down Expand Up @@ -179,6 +185,7 @@ class BluetoothFlossTest : public testing::Test {
raw_ptr<FakeFlossManagerClient> fake_floss_manager_client_;
raw_ptr<FakeFlossAdapterClient> fake_floss_adapter_client_;
raw_ptr<FakeFlossLEScanClient> fake_floss_lescan_client_;
raw_ptr<FakeFlossAdvertiserClient> fake_floss_advertiser_client_;

std::vector<std::unique_ptr<BluetoothDiscoverySession>> discovery_sessions_;

Expand Down
7 changes: 7 additions & 0 deletions device/bluetooth/floss/bluetooth_socket_floss_unittest.cc
Expand Up @@ -19,6 +19,7 @@
#include "device/bluetooth/bluetooth_socket_thread.h"
#include "device/bluetooth/floss/bluetooth_adapter_floss.h"
#include "device/bluetooth/floss/fake_floss_adapter_client.h"
#include "device/bluetooth/floss/fake_floss_advertiser_client.h"
#include "device/bluetooth/floss/fake_floss_lescan_client.h"
#include "device/bluetooth/floss/fake_floss_manager_client.h"
#include "device/bluetooth/floss/fake_floss_socket_manager.h"
Expand Down Expand Up @@ -46,16 +47,21 @@ class BluetoothSocketFlossTest : public testing::Test {
auto fake_floss_adapter_client = std::make_unique<FakeFlossAdapterClient>();
auto fake_floss_socket_manager = std::make_unique<FakeFlossSocketManager>();
auto fake_floss_lescan_client = std::make_unique<FakeFlossLEScanClient>();
auto fake_floss_advertiser_client =
std::make_unique<FakeFlossAdvertiserClient>();

fake_floss_manager_client_ = fake_floss_manager_client.get();
fake_floss_adapter_client_ = fake_floss_adapter_client.get();
fake_floss_socket_manager_ = fake_floss_socket_manager.get();
fake_floss_lescan_client_ = fake_floss_lescan_client.get();
fake_floss_advertiser_client_ = fake_floss_advertiser_client.get();

dbus_setter->SetFlossManagerClient(std::move(fake_floss_manager_client));
dbus_setter->SetFlossAdapterClient(std::move(fake_floss_adapter_client));
dbus_setter->SetFlossSocketManager(std::move(fake_floss_socket_manager));
dbus_setter->SetFlossLEScanClient(std::move(fake_floss_lescan_client));
dbus_setter->SetFlossAdvertiserClient(
std::move(fake_floss_advertiser_client));

InitializeAndEnableAdapter();
}
Expand Down Expand Up @@ -166,6 +172,7 @@ class BluetoothSocketFlossTest : public testing::Test {
raw_ptr<FakeFlossAdapterClient> fake_floss_adapter_client_;
raw_ptr<FakeFlossSocketManager> fake_floss_socket_manager_;
raw_ptr<FakeFlossLEScanClient> fake_floss_lescan_client_;
raw_ptr<FakeFlossAdvertiserClient> fake_floss_advertiser_client_;

base::WeakPtrFactory<BluetoothSocketFlossTest> weak_ptr_factory_{this};
};
Expand Down

0 comments on commit d6c2264

Please sign in to comment.