Vectorize website settings icons in omnibox
[chromium-blink-merge.git] / components / proximity_auth / ble / bluetooth_low_energy_connection.h
blob0efec2abc7ecd0403577d600a250718c8287a937
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
8 #include <queue>
9 #include <string>
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 base {
27 class TaskRunner;
30 namespace proximity_auth {
32 class BluetoothThrottler;
34 // Represents a connection with a remote device over Bluetooth low energy. The
35 // connection is a persistent bidirectional channel for sending and receiving
36 // wire messages. The remote device is the peripheral mode and the service
37 // contains two characteristics: one to send data and another to receive it.
39 // The connection flow is described below.
41 // Discover Reader and Writer Characteristics
42 // |
43 // |
44 // |
45 // Start Notify Session
46 // |
47 // |
48 // |
49 // Write kInviteToConnectSignal to Writer Characteristic
50 // |
51 // |
52 // |
53 // Read kInvitationResponseSignal from Reader Characteristic
54 // |
55 // |
56 // |
57 // Proximity Auth Connection Established
58 class BluetoothLowEnergyConnection : public Connection,
59 public device::BluetoothAdapter::Observer {
60 public:
61 // Signals sent to the remote device to indicate connection related events.
62 enum class ControlSignal : uint32 {
63 kInviteToConnectSignal = 0,
64 kInvitationResponseSignal = 1,
65 kSendSignal = 2,
66 kDisconnectSignal = 3,
69 // The sub-state of a proximity_auth::BluetoothLowEnergyConnection class
70 // extends the IN_PROGRESS state of proximity_auth::Connection::Status.
71 enum class SubStatus {
72 DISCONNECTED,
73 WAITING_GATT_CONNECTION,
74 WAITING_CHARACTERISTICS,
75 CHARACTERISTICS_FOUND,
76 WAITING_NOTIFY_SESSION,
77 NOTIFY_SESSION_READY,
78 WAITING_RESPONSE_SIGNAL,
79 CONNECTED,
82 // Constructs a Bluetooth low energy connection to the service with
83 // |remote_service_| on the |remote_device|. The |adapter| must be already
84 // initaalized and ready. The GATT connection may alreaady be established and
85 // pass through |gatt_connection|. A subsequent call to Connect() must be
86 // made.
87 BluetoothLowEnergyConnection(
88 const RemoteDevice& remote_device,
89 scoped_refptr<device::BluetoothAdapter> adapter,
90 const device::BluetoothUUID remote_service_uuid,
91 const device::BluetoothUUID to_peripheral_char_uuid,
92 const device::BluetoothUUID from_peripheral_char_uuid,
93 BluetoothThrottler* bluetooth_throttler,
94 int max_number_of_write_attempts);
96 ~BluetoothLowEnergyConnection() override;
98 // proximity_auth::Connection:
99 void Connect() override;
100 void Disconnect() override;
102 protected:
103 // Exposed for testing.
104 void SetSubStatus(SubStatus status);
105 SubStatus sub_status() { return sub_status_; }
107 // Sets |task_runner_| for testing.
108 void SetTaskRunnerForTesting(scoped_refptr<base::TaskRunner> task_runner);
110 // Virtual for testing.
111 virtual BluetoothLowEnergyCharacteristicsFinder* CreateCharacteristicsFinder(
112 const BluetoothLowEnergyCharacteristicsFinder::SuccessCallback&
113 success_callback,
114 const BluetoothLowEnergyCharacteristicsFinder::ErrorCallback&
115 error_callback);
117 // proximity_auth::Connection:
118 void SendMessageImpl(scoped_ptr<WireMessage> message) override;
120 // device::BluetoothAdapter::Observer:
121 void DeviceChanged(device::BluetoothAdapter* adapter,
122 device::BluetoothDevice* device) override;
123 void DeviceRemoved(device::BluetoothAdapter* adapter,
124 device::BluetoothDevice* device) override;
125 void GattCharacteristicValueChanged(
126 device::BluetoothAdapter* adapter,
127 device::BluetoothGattCharacteristic* characteristic,
128 const std::vector<uint8>& value) override;
130 private:
131 // Represents a request to write |value| to a some characteristic.
132 // |is_last_write_for_wire_messsage| indicates whether this request
133 // corresponds to the last write request for some wire message.
134 // A WireMessage corresponds to exactly two WriteRequest: the first containing
135 // a kSendSignal + the size of the WireMessage, and the second containing a
136 // SendStatusSignal + the serialized WireMessage.
137 struct WriteRequest {
138 WriteRequest(const std::vector<uint8>& val, bool flag);
139 ~WriteRequest();
141 std::vector<uint8> value;
142 bool is_last_write_for_wire_message;
143 int number_of_failed_attempts;
146 // Creates the GATT connection with |remote_device|.
147 void CreateGattConnection();
149 // Called when a GATT connection is created.
150 void OnGattConnectionCreated(
151 scoped_ptr<device::BluetoothGattConnection> gatt_connection);
153 // Callback called when there is an error creating the GATT connection.
154 void OnCreateGattConnectionError(
155 device::BluetoothDevice::ConnectErrorCode error_code);
157 // Callback called when |to_peripheral_char_| and |from_peripheral_char_| were
158 // found.
159 void OnCharacteristicsFound(const RemoteAttribute& service,
160 const RemoteAttribute& to_peripheral_char,
161 const RemoteAttribute& from_peripheral_char);
163 // Callback called there was an error finding the characteristics.
164 void OnCharacteristicsFinderError(
165 const RemoteAttribute& to_peripheral_char,
166 const RemoteAttribute& from_peripheral_char);
168 // Starts a notify session for |from_peripheral_char_| when ready
169 // (SubStatus::CHARACTERISTICS_FOUND).
170 void StartNotifySession();
172 // Called when a notification session is successfully started for
173 // |from_peripheral_char_| characteristic.
174 void OnNotifySessionStarted(
175 scoped_ptr<device::BluetoothGattNotifySession> notify_session);
177 // Called when there is an error starting a notification session for
178 // |from_peripheral_char_| characteristic.
179 void OnNotifySessionError(device::BluetoothGattService::GattErrorCode);
181 // Stops |notify_session_|.
182 void StopNotifySession();
184 // Sends an invite to connect signal to the peripheral if when ready
185 // (SubStatus::NOTIFY_SESSION_READY).
186 void SendInviteToConnectSignal();
188 // Completes and updates the status accordingly.
189 void CompleteConnection();
191 // This is the only entry point for WriteRequests, which are processed
192 // accordingly the following flow:
193 // 1) |request| is enqueued;
194 // 2) |request| will be processed by ProcessNextWriteRequest() when there is
195 // no pending write request;
196 // 3) |request| will be dequeued when it's successfully processed
197 // (OnRemoteCharacteristicWritten());
198 // 4) |request| is not dequeued if it fails
199 // (OnWriteRemoteCharacteristicError()), it remains on the queue and will be
200 // retried. |request| will remain on the queue until it succeeds or it
201 // triggers a Disconnect() call (after |max_number_of_tries_|).
202 void WriteRemoteCharacteristic(WriteRequest request);
204 // Processes the next request in |write_requests_queue_|.
205 void ProcessNextWriteRequest();
207 // Called when the BluetoothGattCharacteristic::RemoteCharacteristicWrite() is
208 // sucessfully complete.
209 void OnRemoteCharacteristicWritten(bool run_did_send_message_callback);
211 // Called when there is an error writing to the remote characteristic
212 // |to_peripheral_char_|.
213 void OnWriteRemoteCharacteristicError(
214 bool run_did_send_message_callback,
215 device::BluetoothGattService::GattErrorCode error);
217 // Builds the value to be written on |to_peripheral_char_|. The value
218 // corresponds to |signal| concatenated with |payload|.
219 WriteRequest BuildWriteRequest(const std::vector<uint8>& signal,
220 const std::vector<uint8>& bytes,
221 bool is_last_message_for_wire_message);
223 // Clears |write_requests_queue_|.
224 void ClearWriteRequestsQueue();
226 // Returns the Bluetooth address of the remote device.
227 const std::string& GetRemoteDeviceAddress();
229 // Returns the device corresponding to |remote_device_address_|.
230 device::BluetoothDevice* GetRemoteDevice();
232 // Returns the service corresponding to |remote_service_| in the current
233 // device.
234 device::BluetoothGattService* GetRemoteService();
236 // Returns the characteristic corresponding to |identifier| in the current
237 // service.
238 device::BluetoothGattCharacteristic* GetGattCharacteristic(
239 const std::string& identifier);
241 // Convert the first 4 bytes from a byte vector to a uint32.
242 uint32 ToUint32(const std::vector<uint8>& bytes);
244 // Convert an uint32 to a byte vector.
245 const std::vector<uint8> ToByteVector(uint32 value);
247 // The Bluetooth adapter over which the Bluetooth connection will be made.
248 scoped_refptr<device::BluetoothAdapter> adapter_;
250 // Remote service the |gatt_connection_| was established with.
251 RemoteAttribute remote_service_;
253 // Characteristic used to send data to the remote device.
254 RemoteAttribute to_peripheral_char_;
256 // Characteristic used to receive data from the remote device.
257 RemoteAttribute from_peripheral_char_;
259 // Throttles repeated connection attempts to the same device. This is a
260 // workaround for crbug.com/508919. Not owned, must outlive this instance.
261 BluetoothThrottler* bluetooth_throttler_;
263 scoped_refptr<base::TaskRunner> task_runner_;
265 // The GATT connection with the remote device.
266 scoped_ptr<device::BluetoothGattConnection> gatt_connection_;
268 // The characteristics finder for remote device.
269 scoped_ptr<BluetoothLowEnergyCharacteristicsFinder> characteristic_finder_;
271 // The notify session for |from_peripheral_char|.
272 scoped_ptr<device::BluetoothGattNotifySession> notify_session_;
274 // Internal connection status
275 SubStatus sub_status_;
277 // Indicates a receiving operation is in progress. This is set after a
278 // ControlSignal::kSendSignal was received from the remote device.
279 bool receiving_bytes_;
281 // Total number of bytes expected for the current receive operation.
282 std::size_t expected_number_of_incoming_bytes_;
284 // Bytes already received for the current receive operation.
285 std::string incoming_bytes_buffer_;
287 // Indicates there is a BluetoothGattCharacteristic::WriteRemoteCharacteristic
288 // operation pending.
289 bool write_remote_characteristic_pending_;
291 std::queue<WriteRequest> write_requests_queue_;
293 // Maximum number of tries to send any write request.
294 int max_number_of_write_attempts_;
296 // Maximum number of bytes that fit in a single chunk to be written in
297 // |to_peripheral_char_|. Ideally, this should be the maximum value the
298 // peripheral supports and it should be agreed when the GATT connection is
299 // created. Currently, there is no API to find this value. The implementation
300 // uses a hard-coded constant.
301 int max_chunk_size_;
303 // Stores when the instace was created.
304 base::TimeTicks start_time_;
306 // Delay imposed after a GATT connection is created and before any read/write
307 // request is sent to the characteristics. This delay is necessary as a
308 // workaroud for crbug.com/507325. Reading/writing characteristics
309 // immediatelly after the connection is complete fails with GATT_ERROR_FAILED.
310 base::TimeDelta delay_after_gatt_connection_;
312 base::WeakPtrFactory<BluetoothLowEnergyConnection> weak_ptr_factory_;
314 DISALLOW_COPY_AND_ASSIGN(BluetoothLowEnergyConnection);
317 } // namespace proximity_auth
319 #endif // COMPONENTS_PROXIMITY_AUTH_BLUETOOTH_LOW_ENERGY_CONNECTION_H