chromium/device/bluetooth/public/mojom/emulation/fake_bluetooth.mojom

// Copyright 2017 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

module bluetooth.mojom;

import "device/bluetooth/public/mojom/uuid.mojom";


// WORK IN PROGRESS.
// This interface is being developed to support Web Platform Tests for Web
// Bluetooth.
// https://docs.google.com/document/d/1Nhv_oVDCodd1pEH_jj9k8gF4rPGb_84VYaZ9IG8M_WY
//
// These interfaces are not intended to be used directly.
// `web-bluetooth-test.js` makes the Fake Bluetooth interface easier to work
// with.
// *   Calls are synchronous.
// *   IDs are cached.
//
// If another C++ client intends to use Fake Bluetooth a C++ wrapper similar to
// `web-bluetooth-test.js` should be created.
//
// When a Bluetooth service is created the `fake_bluetooth.mojom` and
// `bluetooth/test/fake_*` files should be removed and the client facing test
// wrapper `web-bluetooth-test.js` converted to implement the Bluetooth service
// as needed for tests.
//
// FakeBluetooth and its related interfaces allow clients to control the global
// Bluetooth State as well as simulate Bluetooth events including finding new
// devices, simulating GATT attributes and its descendants, and simulating
// success and error responses.

// Indicates the various states of Central.
enum CentralState {
  ABSENT,
  POWERED_ON,
  POWERED_OFF,
};

// GATT characteristic write type.
enum WriteType {
  kNone,
  kWriteDefaultDeprecated,
  kWriteWithResponse,
  kWriteWithoutResponse,
};

// Stores the external appearance description of the device.
struct Appearance {
  bool has_value;
  int8 value;
};

// Stores the transmission power of a broadcasting device.
struct Power {
  bool has_value;
  int8 value;
};

struct ServiceDataMap {
  map<string, array<uint8>> service_data;
};

// Stores the byte data of the advertisement packet sent by a Bluetooth device.
struct ScanRecord {
  string? name;
  array<UUID>? uuids;
  Appearance appearance;
  Power tx_power;

  // Key is the company identifier and the value is an array of bytes of
  // manufacturer specific data.
  map<uint16, array<uint8>>? manufacturer_data;
  ServiceDataMap? service_data;
};

// Stores the advertisement packet information that is sent by a Bluetooth device.
struct ScanResult {
  string device_address;
  int8 rssi;
  ScanRecord scan_record;
};

// FakeBluetooth allows clients to control the global Bluetooth state.
interface FakeBluetooth {
  // Set it to indicate whether the platform supports BLE. For example, Windows
  // 7 is a platform that doesn't support Low Energy. On the other hand Windows
  // 10 is a platform that does support LE, even if there is no Bluetooth radio
  // available.
  SetLESupported(bool available) => ();

  // Initializes a fake Central with |state| as the initial state.
  SimulateCentral(CentralState state) =>
      (pending_remote<FakeCentral> fake_central);

  // Evaluates whether all responses set by this API have been consumed by this
  // central or otherwise.  This includes responses set by:
  // - SetNextGATTConnectionResponse
  // - SetNextGATTDiscoveryResponse
  // - SetNextReadCharacteristicResponse
  // - SetNextWriteCharacteristicResponse
  // - SetNextSubscribeToNotificationsResponse
  // - SetNextUnsubscribeFromNotificationsResponse
  // - SetNextReadDescriptorResponse
  // - SetNextWriteDescriptorResponse
  // The callback is called with |consumed| set to true if there are no pending
  // responses.
  AllResponsesConsumed() => (bool consumed);
};

// HCI Error Codes from BT 4.2 Vol 2 Part D 1.3 List Of Error Codes.
const uint16 kHCISuccess           = 0x0000;
const uint16 kHCIConnectionTimeout = 0x0008;

// GATT Error codes from BT 4.2 Vol 3 Part F 3.4.1.1 Error Response.
const uint16 kGATTSuccess       = 0x0000;
const uint16 kGATTInvalidHandle = 0x0001;

// Defined in BT 4.2 Vol 3 Part G 3.3.1. Characteristic Properties
struct CharacteristicProperties {
  bool broadcast;
  bool read;
  bool write_without_response;
  bool write;
  bool notify;
  bool indicate;
  bool authenticated_signed_writes;
  bool extended_properties;
};

// FakeCentral allows clients to simulate events that a device in the
// Central/Observer role would receive as well as monitor the operations
// performed by the device in the Central/Observer role.
//
// A "Central" interface would allow its clients to receive advertising events
// and initiate connections to peripherals i.e. operations of two roles
// defined by the Bluetooth Spec: Observer and Central.
// See Bluetooth 4.2 Vol 3 Part C 2.2.2 "Roles when Operating over an
// LE Physical Transport".
interface FakeCentral {
  // Simulates a peripheral with |address|, |name| and |known_service_uuids|
  // that has already been connected to the system. If the peripheral existed
  // already it updates its name and known UUIDs.
  //
  // Platforms offer methods to retrieve devices that have already been
  // connected to the system or weren't connected through the UA e.g. a user
  // connected a peripheral through the system's settings. This method is
  // intended to simulate peripherals that those methods would return.
  // Even though these devices are already connected to the OS, clients
  // need to call the respective connect functions to signal they intend to keep
  // the connection alive.
  SimulatePreconnectedPeripheral(string address,
                                 string name,
                                 map<uint16, array<uint8>> manufacturer_data,
                                 array<UUID> known_service_uuids) => ();

  // Simulates an advertisement packet described in |result| being received by
  // the central. If the central is currently scanning, the detected device will
  // be added to the list of detected devices. Otherwise, the device will be
  // ignored.
  SimulateAdvertisementReceived(ScanResult result) => ();

  // Sets the state of this fake Central to |state|.
  SetState(CentralState state) => ();

  // Sets the next GATT Connection request response for peripheral with
  // |address| to |code|. |code| could be an HCI Error Code from
  // BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a number outside that range
  // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
  // failure
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  SetNextGATTConnectionResponse(string address, uint16 code) => (bool success);

  // Sets the next GATT Discovery request response for peripheral with
  // |address| to |code|. |code| could be an HCI Error Code from
  // BT 4.2 Vol 2 Part D 1.3 List Of Error Codes or a number outside that range
  // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
  // failure
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  //
  // The following procedures defined at BT 4.2 Vol 3 Part G Section 4.
  // "GATT Feature Requirements" are used to discover attributes of the
  // GATT Server:
  //  - Primary Service Discovery
  //  - Relationship Discovery
  //  - Characteristic Discovery
  //  - Characteristic Descriptor Discovery
  // This method aims to simulate the response once all of these procedures
  // have completed or if there was an error during any of them.
  SetNextGATTDiscoveryResponse(string address, uint16 code) => (bool success);

  // Simulates a GATT disconnection from the peripheral with |address|.
  // Calls callback with false if there was any error when simulating the GATT
  // disconnection.
  SimulateGATTDisconnection(string address) => (bool success);

  // Simulates an Indication from the peripheral's GATT `Service Changed`
  // Characteristic from BT 4.2 Vol 3 Part G 7.1. This Indication is signaled
  // when services, characteristics, or descriptors are changed, added, or
  // removed.
  //
  // The value for `Service Changed` is a range of attribute handles that have
  // changed. However, this testing specification works at an abstracted
  // level and does not expose setting attribute handles when adding
  // attributes. Consequently, this simulate method should include the full
  // range of all the peripheral's attribute handle values.
  SimulateGATTServicesChanged(string address) => (bool success);

  // Adds a fake GATT Service with |service_uuid| to |peripheral_address|
  // peripheral. The service will be found found when discovering the
  // peripheral's GATT Attributes. Runs its callback with the fake service's Id.
  // Runs its callback with nullopt if it failed to add the fake service.
  AddFakeService(string peripheral_address, UUID service_uuid)
      => (string? service_id);

  // Removes a fake GATT Services with |service_id| from the fake peripheral
  // with |peripheral_address|.
  RemoveFakeService(string service_id, string peripheral_address)
      => (bool success);

  // Adds a fake GATT Characteristic with |characteristic_uuid| and |properties|
  // to the fake service with |service_id| in |peripheral_address| peripheral.
  // The characteristic will be found when discovering the peripheral's GATT
  // Attributes. Runs its callback with the fake characteristic's Id. Runs its
  // callback with nullopt if it failed to add the fake characteristic.
  AddFakeCharacteristic(
        UUID characteristic_uuid,
        CharacteristicProperties properties,
        string service_id,
        string peripheral_address) => (string? characteristic_id);

  // Removes a fake GATT Characteristic with |identifier| to the fake service
  // with |service_id| in |peripheral_address| peripheral.
  RemoveFakeCharacteristic(
        string identifier,
        string service_id,
        string peripheral_address) => (bool success);

  // Adds a fake GATT Descriptor with |descriptor_uuid| to the fake service with
  // |service_id| in |peripheral_address| peripheral. The descriptor will be
  // found when discovering the peripheral's GATT Attributes. Runs its callback
  // with the fake descriptor's Id. Runs its callback with nullopt if it failed
  // to add the fake descriptor.
  AddFakeDescriptor(UUID descriptor_uuid,
                    string characteristic_id,
                    string service_id,
                    string peripheral_address) => (string? descriptor_id);

  // Removes a fake GATT Descriptor with |descriptor_id| from the fake
  // characteristic with |characteristic_id| in |service_id| fake service in
  // |peripheral_address| peripheral.
  RemoveFakeDescriptor(
        string descriptor_id,
        string characteristic_id,
        string service_id,
        string peripheral_address) => (bool success);

  // Sets the next read response for characteristic with |characteristics_id|
  // in |service_id| and in |peripheral_address| to |code| and |value|.
  // |code| could be a GATT Error Response from
  // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
  // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
  // failure.
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  SetNextReadCharacteristicResponse(uint16 gatt_code, array<uint8>? value,
                                    string characteristic_id, string service_id,
                                    string peripheral_address) => (bool success);

  // Sets the next write response for characteristic with |characteristics_id|
  // in |service_id| and in |peripheral_address| to |code|. |code| could be a
  // GATT Error Response from BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a
  // number outside that range returned by specific platforms e.g. Android
  // returns 0x101 to signal a GATT failure.
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  //
  // Note that if the client performs a write without response procedure the set
  // response will be ignored.
  SetNextWriteCharacteristicResponse(
      uint16 gatt_code,
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success);

  // Sets the next subscribe to notifications response for characteristic with
  // |characteristic_id| in |service_id| and in |peripheral_address| to |code|.
  // |code| could be a GATT Error Response from BT 4.2 Vol 3 Part F 3.4.1.1
  // Error Response or a number outside that range returned by specific
  // platforms e.g. Android returns 0x101 to signal a GATT failure.
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  SetNextSubscribeToNotificationsResponse(
      uint16 gatt_code,
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success);

  // Sets the next unsubscribe from notifications response for characteristic
  // with |characteristic_id| in |service_id| and in |peripheral_address| to
  // |code|. |code| could be a GATT Error Response from BT 4.2 Vol 3
  // Part F 3.4.1.1 Error Response or a number outside that range returned by
  // specific platforms e.g. Android returns 0x101 to signal a GATT failure.
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  SetNextUnsubscribeFromNotificationsResponse(
      uint16 gatt_code,
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success);

  // Returns whether or not a client has subscribed to notifications for a
  // characteristic with |characteristic_id| in |service_id| in
  // |peripheral_address|. If the value can't be retrieved, calls its callback
  // with false.
  IsNotifying(string characteristic_id,
              string service_id,
              string peripheral_address) => (bool success, bool is_notifying);

  // Gets the last successfully written value to the characteristic with
  // |characteristics_id| in |service_id| and in |peripheral_address|.
  // If the value can't be retrieved calls its callback with false. Calls its
  // callback with null value if no value has been written to the
  // characteristic.
  GetLastWrittenCharacteristicValue(
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success, array<uint8>? value,
                                     WriteType write_type);

  // Sets the next read response for descriptor with |descriptor_id| in
  // |characteristics_id| in |service_id| and in |peripheral_address| to |code|
  // and |value|. |code| could be a GATT Error Response from
  // BT 4.2 Vol 3 Part F 3.4.1.1 Error Response or a number outside that range
  // returned by specific platforms e.g. Android returns 0x101 to signal a GATT
  // failure.
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  SetNextReadDescriptorResponse(
      uint16 gatt_code,
      array<uint8>? value,
      string descriptor_id,
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success);

  // Sets the next write response for descriptor with |descriptor_id| in
  // |characteristic_id| in |service_id| and in |peripheral_address| to |code|.
  // |code| could be a GATT Error Response from BT 4.2 Vol 3 Part F 3.4.1.1
  // Error Response or a number outside that range returned by specific
  // platforms e.g. Android returns 0x101 to signal a GATT failure.
  // https://developer.android.com/reference/android/bluetooth/BluetoothGatt.html#GATT_FAILURE
  // Calls callback with false if there was any error when simulating the next
  // response.
  SetNextWriteDescriptorResponse(
      uint16 gatt_code,
      string descriptor_id,
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success);

  // Gets the last successfully written value to the descriptor with
  // |descriptor_id| in |characteristic_id| in |service_id| and in
  // |peripheral_address|. If the value can't be retrieved, calls its callback
  // with false. Calls its callback with null value if no value has been
  // written to the descriptor.
  GetLastWrittenDescriptorValue(
      string descriptor_id,
      string characteristic_id,
      string service_id,
      string peripheral_address) => (bool success, array<uint8>? value);
};