Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(172)

Side by Side Diff: components/proximity_auth/ble/bluetooth_low_energy_connection.cc

Issue 2843443003: [EasyUnlock] Delete unused BLE code. (Closed)
Patch Set: remove BUILD file Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
5 #include "components/proximity_auth/ble/bluetooth_low_energy_connection.h"
6
7 #include <utility>
8
9 #include "base/bind.h"
10 #include "base/location.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/weak_ptr.h"
13 #include "base/task_runner.h"
14 #include "base/threading/thread_task_runner_handle.h"
15 #include "base/time/time.h"
16 #include "components/cryptauth/ble/bluetooth_low_energy_characteristics_finder.h "
17 #include "components/cryptauth/ble/fake_wire_message.h"
18 #include "components/cryptauth/bluetooth_throttler.h"
19 #include "components/cryptauth/connection.h"
20 #include "components/cryptauth/connection_finder.h"
21 #include "components/cryptauth/wire_message.h"
22 #include "components/proximity_auth/logging/logging.h"
23 #include "device/bluetooth/bluetooth_adapter.h"
24 #include "device/bluetooth/bluetooth_device.h"
25 #include "device/bluetooth/bluetooth_gatt_connection.h"
26 #include "device/bluetooth/bluetooth_gatt_notify_session.h"
27 #include "device/bluetooth/bluetooth_remote_gatt_characteristic.h"
28 #include "device/bluetooth/bluetooth_uuid.h"
29
30 using device::BluetoothAdapter;
31 using device::BluetoothDevice;
32 using device::BluetoothGattConnection;
33 using device::BluetoothRemoteGattService;
34 using device::BluetoothRemoteGattCharacteristic;
35 using device::BluetoothGattNotifySession;
36 using device::BluetoothUUID;
37
38 namespace proximity_auth {
39 namespace {
40
41 // The UUID of the characteristic used to send data to the peripheral.
42 const char kToPeripheralCharUUID[] = "977c6674-1239-4e72-993b-502369b8bb5a";
43
44 // The UUID of the characteristic used to receive data from the peripheral.
45 const char kFromPeripheralCharUUID[] = "f4b904a2-a030-43b3-98a8-221c536c03cb";
46
47 // Deprecated signal send as the first byte in send byte operations.
48 const int kFirstByteZero = 0;
49
50 // The maximum number of bytes written in a remote characteristic with a single
51 // write request. This is not the connection MTU, we are assuming that the
52 // remote device allows for writes larger than MTU.
53 const int kMaxChunkSize = 500;
54 } // namespace
55
56 BluetoothLowEnergyConnection::BluetoothLowEnergyConnection(
57 const cryptauth::RemoteDevice& device,
58 scoped_refptr<device::BluetoothAdapter> adapter,
59 const BluetoothUUID remote_service_uuid,
60 cryptauth::BluetoothThrottler* bluetooth_throttler,
61 int max_number_of_write_attempts)
62 : cryptauth::Connection(device),
63 adapter_(adapter),
64 remote_service_({remote_service_uuid, ""}),
65 to_peripheral_char_({BluetoothUUID(kToPeripheralCharUUID), ""}),
66 from_peripheral_char_({BluetoothUUID(kFromPeripheralCharUUID), ""}),
67 bluetooth_throttler_(bluetooth_throttler),
68 task_runner_(base::ThreadTaskRunnerHandle::Get()),
69 sub_status_(SubStatus::DISCONNECTED),
70 receiving_bytes_(false),
71 write_remote_characteristic_pending_(false),
72 max_number_of_write_attempts_(max_number_of_write_attempts),
73 max_chunk_size_(kMaxChunkSize),
74 weak_ptr_factory_(this) {
75 DCHECK(adapter_);
76 DCHECK(adapter_->IsInitialized());
77
78 adapter_->AddObserver(this);
79 }
80
81 BluetoothLowEnergyConnection::~BluetoothLowEnergyConnection() {
82 Disconnect();
83 if (adapter_) {
84 adapter_->RemoveObserver(this);
85 adapter_ = NULL;
86 }
87 }
88
89 void BluetoothLowEnergyConnection::Connect() {
90 DCHECK(sub_status() == SubStatus::DISCONNECTED);
91
92 SetSubStatus(SubStatus::WAITING_GATT_CONNECTION);
93 base::TimeDelta throttler_delay = bluetooth_throttler_->GetDelay();
94 PA_LOG(INFO) << "Connecting in " << throttler_delay;
95
96 start_time_ = base::TimeTicks::Now();
97
98 // If necessary, wait to create a new GATT connection.
99 //
100 // Avoid creating a new GATT connection immediately after a given device was
101 // disconnected. This is a workaround for crbug.com/508919.
102 if (!throttler_delay.is_zero()) {
103 task_runner_->PostDelayedTask(
104 FROM_HERE,
105 base::Bind(&BluetoothLowEnergyConnection::CreateGattConnection,
106 weak_ptr_factory_.GetWeakPtr()),
107 throttler_delay);
108 return;
109 }
110
111 CreateGattConnection();
112 }
113
114 void BluetoothLowEnergyConnection::CreateGattConnection() {
115 DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION);
116
117 BluetoothDevice* remote_device = GetRemoteDevice();
118 if (remote_device) {
119 PA_LOG(INFO) << "Creating GATT connection with "
120 << remote_device->GetAddress();
121
122 remote_device->CreateGattConnection(
123 base::Bind(&BluetoothLowEnergyConnection::OnGattConnectionCreated,
124 weak_ptr_factory_.GetWeakPtr()),
125 base::Bind(&BluetoothLowEnergyConnection::OnCreateGattConnectionError,
126 weak_ptr_factory_.GetWeakPtr()));
127 }
128 }
129
130 void BluetoothLowEnergyConnection::Disconnect() {
131 if (sub_status() != SubStatus::DISCONNECTED) {
132 weak_ptr_factory_.InvalidateWeakPtrs();
133 StopNotifySession();
134 characteristic_finder_.reset();
135 if (gatt_connection_) {
136 PA_LOG(INFO) << "Disconnect from device "
137 << gatt_connection_->GetDeviceAddress();
138
139 // Destroying BluetoothGattConnection also disconnects it.
140 gatt_connection_.reset();
141 }
142
143 // Only transition to the DISCONNECTED state after perfoming all necessary
144 // operations. Otherwise, it'll trigger observers that can pontentially
145 // destroy the current instance (causing a crash).
146 SetSubStatus(SubStatus::DISCONNECTED);
147 }
148 }
149
150 void BluetoothLowEnergyConnection::SetSubStatus(SubStatus new_sub_status) {
151 sub_status_ = new_sub_status;
152
153 // Sets the status of parent class cryptauth::Connection accordingly.
154 if (new_sub_status == SubStatus::CONNECTED) {
155 SetStatus(CONNECTED);
156 } else if (new_sub_status == SubStatus::DISCONNECTED) {
157 SetStatus(DISCONNECTED);
158 } else {
159 SetStatus(IN_PROGRESS);
160 }
161 }
162
163 void BluetoothLowEnergyConnection::SetTaskRunnerForTesting(
164 scoped_refptr<base::TaskRunner> task_runner) {
165 task_runner_ = task_runner;
166 }
167
168 void BluetoothLowEnergyConnection::SendMessageImpl(
169 std::unique_ptr<cryptauth::WireMessage> message) {
170 PA_LOG(INFO) << "Sending message " << message->Serialize();
171 std::string serialized_msg = message->Serialize();
172
173 // [First write]: Build a header with the [send signal] + [size of the
174 // message].
175 WriteRequest write_request = BuildWriteRequest(
176 ToByteVector(static_cast<uint32_t>(ControlSignal::kSendSignal)),
177 ToByteVector(static_cast<uint32_t>(serialized_msg.size())), false);
178
179 // [First write]: Fill the it with a prefix of |serialized_msg| up to
180 // |max_chunk_size_|.
181 size_t first_chunk_size = std::min(
182 max_chunk_size_ - write_request.value.size(), serialized_msg.size());
183 std::vector<uint8_t> bytes(serialized_msg.begin(),
184 serialized_msg.begin() + first_chunk_size);
185 write_request.value.insert(write_request.value.end(), bytes.begin(),
186 bytes.end());
187
188 bool is_last_write_request = first_chunk_size == serialized_msg.size();
189 write_request.is_last_write_for_wire_message = is_last_write_request;
190 WriteRemoteCharacteristic(write_request);
191 if (is_last_write_request)
192 return;
193
194 // [Other write requests]: Each chunk has to include a deprecated signal:
195 // |kFirstByteZero| as the first byte.
196 int chunk_size = max_chunk_size_ - 1;
197 std::vector<uint8_t> kFirstByteZeroVector;
198 kFirstByteZeroVector.push_back(static_cast<uint8_t>(kFirstByteZero));
199
200 int message_size = static_cast<int>(serialized_msg.size());
201 int start_index = first_chunk_size;
202 while (start_index < message_size) {
203 int end_index = (start_index + chunk_size) <= message_size
204 ? (start_index + chunk_size)
205 : message_size;
206 bool is_last_write_request = (end_index == message_size);
207 write_request = BuildWriteRequest(
208 kFirstByteZeroVector,
209 std::vector<uint8_t>(serialized_msg.begin() + start_index,
210 serialized_msg.begin() + end_index),
211 is_last_write_request);
212 WriteRemoteCharacteristic(write_request);
213 start_index = end_index;
214 }
215 }
216
217 // Changes in the GATT connection with the remote device should be observed
218 // here. If the GATT connection is dropped, we should call Disconnect() anyway,
219 // so the object can notify its observers.
220 void BluetoothLowEnergyConnection::DeviceChanged(BluetoothAdapter* adapter,
221 BluetoothDevice* device) {
222 DCHECK(device);
223 if (sub_status() == SubStatus::DISCONNECTED ||
224 device->GetAddress() != GetDeviceAddress())
225 return;
226
227 if (sub_status() != SubStatus::WAITING_GATT_CONNECTION &&
228 !device->IsConnected()) {
229 PA_LOG(INFO) << "GATT connection dropped " << GetDeviceAddress()
230 << "\ndevice connected: " << device->IsConnected()
231 << "\ngatt connection: "
232 << (gatt_connection_ ? gatt_connection_->IsConnected()
233 : false);
234 Disconnect();
235 }
236 }
237
238 void BluetoothLowEnergyConnection::DeviceRemoved(BluetoothAdapter* adapter,
239 BluetoothDevice* device) {
240 DCHECK(device);
241 if (sub_status_ == SubStatus::DISCONNECTED ||
242 device->GetAddress() != GetDeviceAddress())
243 return;
244
245 PA_LOG(INFO) << "Device removed " << GetDeviceAddress();
246 Disconnect();
247 }
248
249 void BluetoothLowEnergyConnection::GattCharacteristicValueChanged(
250 BluetoothAdapter* adapter,
251 BluetoothRemoteGattCharacteristic* characteristic,
252 const std::vector<uint8_t>& value) {
253 DCHECK_EQ(adapter, adapter_.get());
254 if (sub_status() != SubStatus::WAITING_RESPONSE_SIGNAL &&
255 sub_status() != SubStatus::CONNECTED)
256 return;
257
258 PA_LOG(INFO) << "Characteristic value changed: "
259 << characteristic->GetUUID().canonical_value();
260
261 if (characteristic->GetIdentifier() == from_peripheral_char_.id) {
262 if (receiving_bytes_) {
263 // Ignoring the first byte, as it contains a deprecated signal.
264 const std::string bytes(value.begin() + 1, value.end());
265 incoming_bytes_buffer_.append(bytes);
266 if (incoming_bytes_buffer_.size() >= expected_number_of_incoming_bytes_) {
267 OnBytesReceived(incoming_bytes_buffer_);
268 receiving_bytes_ = false;
269 }
270 return;
271 }
272
273 if (value.size() < 4) {
274 PA_LOG(WARNING) << "Incoming data corrupted, no signal found.";
275 return;
276 }
277
278 const ControlSignal signal = static_cast<ControlSignal>(ToUint32(value));
279 switch (signal) {
280 case ControlSignal::kInvitationResponseSignal:
281 if (sub_status() == SubStatus::WAITING_RESPONSE_SIGNAL)
282 CompleteConnection();
283 break;
284 case ControlSignal::kInviteToConnectSignal:
285 break;
286 case ControlSignal::kSendSignal: {
287 if (value.size() < 8) {
288 PA_LOG(WARNING)
289 << "Incoming data corrupted, expected message size not found.";
290 return;
291 }
292 std::vector<uint8_t> size(value.begin() + 4, value.begin() + 8);
293 expected_number_of_incoming_bytes_ =
294 static_cast<size_t>(ToUint32(size));
295 receiving_bytes_ = true;
296 incoming_bytes_buffer_.clear();
297
298 const std::string bytes(value.begin() + 8, value.end());
299 incoming_bytes_buffer_.append(bytes);
300 if (incoming_bytes_buffer_.size() >=
301 expected_number_of_incoming_bytes_) {
302 OnBytesReceived(incoming_bytes_buffer_);
303 receiving_bytes_ = false;
304 }
305 break;
306 }
307 case ControlSignal::kDisconnectSignal:
308 PA_LOG(INFO) << "Disconnect signal received.";
309 Disconnect();
310 break;
311 }
312 }
313 }
314
315 BluetoothLowEnergyConnection::WriteRequest::WriteRequest(
316 const std::vector<uint8_t>& val,
317 bool flag)
318 : value(val),
319 is_last_write_for_wire_message(flag),
320 number_of_failed_attempts(0) {}
321
322 BluetoothLowEnergyConnection::WriteRequest::WriteRequest(
323 const WriteRequest& other) = default;
324
325 BluetoothLowEnergyConnection::WriteRequest::~WriteRequest() {}
326
327 void BluetoothLowEnergyConnection::CompleteConnection() {
328 PA_LOG(INFO) << "Connection completed. Time elapsed: "
329 << base::TimeTicks::Now() - start_time_;
330 SetSubStatus(SubStatus::CONNECTED);
331 }
332
333 void BluetoothLowEnergyConnection::OnCreateGattConnectionError(
334 device::BluetoothDevice::ConnectErrorCode error_code) {
335 DCHECK(sub_status_ == SubStatus::WAITING_GATT_CONNECTION);
336 PA_LOG(WARNING) << "Error creating GATT connection to "
337 << remote_device().bluetooth_address
338 << "error code: " << error_code;
339 Disconnect();
340 }
341
342 void BluetoothLowEnergyConnection::OnGattConnectionCreated(
343 std::unique_ptr<device::BluetoothGattConnection> gatt_connection) {
344 DCHECK(sub_status() == SubStatus::WAITING_GATT_CONNECTION);
345 PA_LOG(INFO) << "GATT connection with " << gatt_connection->GetDeviceAddress()
346 << " created.";
347 PrintTimeElapsed();
348
349 // Informing |bluetooth_trottler_| a new connection was established.
350 bluetooth_throttler_->OnConnection(this);
351
352 gatt_connection_ = std::move(gatt_connection);
353 SetSubStatus(SubStatus::WAITING_CHARACTERISTICS);
354 characteristic_finder_.reset(CreateCharacteristicsFinder(
355 base::Bind(&BluetoothLowEnergyConnection::OnCharacteristicsFound,
356 weak_ptr_factory_.GetWeakPtr()),
357 base::Bind(&BluetoothLowEnergyConnection::OnCharacteristicsFinderError,
358 weak_ptr_factory_.GetWeakPtr())));
359 }
360
361 cryptauth::BluetoothLowEnergyCharacteristicsFinder*
362 BluetoothLowEnergyConnection::CreateCharacteristicsFinder(
363 const cryptauth::BluetoothLowEnergyCharacteristicsFinder::SuccessCallback&
364 success_callback,
365 const cryptauth::BluetoothLowEnergyCharacteristicsFinder::ErrorCallback&
366 error_callback) {
367 return new cryptauth::BluetoothLowEnergyCharacteristicsFinder(
368 adapter_, GetRemoteDevice(), remote_service_, to_peripheral_char_,
369 from_peripheral_char_, success_callback, error_callback);
370 }
371
372 void BluetoothLowEnergyConnection::OnCharacteristicsFound(
373 const cryptauth::RemoteAttribute& service,
374 const cryptauth::RemoteAttribute& to_peripheral_char,
375 const cryptauth::RemoteAttribute& from_peripheral_char) {
376 PA_LOG(INFO) << "Remote chacteristics found.";
377 PrintTimeElapsed();
378
379 DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS);
380 remote_service_ = service;
381 to_peripheral_char_ = to_peripheral_char;
382 from_peripheral_char_ = from_peripheral_char;
383
384 SetSubStatus(SubStatus::CHARACTERISTICS_FOUND);
385 StartNotifySession();
386 }
387
388 void BluetoothLowEnergyConnection::OnCharacteristicsFinderError(
389 const cryptauth::RemoteAttribute& to_peripheral_char,
390 const cryptauth::RemoteAttribute& from_peripheral_char) {
391 DCHECK(sub_status() == SubStatus::WAITING_CHARACTERISTICS);
392 PA_LOG(WARNING) << "Connection error, missing characteristics for SmartLock "
393 "service.\n"
394 << (to_peripheral_char.id.empty()
395 ? to_peripheral_char.uuid.canonical_value()
396 : "")
397 << (from_peripheral_char.id.empty()
398 ? ", " + from_peripheral_char.uuid.canonical_value()
399 : "") << " not found.";
400
401 Disconnect();
402 }
403
404 void BluetoothLowEnergyConnection::StartNotifySession() {
405 if (sub_status() == SubStatus::CHARACTERISTICS_FOUND) {
406 BluetoothRemoteGattCharacteristic* characteristic =
407 GetGattCharacteristic(from_peripheral_char_.id);
408 DCHECK(characteristic);
409
410 // This is a workaround for crbug.com/507325. If |characteristic| is already
411 // notifying |characteristic->StartNotifySession()| will fail with
412 // GATT_ERROR_FAILED.
413 if (characteristic->IsNotifying()) {
414 PA_LOG(INFO) << characteristic->GetUUID().canonical_value()
415 << " already notifying.";
416 SetSubStatus(SubStatus::NOTIFY_SESSION_READY);
417 SendInviteToConnectSignal();
418 return;
419 }
420
421 SetSubStatus(SubStatus::WAITING_NOTIFY_SESSION);
422 characteristic->StartNotifySession(
423 base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionStarted,
424 weak_ptr_factory_.GetWeakPtr()),
425 base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionError,
426 weak_ptr_factory_.GetWeakPtr()));
427 }
428 }
429
430 void BluetoothLowEnergyConnection::OnNotifySessionError(
431 BluetoothRemoteGattService::GattErrorCode error) {
432 DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION);
433 PA_LOG(WARNING) << "Error starting notification session: " << error;
434 Disconnect();
435 }
436
437 void BluetoothLowEnergyConnection::OnNotifySessionStarted(
438 std::unique_ptr<BluetoothGattNotifySession> notify_session) {
439 DCHECK(sub_status() == SubStatus::WAITING_NOTIFY_SESSION);
440 PA_LOG(INFO) << "Notification session started "
441 << notify_session->GetCharacteristicIdentifier();
442 PrintTimeElapsed();
443
444 SetSubStatus(SubStatus::NOTIFY_SESSION_READY);
445 notify_session_ = std::move(notify_session);
446
447 SendInviteToConnectSignal();
448 }
449
450 void BluetoothLowEnergyConnection::StopNotifySession() {
451 if (notify_session_) {
452 notify_session_->Stop(base::Bind(&base::DoNothing));
453 notify_session_.reset();
454 }
455 }
456
457 void BluetoothLowEnergyConnection::SendInviteToConnectSignal() {
458 if (sub_status() == SubStatus::NOTIFY_SESSION_READY) {
459 PA_LOG(INFO) << "Sending invite to connect signal";
460 SetSubStatus(SubStatus::WAITING_RESPONSE_SIGNAL);
461
462 WriteRequest write_request = BuildWriteRequest(
463 ToByteVector(
464 static_cast<uint32_t>(ControlSignal::kInviteToConnectSignal)),
465 std::vector<uint8_t>(), false);
466
467 WriteRemoteCharacteristic(write_request);
468 }
469 }
470
471 void BluetoothLowEnergyConnection::WriteRemoteCharacteristic(
472 WriteRequest request) {
473 write_requests_queue_.push(request);
474 ProcessNextWriteRequest();
475 }
476
477 void BluetoothLowEnergyConnection::ProcessNextWriteRequest() {
478 BluetoothRemoteGattCharacteristic* characteristic =
479 GetGattCharacteristic(to_peripheral_char_.id);
480 if (!write_requests_queue_.empty() && !write_remote_characteristic_pending_ &&
481 characteristic) {
482 write_remote_characteristic_pending_ = true;
483 WriteRequest next_request = write_requests_queue_.front();
484 PA_LOG(INFO) << "Writing characteristic...";
485 characteristic->WriteRemoteCharacteristic(
486 next_request.value,
487 base::Bind(&BluetoothLowEnergyConnection::OnRemoteCharacteristicWritten,
488 weak_ptr_factory_.GetWeakPtr(),
489 next_request.is_last_write_for_wire_message),
490 base::Bind(
491 &BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError,
492 weak_ptr_factory_.GetWeakPtr(),
493 next_request.is_last_write_for_wire_message));
494 }
495 }
496
497 void BluetoothLowEnergyConnection::OnRemoteCharacteristicWritten(
498 bool run_did_send_message_callback) {
499 PA_LOG(INFO) << "Characteristic written.";
500 write_remote_characteristic_pending_ = false;
501 // TODO(sacomoto): Actually pass the current message to the observer.
502 if (run_did_send_message_callback)
503 OnDidSendMessage(cryptauth::WireMessage(std::string(), std::string()),
504 true);
505
506 // Removes the top of queue (already processed) and process the next request.
507 DCHECK(!write_requests_queue_.empty());
508 write_requests_queue_.pop();
509 ProcessNextWriteRequest();
510 }
511
512 void BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError(
513 bool run_did_send_message_callback,
514 BluetoothRemoteGattService::GattErrorCode error) {
515 PA_LOG(WARNING) << "Error " << error << " writing characteristic: "
516 << to_peripheral_char_.uuid.canonical_value();
517 write_remote_characteristic_pending_ = false;
518 // TODO(sacomoto): Actually pass the current message to the observer.
519 if (run_did_send_message_callback)
520 OnDidSendMessage(cryptauth::WireMessage(std::string(), std::string()),
521 false);
522
523 // Increases the number of failed attempts and retry.
524 DCHECK(!write_requests_queue_.empty());
525 if (++write_requests_queue_.front().number_of_failed_attempts >=
526 max_number_of_write_attempts_) {
527 Disconnect();
528 return;
529 }
530 ProcessNextWriteRequest();
531 }
532
533 BluetoothLowEnergyConnection::WriteRequest
534 BluetoothLowEnergyConnection::BuildWriteRequest(
535 const std::vector<uint8_t>& signal,
536 const std::vector<uint8_t>& bytes,
537 bool is_last_write_for_wire_message) {
538 std::vector<uint8_t> value(signal.begin(), signal.end());
539 value.insert(value.end(), bytes.begin(), bytes.end());
540 return WriteRequest(value, is_last_write_for_wire_message);
541 }
542
543 void BluetoothLowEnergyConnection::PrintTimeElapsed() {
544 PA_LOG(INFO) << "Time elapsed: " << base::TimeTicks::Now() - start_time_;
545 }
546
547 std::string BluetoothLowEnergyConnection::GetDeviceAddress() {
548 // When the remote device is connected we should rely on the address given by
549 // |gatt_connection_|. As the device address may change if the device is
550 // paired. The address in |gatt_connection_| is automatically updated in this
551 // case.
552 return gatt_connection_ ? gatt_connection_->GetDeviceAddress()
553 : remote_device().bluetooth_address;
554 }
555
556 BluetoothDevice* BluetoothLowEnergyConnection::GetRemoteDevice() {
557 // It's not possible to simply use
558 // |adapter_->GetDevice(GetDeviceAddress())| to find the device with MAC
559 // address |GetDeviceAddress()|. For paired devices,
560 // BluetoothAdapter::GetDevice(XXX) searches for the temporary MAC address
561 // XXX, whereas |GetDeviceAddress()| is the real MAC address. This is a
562 // bug in the way device::BluetoothAdapter is storing the devices (see
563 // crbug.com/497841).
564 std::vector<BluetoothDevice*> devices = adapter_->GetDevices();
565 for (auto* device : devices) {
566 if (device->GetAddress() == GetDeviceAddress())
567 return device;
568 }
569
570 return nullptr;
571 }
572
573 BluetoothRemoteGattService* BluetoothLowEnergyConnection::GetRemoteService() {
574 BluetoothDevice* remote_device = GetRemoteDevice();
575 if (!remote_device) {
576 PA_LOG(WARNING) << "Remote device not found.";
577 return NULL;
578 }
579 if (remote_service_.id.empty()) {
580 std::vector<BluetoothRemoteGattService*> services =
581 remote_device->GetGattServices();
582 for (const auto* service : services)
583 if (service->GetUUID() == remote_service_.uuid) {
584 remote_service_.id = service->GetIdentifier();
585 break;
586 }
587 }
588 return remote_device->GetGattService(remote_service_.id);
589 }
590
591 BluetoothRemoteGattCharacteristic*
592 BluetoothLowEnergyConnection::GetGattCharacteristic(
593 const std::string& gatt_characteristic) {
594 BluetoothRemoteGattService* remote_service = GetRemoteService();
595 if (!remote_service) {
596 PA_LOG(WARNING) << "Remote service not found.";
597 return NULL;
598 }
599 return remote_service->GetCharacteristic(gatt_characteristic);
600 }
601
602 // TODO(sacomoto): make this robust to byte ordering in both sides of the
603 // SmartLock BLE socket.
604 uint32_t BluetoothLowEnergyConnection::ToUint32(
605 const std::vector<uint8_t>& bytes) {
606 return bytes[0] | (bytes[1] << 8) | (bytes[2] << 16) | (bytes[3] << 24);
607 }
608
609 // TODO(sacomoto): make this robust to byte ordering in both sides of the
610 // SmartLock BLE socket.
611 const std::vector<uint8_t> BluetoothLowEnergyConnection::ToByteVector(
612 const uint32_t value) {
613 std::vector<uint8_t> bytes(4, 0);
614 bytes[0] = static_cast<uint8_t>(value);
615 bytes[1] = static_cast<uint8_t>(value >> 8);
616 bytes[2] = static_cast<uint8_t>(value >> 16);
617 bytes[3] = static_cast<uint8_t>(value >> 24);
618 return bytes;
619 }
620
621 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698