1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #ifndef COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H
6 #define COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H
11 #include "base/macros.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/time/time.h"
16 #include "components/proximity_auth/ble/bluetooth_low_energy_characteristics_finder.h"
17 #include "components/proximity_auth/ble/fake_wire_message.h"
18 #include "components/proximity_auth/ble/remote_attribute.h"
19 #include "components/proximity_auth/connection.h"
20 #include "device/bluetooth/bluetooth_adapter.h"
21 #include "device/bluetooth/bluetooth_device.h"
22 #include "device/bluetooth/bluetooth_gatt_characteristic.h"
23 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
24 #include "device/bluetooth/bluetooth_uuid.h"
26 namespace proximity_auth
{
28 // Represents a connection with a remote device over Bluetooth low energy. The
29 // connection is a persistent bidirectional channel for sending and receiving
30 // wire messages. The remote device is the peripheral mode and the service
31 // contains two characteristics: one to send data and another to receive it.
33 // The connection flow is described below.
35 // Discover Reader and Writer Characteristics
39 // Start Notify Session
43 // Write kInviteToConnectSignal to Writer Characteristic
47 // Read kInvitationResponseSignal from Reader Characteristic
51 // Proximity Auth Connection Established
52 class BluetoothLowEnergyConnection
: public Connection
,
53 public device::BluetoothAdapter::Observer
{
55 // Signals sent to the remote device to indicate connection related events.
56 enum class ControlSignal
: uint32
{
57 kInviteToConnectSignal
= 0,
58 kInvitationResponseSignal
= 1,
60 kDisconnectSignal
= 3,
63 // The sub-state of a proximity_auth::BluetoothLowEnergyConnection class
64 // extends the IN_PROGRESS state of proximity_auth::Connection::Status.
65 enum class SubStatus
{
67 WAITING_GATT_CONNECTION
,
68 GATT_CONNECTION_ESTABLISHED
,
69 WAITING_CHARACTERISTICS
,
70 CHARACTERISTICS_FOUND
,
71 WAITING_NOTIFY_SESSION
,
73 WAITING_RESPONSE_SIGNAL
,
77 // Constructs a Bluetooth low energy connection to the service with
78 // |remote_service_| on the |remote_device|. The |adapter| must be already
79 // initaalized and ready. The GATT connection may alreaady be established and
80 // pass through |gatt_connection|. A subsequent call to Connect() must be
82 BluetoothLowEnergyConnection(
83 const RemoteDevice
& remote_device
,
84 scoped_refptr
<device::BluetoothAdapter
> adapter
,
85 const device::BluetoothUUID remote_service_uuid
,
86 const device::BluetoothUUID to_peripheral_char_uuid
,
87 const device::BluetoothUUID from_peripheral_char_uuid
,
88 scoped_ptr
<device::BluetoothGattConnection
> gatt_connection
,
89 int max_number_of_write_attempts
);
91 ~BluetoothLowEnergyConnection() override
;
93 // proximity_auth::Connection:
94 void Connect() override
;
95 void Disconnect() override
;
98 // Exposed for testing.
99 void SetSubStatus(SubStatus status
);
100 SubStatus
sub_status() { return sub_status_
; }
102 // Virtual for testing.
103 virtual BluetoothLowEnergyCharacteristicsFinder
* CreateCharacteristicsFinder(
104 const BluetoothLowEnergyCharacteristicsFinder::SuccessCallback
&
106 const BluetoothLowEnergyCharacteristicsFinder::ErrorCallback
&
109 // proximity_auth::Connection:
110 void SendMessageImpl(scoped_ptr
<WireMessage
> message
) override
;
111 scoped_ptr
<WireMessage
> DeserializeWireMessage(
112 bool* is_incomplete_message
) override
;
114 // device::BluetoothAdapter::Observer:
115 void DeviceChanged(device::BluetoothAdapter
* adapter
,
116 device::BluetoothDevice
* device
) override
;
117 void DeviceRemoved(device::BluetoothAdapter
* adapter
,
118 device::BluetoothDevice
* device
) override
;
119 void GattCharacteristicValueChanged(
120 device::BluetoothAdapter
* adapter
,
121 device::BluetoothGattCharacteristic
* characteristic
,
122 const std::vector
<uint8
>& value
) override
;
125 // Represents a request to write |value| to a some characteristic.
126 // |is_last_write_for_wire_messsage| indicates whether this request
127 // corresponds to the last write request for some wire message.
128 // A WireMessage corresponds to exactly two WriteRequest: the first containing
129 // a kSendSignal + the size of the WireMessage, and the second containing a
130 // SendStatusSignal + the serialized WireMessage.
131 struct WriteRequest
{
132 WriteRequest(const std::vector
<uint8
>& val
, bool flag
);
135 std::vector
<uint8
> value
;
136 bool is_last_write_for_wire_message
;
137 int number_of_failed_attempts
;
140 // Called when a GATT connection is created or received by the constructor.
141 void OnGattConnectionCreated(
142 scoped_ptr
<device::BluetoothGattConnection
> gatt_connection
);
144 // Callback called when there is an error creating the connection.
145 void OnCreateGattConnectionError(
146 device::BluetoothDevice::ConnectErrorCode error_code
);
148 // Callback called when |to_peripheral_char_| and |from_peripheral_char_| were
150 void OnCharacteristicsFound(const RemoteAttribute
& service
,
151 const RemoteAttribute
& to_peripheral_char
,
152 const RemoteAttribute
& from_peripheral_char
);
154 // Callback called there was an error finding the characteristics.
155 void OnCharacteristicsFinderError(
156 const RemoteAttribute
& to_peripheral_char
,
157 const RemoteAttribute
& from_peripheral_char
);
159 // Starts a notify session for |from_peripheral_char_| when ready
160 // (SubStatus::CHARACTERISTICS_FOUND).
161 void StartNotifySession();
163 // Called when a notification session is successfully started for
164 // |from_peripheral_char_| characteristic.
165 void OnNotifySessionStarted(
166 scoped_ptr
<device::BluetoothGattNotifySession
> notify_session
);
168 // Called when there is an error starting a notification session for
169 // |from_peripheral_char_| characteristic.
170 void OnNotifySessionError(device::BluetoothGattService::GattErrorCode
);
172 // Stops |notify_session_|.
173 void StopNotifySession();
175 // Sends an invite to connect signal to the peripheral if when ready
176 // (SubStatus::NOTIFY_SESSION_READY).
177 void SendInviteToConnectSignal();
179 // Completes and updates the status accordingly.
180 void CompleteConnection();
182 // This is the only entry point for WriteRequests, which are processed
183 // accordingly the following flow:
184 // 1) |request| is enqueued;
185 // 2) |request| will be processed by ProcessNextWriteRequest() when there is
186 // no pending write request;
187 // 3) |request| will be dequeued when it's successfully processed
188 // (OnRemoteCharacteristicWritten());
189 // 4) |request| is not dequeued if it fails
190 // (OnWriteRemoteCharacteristicError()), it remains on the queue and will be
191 // retried. |request| will remain on the queue until it succeeds or it
192 // triggers a Disconnect() call (after |max_number_of_tries_|).
193 void WriteRemoteCharacteristic(WriteRequest request
);
195 // Processes the next request in |write_requests_queue_|.
196 void ProcessNextWriteRequest();
198 // Called when the BluetoothGattCharacteristic::RemoteCharacteristicWrite() is
199 // sucessfully complete.
200 void OnRemoteCharacteristicWritten(bool run_did_send_message_callback
);
202 // Called when there is an error writing to the remote characteristic
203 // |to_peripheral_char_|.
204 void OnWriteRemoteCharacteristicError(
205 bool run_did_send_message_callback
,
206 device::BluetoothGattService::GattErrorCode error
);
208 // Builds the value to be written on |to_peripheral_char_|. The value
209 // corresponds to |signal| concatenated with |payload|.
210 WriteRequest
BuildWriteRequest(const std::vector
<uint8
>& signal
,
211 const std::vector
<uint8
>& bytes
,
212 bool is_last_message_for_wire_message
);
214 // Clears |write_requests_queue_|.
215 void ClearWriteRequestsQueue();
217 // Returns the Bluetooth address of the remote device.
218 const std::string
& GetRemoteDeviceAddress();
220 // Returns the device corresponding to |remote_device_address_|.
221 device::BluetoothDevice
* GetRemoteDevice();
223 // Returns the service corresponding to |remote_service_| in the current
225 device::BluetoothGattService
* GetRemoteService();
227 // Returns the characteristic corresponding to |identifier| in the current
229 device::BluetoothGattCharacteristic
* GetGattCharacteristic(
230 const std::string
& identifier
);
232 // Convert the first 4 bytes from a byte vector to a uint32.
233 uint32
ToUint32(const std::vector
<uint8
>& bytes
);
235 // Convert an uint32 to a byte vector.
236 const std::vector
<uint8
> ToByteVector(uint32 value
);
238 // The Bluetooth adapter over which the Bluetooth connection will be made.
239 scoped_refptr
<device::BluetoothAdapter
> adapter_
;
241 // Remote service the |gatt_connection_| was established with.
242 RemoteAttribute remote_service_
;
244 // Characteristic used to send data to the remote device.
245 RemoteAttribute to_peripheral_char_
;
247 // Characteristic used to receive data from the remote device.
248 RemoteAttribute from_peripheral_char_
;
250 // The GATT connection with the remote device.
251 scoped_ptr
<device::BluetoothGattConnection
> gatt_connection_
;
253 // The characteristics finder for remote device.
254 scoped_ptr
<BluetoothLowEnergyCharacteristicsFinder
> characteristic_finder_
;
256 // The notify session for |from_peripheral_char|.
257 scoped_ptr
<device::BluetoothGattNotifySession
> notify_session_
;
259 // Internal connection status
260 SubStatus sub_status_
;
262 // Indicates a receiving operation is in progress. This is set after a
263 // ControlSignal::kSendSignal was received from the remote device.
264 bool receiving_bytes_
;
266 // Total number of bytes expected for the current receive operation.
267 std::size_t expected_number_of_incoming_bytes_
;
269 // Bytes already received for the current receive operation.
270 std::string incoming_bytes_buffer_
;
272 // Indicates there is a BluetoothGattCharacteristic::WriteRemoteCharacteristic
273 // operation pending.
274 bool write_remote_characteristic_pending_
;
276 std::queue
<WriteRequest
> write_requests_queue_
;
278 // Maximum number of tries to send any write request.
279 int max_number_of_write_attempts_
;
281 // Maximum number of bytes that fit in a single chunk to be written in
282 // |to_peripheral_char_|. Ideally, this should be the maximum value the
283 // peripheral supports and it should be agreed when the GATT connection is
284 // created. Currently, there is no API to find this value. The implementation
285 // uses a hard-coded constant.
288 // Stores when the instace was created.
289 base::TimeTicks start_time_
;
291 base::WeakPtrFactory
<BluetoothLowEnergyConnection
> weak_ptr_factory_
;
293 DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyConnection
);
296 } // namespace proximity_auth
298 #endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H