| // Copyright 2016 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 COMPONENTS_ARC_BLUETOOTH_ARC_BLUETOOTH_BRIDGE_H_ |
| #define COMPONENTS_ARC_BLUETOOTH_ARC_BLUETOOTH_BRIDGE_H_ |
| |
| #include <stdint.h> |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <unordered_map> |
| #include <unordered_set> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/timer/timer.h" |
| #include "components/arc/arc_service.h" |
| #include "components/arc/common/bluetooth.mojom.h" |
| #include "components/arc/instance_holder.h" |
| #include "device/bluetooth/bluetooth_adapter.h" |
| #include "device/bluetooth/bluetooth_adapter_factory.h" |
| #include "device/bluetooth/bluetooth_advertisement.h" |
| #include "device/bluetooth/bluetooth_device.h" |
| #include "device/bluetooth/bluetooth_discovery_session.h" |
| #include "device/bluetooth/bluetooth_local_gatt_service.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_descriptor.h" |
| #include "device/bluetooth/bluetooth_remote_gatt_service.h" |
| #include "device/bluetooth/bluez/bluetooth_adapter_bluez.h" |
| #include "mojo/public/cpp/bindings/binding.h" |
| |
| namespace arc { |
| |
| class ArcBridgeService; |
| |
| class ArcBluetoothBridge |
| : public ArcService, |
| public InstanceHolder<mojom::BluetoothInstance>::Observer, |
| public device::BluetoothAdapter::Observer, |
| public device::BluetoothAdapterFactory::AdapterCallback, |
| public device::BluetoothLocalGattService::Delegate, |
| public mojom::BluetoothHost { |
| public: |
| explicit ArcBluetoothBridge(ArcBridgeService* bridge_service); |
| ~ArcBluetoothBridge() override; |
| |
| // Overridden from InstanceHolder<mojom::BluetoothInstance>::Observer: |
| void OnInstanceReady() override; |
| void OnInstanceClosed() override; |
| |
| void OnAdapterInitialized(scoped_refptr<device::BluetoothAdapter> adapter); |
| |
| // Overridden from device::BluetoothAdadpter::Observer |
| void DeviceAdded(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device) override; |
| |
| void DeviceChanged(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device) override; |
| |
| void DeviceAddressChanged(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device, |
| const std::string& old_address) override; |
| |
| void DevicePairedChanged(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device, |
| bool new_paired_status) override; |
| |
| void DeviceRemoved(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device) override; |
| |
| void GattServiceAdded(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device, |
| device::BluetoothRemoteGattService* service) override; |
| |
| void GattServiceRemoved(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device, |
| device::BluetoothRemoteGattService* service) override; |
| |
| void GattServicesDiscovered(device::BluetoothAdapter* adapter, |
| device::BluetoothDevice* device) override; |
| |
| void GattDiscoveryCompleteForService( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattService* service) override; |
| |
| void GattServiceChanged(device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattService* service) override; |
| |
| void GattCharacteristicAdded( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattCharacteristic* characteristic) override; |
| |
| void GattCharacteristicRemoved( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattCharacteristic* characteristic) override; |
| |
| void GattDescriptorAdded( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattDescriptor* descriptor) override; |
| |
| void GattDescriptorRemoved( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattDescriptor* descriptor) override; |
| |
| void GattCharacteristicValueChanged( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattCharacteristic* characteristic, |
| const std::vector<uint8_t>& value) override; |
| |
| void GattDescriptorValueChanged( |
| device::BluetoothAdapter* adapter, |
| device::BluetoothRemoteGattDescriptor* descriptor, |
| const std::vector<uint8_t>& value) override; |
| |
| // Overridden from device::BluetoothLocalGattService::Delegate |
| void OnCharacteristicReadRequest( |
| const device::BluetoothDevice* device, |
| const device::BluetoothLocalGattCharacteristic* characteristic, |
| int offset, |
| const ValueCallback& callback, |
| const ErrorCallback& error_callback) override; |
| |
| void OnCharacteristicWriteRequest( |
| const device::BluetoothDevice* device, |
| const device::BluetoothLocalGattCharacteristic* characteristic, |
| const std::vector<uint8_t>& value, |
| int offset, |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) override; |
| |
| void OnDescriptorReadRequest( |
| const device::BluetoothDevice* device, |
| const device::BluetoothLocalGattDescriptor* descriptor, |
| int offset, |
| const ValueCallback& callback, |
| const ErrorCallback& error_callback) override; |
| |
| void OnDescriptorWriteRequest( |
| const device::BluetoothDevice* device, |
| const device::BluetoothLocalGattDescriptor* descriptor, |
| const std::vector<uint8_t>& value, |
| int offset, |
| const base::Closure& callback, |
| const ErrorCallback& error_callback) override; |
| |
| void OnNotificationsStart( |
| const device::BluetoothDevice* device, |
| const device::BluetoothLocalGattCharacteristic* characteristic) override; |
| |
| void OnNotificationsStop( |
| const device::BluetoothDevice* device, |
| const device::BluetoothLocalGattCharacteristic* characteristic) override; |
| |
| // Bluetooth Mojo host interface |
| void EnableAdapter(const EnableAdapterCallback& callback) override; |
| void DisableAdapter(const DisableAdapterCallback& callback) override; |
| |
| void GetAdapterProperty(mojom::BluetoothPropertyType type) override; |
| void SetAdapterProperty(mojom::BluetoothPropertyPtr property) override; |
| |
| void GetRemoteDeviceProperty(mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothPropertyType type) override; |
| void SetRemoteDeviceProperty(mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothPropertyPtr property) override; |
| void GetRemoteServiceRecord(mojom::BluetoothAddressPtr remote_addr, |
| const device::BluetoothUUID& uuid) override; |
| |
| void GetRemoteServices(mojom::BluetoothAddressPtr remote_addr) override; |
| |
| void StartDiscovery() override; |
| void CancelDiscovery() override; |
| |
| void CreateBond(mojom::BluetoothAddressPtr addr, int32_t transport) override; |
| void RemoveBond(mojom::BluetoothAddressPtr addr) override; |
| void CancelBond(mojom::BluetoothAddressPtr addr) override; |
| |
| void GetConnectionState(mojom::BluetoothAddressPtr addr, |
| const GetConnectionStateCallback& callback) override; |
| |
| // Bluetooth Mojo host interface - Bluetooth Gatt Client functions |
| void StartLEScan() override; |
| void StopLEScan() override; |
| void ConnectLEDevice(mojom::BluetoothAddressPtr remote_addr) override; |
| void DisconnectLEDevice(mojom::BluetoothAddressPtr remote_addr) override; |
| void StartLEListen(const StartLEListenCallback& callback) override; |
| void StopLEListen(const StopLEListenCallback& callback) override; |
| void SearchService(mojom::BluetoothAddressPtr remote_addr) override; |
| |
| void GetGattDB(mojom::BluetoothAddressPtr remote_addr) override; |
| void ReadGattCharacteristic( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| const ReadGattCharacteristicCallback& callback) override; |
| void WriteGattCharacteristic( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| mojom::BluetoothGattValuePtr value, |
| const WriteGattCharacteristicCallback& callback) override; |
| void ReadGattDescriptor(mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| mojom::BluetoothGattIDPtr desc_id, |
| const ReadGattDescriptorCallback& callback) override; |
| void WriteGattDescriptor( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| mojom::BluetoothGattIDPtr desc_id, |
| mojom::BluetoothGattValuePtr value, |
| const WriteGattDescriptorCallback& callback) override; |
| void RegisterForGattNotification( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| const RegisterForGattNotificationCallback& callback) override; |
| void DeregisterForGattNotification( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| const DeregisterForGattNotificationCallback& callback) override; |
| void ReadRemoteRssi(mojom::BluetoothAddressPtr remote_addr, |
| const ReadRemoteRssiCallback& callback) override; |
| |
| void OpenBluetoothSocket( |
| const OpenBluetoothSocketCallback& callback) override; |
| |
| // Bluetooth Mojo host interface - Bluetooth Gatt Server functions |
| // Android counterpart link: |
| // https://source.android.com/devices/halref/bt__gatt__server_8h.html |
| // Create a new service. Chrome will create an integer service handle based on |
| // that BlueZ identifier that will pass back to Android in the callback. |
| // num_handles: number of handle for characteristic / descriptor that will be |
| // created in this service |
| void AddService(mojom::BluetoothGattServiceIDPtr service_id, |
| int32_t num_handles, |
| const AddServiceCallback& callback) override; |
| // Add a characteristic to a service and pass the characteristic handle back. |
| void AddCharacteristic(int32_t service_handle, |
| const device::BluetoothUUID& uuid, |
| int32_t properties, |
| int32_t permissions, |
| const AddCharacteristicCallback& callback) override; |
| // Add a descriptor to the last characteristic added to the given service |
| // and pass the descriptor handle back. |
| void AddDescriptor(int32_t service_handle, |
| const device::BluetoothUUID& uuid, |
| int32_t permissions, |
| const AddDescriptorCallback& callback) override; |
| // Start a local service. |
| void StartService(int32_t service_handle, |
| const StartServiceCallback& callback) override; |
| // Stop a local service. |
| void StopService(int32_t service_handle, |
| const StopServiceCallback& callback) override; |
| // Delete a local service. |
| void DeleteService(int32_t service_handle, |
| const DeleteServiceCallback& callback) override; |
| // Send value indication to a remote device. |
| void SendIndication(int32_t attribute_handle, |
| mojom::BluetoothAddressPtr address, |
| bool confirm, |
| const std::vector<uint8_t>& value, |
| const SendIndicationCallback& callback) override; |
| |
| // Bluetooth Mojo host interface - Bluetooth SDP functions |
| void GetSdpRecords(mojom::BluetoothAddressPtr remote_addr, |
| const device::BluetoothUUID& target_uuid) override; |
| void CreateSdpRecord(mojom::BluetoothSdpRecordPtr record_mojo, |
| const CreateSdpRecordCallback& callback) override; |
| void RemoveSdpRecord(uint32_t service_handle, |
| const RemoveSdpRecordCallback& callback) override; |
| |
| // Set up or disable multiple advertising. |
| void ReserveAdvertisementHandle( |
| const ReserveAdvertisementHandleCallback& callback) override; |
| void BroadcastAdvertisement( |
| int32_t adv_handle, |
| std::unique_ptr<device::BluetoothAdvertisement::Data> advertisement, |
| const BroadcastAdvertisementCallback& callback) override; |
| void ReleaseAdvertisementHandle( |
| int32_t adv_handle, |
| const ReleaseAdvertisementHandleCallback& callback) override; |
| |
| // Chrome observer callbacks |
| void OnPoweredOn( |
| const base::Callback<void(mojom::BluetoothAdapterState)>& callback) const; |
| void OnPoweredOff( |
| const base::Callback<void(mojom::BluetoothAdapterState)>& callback) const; |
| void OnPoweredError( |
| const base::Callback<void(mojom::BluetoothAdapterState)>& callback) const; |
| void OnDiscoveryStarted( |
| std::unique_ptr<device::BluetoothDiscoverySession> session); |
| void OnDiscoveryStopped(); |
| void OnDiscoveryError(); |
| void OnPairing(mojom::BluetoothAddressPtr addr) const; |
| void OnPairedDone(mojom::BluetoothAddressPtr addr) const; |
| void OnPairedError( |
| mojom::BluetoothAddressPtr addr, |
| device::BluetoothDevice::ConnectErrorCode error_code) const; |
| void OnForgetDone(mojom::BluetoothAddressPtr addr) const; |
| void OnForgetError(mojom::BluetoothAddressPtr addr) const; |
| |
| void OnGattConnectStateChanged(mojom::BluetoothAddressPtr addr, |
| bool connected) const; |
| void OnGattConnected( |
| mojom::BluetoothAddressPtr addr, |
| std::unique_ptr<device::BluetoothGattConnection> connection); |
| void OnGattConnectError( |
| mojom::BluetoothAddressPtr addr, |
| device::BluetoothDevice::ConnectErrorCode error_code) const; |
| void OnGattDisconnected(mojom::BluetoothAddressPtr addr); |
| |
| void OnStartLEListenDone(const StartLEListenCallback& callback, |
| scoped_refptr<device::BluetoothAdvertisement> adv); |
| void OnStartLEListenError( |
| const StartLEListenCallback& callback, |
| device::BluetoothAdvertisement::ErrorCode error_code); |
| |
| void OnStopLEListenDone(const StopLEListenCallback& callback); |
| void OnStopLEListenError( |
| const StopLEListenCallback& callback, |
| device::BluetoothAdvertisement::ErrorCode error_code); |
| |
| void OnGattNotifyStartDone( |
| const RegisterForGattNotificationCallback& callback, |
| const std::string char_string_id, |
| std::unique_ptr<device::BluetoothGattNotifySession> notify_session); |
| |
| private: |
| std::vector<mojom::BluetoothPropertyPtr> GetDeviceProperties( |
| mojom::BluetoothPropertyType type, |
| const device::BluetoothDevice* device) const; |
| std::vector<mojom::BluetoothPropertyPtr> GetAdapterProperties( |
| mojom::BluetoothPropertyType type) const; |
| std::vector<mojom::BluetoothAdvertisingDataPtr> GetAdvertisingData( |
| const device::BluetoothDevice* device) const; |
| |
| void SendCachedDevicesFound() const; |
| |
| device::BluetoothRemoteGattCharacteristic* FindGattCharacteristic( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id) const; |
| |
| device::BluetoothRemoteGattDescriptor* FindGattDescriptor( |
| mojom::BluetoothAddressPtr remote_addr, |
| mojom::BluetoothGattServiceIDPtr service_id, |
| mojom::BluetoothGattIDPtr char_id, |
| mojom::BluetoothGattIDPtr desc_id) const; |
| |
| // Propagates the list of paired device to Android. |
| void SendCachedPairedDevices() const; |
| |
| bool IsGattServerAttributeHandleAvailable(int need); |
| int32_t GetNextGattServerAttributeHandle(); |
| template <class LocalGattAttribute> |
| int32_t CreateGattAttributeHandle(LocalGattAttribute* attribute); |
| |
| // Common code for OnCharacteristicReadRequest and OnDescriptorReadRequest |
| template <class LocalGattAttribute> |
| void OnGattAttributeReadRequest(const device::BluetoothDevice* device, |
| const LocalGattAttribute* attribute, |
| int offset, |
| const ValueCallback& success_callback, |
| const ErrorCallback& error_callback); |
| |
| // Common code for OnCharacteristicWriteRequest and OnDescriptorWriteRequest |
| template <class LocalGattAttribute> |
| void OnGattAttributeWriteRequest(const device::BluetoothDevice* device, |
| const LocalGattAttribute* attribute, |
| const std::vector<uint8_t>& value, |
| int offset, |
| const base::Closure& success_callback, |
| const ErrorCallback& error_callback); |
| |
| void OnSetDiscoverable(bool discoverable, bool success, uint32_t timeout); |
| void SetDiscoverable(bool discoverable, uint32_t timeout); |
| |
| void OnGetServiceRecordsDone( |
| mojom::BluetoothAddressPtr remote_addr, |
| const device::BluetoothUUID& target_uuid, |
| const std::vector<bluez::BluetoothServiceRecordBlueZ>& records_bluez); |
| void OnGetServiceRecordsError( |
| mojom::BluetoothAddressPtr remote_addr, |
| const device::BluetoothUUID& target_uuid, |
| bluez::BluetoothServiceRecordBlueZ::ErrorCode error_code); |
| |
| void OnSetAdapterProperty(mojom::BluetoothStatus success, |
| mojom::BluetoothPropertyPtr property); |
| |
| // Callbacks for managing advertisements registered from the instance. |
| |
| // Called when we have an open slot in the advertisement map and want to |
| // register the advertisement given by |data| for handle |adv_handle|. |
| void OnReadyToRegisterAdvertisement( |
| const BroadcastAdvertisementCallback& callback, |
| int32_t adv_handle, |
| std::unique_ptr<device::BluetoothAdvertisement::Data> data); |
| // Called when we've successfully registered a new advertisement for |
| // handle |adv_handle|. |
| void OnRegisterAdvertisementDone( |
| const BroadcastAdvertisementCallback& callback, |
| int32_t adv_handle, |
| scoped_refptr<device::BluetoothAdvertisement> advertisement); |
| // Called when the attempt to register an advertisement for handle |
| // |adv_handle| has failed. |adv_handle| remains reserved, but no |
| // advertisement is associated with it. |
| void OnRegisterAdvertisementError( |
| const BroadcastAdvertisementCallback& callback, |
| int32_t adv_handle, |
| device::BluetoothAdvertisement::ErrorCode error_code); |
| // Both of the following are called after we've tried to unregister |
| // the advertisement for |adv_handle|. Either way, we will no |
| // longer be broadcasting this advertisement, so in either case, the |
| // handle can be released. |
| void OnUnregisterAdvertisementDone( |
| const ReleaseAdvertisementHandleCallback& callback, |
| int32_t adv_handle); |
| void OnUnregisterAdvertisementError( |
| const ReleaseAdvertisementHandleCallback& callback, |
| int32_t adv_handle, |
| device::BluetoothAdvertisement::ErrorCode error_code); |
| // Find the next free advertisement handle and put it in *adv_handle, |
| // or return false if the advertisement map is full. |
| bool GetAdvertisementHandle(int32_t* adv_handle); |
| |
| void SendDevice(const device::BluetoothDevice* device) const; |
| |
| mojo::Binding<mojom::BluetoothHost> binding_; |
| |
| scoped_refptr<bluez::BluetoothAdapterBlueZ> bluetooth_adapter_; |
| scoped_refptr<device::BluetoothAdvertisement> advertisment_; |
| std::unique_ptr<device::BluetoothDiscoverySession> discovery_session_; |
| std::unordered_map<std::string, |
| std::unique_ptr<device::BluetoothGattNotifySession>> |
| notification_session_; |
| // Map from Android int handle to Chrome (BlueZ) string identifier. |
| std::unordered_map<int32_t, std::string> gatt_identifier_; |
| // Map from Chrome (BlueZ) string identifier to android int handle. |
| std::unordered_map<std::string, int32_t> gatt_handle_; |
| // Store last GattCharacteristic added to each GattService for GattServer. |
| std::unordered_map<int32_t, int32_t> last_characteristic_; |
| // Monotonically increasing value to use as handle to give to Android side. |
| int32_t gatt_server_attribute_next_handle_ = 0; |
| // Keeps track of all devices which initiated a GATT connection to us. |
| std::unordered_set<std::string> gatt_connection_cache_; |
| // Map of device address to GATT connection objects for connections we |
| // have made. We need to hang on to these as long as the connection is |
| // active since their destructors will drop the connections otherwise. |
| std::unordered_map<std::string, |
| std::unique_ptr<device::BluetoothGattConnection>> |
| gatt_connections_; |
| // Timer to turn discovery off. |
| base::OneShotTimer discovery_off_timer_; |
| // Timer to turn adapter discoverable off. |
| base::OneShotTimer discoverable_off_timer_; |
| |
| // Holds advertising data registered by the instance. |
| // |
| // When a handle is reserved, an entry is placed into the advertisements_ |
| // map. This entry is not yet associated with a device::BluetoothAdvertisement |
| // because the instance hasn't sent us any advertising data yet, so its |
| // mapped value is nullptr until that happens. Thus we have three states for a |
| // handle: |
| // * unmapped -> free |
| // * mapped to nullptr -> reserved, awaiting data |
| // * mapped to a device::BluetoothAdvertisement -> in use, and the mapped |
| // BluetoothAdvertisement is currently registered with the adapter. |
| // TODO(crbug.com/658385) Change back to 5 when we support setting signal |
| // strength per each advertisement slot. |
| enum { kMaxAdvertisements = 1 }; |
| std::map<int32_t, scoped_refptr<device::BluetoothAdvertisement>> |
| advertisements_; |
| |
| THREAD_CHECKER(thread_checker_); |
| |
| // WeakPtrFactory to use for callbacks. |
| base::WeakPtrFactory<ArcBluetoothBridge> weak_factory_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ArcBluetoothBridge); |
| }; |
| |
| } // namespace arc |
| |
| #endif // COMPONENTS_ARC_BLUETOOTH_ARC_BLUETOOTH_BRIDGE_H_ |