blob: e428cc10251a47b7c7ed148a918f8c83729ad4d8 [file] [log] [blame]
// 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_BLUETOOTH_DEVICE_FLOSS_H_
#define DEVICE_BLUETOOTH_FLOSS_BLUETOOTH_DEVICE_FLOSS_H_
#include <string>
#include "base/memory/weak_ptr.h"
#include "base/task/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "build/build_config.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluetooth_device.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/bluetooth_socket_thread.h"
#include "device/bluetooth/floss/bluetooth_adapter_floss.h"
#include "device/bluetooth/floss/bluetooth_pairing_floss.h"
#include "device/bluetooth/floss/bluetooth_socket_floss.h"
#include "device/bluetooth/floss/floss_adapter_client.h"
#include "device/bluetooth/floss/floss_gatt_manager_client.h"
namespace floss {
// BluetoothDeviceFloss implements device::BluetoothDevice for platforms using
// Floss (Linux front-end for Fluoride). Objects of this type should be managed
// by BluetoothAdapterFloss, which also manages device lifetimes.
//
// This class is not thread-safe but is only called from the UI thread.
class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceFloss
: public device::BluetoothDevice,
public FlossGattClientObserver {
public:
enum class ConnectingState {
kIdle = 0,
kACLConnecting,
kProfilesConnecting,
kProfilesConnected,
};
enum class GattConnectingState {
kGattDisconnected = 0,
kGattConnecting,
kGattConnected,
};
BluetoothDeviceFloss(const BluetoothDeviceFloss&) = delete;
BluetoothDeviceFloss& operator=(const BluetoothDeviceFloss&) = delete;
BluetoothDeviceFloss(
BluetoothAdapterFloss* adapter,
const FlossDeviceId& device,
scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
scoped_refptr<device::BluetoothSocketThread> socket_thread);
~BluetoothDeviceFloss() override;
// BluetoothDevice override
uint32_t GetBluetoothClass() const override;
device::BluetoothTransport GetType() const override;
std::string GetAddress() const override;
AddressType GetAddressType() const override;
VendorIDSource GetVendorIDSource() const override;
uint16_t GetVendorID() const override;
uint16_t GetProductID() const override;
uint16_t GetDeviceID() const override;
uint16_t GetAppearance() const override;
absl::optional<std::string> GetName() const override;
bool IsPaired() const override;
#if BUILDFLAG(IS_CHROMEOS)
bool IsBonded() const override;
#endif // BUILDFLAG(IS_CHROMEOS)
bool IsConnected() const override;
bool IsGattConnected() const override;
bool IsConnectable() const override;
bool IsConnecting() const override;
UUIDSet GetUUIDs() const override;
absl::optional<int8_t> GetInquiryTxPower() const override;
bool ExpectingPinCode() const override;
bool ExpectingPasskey() const override;
bool ExpectingConfirmation() const override;
void GetConnectionInfo(ConnectionInfoCallback callback) override;
void SetConnectionLatency(ConnectionLatency connection_latency,
base::OnceClosure callback,
ErrorCallback error_callback) override;
void Connect(device::BluetoothDevice::PairingDelegate* pairing_delegate,
ConnectCallback callback) override;
#if BUILDFLAG(IS_CHROMEOS)
void ConnectClassic(
device::BluetoothDevice::PairingDelegate* pairing_delegate,
ConnectCallback callback) override;
#endif // BUILDFLAG(IS_CHROMEOS)
void SetPinCode(const std::string& pincode) override;
void SetPasskey(uint32_t passkey) override;
void ConfirmPairing() override;
void RejectPairing() override;
void CancelPairing() override;
void Disconnect(base::OnceClosure callback,
ErrorCallback error_callback) override;
void Forget(base::OnceClosure callback,
ErrorCallback error_callback) override;
void ConnectToService(const device::BluetoothUUID& uuid,
ConnectToServiceCallback callback,
ConnectToServiceErrorCallback error_callback) override;
void ConnectToServiceInsecurely(
const device::BluetoothUUID& uuid,
ConnectToServiceCallback callback,
ConnectToServiceErrorCallback error_callback) override;
std::unique_ptr<device::BluetoothGattConnection>
CreateBluetoothGattConnectionObject() override;
void SetGattServicesDiscoveryComplete(bool complete) override;
bool IsGattServicesDiscoveryComplete() const override;
void Pair(device::BluetoothDevice::PairingDelegate* pairing_delegate,
ConnectCallback callback) override;
BluetoothPairingFloss* BeginPairing(
BluetoothDevice::PairingDelegate* pairing_delegate);
#if BUILDFLAG(IS_CHROMEOS)
bool UsingReliableWrite() const { return using_reliable_write_; }
void BeginReliableWrite();
void ExecuteWrite(base::OnceClosure callback,
ExecuteWriteErrorCallback error_callback) override;
void AbortWrite(base::OnceClosure callback,
AbortWriteErrorCallback error_callback) override;
#endif // BUILDFLAG(IS_CHROMEOS)
FlossDeviceId AsFlossDeviceId() const;
// Floss always distinguishes between IsBonded and IsPaired so provide
// a publicly accessible implementation.
bool IsBondedImpl() const;
void SetName(const std::string& name);
FlossAdapterClient::BondState GetBondState() { return bond_state_; }
void SetBondState(
FlossAdapterClient::BondState bond_state,
absl::optional<BluetoothDevice::ConnectErrorCode> error_code);
void SetIsConnected(bool is_connected);
void SetConnectionState(uint32_t state);
void ResetPairing();
BluetoothPairingFloss* pairing() const { return pairing_.get(); }
void InitializeDeviceProperties(base::OnceClosure callback);
bool IsReadingProperties() const { return property_reads_triggered_; }
bool HasReadProperties() const { return property_reads_completed_; }
// FlossGattClientObserver overrides
void GattClientConnectionState(GattStatus status,
int32_t client_id,
bool connected,
std::string address) override;
void GattSearchComplete(std::string address,
const std::vector<GattService>& services,
GattStatus status) override;
void GattConnectionUpdated(std::string address,
int32_t interval,
int32_t latency,
int32_t timeout,
GattStatus status) override;
void GattConfigureMtu(std::string address,
int32_t mtu,
GattStatus status) override;
#if BUILDFLAG(IS_CHROMEOS)
void GattExecuteWrite(std::string address, GattStatus status) override;
#endif
// Returns the adapter which owns this device instance.
BluetoothAdapterFloss* adapter() const {
return static_cast<BluetoothAdapterFloss*>(adapter_);
}
protected:
// BluetoothDevice override
void CreateGattConnectionImpl(
absl::optional<device::BluetoothUUID> service_uuid) override;
void UpgradeToFullDiscovery() override;
void DisconnectGatt() override;
private:
// Invoked when no connection established during connecting.
void ConnectionIncomplete();
// Method to connect profiles.
void ConnectAllEnabledProfiles();
// Updates the state of connecting and calls callbacks accordingly.
void UpdateConnectingState(
ConnectingState state,
absl::optional<BluetoothDevice::ConnectErrorCode> error);
// Updates the state of gatt connecting.
void UpdateGattConnectingState(GattConnectingState state);
// Triggers the pending callback of Connect() method.
void TriggerConnectCallback(
absl::optional<BluetoothDevice::ConnectErrorCode> error_code);
void OnGetRemoteType(DBusResult<FlossAdapterClient::BluetoothDeviceType> ret);
void OnGetRemoteClass(DBusResult<uint32_t> ret);
void OnGetRemoteAppearance(DBusResult<uint16_t> ret);
void OnGetRemoteUuids(DBusResult<UUIDList> ret);
void OnConnectAllEnabledProfiles(DBusResult<Void> ret);
void OnDisconnectAllEnabledProfiles(base::OnceClosure callback,
ErrorCallback error_callback,
DBusResult<Void> ret);
// Intercept errors when connecting to an L2CAP or RFCOMM socket. This keeps
// a reference to the |socket| so that it does not go out of scope until after
// the error is completed.
void OnConnectToServiceError(scoped_refptr<BluetoothSocketFloss> socket,
ConnectToServiceErrorCallback error_callback,
const std::string& error_message);
void TriggerInitDevicePropertiesCallback();
void OnConnectGatt(DBusResult<Void> ret);
void OnSetConnectionLatency(base::OnceClosure callback,
ErrorCallback error_callback,
DBusResult<Void> ret);
#if BUILDFLAG(IS_CHROMEOS)
void OnExecuteWrite(base::OnceClosure callback,
ExecuteWriteErrorCallback error_callback,
DBusResult<Void> ret);
#endif // BUILDFLAG(IS_CHROMEOS)
absl::optional<ConnectCallback> pending_callback_on_connect_profiles_ =
absl::nullopt;
// Timer to stop waiting for a successful connect complete.
base::OneShotTimer connection_incomplete_timer_;
absl::optional<base::OnceClosure> pending_callback_on_init_props_ =
absl::nullopt;
// Callbacks for a pending |SetConnectionLatency|.
absl::optional<std::pair<base::OnceClosure, ErrorCallback>>
pending_set_connection_latency_ = absl::nullopt;
#if BUILDFLAG(IS_CHROMEOS)
// Callbacks for a pending |ExecuteWrite| or |AbortWrite|.
absl::optional<std::pair<base::OnceClosure, ExecuteWriteErrorCallback>>
pending_execute_write_ = absl::nullopt;
// Writes are using reliable writes.
bool using_reliable_write_ = false;
#endif // BUILDFLAG(IS_CHROMEOS)
// Number of pending device properties to initialize
int num_pending_properties_ = 0;
// Address of this device. Changing this should necessitate creating a new
// BluetoothDeviceFloss object.
const std::string address_;
// Name of this device. Can be queried later and isn't mandatory for creation.
std::string name_;
// Transport type of device.
// TODO(b/204708206): Update with property framework when available
device::BluetoothTransport transport_ =
device::BluetoothTransport::BLUETOOTH_TRANSPORT_CLASSIC;
// Class of device.
// TODO(b/204708206): Update with property framework when available
uint32_t cod_ = 0;
// Appearance of device.
// TODO(b/204708206): Update with property framework when available
uint16_t appearance_ = 0;
// Whether the device is bonded/paired.
FlossAdapterClient::BondState bond_state_ =
FlossAdapterClient::BondState::kNotBonded;
// Whether the device is connected at link layer level (not profile level).
// Updated via |SetIsConnected| only.
bool is_acl_connected_ = false;
// Are all services resolved? Only true if full discovery is completed. See
// |IsGattServicesDiscoveryComplete| for more info.
bool svc_resolved_ = false;
// Have we triggered initial property reads?
bool property_reads_triggered_ = false;
// Have we completed reading properties?
bool property_reads_completed_ = false;
// Specific uuid to search for after gatt connection is established. If this
// is not set, then we do full discovery.
absl::optional<device::BluetoothUUID> search_uuid;
// Similar to is_acl_connected_ but contains the full connection state
// (including encryption). This is updated when |SetConnectionState| is called
// or when |SetIsConnected| is called.
// (https://android.googlesource.com/platform/system/bt/+/refs/heads/android10-c2f2-release/btif/src/btif_dm.cc#737),
// This is used for determining if the device is paired.
uint32_t connection_state_ = 0;
// The status of profile connecting.
ConnectingState connecting_state_ = ConnectingState::kIdle;
// The status of GATT connecting.
GattConnectingState gatt_connecting_state_ =
GattConnectingState::kGattDisconnected;
// UI thread task runner and socket thread used to create sockets.
scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
scoped_refptr<device::BluetoothSocketThread> socket_thread_;
// Represents currently ongoing pairing with this remote device.
std::unique_ptr<BluetoothPairingFloss> pairing_;
base::WeakPtrFactory<BluetoothDeviceFloss> weak_ptr_factory_{this};
};
} // namespace floss
#endif // DEVICE_BLUETOOTH_FLOSS_BLUETOOTH_DEVICE_FLOSS_H_