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

Side by Side Diff: components/proximity_auth/bluetooth_low_energy_connection_finder.cc

Issue 2845473002: Revert of [EasyUnlock] Update BluetoothLowEnergyConnectionFinder to look for EIDs. (Closed)
Patch Set: Created 3 years, 8 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/bluetooth_low_energy_connection_finder.h"
6
7 #include <memory>
8 #include <string>
9 #include <utility>
10
11 #include "base/bind.h"
12 #include "base/bind_helpers.h"
13 #include "base/location.h"
14 #include "base/logging.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/strings/utf_string_conversions.h"
17 #include "base/threading/thread_task_runner_handle.h"
18 #include "components/cryptauth/ble/bluetooth_low_energy_weave_client_connection. h"
19 #include "components/cryptauth/bluetooth_throttler.h"
20 #include "components/cryptauth/connection.h"
21 #include "components/proximity_auth/logging/logging.h"
22 #include "device/bluetooth/bluetooth_adapter_factory.h"
23 #include "device/bluetooth/bluetooth_common.h"
24 #include "device/bluetooth/bluetooth_device.h"
25 #include "device/bluetooth/bluetooth_discovery_session.h"
26 #include "device/bluetooth/bluetooth_uuid.h"
27
28 using device::BluetoothAdapter;
29 using device::BluetoothDevice;
30 using device::BluetoothGattConnection;
31 using device::BluetoothDiscoveryFilter;
32
33 namespace proximity_auth {
34 namespace {
35 const char kAdvertisementUUID[] = "0000fe50-0000-1000-8000-00805f9b34fb";
36 const char kBLEGattServiceUUID[] = "b3b7e28e-a000-3e17-bd86-6e97b9e28c11";
37 const int kRestartDiscoveryOnErrorDelaySeconds = 2;
38 } // namespace
39
40 BluetoothLowEnergyConnectionFinder::BluetoothLowEnergyConnectionFinder(
41 const cryptauth::RemoteDevice remote_device,
42 const std::vector<cryptauth::BeaconSeed>& beacon_seeds,
43 cryptauth::BluetoothThrottler* bluetooth_throttler)
44 : BluetoothLowEnergyConnectionFinder(
45 remote_device,
46 beacon_seeds,
47 base::MakeUnique<cryptauth::BackgroundEidGenerator>(),
48 bluetooth_throttler) {}
49
50 BluetoothLowEnergyConnectionFinder::BluetoothLowEnergyConnectionFinder(
51 const cryptauth::RemoteDevice remote_device,
52 const std::vector<cryptauth::BeaconSeed>& beacon_seeds,
53 std::unique_ptr<cryptauth::BackgroundEidGenerator> eid_generator,
54 cryptauth::BluetoothThrottler* bluetooth_throttler)
55 : remote_device_(remote_device),
56 beacon_seeds_(beacon_seeds),
57 eid_generator_(std::move(eid_generator)),
58 bluetooth_throttler_(bluetooth_throttler),
59 weak_ptr_factory_(this) {}
60
61 BluetoothLowEnergyConnectionFinder::~BluetoothLowEnergyConnectionFinder() {
62 if (discovery_session_) {
63 StopDiscoverySession();
64 }
65
66 if (connection_) {
67 connection_->RemoveObserver(this);
68 connection_.reset();
69 }
70
71 if (adapter_) {
72 adapter_->RemoveObserver(this);
73 adapter_ = NULL;
74 }
75 }
76
77 void BluetoothLowEnergyConnectionFinder::Find(
78 const cryptauth::ConnectionFinder::ConnectionCallback&
79 connection_callback) {
80 if (!device::BluetoothAdapterFactory::IsBluetoothSupported()) {
81 PA_LOG(WARNING) << "Bluetooth is unsupported on this platform. Aborting.";
82 return;
83 }
84 PA_LOG(INFO) << "Finding connection";
85
86 connection_callback_ = connection_callback;
87
88 device::BluetoothAdapterFactory::GetAdapter(
89 base::Bind(&BluetoothLowEnergyConnectionFinder::OnAdapterInitialized,
90 weak_ptr_factory_.GetWeakPtr()));
91 }
92
93 // It's not necessary to observe |AdapterPresentChanged| too. When |adapter_| is
94 // present, but not powered, it's not possible to scan for new devices.
95 void BluetoothLowEnergyConnectionFinder::AdapterPoweredChanged(
96 BluetoothAdapter* adapter,
97 bool powered) {
98 DCHECK_EQ(adapter_.get(), adapter);
99 PA_LOG(INFO) << "Adapter powered: " << powered;
100
101 // Important: do not rely on |adapter->IsDiscoverying()| to verify if there is
102 // an active discovery session. We need to create our own with an specific
103 // filter.
104 if (powered && (!discovery_session_ || !discovery_session_->IsActive()))
105 StartDiscoverySession();
106 }
107
108 void BluetoothLowEnergyConnectionFinder::DeviceAdded(BluetoothAdapter* adapter,
109 BluetoothDevice* device) {
110 DCHECK_EQ(adapter_.get(), adapter);
111 DCHECK(device);
112
113 // Note: Only consider |device| when it was actually added/updated during a
114 // scanning, otherwise the device is stale and the GATT connection will fail.
115 // For instance, when |adapter_| change status from unpowered to powered,
116 // |DeviceAdded| is called for each paired |device|.
117 if (adapter_->IsPowered() && discovery_session_ &&
118 discovery_session_->IsActive())
119 HandleDeviceUpdated(device);
120 }
121
122 void BluetoothLowEnergyConnectionFinder::DeviceChanged(
123 BluetoothAdapter* adapter,
124 BluetoothDevice* device) {
125 DCHECK_EQ(adapter_.get(), adapter);
126 DCHECK(device);
127
128 // Note: Only consider |device| when it was actually added/updated during a
129 // scanning, otherwise the device is stale and the GATT connection will fail.
130 // For instance, when |adapter_| change status from unpowered to powered,
131 // |DeviceAdded| is called for each paired |device|.
132 if (adapter_->IsPowered() && discovery_session_ &&
133 discovery_session_->IsActive())
134 HandleDeviceUpdated(device);
135 }
136
137 void BluetoothLowEnergyConnectionFinder::HandleDeviceUpdated(
138 BluetoothDevice* device) {
139 // Ensuring only one call to |CreateConnection()| is made. A new |connection_|
140 // can be created only when the previous one disconnects, triggering a call to
141 // |OnConnectionStatusChanged|.
142 if (connection_)
143 return;
144
145 if (IsRightDevice(device)) {
146 PA_LOG(INFO) << "Connecting to device " << device->GetAddress();
147 connection_ = CreateConnection(device->GetAddress());
148 connection_->AddObserver(this);
149 connection_->Connect();
150
151 StopDiscoverySession();
152 }
153 }
154
155 bool BluetoothLowEnergyConnectionFinder::IsRightDevice(
156 BluetoothDevice* device) {
157 if (!device)
158 return false;
159
160 device::BluetoothUUID advertisement_uuid(kAdvertisementUUID);
161 const std::vector<uint8_t>* service_data =
162 device->GetServiceDataForUUID(advertisement_uuid);
163 if (!service_data)
164 return false;
165
166 std::string service_data_string(service_data->begin(), service_data->end());
167 std::vector<std::string> nearest_eids =
168 eid_generator_->GenerateNearestEids(beacon_seeds_);
169 for (const std::string& eid : nearest_eids) {
170 if (eid == service_data_string) {
171 PA_LOG(INFO) << "Found a matching EID: " << eid;
172 return true;
173 }
174 }
175 return false;
176 }
177
178 void BluetoothLowEnergyConnectionFinder::OnAdapterInitialized(
179 scoped_refptr<BluetoothAdapter> adapter) {
180 PA_LOG(INFO) << "Adapter ready";
181 adapter_ = adapter;
182 adapter_->AddObserver(this);
183 StartDiscoverySession();
184 }
185
186 void BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStarted(
187 std::unique_ptr<device::BluetoothDiscoverySession> discovery_session) {
188 PA_LOG(INFO) << "Discovery session started";
189 discovery_session_ = std::move(discovery_session);
190 }
191
192 void BluetoothLowEnergyConnectionFinder::OnStartDiscoverySessionError() {
193 PA_LOG(WARNING) << "Error starting discovery session, restarting in "
194 << kRestartDiscoveryOnErrorDelaySeconds << " seconds.";
195 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
196 FROM_HERE,
197 base::Bind(
198 &BluetoothLowEnergyConnectionFinder::RestartDiscoverySessionAsync,
199 weak_ptr_factory_.GetWeakPtr()),
200 base::TimeDelta::FromSeconds(kRestartDiscoveryOnErrorDelaySeconds));
201 }
202
203 void BluetoothLowEnergyConnectionFinder::StartDiscoverySession() {
204 DCHECK(adapter_);
205 if (discovery_session_ && discovery_session_->IsActive()) {
206 PA_LOG(INFO) << "Discovery session already active";
207 return;
208 }
209
210 // Discover only low energy (LE) devices.
211 std::unique_ptr<BluetoothDiscoveryFilter> filter(
212 new BluetoothDiscoveryFilter(device::BLUETOOTH_TRANSPORT_LE));
213
214 adapter_->StartDiscoverySessionWithFilter(
215 std::move(filter),
216 base::Bind(&BluetoothLowEnergyConnectionFinder::OnDiscoverySessionStarted,
217 weak_ptr_factory_.GetWeakPtr()),
218 base::Bind(
219 &BluetoothLowEnergyConnectionFinder::OnStartDiscoverySessionError,
220 weak_ptr_factory_.GetWeakPtr()));
221 }
222
223 void BluetoothLowEnergyConnectionFinder::StopDiscoverySession() {
224 PA_LOG(INFO) << "Stopping discovery session";
225 // Destroying the discovery session also stops it.
226 discovery_session_.reset();
227 }
228
229 std::unique_ptr<cryptauth::Connection>
230 BluetoothLowEnergyConnectionFinder::CreateConnection(
231 const std::string& device_address) {
232 return cryptauth::weave::BluetoothLowEnergyWeaveClientConnection::Factory::
233 NewInstance(remote_device_, device_address, adapter_,
234 device::BluetoothUUID(kBLEGattServiceUUID),
235 bluetooth_throttler_);
236 }
237
238 void BluetoothLowEnergyConnectionFinder::OnConnectionStatusChanged(
239 cryptauth::Connection* connection,
240 cryptauth::Connection::Status old_status,
241 cryptauth::Connection::Status new_status) {
242 DCHECK_EQ(connection, connection_.get());
243 PA_LOG(INFO) << "OnConnectionStatusChanged: " << old_status << " -> "
244 << new_status;
245
246 if (!connection_callback_.is_null() && connection_->IsConnected()) {
247 adapter_->RemoveObserver(this);
248 connection_->RemoveObserver(this);
249
250 // If we invoke the callback now, the callback function may install its own
251 // observer to |connection_|. Because we are in the ConnectionObserver
252 // callstack, this new observer will receive this connection event.
253 // Therefore, we need to invoke the callback or restart discovery
254 // asynchronously.
255 base::ThreadTaskRunnerHandle::Get()->PostTask(
256 FROM_HERE,
257 base::Bind(&BluetoothLowEnergyConnectionFinder::InvokeCallbackAsync,
258 weak_ptr_factory_.GetWeakPtr()));
259 } else if (old_status == cryptauth::Connection::IN_PROGRESS) {
260 PA_LOG(WARNING) << "Connection failed. Retrying.";
261 base::ThreadTaskRunnerHandle::Get()->PostTask(
262 FROM_HERE,
263 base::Bind(
264 &BluetoothLowEnergyConnectionFinder::RestartDiscoverySessionAsync,
265 weak_ptr_factory_.GetWeakPtr()));
266 }
267 }
268
269 void BluetoothLowEnergyConnectionFinder::RestartDiscoverySessionAsync() {
270 PA_LOG(INFO) << "Restarting discovery session.";
271 connection_.reset();
272 if (!discovery_session_ || !discovery_session_->IsActive())
273 StartDiscoverySession();
274 }
275
276 void BluetoothLowEnergyConnectionFinder::InvokeCallbackAsync() {
277 connection_callback_.Run(std::move(connection_));
278 }
279
280 } // namespace proximity_auth
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698