blob: 3d1d69fdf7919e98f511adf685a204ee5b88ef19 [file] [log] [blame]
// Copyright (c) 2013 The Chromium 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 DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
#define DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_
#include <cstdint>
#include <map>
#include <memory>
#include <vector>
#include "base/bind.h"
#include "base/callback.h"
#include "base/observer_list.h"
#include "base/optional.h"
#include "dbus/object_path.h"
#include "dbus/property.h"
#include "device/bluetooth/bluetooth_common.h"
#include "device/bluetooth/bluetooth_export.h"
#include "device/bluetooth/dbus/bluetooth_agent_service_provider.h"
#include "device/bluetooth/dbus/bluetooth_device_client.h"
#include "device/bluetooth/dbus/bluetooth_profile_service_provider.h"
namespace bluez {
// FakeBluetoothDeviceClient simulates the behavior of the Bluetooth Daemon
// device objects and is used both in test cases in place of a mock and on
// the Linux desktop.
class DEVICE_BLUETOOTH_EXPORT FakeBluetoothDeviceClient
: public BluetoothDeviceClient {
public:
struct Properties : public BluetoothDeviceClient::Properties {
explicit Properties(const PropertyChangedCallback& callback);
~Properties() override;
// dbus::PropertySet override
void Get(dbus::PropertyBase* property,
dbus::PropertySet::GetCallback callback) override;
void GetAll() override;
void Set(dbus::PropertyBase* property,
dbus::PropertySet::SetCallback callback) override;
};
struct SimulatedPairingOptions {
SimulatedPairingOptions();
~SimulatedPairingOptions();
bool incoming = false;
std::string pairing_method;
std::string pairing_auth_token;
std::string pairing_action;
};
// Stores properties of a device that is about to be created.
struct IncomingDeviceProperties {
IncomingDeviceProperties();
~IncomingDeviceProperties();
std::string device_address;
std::string device_alias;
int device_class = 0;
std::string device_name;
std::string device_path;
bool is_trusted = true;
bool incoming = false;
std::string pairing_action;
std::string pairing_auth_token;
std::string pairing_method;
};
FakeBluetoothDeviceClient();
~FakeBluetoothDeviceClient() override;
// Causes Connect() calls to never finish.
void LeaveConnectionsPending();
// BluetoothDeviceClient overrides
void Init(dbus::Bus* bus, const std::string& bluetooth_service_name) override;
void AddObserver(Observer* observer) override;
void RemoveObserver(Observer* observer) override;
std::vector<dbus::ObjectPath> GetDevicesForAdapter(
const dbus::ObjectPath& adapter_path) override;
Properties* GetProperties(const dbus::ObjectPath& object_path) override;
void Connect(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void Disconnect(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void ConnectProfile(const dbus::ObjectPath& object_path,
const std::string& uuid,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void DisconnectProfile(const dbus::ObjectPath& object_path,
const std::string& uuid,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void Pair(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void CancelPairing(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void GetConnInfo(const dbus::ObjectPath& object_path,
const ConnInfoCallback& callback,
const ErrorCallback& error_callback) override;
void SetLEConnectionParameters(const dbus::ObjectPath& object_path,
const ConnectionParameters& conn_params,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void GetServiceRecords(const dbus::ObjectPath& object_path,
const ServiceRecordsCallback& callback,
const ErrorCallback& error_callback) override;
void ExecuteWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void AbortWrite(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback) override;
void SetSimulationIntervalMs(int interval_ms);
// Simulates discovery of devices for the given adapter.
void BeginDiscoverySimulation(const dbus::ObjectPath& adapter_path);
void EndDiscoverySimulation(const dbus::ObjectPath& adapter_path);
// Simulates incoming pairing of devices for the given adapter.
void BeginIncomingPairingSimulation(const dbus::ObjectPath& adapter_path);
void EndIncomingPairingSimulation(const dbus::ObjectPath& adapter_path);
// Creates a device from the set we return for the given adapter.
void CreateDevice(const dbus::ObjectPath& adapter_path,
const dbus::ObjectPath& device_path);
// Creates a device with the given properties.
void CreateDeviceWithProperties(const dbus::ObjectPath& adapter_path,
const IncomingDeviceProperties& props);
// Creates and returns a list of std::unique_ptr<base::DictionaryValue>
// objects, which contain all the data from the constants for devices with
// predefined behavior.
std::unique_ptr<base::ListValue> GetBluetoothDevicesAsDictionaries() const;
SimulatedPairingOptions* GetPairingOptions(
const dbus::ObjectPath& object_path);
// Removes a device from the set we return for the given adapter.
void RemoveDevice(const dbus::ObjectPath& adapter_path,
const dbus::ObjectPath& device_path);
// Simulates a pairing for the device with the given D-Bus object path,
// |object_path|. Set |incoming_request| to true if simulating an incoming
// pairing request, false for an outgoing one. On successful completion
// |callback| will be called, on failure, |error_callback| is called.
void SimulatePairing(const dbus::ObjectPath& object_path,
bool incoming_request,
const base::Closure& callback,
const ErrorCallback& error_callback);
// Updates the connection properties of the fake device that will be returned
// by GetConnInfo.
void UpdateConnectionInfo(uint16_t connection_rssi,
uint16_t transmit_power,
uint16_t max_transmit_power);
// Test specific functions:
// Remove all test devices from this client.
void RemoveAllDevices();
// Create a test Bluetooth device with the given properties.
void CreateTestDevice(
const dbus::ObjectPath& adapter_path,
const base::Optional<std::string> name,
const std::string alias,
const std::string device_address,
const std::vector<std::string>& service_uuids,
device::BluetoothTransport type,
const std::map<std::string, std::vector<uint8_t>>& service_data,
const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data);
void set_delay_start_discovery(bool value) { delay_start_discovery_ = value; }
// Updates the inquiry RSSI property of fake device with object path
// |object_path| to |rssi|, if the fake device exists.
void UpdateDeviceRSSI(const dbus::ObjectPath& object_path, int16_t rssi);
// Updates service UUIDs, service data, and manufacturer data of the fake
// device with the given |object_path|. The |service_uuids| values are
// appended, while |service_data| and |manufacturer_data| are merged into the
// existing property values. Has no effect if the fake device does not exist.
void UpdateServiceAndManufacturerData(
const dbus::ObjectPath& object_path,
const std::vector<std::string>& service_uuids,
const std::map<std::string, std::vector<uint8_t>>& service_data,
const std::map<uint16_t, std::vector<uint8_t>>& manufacturer_data);
// Updates the EIR property of fake device with object path |object_path| to
// |eir|, if the fake device exists.
void UpdateEIR(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& eir);
// Adds a pending prepare write request to |object_path|.
void AddPrepareWriteRequest(const dbus::ObjectPath& object_path,
const std::vector<uint8_t>& value);
static const char kTestPinCode[];
static const int kTestPassKey;
static const char kPairingMethodNone[];
static const char kPairingMethodPinCode[];
static const char kPairingMethodPassKey[];
static const char kPairingActionConfirmation[];
static const char kPairingActionDisplay[];
static const char kPairingActionFail[];
static const char kPairingActionRequest[];
// Object paths, names, addresses and bluetooth classes of the devices
// we can emulate.
static const char kPairedDevicePath[];
static const char kPairedDeviceName[];
static const char kPairedDeviceAlias[];
static const char kPairedDeviceAddress[];
static const uint32_t kPairedDeviceClass;
static const char kLegacyAutopairPath[];
static const char kLegacyAutopairName[];
static const char kLegacyAutopairAddress[];
static const uint32_t kLegacyAutopairClass;
static const char kDisplayPinCodePath[];
static const char kDisplayPinCodeName[];
static const char kDisplayPinCodeAddress[];
static const uint32_t kDisplayPinCodeClass;
static const char kVanishingDevicePath[];
static const char kVanishingDeviceName[];
static const char kVanishingDeviceAddress[];
static const uint32_t kVanishingDeviceClass;
static const char kConnectUnpairablePath[];
static const char kConnectUnpairableName[];
static const char kConnectUnpairableAddress[];
static const uint32_t kConnectUnpairableClass;
static const char kDisplayPasskeyPath[];
static const char kDisplayPasskeyName[];
static const char kDisplayPasskeyAddress[];
static const uint32_t kDisplayPasskeyClass;
static const char kRequestPinCodePath[];
static const char kRequestPinCodeName[];
static const char kRequestPinCodeAddress[];
static const uint32_t kRequestPinCodeClass;
static const char kConfirmPasskeyPath[];
static const char kConfirmPasskeyName[];
static const char kConfirmPasskeyAddress[];
static const uint32_t kConfirmPasskeyClass;
static const char kRequestPasskeyPath[];
static const char kRequestPasskeyName[];
static const char kRequestPasskeyAddress[];
static const uint32_t kRequestPasskeyClass;
static const char kUnconnectableDevicePath[];
static const char kUnconnectableDeviceName[];
static const char kUnconnectableDeviceAddress[];
static const uint32_t kUnconnectableDeviceClass;
static const char kUnpairableDevicePath[];
static const char kUnpairableDeviceName[];
static const char kUnpairableDeviceAddress[];
static const uint32_t kUnpairableDeviceClass;
static const char kJustWorksPath[];
static const char kJustWorksName[];
static const char kJustWorksAddress[];
static const uint32_t kJustWorksClass;
static const char kLowEnergyPath[];
static const char kLowEnergyName[];
static const char kLowEnergyAddress[];
static const uint32_t kLowEnergyClass;
static const char kDualPath[];
static const char kDualName[];
static const char kDualAddress[];
static const char kPairedUnconnectableDevicePath[];
static const char kPairedUnconnectableDeviceName[];
static const char kPairedUnconnectableDeviceAlias[];
static const char kPairedUnconnectableDeviceAddress[];
static const uint32_t kPairedUnconnectableDeviceClass;
static const char kConnectedTrustedNotPairedDevicePath[];
static const char kConnectedTrustedNotPairedDeviceAddress[];
static const char kConnectedTrustedNotPairedDeviceName[];
static const uint32_t kConnectedTrustedNotPairedDeviceClass;
private:
// Property callback passed when we create Properties* structures.
void OnPropertyChanged(const dbus::ObjectPath& object_path,
const std::string& property_name);
void DiscoverySimulationTimer();
void IncomingPairingSimulationTimer();
void CompleteSimulatedPairing(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback);
void TimeoutSimulatedPairing(const dbus::ObjectPath& object_path,
const ErrorCallback& error_callback);
void CancelSimulatedPairing(const dbus::ObjectPath& object_path,
const ErrorCallback& error_callback);
void RejectSimulatedPairing(const dbus::ObjectPath& object_path,
const ErrorCallback& error_callback);
void FailSimulatedPairing(const dbus::ObjectPath& object_path,
const ErrorCallback& error_callback);
void AddInputDeviceIfNeeded(const dbus::ObjectPath& object_path,
Properties* properties);
// If fake device with |object_path| exists, sets its inquiry RSSI property
// to false and notifies that the property changed.
void InvalidateDeviceRSSI(const dbus::ObjectPath& object_path);
void PinCodeCallback(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback,
BluetoothAgentServiceProvider::Delegate::Status status,
const std::string& pincode);
void PasskeyCallback(const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback,
BluetoothAgentServiceProvider::Delegate::Status status,
uint32_t passkey);
void ConfirmationCallback(
const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback,
BluetoothAgentServiceProvider::Delegate::Status status);
void SimulateKeypress(uint16_t entered,
const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback);
void ConnectionCallback(
const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback,
BluetoothProfileServiceProvider::Delegate::Status status);
void DisconnectionCallback(
const dbus::ObjectPath& object_path,
const base::Closure& callback,
const ErrorCallback& error_callback,
BluetoothProfileServiceProvider::Delegate::Status status);
// List of observers interested in event notifications from us.
base::ObserverList<Observer>::Unchecked observers_;
using PropertiesMap =
std::map<const dbus::ObjectPath, std::unique_ptr<Properties>>;
PropertiesMap properties_map_;
std::vector<dbus::ObjectPath> device_list_;
// Properties which are used to decied which method of pairing should
// be done on request.
using PairingOptionsMap = std::map<const dbus::ObjectPath,
std::unique_ptr<SimulatedPairingOptions>>;
PairingOptionsMap pairing_options_map_;
int simulation_interval_ms_;
uint32_t discovery_simulation_step_;
uint32_t incoming_pairing_simulation_step_;
bool pairing_cancelled_;
int16_t connection_rssi_;
int16_t transmit_power_;
int16_t max_transmit_power_;
// Controls the fake behavior to allow more extensive UI testing without
// having to cycle the discovery simulation.
bool delay_start_discovery_;
// Pending prepare write requests.
std::vector<std::pair<dbus::ObjectPath, std::vector<uint8_t>>>
prepare_write_requests_;
bool should_leave_connections_pending_;
};
} // namespace bluez
#endif // DEVICE_BLUETOOTH_DBUS_FAKE_BLUETOOTH_DEVICE_CLIENT_H_