1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
|
// Copyright 2021 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_FLOSS_ADAPTER_CLIENT_H_
#define DEVICE_BLUETOOTH_FLOSS_FLOSS_ADAPTER_CLIENT_H_
#include <memory>
#include <string>
#include "base/functional/callback.h"
#include "base/gtest_prod_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "dbus/exported_object.h"
#include "dbus/object_path.h"
#include "device/bluetooth/bluetooth_adapter.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/floss/floss_dbus_client.h"
#include "device/bluetooth/floss/floss_sdp_types.h"
namespace dbus {
class ErrorResponse;
class ObjectPath;
class Response;
} // namespace dbus
namespace floss {
// The adapter client represents a specific adapter and exposes some common
// functionality on it (such as discovery and bonding). It is managed by
// FlossClientBundle and will be initialized only when the chosen adapter is
// powered on (presence and power management is done by |FlossManagerClient|).
class DEVICE_BLUETOOTH_EXPORT FlossAdapterClient : public FlossDBusClient {
public:
enum class BluetoothDeviceType {
kUnknown = 0,
kBredr = 1,
kBle = 2,
kDual = 3,
};
enum class BluetoothSspVariant {
kPasskeyConfirmation = 0,
kPasskeyEntry = 1,
kConsent = 2,
kPasskeyNotification = 3,
};
enum class BondState {
kNotBonded = 0,
kBondingInProgress = 1,
kBonded = 2,
};
enum class ConnectionState {
kDisconnected = 0,
kConnectedOnly = 1,
kPairedBREDROnly = 3,
kPairedLEOnly = 5,
kPairedBoth = 7,
};
enum class BtPropertyType {
kBdName = 0x1,
kBdAddr,
kUuids,
kClassOfDevice,
kTypeOfDevice,
kServiceRecord,
kAdapterScanMode,
kAdapterBondedDevices,
kAdapterDiscoverableTimeout,
kRemoteFriendlyName,
kRemoteRssi,
kRemoteVersionInfo,
kLocalLeFeatures,
kLocalIoCaps,
kLocalIoCapsBle,
kDynamicAudioBuffer,
kRemoteIsCoordinatedSetMember,
kAppearance,
kVendorProductInfo,
// Unimplemented:
// BT_PROPERTY_WL_MEDIA_PLAYERS_LIST,
// BT_PROPERTY_REMOTE_ASHA_CAPABILITY,
// BT_PROPERTY_REMOTE_ASHA_TRUNCATED_HISYNCID,
// BT_PROPERTY_REMOTE_MODEL_NUM,
kRemoteAddrType = 0x18,
kUnknown = 0xFE,
kRemoteDeviceTimestamp = 0xFF,
};
enum class BtDiscoverableMode : uint32_t {
kNonDiscoverable = 0,
kLimitedDiscoverable = 1,
kGeneralDiscoverable = 2,
};
enum class BtAddressType {
kPublic = 0,
kRandom,
kPublicId,
kRandomId,
kUnknown = 0xfe,
kAnonymous = 0xff,
};
enum class BtAdapterRole {
kCentral = 0,
kPeripheral,
kCentralPeripheral,
};
struct VendorProductInfo {
uint8_t vendorIdSrc;
uint16_t vendorId;
uint16_t productId;
uint16_t version;
VendorProductInfo()
: vendorIdSrc(
device::BluetoothDevice::VendorIDSource::VENDOR_ID_UNKNOWN),
vendorId(),
productId(),
version() {}
};
class Observer : public base::CheckedObserver {
public:
Observer(const Observer&) = delete;
Observer& operator=(const Observer&) = delete;
Observer() = default;
~Observer() override = default;
// Notification sent when the adapter address has changed.
virtual void AdapterAddressChanged(const std::string& address) {}
// Notification sent when the adapter address has changed.
virtual void DiscoverableChanged(bool discoverable) {}
// Notification sent when the discovering state has changed.
virtual void AdapterDiscoveringChanged(bool state) {}
// Notification sent when discovery has found a device. This notification
// is not guaranteed to be unique per Chrome discovery session (i.e. you can
// get the same device twice).
virtual void AdapterFoundDevice(const FlossDeviceId& device_found) {}
// Notification sent when a found device is cleared. It will be sent when
// a device found during discovery is determined to be stale (was last seen
// some amount of time ago).
virtual void AdapterClearedDevice(const FlossDeviceId& device_cleared) {}
// Notification sent when a found device has forgotten its keys or been
// reset. It will be sent when bond loss is detected.
virtual void AdapterKeyMissingDevice(const FlossDeviceId& device) {}
// Notification sent when a device property has changed.
virtual void AdapterDevicePropertyChanged(BtPropertyType prop_type,
const FlossDeviceId& device) {}
// Notification sent for Simple Secure Pairing.
virtual void AdapterSspRequest(const FlossDeviceId& remote_device,
uint32_t cod,
BluetoothSspVariant variant,
uint32_t passkey) {}
// Notification sent for legacy pairing to display auto-gen pin code.
virtual void AdapterPinDisplay(const FlossDeviceId& remote_device,
std::string pincode) {}
// Notification sent for legacy pairing to ask user input pin code.
virtual void AdapterPinRequest(const FlossDeviceId& remote_device,
uint32_t cod,
bool min_16_digit) {}
// Notification sent when a bonding state changes for a remote device.
// TODO(b:202334519): Change status type to enum once Floss has the enum.
virtual void DeviceBondStateChanged(const FlossDeviceId& remote_device,
uint32_t status,
BondState bond_state) {}
// Notification sent when a remote device becomes connected.
virtual void AdapterDeviceConnected(const FlossDeviceId& device) {}
// Notification sent when a remote device becomes disconnected.
virtual void AdapterDeviceDisconnected(const FlossDeviceId& device) {}
// Notification sent when a remote device fails to connect.
virtual void AdapterDeviceConnectionFailed(const FlossDeviceId& device,
uint32_t status) {}
// Notification sent when requested SDP search has completed.
virtual void SdpSearchComplete(const FlossDeviceId device,
const device::BluetoothUUID uuid,
const std::vector<BtSdpRecord>& records) {}
// Notification sent when an SDP record has finished being created and
// assigned a handle.
virtual void SdpRecordCreated(const BtSdpRecord record,
const int32_t handle) {}
};
// Error: No such adapter.
static const char kErrorUnknownAdapter[];
// Creates the instance.
static std::unique_ptr<FlossAdapterClient> Create();
// Checks if a connection state indicates that it is paired.
static bool IsConnectionPaired(uint32_t connection_state);
FlossAdapterClient(const FlossAdapterClient&) = delete;
FlossAdapterClient& operator=(const FlossAdapterClient&) = delete;
FlossAdapterClient();
~FlossAdapterClient() override;
// Manage observers.
void AddObserver(Observer* observer);
bool HasObserver(Observer* observer);
void RemoveObserver(Observer* observer);
// Get the address of this adapter.
const std::string& GetAddress() const { return property_address_.Get(); }
// Get the name of this adapter.
const std::string& GetName() const { return property_name_.Get(); }
// Set the name of this adapter.
virtual void SetName(ResponseCallback<Void> callback,
const std::string& name);
// Get whether adapter is discoverable.
bool GetDiscoverable() const { return property_discoverable_.Get(); }
// Set whether adapter is discoverable.
virtual void SetDiscoverable(ResponseCallback<Void> callback,
bool discoverable);
// Set adapter discoverability mode.
virtual void SetDiscoverable(ResponseCallback<Void> callback,
BtDiscoverableMode mode,
uint32_t duration);
// Get the discoverable timeout for the adapter. Updates whenever the
// discoverable state changes.
uint32_t GetDiscoverableTimeout() const { return discoverable_timeout_; }
// Indicates if LE extended advertising is supported.
bool IsExtAdvSupported() const { return property_ext_adv_supported_.Get(); }
// Start a discovery session.
virtual void StartDiscovery(ResponseCallback<Void> callback);
// Cancel the active discovery session.
virtual void CancelDiscovery(ResponseCallback<Void> callback);
// Create a bond with the given device and transport.
virtual void CreateBond(ResponseCallback<bool> callback,
FlossDeviceId device,
BluetoothTransport transport);
// Create a bond with the given device and transport. API version >= 0.4.0,
// add callback status.
virtual void CreateBond(
ResponseCallback<FlossDBusClient::BtifStatus> callback,
FlossDeviceId device,
BluetoothTransport transport);
// Cancel a bond process.
virtual void CancelBondProcess(ResponseCallback<bool> callback,
FlossDeviceId device);
// Removes bonding.
virtual void RemoveBond(ResponseCallback<bool> callback,
FlossDeviceId device);
// Gets the transport type of the device.
virtual void GetRemoteType(ResponseCallback<BluetoothDeviceType> callback,
FlossDeviceId device);
// Gets class of a device.
virtual void GetRemoteClass(ResponseCallback<uint32_t> callback,
FlossDeviceId device);
// Gets appearance of a device.
virtual void GetRemoteAppearance(ResponseCallback<uint16_t> callback,
FlossDeviceId device);
// Get connection state of a device.
// TODO(b/202334519): Change return type to enum instead of u32
virtual void GetConnectionState(ResponseCallback<uint32_t> callback,
const FlossDeviceId& device);
// Gets UUIDs of a device.
virtual void GetRemoteUuids(
ResponseCallback<device::BluetoothDevice::UUIDList> callback,
FlossDeviceId device);
// Triggers SDP to fetch UUIDs of a device.
virtual void FetchRemoteUuids(ResponseCallback<bool> callback,
FlossDeviceId device);
// Gets the Vendor and Product Id of a device
virtual void GetRemoteVendorProductInfo(
ResponseCallback<VendorProductInfo> callback,
FlossDeviceId device);
// Gets the address type of a device
virtual void GetRemoteAddressType(ResponseCallback<BtAddressType> callback,
FlossDeviceId device);
// Get bonding state of a device.
virtual void GetBondState(ResponseCallback<uint32_t> callback,
const FlossDeviceId& device);
// Connect to all enabled profiles.
virtual void ConnectAllEnabledProfiles(ResponseCallback<Void> callback,
const FlossDeviceId& device);
// Connect to all enabled profiles. API version >= 0.4.0, add callback status.
virtual void ConnectAllEnabledProfiles(
ResponseCallback<FlossDBusClient::BtifStatus> callback,
const FlossDeviceId& device);
// Disconnect all enabled profiles.
virtual void DisconnectAllEnabledProfiles(ResponseCallback<Void> callback,
const FlossDeviceId& device);
// Indicates whether the user approves the pairing, if accepted then a pairing
// should be completed on the remote device.
virtual void SetPairingConfirmation(ResponseCallback<Void> callback,
const FlossDeviceId& device,
bool accept);
// Indicates whether the user approves the pairing with the given pin.
virtual void SetPin(ResponseCallback<Void> callback,
const FlossDeviceId& device,
bool accept,
const std::vector<uint8_t>& pin);
// Indicates whether the user approves the pairing with the given passkey.
virtual void SetPasskey(ResponseCallback<Void> callback,
const FlossDeviceId& device,
bool accept,
const std::vector<uint8_t>& passkey);
// Returns bonded devices.
virtual void GetBondedDevices();
// Returns connected devices.
virtual void GetConnectedDevices();
// Initiate an SDP search on device for uuid. Search results provided through
// |OnSdpSearchComplete|.
virtual void SdpSearch(ResponseCallback<bool> callback,
const FlossDeviceId& device,
device::BluetoothUUID uuid);
// Create a new SDP record in this device's SDP server. Record handle is
// returned via |SdpRecordCreated|.
virtual void CreateSdpRecord(ResponseCallback<bool> callback,
const BtSdpRecord& record);
// Remove an SDP record by its record handle.
virtual void RemoveSdpRecord(ResponseCallback<bool> callback,
const int32_t& handle);
std::vector<BtAdapterRole> GetSupportedRoles() {
return property_roles_.Get();
}
// Get the object path for this adapter.
const dbus::ObjectPath* GetObjectPath() const { return &adapter_path_; }
// Initialize the adapter client.
void Init(dbus::Bus* bus,
const std::string& service_name,
const int adapter_index,
base::Version version,
base::OnceClosure on_ready) override;
protected:
friend class FlossAdapterClientTest;
// Handle callback |OnAdapterPropertyChanged| on exported object path.
void OnAdapterPropertyChanged(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// When address property is updated.
void OnAddressChanged(const std::string& address);
// When name property is updated.
void OnNameChanged(const std::string& name);
// When discoverable property is updated.
void OnDiscoverableChanged(const bool& discoverable);
// Handle callback |OnDiscoveringChanged| on exported object path.
void OnDiscoveringChanged(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDeviceFound| on exported object path.
void OnDeviceFound(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDeviceCleared| on exported object path.
void OnDeviceCleared(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDeviceKeyMissing| on exported object path.
void OnDeviceKeyMissing(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDevicePropertiesChanged| on exported object path.
void OnDevicePropertiesChanged(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnSspRequest| on exported object path.
void OnSspRequest(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnPinDisplay| on exported object path.
void OnPinDisplay(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnPinRequest| on exported object path.
void OnPinRequest(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnBondStateChanged| on exported object path.
void OnBondStateChanged(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnSdpSearchComplete| on exported object path.
void OnSdpSearchComplete(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnSdpRecordCreated| on exported object path.
void OnSdpRecordCreated(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDeviceConnected| on exported object path.
void OnDeviceConnected(dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDeviceDisconnected| on exported object path.
void OnDeviceDisconnected(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle callback |OnDeviceConnectionFailed| on exported object path.
void OnDeviceConnectionFailed(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender response_sender);
// Handle GetBondedDevices.
void OnGetBondedDevices(DBusResult<std::vector<FlossDeviceId>> ret);
// Handle GetConnectedDevices.
void OnGetConnectedDevices(DBusResult<std::vector<FlossDeviceId>> ret);
// Calls GetDiscoverableTimeout.
void UpdateDiscoverableTimeout();
// Handle GetDiscoverableTimeout and cache the returned value.
void OnDiscoverableTimeout(DBusResult<uint32_t> ret);
// Handle |RegisterCallback| result and store callback ID.
void OnRegisterCallback(DBusResult<uint32_t> ret);
// Handle |RegisterConnectionCallback| result and store callback ID.
void OnRegisterConnectionCallback(DBusResult<uint32_t> ret);
// Handle both |UnregisterCallback| and |UnregisterConnectionCallback|.
void OnUnregisterCallbacks(DBusResult<bool> ret);
// List of observers interested in event notifications from this client.
base::ObserverList<Observer> observers_;
// Managed by FlossDBusManager - we keep local pointer to access object proxy.
raw_ptr<dbus::Bus> bus_ = nullptr;
// Adapter managed by this client.
dbus::ObjectPath adapter_path_;
// Service which implements the adapter interface.
std::string service_name_;
// Object path for exported callbacks registered to this client.
std::string exported_callback_path_;
// Cached discoverable timeout value (updates on init and on discoverable
// state changes).
uint32_t discoverable_timeout_ = 0;
private:
FRIEND_TEST_ALL_PREFIXES(FlossAdapterClientTest, CallAdapterMethods);
template <typename R, typename... Args>
void CallAdapterMethod(ResponseCallback<R> callback,
const char* member,
Args... args) {
CallMethod(std::move(callback), bus_, service_name_, kAdapterInterface,
adapter_path_, member, args...);
}
FlossProperty<std::string> property_address_{
kAdapterInterface, adapter::kCallbackInterface, adapter::kGetAddress,
adapter::kOnAddressChanged};
FlossProperty<std::string> property_name_{
kAdapterInterface, adapter::kCallbackInterface, adapter::kGetName,
adapter::kOnNameChanged};
FlossProperty<bool> property_discoverable_{
kAdapterInterface, adapter::kCallbackInterface, adapter::kGetDiscoverable,
adapter::kOnDiscoverableChanged};
FlossProperty<bool> property_ext_adv_supported_{
kAdapterInterface, adapter::kCallbackInterface,
adapter::kIsLeExtendedAdvertisingSupported, nullptr};
FlossProperty<std::vector<BtAdapterRole>> property_roles_{
kAdapterInterface, adapter::kCallbackInterface,
adapter::kGetSupportedRoles, nullptr};
// Object path for exported callbacks registered against adapter interface.
static const char kExportedCallbacksPath[];
// Signal when client is ready to be used.
base::OnceClosure on_ready_;
// Number of callbacks pending registration before client is ready to use.
int pending_register_calls_ = 0;
// Callback ID used for callbacks registered to this client.
std::optional<uint32_t> callback_id_;
// Callback ID used for connection callbacks registered to this client.
std::optional<uint32_t> connection_callback_id_;
base::WeakPtrFactory<FlossAdapterClient> weak_ptr_factory_{this};
};
} // namespace floss
#endif // DEVICE_BLUETOOTH_FLOSS_FLOSS_ADAPTER_CLIENT_H_
|