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

Unified Diff: components/proximity_auth/ble/bluetooth_low_energy_connection.cc

Issue 1116963002: Bluetooth low energy connection. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Removing debug messages Created 5 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 side-by-side diff with in-line comments
Download patch
Index: components/proximity_auth/ble/bluetooth_low_energy_connection.cc
diff --git a/components/proximity_auth/ble/bluetooth_low_energy_connection.cc b/components/proximity_auth/ble/bluetooth_low_energy_connection.cc
new file mode 100644
index 0000000000000000000000000000000000000000..bb671b1a04b45c7881a5d1835e7a93b5c9920107
--- /dev/null
+++ b/components/proximity_auth/ble/bluetooth_low_energy_connection.cc
@@ -0,0 +1,274 @@
+// Copyright 2015 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.
+
+#include "components/proximity_auth/ble/bluetooth_low_energy_connection.h"
+
+#include "base/bind.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/weak_ptr.h"
+#include "components/proximity_auth/connection_finder.h"
+#include "components/proximity_auth/ble/fake_wire_message.h"
+#include "components/proximity_auth/wire_message.h"
+#include "device/bluetooth/bluetooth_adapter.h"
+#include "device/bluetooth/bluetooth_device.h"
+#include "device/bluetooth/bluetooth_gatt_characteristic.h"
+#include "device/bluetooth/bluetooth_gatt_connection.h"
+#include "device/bluetooth/bluetooth_gatt_notify_session.h"
+#include "device/bluetooth/bluetooth_uuid.h"
+
+using device::BluetoothAdapter;
+using device::BluetoothDevice;
+using device::BluetoothGattConnection;
+using device::BluetoothGattService;
+using device::BluetoothGattCharacteristic;
+using device::BluetoothGattNotifySession;
+using device::BluetoothUUID;
+
+namespace proximity_auth {
+
+BluetoothLowEnergyConnection::BluetoothLowEnergyConnection(
+ const RemoteDevice& device,
+ scoped_refptr<device::BluetoothAdapter> adapter,
+ BluetoothUUID remote_service_uuid,
+ scoped_ptr<BluetoothGattConnection> gatt_connection)
+ : Connection(device),
+ adapter_(adapter),
+ remote_service_uuid_(remote_service_uuid),
+ connection_(gatt_connection.Pass()),
+ notify_session_pending_(false),
+ weak_ptr_factory_(this) {
+ if (connection_) {
msarda 2015/05/05 11:56:13 Can |connection_| be null? If not, then it is bett
sacomoto 2015/05/06 13:47:58 Done.
+ SetStatus(IN_PROGRESS);
+ }
+
+ if (adapter_) {
msarda 2015/05/05 11:56:14 DCHECK(adapter_)?
sacomoto 2015/05/06 13:47:58 Done.
+ adapter_->AddObserver(this);
+ }
+}
+
+BluetoothLowEnergyConnection::~BluetoothLowEnergyConnection() {
+ Disconnect();
+ if (adapter_) {
+ adapter_->RemoveObserver(this);
+ adapter_ = NULL;
+ }
+}
+
+void BluetoothLowEnergyConnection::Connect() {
+ NOTREACHED();
+}
+
+void BluetoothLowEnergyConnection::Disconnect() {
+ StopNotifySession();
+ if (connection_) {
+ connection_.reset();
+ BluetoothDevice* device = GetRemoteDevice();
+ if (device) {
+ VLOG(1) << "Forget device " << device->GetAddress();
+ device->Forget(base::Bind(&base::DoNothing));
msarda 2015/05/05 11:56:14 Please add a comment that disconnect actually forg
sacomoto 2015/05/06 13:47:58 Done.
+ }
+ }
+}
+
+// TODO(sacomoto): Send a Socketeer incoming signal. Implement a sender with
msarda 2015/05/05 11:56:13 Remove all reference to Socketeer.
sacomoto 2015/05/06 13:47:58 Done.
+// full support for messages larger than a single characteristic value.
+void BluetoothLowEnergyConnection::SendMessageImpl(
+ scoped_ptr<WireMessage> message) {
+ DCHECK(!GetGattCharacteristic(to_peripheral_char_id_));
+ VLOG(1) << "Sending message " << message->Serialize();
+
+ std::string serialized_message = message->Serialize();
+ std::vector<uint8> bytes(serialized_message.begin(),
+ serialized_message.end());
+
+ GetGattCharacteristic(to_peripheral_char_id_)
+ ->WriteRemoteCharacteristic(
+ bytes, base::Bind(&base::DoNothing),
+ base::Bind(
+ &BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothLowEnergyConnection::DeviceRemoved(BluetoothAdapter* adapter,
+ BluetoothDevice* device) {
+ if (device && device->GetAddress() == remote_device_address()) {
+ VLOG(1) << "device removed " << remote_device_address();
msarda 2015/05/05 11:56:13 Log should state with CAPS: s/device/Device
sacomoto 2015/05/06 13:47:57 Done.
+ Disconnect();
+ }
+}
+
+void BluetoothLowEnergyConnection::GattDiscoveryCompleteForService(
+ BluetoothAdapter* adapter,
+ BluetoothGattService* service) {
+ if (service && service->GetUUID() == remote_service_uuid_) {
+ VLOG(1) << "All characteristics discovered for "
+ << remote_service_uuid_.canonical_value();
+
+ std::vector<device::BluetoothGattCharacteristic*> characteristics =
+ service->GetCharacteristics();
+ for (auto iter = characteristics.begin(); iter != characteristics.end();
+ iter++) {
+ HandleCharacteristicUpdate(*iter);
+ }
+
+ if (to_peripheral_char_id_.empty() || from_peripheral_char_id_.empty()) {
+ VLOG(1) << "Connection error, missing characteristics for service.";
msarda 2015/05/05 11:56:13 s/service/Smart Lock service
msarda 2015/05/05 11:56:13 Please also log which one of |to_peripheral_char_i
sacomoto 2015/05/06 13:47:58 Done.
sacomoto 2015/05/06 13:47:58 Done.
+ Disconnect();
+ }
+ }
+}
+
+void BluetoothLowEnergyConnection::GattCharacteristicAdded(
+ BluetoothAdapter* adapter,
+ BluetoothGattCharacteristic* characteristic) {
+ VLOG(1) << "new char found: " << characteristic->GetUUID().canonical_value();
+ HandleCharacteristicUpdate(characteristic);
+}
+
+// TODO(sacomoto): Parse the Sockeeter incoming signal. Implement a receiver
msarda 2015/05/05 11:56:13 Remove Socketeer.
sacomoto 2015/05/06 13:47:58 Done.
+// with full suport for messages larger than a single characteristic value.
+void BluetoothLowEnergyConnection::GattCharacteristicValueChanged(
+ BluetoothAdapter* adapter,
+ BluetoothGattCharacteristic* characteristic,
+ const std::vector<uint8>& value) {
+ VLOG(1) << "Characteristic value changed: "
+ << characteristic->GetUUID().canonical_value();
+ if (characteristic->GetIdentifier() == from_peripheral_char_id_) {
+ std::string message(value.begin(), value.end());
+ VLOG(1) << "value: " << message;
+ // TODO(sacomoto): Actually handle the message and call OnBytesReceived when
+ // complete.
+ }
+}
+
+scoped_ptr<WireMessage> BluetoothLowEnergyConnection::DeserializeWireMessage(
+ bool* is_incomplete_message) {
+ return FakeWireMessage::Deserialize(received_bytes(), is_incomplete_message);
+}
+
+void BluetoothLowEnergyConnection::HandleCharacteristicUpdate(
+ BluetoothGattCharacteristic* characteristic) {
+ // Checks if |characteristic| is equal to |from_peripheral_char_| or
+ // |to_peripheral_char_| are present.
+ UpdateCharacteristicsStatus(characteristic);
+
+ // Starts a notify session for |from_peripheral_char_|.
+ if (characteristic->GetIdentifier() == from_peripheral_char_id_)
+ StartNotifySession();
+
+ // Checks if the connection is complete.
+ CompleteConnection();
+}
+
+void BluetoothLowEnergyConnection::CompleteConnection() {
+ if (status() == IN_PROGRESS && !to_peripheral_char_id_.empty() &&
+ !from_peripheral_char_id_.empty() && notify_session_) {
+ VLOG(1) << "Connection completed";
+ SetStatus(CONNECTED);
+ SendInviteToConnectSignal();
msarda 2015/05/05 11:56:13 Should we wait for a reply to invite signal before
sacomoto 2015/05/06 13:47:58 Done.
+ }
+}
+
+void BluetoothLowEnergyConnection::StartNotifySession() {
+ BluetoothGattCharacteristic* characteristic =
+ GetGattCharacteristic(from_peripheral_char_id_);
+ if (!characteristic) {
+ VLOG(1) << "Characteristic " << from_peripheral_char_ << " not found.";
+ return;
+ }
+
+ if (notify_session_ || notify_session_pending_) {
+ VLOG(1) << "Notify session already started.";
+ return;
+ }
+
+ notify_session_pending_ = true;
+ characteristic->StartNotifySession(
+ base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionStarted,
+ weak_ptr_factory_.GetWeakPtr()),
+ base::Bind(&BluetoothLowEnergyConnection::OnNotifySessionError,
+ weak_ptr_factory_.GetWeakPtr()));
+}
+
+void BluetoothLowEnergyConnection::OnNotifySessionError(
+ BluetoothGattService::GattErrorCode error) {
+ VLOG(1) << "Error starting notification session: " << error;
+ notify_session_pending_ = false;
+}
+
+void BluetoothLowEnergyConnection::OnNotifySessionStarted(
+ scoped_ptr<BluetoothGattNotifySession> notify_session) {
+ VLOG(1) << "Notification session started "
+ << notify_session->GetCharacteristicIdentifier();
+ notify_session_ = notify_session.Pass();
+ notify_session_pending_ = false;
+
+ // Checks if the connection is complete.
+ CompleteConnection();
+}
+
+void BluetoothLowEnergyConnection::StopNotifySession() {
+ if (notify_session_) {
+ notify_session_->Stop(base::Bind(&base::DoNothing));
+ notify_session_.reset();
+ }
+}
+
+void BluetoothLowEnergyConnection::OnWriteRemoteCharacteristicError(
+ BluetoothGattService::GattErrorCode error) {
+ VLOG(1) << "Error writing characteristic" << to_peripheral_char_;
+}
+
+void BluetoothLowEnergyConnection::SendInviteToConnectSignal() {
+ // From Socketeer library: connect signal is 0 (32-bit int).
+ const char connect_signal[4] = {};
+ SendMessage(scoped_ptr<FakeWireMessage>(new FakeWireMessage(connect_signal)));
+}
+
+void BluetoothLowEnergyConnection::UpdateCharacteristicsStatus(
+ BluetoothGattCharacteristic* characteristic) {
+ if (characteristic) {
+ std::string canonical_value = characteristic->GetUUID().canonical_value();
+ VLOG(1) << canonical_value;
+ if (to_peripheral_char_ == canonical_value) {
+ to_peripheral_char_id_ = characteristic->GetIdentifier();
+ }
+ if (from_peripheral_char_ == canonical_value) {
+ from_peripheral_char_id_ = characteristic->GetIdentifier();
+ }
+ BluetoothGattService* service = characteristic->GetService();
+ if (service && service->GetUUID() == remote_service_uuid_)
+ remote_service_id_ = service->GetIdentifier();
+ }
+}
+
+BluetoothDevice* BluetoothLowEnergyConnection::GetRemoteDevice() {
+ if (!adapter_ || !adapter_->IsInitialized()) {
+ VLOG(1) << "adapter not ready";
+ return NULL;
+ }
+ return adapter_->GetDevice(remote_device_address());
+}
+
+BluetoothGattService* BluetoothLowEnergyConnection::GetRemoteService() {
+ BluetoothDevice* remote_device = GetRemoteDevice();
+ if (!remote_device) {
+ VLOG(1) << "device not found";
+ return NULL;
+ }
+ return remote_device->GetGattService(remote_service_id_);
+}
+
+BluetoothGattCharacteristic*
+BluetoothLowEnergyConnection::GetGattCharacteristic(
+ const std::string& gatt_characteristic) {
+ BluetoothGattService* remote_service = GetRemoteService();
+ if (!remote_service) {
+ VLOG(1) << "service not found";
+ return NULL;
+ }
+ return remote_service->GetCharacteristic(gatt_characteristic);
+}
+
+} // namespace proximity_auth

Powered by Google App Engine
This is Rietveld 408576698