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

Side by Side Diff: device/bluetooth/bluetooth_adapter_mac.mm

Issue 1165053003: Adding support for Low Energy device discovery to BluetoothAdapterMac (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 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
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "device/bluetooth/bluetooth_adapter_mac.h" 5 #include "device/bluetooth/bluetooth_adapter_mac.h"
6 6
7 #import <IOBluetooth/objc/IOBluetoothDevice.h> 7 #import <IOBluetooth/objc/IOBluetoothDevice.h>
8 #import <IOBluetooth/objc/IOBluetoothHostController.h> 8 #import <IOBluetooth/objc/IOBluetoothHostController.h>
9 9
10 #include <string> 10 #include <string>
11 11
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
14 #include "base/containers/hash_tables.h" 14 #include "base/containers/hash_tables.h"
15 #include "base/location.h" 15 #include "base/location.h"
16 #include "base/mac/sdk_forward_declarations.h" 16 #include "base/mac/sdk_forward_declarations.h"
17 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
18 #include "base/profiler/scoped_tracker.h" 18 #include "base/profiler/scoped_tracker.h"
19 #include "base/sequenced_task_runner.h" 19 #include "base/sequenced_task_runner.h"
20 #include "base/single_thread_task_runner.h" 20 #include "base/single_thread_task_runner.h"
21 #include "base/strings/sys_string_conversions.h" 21 #include "base/strings/sys_string_conversions.h"
22 #include "base/thread_task_runner_handle.h" 22 #include "base/thread_task_runner_handle.h"
23 #include "base/time/time.h" 23 #include "base/time/time.h"
24 #include "device/bluetooth/bluetooth_device_mac.h" 24 #include "device/bluetooth/bluetooth_device_mac.h"
25 #include "device/bluetooth/bluetooth_discovery_session.h"
25 #include "device/bluetooth/bluetooth_socket_mac.h" 26 #include "device/bluetooth/bluetooth_socket_mac.h"
26 #include "device/bluetooth/bluetooth_uuid.h" 27 #include "device/bluetooth/bluetooth_uuid.h"
27 28
28 namespace { 29 namespace {
29 30
30 // The frequency with which to poll the adapter for updates. 31 // The frequency with which to poll the adapter for updates.
31 const int kPollIntervalMs = 500; 32 const int kPollIntervalMs = 500;
32 33
33 // The length of time that must elapse since the last Inquiry response before a 34 // The length of time that must elapse since the last Inquiry response before a
34 // discovered Classic device is considered to be no longer available. 35 // discovered Classic device is considered to be no longer available.
(...skipping 15 matching lines...) Expand all
50 adapter->Init(); 51 adapter->Init();
51 return adapter->weak_ptr_factory_.GetWeakPtr(); 52 return adapter->weak_ptr_factory_.GetWeakPtr();
52 } 53 }
53 54
54 BluetoothAdapterMac::BluetoothAdapterMac() 55 BluetoothAdapterMac::BluetoothAdapterMac()
55 : BluetoothAdapter(), 56 : BluetoothAdapter(),
56 powered_(false), 57 powered_(false),
57 num_discovery_sessions_(0), 58 num_discovery_sessions_(0),
58 classic_discovery_manager_( 59 classic_discovery_manager_(
59 BluetoothDiscoveryManagerMac::CreateClassic(this)), 60 BluetoothDiscoveryManagerMac::CreateClassic(this)),
61 low_energy_discovery_manager_(
62 BluetoothLowEnergyDiscoveryManagerMac::Create(this)),
60 weak_ptr_factory_(this) { 63 weak_ptr_factory_(this) {
61 DCHECK(classic_discovery_manager_.get()); 64 DCHECK(classic_discovery_manager_.get());
62 } 65 }
63 66
64 BluetoothAdapterMac::~BluetoothAdapterMac() { 67 BluetoothAdapterMac::~BluetoothAdapterMac() {
65 } 68 }
66 69
67 std::string BluetoothAdapterMac::GetAddress() const { 70 std::string BluetoothAdapterMac::GetAddress() const {
68 return address_; 71 return address_;
69 } 72 }
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
102 } 105 }
103 106
104 void BluetoothAdapterMac::SetDiscoverable( 107 void BluetoothAdapterMac::SetDiscoverable(
105 bool discoverable, 108 bool discoverable,
106 const base::Closure& callback, 109 const base::Closure& callback,
107 const ErrorCallback& error_callback) { 110 const ErrorCallback& error_callback) {
108 NOTIMPLEMENTED(); 111 NOTIMPLEMENTED();
109 } 112 }
110 113
111 bool BluetoothAdapterMac::IsDiscovering() const { 114 bool BluetoothAdapterMac::IsDiscovering() const {
112 return classic_discovery_manager_->IsDiscovering(); 115 return (classic_discovery_manager_->IsDiscovering() ||
116 low_energy_discovery_manager_->IsDiscovering());
113 } 117 }
114 118
115 void BluetoothAdapterMac::CreateRfcommService( 119 void BluetoothAdapterMac::CreateRfcommService(
116 const BluetoothUUID& uuid, 120 const BluetoothUUID& uuid,
117 const ServiceOptions& options, 121 const ServiceOptions& options,
118 const CreateServiceCallback& callback, 122 const CreateServiceCallback& callback,
119 const CreateServiceErrorCallback& error_callback) { 123 const CreateServiceErrorCallback& error_callback) {
120 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket(); 124 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
121 socket->ListenUsingRfcomm( 125 socket->ListenUsingRfcomm(
122 this, uuid, options, base::Bind(callback, socket), error_callback); 126 this, uuid, options, base::Bind(callback, socket), error_callback);
(...skipping 18 matching lines...) Expand all
141 } 145 }
142 146
143 void BluetoothAdapterMac::RegisterAdvertisement( 147 void BluetoothAdapterMac::RegisterAdvertisement(
144 scoped_ptr<BluetoothAdvertisement::Data> advertisement_data, 148 scoped_ptr<BluetoothAdvertisement::Data> advertisement_data,
145 const CreateAdvertisementCallback& callback, 149 const CreateAdvertisementCallback& callback,
146 const CreateAdvertisementErrorCallback& error_callback) { 150 const CreateAdvertisementErrorCallback& error_callback) {
147 NOTIMPLEMENTED(); 151 NOTIMPLEMENTED();
148 error_callback.Run(BluetoothAdvertisement::ERROR_UNSUPPORTED_PLATFORM); 152 error_callback.Run(BluetoothAdvertisement::ERROR_UNSUPPORTED_PLATFORM);
149 } 153 }
150 154
151 void BluetoothAdapterMac::DeviceFound(IOBluetoothDevice* device) { 155 void BluetoothAdapterMac::ClassicDeviceFound(IOBluetoothDevice* device) {
152 DeviceAdded(device); 156 ClassicDeviceAdded(device);
153 } 157 }
154 158
155 void BluetoothAdapterMac::DiscoveryStopped(bool unexpected) { 159 void BluetoothAdapterMac::ClassicDiscoveryStopped(bool unexpected) {
156 if (unexpected) { 160 if (unexpected) {
157 DVLOG(1) << "Discovery stopped unexpectedly"; 161 DVLOG(1) << "Discovery stopped unexpectedly";
158 num_discovery_sessions_ = 0; 162 num_discovery_sessions_ = 0;
159 MarkDiscoverySessionsAsInactive(); 163 MarkDiscoverySessionsAsInactive();
160 } 164 }
161 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 165 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
162 observers_, 166 observers_,
163 AdapterDiscoveringChanged(this, false)); 167 AdapterDiscoveringChanged(this, false));
164 } 168 }
165 169
166 void BluetoothAdapterMac::DeviceConnected(IOBluetoothDevice* device) { 170 void BluetoothAdapterMac::DeviceConnected(IOBluetoothDevice* device) {
167 // TODO(isherman): Investigate whether this method can be replaced with a call 171 // TODO(isherman): Investigate whether this method can be replaced with a call
168 // to +registerForConnectNotifications:selector:. 172 // to +registerForConnectNotifications:selector:.
169 DVLOG(1) << "Adapter registered a new connection from device with address: " 173 DVLOG(1) << "Adapter registered a new connection from device with address: "
170 << BluetoothDeviceMac::GetDeviceAddress(device); 174 << BluetoothDeviceMac::GetDeviceAddress(device);
171 DeviceAdded(device); 175 ClassicDeviceAdded(device);
176 }
177
178 bool BluetoothAdapterMac::StartDiscovery(
scheib 2015/06/05 18:10:20 Move to after SetDiscoveryFilter. "Method definiti
krstnmnlsn 2015/06/09 01:08:10 Right. I went ahead and moved RemovePairingDelega
179 BluetoothDiscoveryFilter* discovery_filter) {
180 // Default to dual discovery if |discovery_filter| is NULL.
181 BluetoothDiscoveryFilter::TransportMask transport =
182 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL;
183 if (discovery_filter)
184 transport = discovery_filter->GetTransport();
185
186 if ((transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC) &&
scheib 2015/06/05 18:10:20 We should find a mix of classic and LE devices and
krstnmnlsn 2015/06/09 01:08:10 Manually tested and added a short comment (cannot
187 !classic_discovery_manager_->IsDiscovering()) {
188 // TODO(krstnmnlsn): If a classic discovery session is already running then
189 // we should update its filter.
190 if (!classic_discovery_manager_->StartDiscovery()) {
191 DVLOG(1) << "Failed to add a classic discovery session";
192 return false;
193 }
194 }
195 if (transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_LE) {
196 // Begin a low energy discovery session or update it if one is already
197 // running.
198 low_energy_discovery_manager_->StartDiscovery(BluetoothDevice::UUIDList());
199 }
200 return true;
172 } 201 }
173 202
174 void BluetoothAdapterMac::AddDiscoverySession( 203 void BluetoothAdapterMac::AddDiscoverySession(
175 BluetoothDiscoveryFilter* discovery_filter, 204 BluetoothDiscoveryFilter* discovery_filter,
176 const base::Closure& callback, 205 const base::Closure& callback,
177 const ErrorCallback& error_callback) { 206 const ErrorCallback& error_callback) {
178 DVLOG(1) << __func__; 207 DVLOG(1) << __func__;
179 if (num_discovery_sessions_ > 0) { 208 if (num_discovery_sessions_ > 0) {
180 DCHECK(IsDiscovering()); 209 DCHECK(IsDiscovering());
181 num_discovery_sessions_++; 210 num_discovery_sessions_++;
211 // We are already running a discovery session, notify the system if the
212 // filter has changed.
213 if (!StartDiscovery(discovery_filter)) {
scheib 2015/06/06 05:09:48 Without seeing the plans for how differing filters
krstnmnlsn 2015/06/09 01:08:09 Recap/continuing of offline discussion: The plans
214 error_callback.Run();
215 return;
216 }
182 callback.Run(); 217 callback.Run();
183 return; 218 return;
184 } 219 }
185 220
186 DCHECK_EQ(0, num_discovery_sessions_); 221 DCHECK_EQ(0, num_discovery_sessions_);
187 222
188 if (!classic_discovery_manager_->StartDiscovery()) { 223 if (!StartDiscovery(discovery_filter)) {
189 DVLOG(1) << "Failed to add a discovery session";
190 error_callback.Run(); 224 error_callback.Run();
191 return; 225 return;
192 } 226 }
193 227
194 DVLOG(1) << "Added a discovery session"; 228 DVLOG(1) << "Added a discovery session";
195 num_discovery_sessions_++; 229 num_discovery_sessions_++;
196 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 230 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
197 observers_, 231 observers_,
198 AdapterDiscoveringChanged(this, true)); 232 AdapterDiscoveringChanged(this, true));
199 callback.Run(); 233 callback.Run();
(...skipping 12 matching lines...) Expand all
212 callback.Run(); 246 callback.Run();
213 return; 247 return;
214 } 248 }
215 249
216 if (num_discovery_sessions_ == 0) { 250 if (num_discovery_sessions_ == 0) {
217 DVLOG(1) << "No active discovery sessions. Returning error."; 251 DVLOG(1) << "No active discovery sessions. Returning error.";
218 error_callback.Run(); 252 error_callback.Run();
219 return; 253 return;
220 } 254 }
221 255
222 if (!classic_discovery_manager_->StopDiscovery()) { 256 // Default to dual discovery if |discovery_filter| is NULL.
223 DVLOG(1) << "Failed to stop discovery"; 257 BluetoothDiscoveryFilter::TransportMask transport =
224 error_callback.Run(); 258 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL;
225 return; 259 if (discovery_filter)
260 transport = discovery_filter->GetTransport();
261
262 if (transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC) {
263 if (!classic_discovery_manager_->StopDiscovery()) {
264 DVLOG(1) << "Failed to stop classic discovery";
265 error_callback.Run();
266 return;
267 }
268 }
269 if (transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_LE) {
270 low_energy_discovery_manager_->StopDiscovery();
226 } 271 }
227 272
228 DVLOG(1) << "Discovery stopped"; 273 DVLOG(1) << "Discovery stopped";
229 num_discovery_sessions_--; 274 num_discovery_sessions_--;
230 callback.Run(); 275 callback.Run();
231 } 276 }
232 277
233 void BluetoothAdapterMac::SetDiscoveryFilter( 278 void BluetoothAdapterMac::SetDiscoveryFilter(
234 scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, 279 scoped_ptr<BluetoothDiscoveryFilter> discovery_filter,
235 const base::Closure& callback, 280 const base::Closure& callback,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 "461181 BluetoothAdapterMac::PollAdapter::UpdateDevices")); 361 "461181 BluetoothAdapterMac::PollAdapter::UpdateDevices"));
317 UpdateDevices(); 362 UpdateDevices();
318 363
319 ui_task_runner_->PostDelayedTask( 364 ui_task_runner_->PostDelayedTask(
320 FROM_HERE, 365 FROM_HERE,
321 base::Bind(&BluetoothAdapterMac::PollAdapter, 366 base::Bind(&BluetoothAdapterMac::PollAdapter,
322 weak_ptr_factory_.GetWeakPtr()), 367 weak_ptr_factory_.GetWeakPtr()),
323 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); 368 base::TimeDelta::FromMilliseconds(kPollIntervalMs));
324 } 369 }
325 370
326 void BluetoothAdapterMac::DeviceAdded(IOBluetoothDevice* device) { 371 void BluetoothAdapterMac::ClassicDeviceAdded(IOBluetoothDevice* device) {
327 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); 372 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
328 373
329 // Only notify observers once per device. 374 // Only notify observers once per device.
330 if (devices_.count(device_address)) 375 if (devices_.count(device_address))
331 return; 376 return;
332 377
333 devices_[device_address] = new BluetoothDeviceMac(device); 378 devices_[device_address] = new BluetoothDeviceMac(device);
334 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 379 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
335 observers_, 380 observers_,
336 DeviceAdded(this, devices_[device_address])); 381 DeviceAdded(this, devices_[device_address]));
337 } 382 }
338 383
384 // TODO(krstnmnlsn): This method to be implemented as soon as UpdateDevices can
385 // handle instances of LowEnergyBluetoothDevice in |devices_|.
scheib 2015/06/05 18:10:20 Add a reference to the issue number to do that wor
krstnmnlsn 2015/06/09 01:08:09 Done.
386 void BluetoothAdapterMac::LowEnergyDeviceUpdated(
387 CBPeripheral* peripheral,
388 NSDictionary* advertisementData,
389 int rssi) {
390 NOTIMPLEMENTED();
scheib 2015/06/05 18:10:20 We expect LE sessions will be started, so we can't
krstnmnlsn 2015/06/09 01:08:09 Done.
391 }
392
393 // TODO(krstnmnlsn): This method assumes all BluetoothDevices in devices_ are
394 // instances of BluetoothDeviceMac. Add support for low energy devices.
scheib 2015/06/05 18:10:20 issue number.
krstnmnlsn 2015/06/09 01:08:09 Done.
339 void BluetoothAdapterMac::UpdateDevices() { 395 void BluetoothAdapterMac::UpdateDevices() {
340 // Notify observers if any previously seen devices are no longer available, 396 // Notify observers if any previously seen devices are no longer available,
341 // i.e. if they are no longer paired, connected, nor recently discovered via 397 // i.e. if they are no longer paired, connected, nor recently discovered via
342 // an inquiry. 398 // an inquiry.
343 std::set<std::string> removed_devices; 399 std::set<std::string> removed_devices;
344 for (DevicesMap::iterator it = devices_.begin(); it != devices_.end(); ++it) { 400 for (DevicesMap::iterator it = devices_.begin(); it != devices_.end(); ++it) {
345 BluetoothDevice* device = it->second; 401 BluetoothDevice* device = it->second;
346 if (device->IsPaired() || device->IsConnected()) 402 if (device->IsPaired() || device->IsConnected())
347 continue; 403 continue;
348 404
349 NSDate* last_inquiry_update = 405 NSDate* last_inquiry_update =
350 static_cast<BluetoothDeviceMac*>(device)->GetLastInquiryUpdate(); 406 static_cast<BluetoothDeviceMac*>(device)->GetLastInquiryUpdate();
351 if (last_inquiry_update && 407 if (last_inquiry_update &&
352 -[last_inquiry_update timeIntervalSinceNow] < kDiscoveryTimeoutSec) 408 -[last_inquiry_update timeIntervalSinceNow] < kDiscoveryTimeoutSec)
353 continue; 409 continue;
354 410
355 FOR_EACH_OBSERVER( 411 FOR_EACH_OBSERVER(
356 BluetoothAdapter::Observer, observers_, DeviceRemoved(this, device)); 412 BluetoothAdapter::Observer, observers_, DeviceRemoved(this, device));
357 delete device; 413 delete device;
358 removed_devices.insert(it->first); 414 removed_devices.insert(it->first);
359 // The device will be erased from the map in the loop immediately below. 415 // The device will be erased from the map in the loop immediately below.
360 } 416 }
361 for (const std::string& device_address : removed_devices) { 417 for (const std::string& device_address : removed_devices) {
362 size_t num_removed = devices_.erase(device_address); 418 size_t num_removed = devices_.erase(device_address);
363 DCHECK_EQ(num_removed, 1U); 419 DCHECK_EQ(num_removed, 1U);
364 } 420 }
365 421
366 // Add any new paired devices. 422 // Add any new paired devices.
367 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { 423 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) {
368 DeviceAdded(device); 424 ClassicDeviceAdded(device);
369 } 425 }
370 } 426 }
371 427
372 } // namespace device 428 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698