blob: 5209f3cca6d81566c744e5ad8244c77d2fec48fc [file] [log] [blame]
// Copyright 2018 The Chromium OS 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 BLUETOOTH_NEWBLUED_DEVICE_INTERFACE_HANDLER_H_
#define BLUETOOTH_NEWBLUED_DEVICE_INTERFACE_HANDLER_H_
#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>
#include <base/memory/ref_counted.h>
#include <base/memory/weak_ptr.h>
#include <dbus/bus.h>
#include "bluetooth/common/exported_object_manager_wrapper.h"
#include "bluetooth/newblued/newblue.h"
#include "bluetooth/newblued/property.h"
#include "bluetooth/newblued/uuid.h"
namespace bluetooth {
// Structure representing a discovered device.
struct Device {
Device();
explicit Device(const std::string& address);
// MAC address (in format XX:XX:XX:XX:XX:XX).
std::string address;
// Whether the MAC address is a random address.
bool is_random_address;
// [mandatory] Whether the device is paired.
Property<bool> paired;
// [mandatory] Whether the device is connected.
Property<bool> connected;
// [mandatory] Whether the device is in the white list.
Property<bool> trusted;
// [mandatory] Whether the device is in the black list.
Property<bool> blocked;
// [mandatory] Whether the services provided by the device has been resolved.
Property<bool> services_resolved;
// [mandatory] A readable and writable alias given to the device.
Property<std::string> alias;
// Actual alias provided by the user.
std::string internal_alias;
// [optional] A readable name of the device.
Property<std::string> name;
// [optional] Transmission power level of the advertisement packet
Property<int16_t> tx_power;
// [optional] RSSI of last received inquiry response.
Property<int16_t> rssi;
// [optional] Class of the device.
Property<uint32_t> eir_class;
// [optional] External appearance of the device.
Property<uint16_t> appearance;
// [optional] Icon type of the device based on the value of |appearance|.
Property<std::string> icon;
// [optional] Advertising flags.
Property<std::vector<uint8_t>> flags;
// [optional] Service UUIDs of 16-bit 32-bit and 128-bit.
Property<std::set<Uuid>> service_uuids;
// [optional] Service data associated with UUIDs.
Property<std::map<Uuid, std::vector<uint8_t>>> service_data;
// [optional] Manufacturer identifier with the extra manufacturer data
Property<std::map<uint16_t, std::vector<uint8_t>>> manufacturer;
DISALLOW_COPY_AND_ASSIGN(Device);
};
// Handles org.bluez.Device1 interface.
class DeviceInterfaceHandler {
// Represents a pairing session.
struct PairSession {
std::string address;
std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> pair_response;
std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>>
cancel_pair_response;
};
public:
// |newblue| and |exported_object_manager_wrapper| not owned, caller must make
// sure it outlives this object.
DeviceInterfaceHandler(
scoped_refptr<dbus::Bus> bus,
Newblue* newblue,
ExportedObjectManagerWrapper* exported_object_manager_wrapper);
virtual ~DeviceInterfaceHandler() = default;
// Starts listening pair state events from Newblue.
bool Init();
// Returns weak pointer of this object.
base::WeakPtr<DeviceInterfaceHandler> GetWeakPtr();
// Called when an update of a device info is received.
void OnDeviceDiscovered(const std::string& address,
uint8_t address_type,
int8_t rssi,
uint8_t reply_type,
const std::vector<uint8_t>& eir);
private:
// Installs org.bluez.Device1 method handlers.
void AddDeviceMethodHandlers(ExportedInterface* device_interface);
// D-Bus method handlers for device objects.
void HandlePair(
std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
dbus::Message* message);
void HandleCancelPairing(
std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
dbus::Message* message);
void HandleConnect(
std::unique_ptr<brillo::dbus_utils::DBusMethodResponse<>> response,
dbus::Message* message);
// TODO(mcchou): Handle the rest of the D-Bus methods of the device interface.
// Connect()
// Disconnect()
// ConnectProfile() - No op, but we may need dummy implementation later.
// DisconnectPorfile() - No op, but we may need dummy implementation later.
// GetServiceRecords() - No op, but we may need dummy implementation later.
// ExecuteWrite()
// Finds a device from |discovered_devices_| with the given |device_address|.
// Returns nullptr if no such device is found.
Device* FindDevice(const std::string& device_address);
// Exposes or updates the device object's property depends on the whether it
// was exposed before or should be forced updated.
template <typename T>
void UpdateDeviceProperty(ExportedInterface* interface,
const std::string& property_name,
const Property<T>& property,
bool force_export) {
if (force_export || property.updated()) {
interface->EnsureExportedPropertyRegistered<T>(property_name)
->SetValue(property.value());
}
}
// Exposes or updates the device object's property depends on the whether it
// was exposed before or should be forced updated. Takes a converter function
// which converts the value of a property into the value for exposing.
template <typename T, typename U>
void UpdateDeviceProperty(ExportedInterface* interface,
const std::string& property_name,
const Property<U>& property,
T (*converter)(const U&),
bool force_export) {
if (force_export || property.updated()) {
interface->EnsureExportedPropertyRegistered<T>(property_name)
->SetValue(converter(property.value()));
}
}
// Exposes all mandatory device object's properties and update the properties
// for the existing devices by either exposing them if not exposed before or
// emitting the value changes if any.
void UpdateDeviceProperties(ExportedInterface* interface,
const Device& device,
bool is_new_device);
// Updates EIR data of |device|.
static void UpdateEir(Device* device, const std::vector<uint8_t>& eir);
// Updates the service UUIDs based on data of EirTypes including
// UUID16_INCOMPLETE, UUID16_COMPLETE, UUID32_INCOMPLETE, UUID32_COMPLETE,
// UUID128_INCOMPLETE and UUID128_COMPLETE.
static void UpdateServiceUuids(std::set<Uuid>* service_uuids,
uint8_t uuid_size,
const uint8_t* data,
uint8_t data_len);
// Updates the service data based on data of EirTypes including SVC_DATA16,
// SVC_DATA32 and SVC_DATA128.
static void UpdateServiceData(
std::map<Uuid, std::vector<uint8_t>>* service_data,
uint8_t uuid_size,
const uint8_t* data,
uint8_t data_len);
// Resets the update status of device properties.
void ClearPropertiesUpdated(Device* device);
// Determines the security requirements based on the appearance of a device.
// Returns true if determined. The default security requirements
// (bond:true MITM:false) are used.
struct smPairSecurityRequirements DetermineSecurityRequirements(
const Device& device);
// Called when a pairing state changed event is received.
void OnPairStateChanged(const std::string& address,
PairState pair_state,
PairError pair_error);
scoped_refptr<dbus::Bus> bus_;
Newblue* newblue_;
ExportedObjectManagerWrapper* exported_object_manager_wrapper_;
UniqueId pair_observer_id_;
// Keeps the discovered devices.
// TODO(sonnysasaka): Clear old devices according to BlueZ mechanism.
std::map<std::string, std::unique_ptr<Device>> discovered_devices_;
// Device object path and its response to the ongoing pairing/cancelpairing
// request. <device address, D-Bus method response to pairing, D-Bus
// method response to cancel pairing>
struct PairSession ongoing_pairing_;
// Must come last so that weak pointers will be invalidated before other
// members are destroyed.
base::WeakPtrFactory<DeviceInterfaceHandler> weak_ptr_factory_;
FRIEND_TEST(DeviceInterfaceHandlerTest, UpdateEirNormal);
FRIEND_TEST(DeviceInterfaceHandlerTest, UpdateEirAbnormal);
DISALLOW_COPY_AND_ASSIGN(DeviceInterfaceHandler);
};
} // namespace bluetooth
#endif // BLUETOOTH_NEWBLUED_DEVICE_INTERFACE_HANDLER_H_