blob: 4f92290f6dfd76654a3a6b6ffb5c6c7fec23de79 [file] [log] [blame]
// Copyright 2021 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_FAKE_ADAPTER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_FAKE_ADAPTER_H_
#include "adapter.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/fake_channel.h"
namespace bt::gap::testing {
// FakeAdapter is a fake implementation of Adapter that can be used in higher layer unit tests (e.g.
// FIDL tests).
class FakeAdapter final : public Adapter {
public:
FakeAdapter();
~FakeAdapter() override = default;
// Adapter overrides:
AdapterId identifier() const override { return AdapterId(0); }
bool Initialize(InitializeCallback callback, fit::closure transport_closed_callback) override;
void ShutDown() override;
bool IsInitializing() const override { return init_state_ == InitState::kInitializing; }
bool IsInitialized() const override { return init_state_ == InitState::kInitialized; }
// TODO(fxbug.dev/62791): Refactor AdapterState so that FakeAdapter can set member variables (or
// remove AdapterState altogether).
const AdapterState& state() const override { return state_; }
class FakeLowEnergy final : public LowEnergy {
public:
struct RegisteredAdvertisement {
AdvertisingData data;
AdvertisingData scan_rsp;
std::optional<ConnectableAdvertisingParameters> connectable;
AdvertisingInterval interval;
bool anonymous;
bool include_tx_power_level;
};
struct Connection {
PeerId peer_id;
LowEnergyConnectionOptions options;
};
explicit FakeLowEnergy(FakeAdapter* adapter) : adapter_(adapter) {}
~FakeLowEnergy() override = default;
const std::unordered_map<AdvertisementId, RegisteredAdvertisement>&
registered_advertisements() {
return advertisements_;
}
const std::unordered_map<PeerId, Connection>& connections() const { return connections_; }
// LowEnergy overrides:
// If Connect is called multiple times, only the connection options of the last call will be
// reported in connections().
void Connect(PeerId peer_id, ConnectionResultCallback callback,
LowEnergyConnectionOptions connection_options) override;
bool Disconnect(PeerId peer_id) override;
void Pair(PeerId peer_id, sm::SecurityLevel pairing_level, sm::BondableMode bondable_mode,
sm::ResultFunction<> cb) override {}
void SetSecurityMode(LESecurityMode mode) override {}
LESecurityMode security_mode() const override { return adapter_->le_security_mode_; }
void StartAdvertising(AdvertisingData data, AdvertisingData scan_rsp,
AdvertisingInterval interval, bool anonymous, bool include_tx_power_level,
std::optional<ConnectableAdvertisingParameters> connectable,
AdvertisingStatusCallback status_callback) override;
void StopAdvertising(AdvertisementId advertisement_id) override {}
void StartDiscovery(bool active, SessionCallback callback) override {}
void EnablePrivacy(bool enabled) override {}
void set_irk(const std::optional<UInt128>& irk) override {}
std::optional<UInt128> irk() const override { return std::nullopt; }
void set_request_timeout_for_testing(zx::duration value) override {}
void set_scan_period_for_testing(zx::duration period) override {}
private:
FakeAdapter* adapter_;
AdvertisementId next_advertisement_id_ = AdvertisementId(1);
std::unordered_map<AdvertisementId, RegisteredAdvertisement> advertisements_;
std::unordered_map<PeerId, Connection> connections_;
};
LowEnergy* le() const override { return fake_le_.get(); }
FakeLowEnergy* fake_le() const { return fake_le_.get(); }
class FakeBrEdr final : public BrEdr {
public:
struct RegisteredService {
std::vector<sdp::ServiceRecord> records;
l2cap::ChannelParameters channel_params;
ServiceConnectCallback connect_callback;
};
struct RegisteredSearch {
UUID uuid;
std::unordered_set<sdp::AttributeId> attributes;
SearchCallback callback;
};
FakeBrEdr() = default;
~FakeBrEdr() override = default;
// Called with a reference to the l2cap::FakeChannel created when a channel is connected with
// Connect().
using ChannelCallback = fit::function<void(fbl::RefPtr<l2cap::testing::FakeChannel>)>;
void set_l2cap_channel_callback(ChannelCallback cb) { channel_cb_ = std::move(cb); }
// Notifies all registered searches associated with the provided |uuid| with the peer's
// service |attributes|.
void TriggerServiceFound(PeerId peer_id, UUID uuid,
std::map<sdp::AttributeId, sdp::DataElement> attributes);
const std::map<RegistrationHandle, RegisteredService>& registered_services() const {
return registered_services_;
}
const std::map<RegistrationHandle, RegisteredSearch>& registered_searches() const {
return registered_searches_;
}
// BrEdr overrides:
[[nodiscard]] bool Connect(PeerId peer_id, ConnectResultCallback callback) override {
return false;
}
bool Disconnect(PeerId peer_id, DisconnectReason reason) override { return false; }
void OpenL2capChannel(PeerId peer_id, l2cap::PSM psm,
BrEdrSecurityRequirements security_requirements,
l2cap::ChannelParameters params, l2cap::ChannelCallback cb) override;
PeerId GetPeerId(hci_spec::ConnectionHandle handle) const override { return PeerId(); }
SearchId AddServiceSearch(const UUID& uuid, std::unordered_set<sdp::AttributeId> attributes,
SearchCallback callback) override;
bool RemoveServiceSearch(SearchId id) override { return false; }
void Pair(PeerId peer_id, BrEdrSecurityRequirements security,
hci::ResultFunction<> callback) override {}
void SetConnectable(bool connectable, hci::ResultFunction<> status_cb) override {}
void RequestDiscovery(DiscoveryCallback callback) override {}
void RequestDiscoverable(DiscoverableCallback callback) override {}
RegistrationHandle RegisterService(std::vector<sdp::ServiceRecord> records,
l2cap::ChannelParameters chan_params,
ServiceConnectCallback conn_cb) override;
bool UnregisterService(RegistrationHandle handle) override { return false; }
std::optional<ScoRequestHandle> OpenScoConnection(
PeerId peer_id, hci_spec::SynchronousConnectionParameters parameters,
sco::ScoConnectionManager::OpenConnectionCallback callback) override {
return std::nullopt;
}
std::optional<ScoRequestHandle> AcceptScoConnection(
PeerId peer_id, std::vector<hci_spec::SynchronousConnectionParameters> parameters,
sco::ScoConnectionManager::AcceptConnectionCallback callback) override {
return std::nullopt;
}
private:
// Callback used by tests to get new channel refs.
ChannelCallback channel_cb_;
RegistrationHandle next_service_handle_ = 1;
RegistrationHandle next_search_handle_ = 1;
std::map<RegistrationHandle, RegisteredService> registered_services_;
std::map<RegistrationHandle, RegisteredSearch> registered_searches_;
};
BrEdr* bredr() const override { return fake_bredr_.get(); }
FakeBrEdr* fake_bredr() const { return fake_bredr_.get(); }
PeerCache* peer_cache() override { return &peer_cache_; }
bool AddBondedPeer(BondingData bonding_data) override { return true; }
void SetPairingDelegate(fxl::WeakPtr<PairingDelegate> delegate) override {}
bool IsDiscoverable() const override { return is_discoverable_; }
bool IsDiscovering() const override { return is_discovering_; }
void SetLocalName(std::string name, hci::ResultFunction<> callback) override;
std::string local_name() const override { return local_name_; }
void SetDeviceClass(DeviceClass dev_class, hci::ResultFunction<> callback) override;
void set_auto_connect_callback(AutoConnectCallback callback) override {}
void AttachInspect(inspect::Node& parent, std::string name) override {}
fxl::WeakPtr<Adapter> AsWeakPtr() override { return weak_ptr_factory_.GetWeakPtr(); }
private:
enum InitState {
kNotInitialized = 0,
kInitializing,
kInitialized,
};
InitState init_state_;
AdapterState state_;
PeerCache peer_cache_;
std::unique_ptr<FakeLowEnergy> fake_le_;
std::unique_ptr<FakeBrEdr> fake_bredr_;
bool is_discoverable_ = true;
bool is_discovering_ = true;
std::string local_name_;
DeviceClass device_class_;
LESecurityMode le_security_mode_;
fxl::WeakPtrFactory<FakeAdapter> weak_ptr_factory_;
};
} // namespace bt::gap::testing
#endif // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_FAKE_ADAPTER_H_