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

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: comment fixes Created 5 years, 5 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 void BluetoothAdapterMac::RemovePairingDelegateInternal(
179 BluetoothDevice::PairingDelegate* pairing_delegate) {
172 } 180 }
173 181
174 void BluetoothAdapterMac::AddDiscoverySession( 182 void BluetoothAdapterMac::AddDiscoverySession(
175 BluetoothDiscoveryFilter* discovery_filter, 183 BluetoothDiscoveryFilter* discovery_filter,
176 const base::Closure& callback, 184 const base::Closure& callback,
177 const ErrorCallback& error_callback) { 185 const ErrorCallback& error_callback) {
178 DVLOG(1) << __func__; 186 DVLOG(1) << __func__;
179 if (num_discovery_sessions_ > 0) { 187 if (num_discovery_sessions_ > 0) {
180 DCHECK(IsDiscovering()); 188 DCHECK(IsDiscovering());
181 num_discovery_sessions_++; 189 num_discovery_sessions_++;
190 // We are already running a discovery session, notify the system if the
191 // filter has changed.
192 if (!StartDiscovery(discovery_filter)) {
193 error_callback.Run();
194 return;
195 }
182 callback.Run(); 196 callback.Run();
183 return; 197 return;
184 } 198 }
185 199
186 DCHECK_EQ(0, num_discovery_sessions_); 200 DCHECK_EQ(0, num_discovery_sessions_);
187 201
188 if (!classic_discovery_manager_->StartDiscovery()) { 202 if (!StartDiscovery(discovery_filter)) {
189 DVLOG(1) << "Failed to add a discovery session";
190 error_callback.Run(); 203 error_callback.Run();
191 return; 204 return;
192 } 205 }
193 206
194 DVLOG(1) << "Added a discovery session"; 207 DVLOG(1) << "Added a discovery session";
195 num_discovery_sessions_++; 208 num_discovery_sessions_++;
196 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 209 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
197 observers_, 210 observers_,
198 AdapterDiscoveringChanged(this, true)); 211 AdapterDiscoveringChanged(this, true));
199 callback.Run(); 212 callback.Run();
(...skipping 12 matching lines...) Expand all
212 callback.Run(); 225 callback.Run();
213 return; 226 return;
214 } 227 }
215 228
216 if (num_discovery_sessions_ == 0) { 229 if (num_discovery_sessions_ == 0) {
217 DVLOG(1) << "No active discovery sessions. Returning error."; 230 DVLOG(1) << "No active discovery sessions. Returning error.";
218 error_callback.Run(); 231 error_callback.Run();
219 return; 232 return;
220 } 233 }
221 234
222 if (!classic_discovery_manager_->StopDiscovery()) { 235 // Default to dual discovery if |discovery_filter| is NULL.
223 DVLOG(1) << "Failed to stop discovery"; 236 BluetoothDiscoveryFilter::TransportMask transport =
224 error_callback.Run(); 237 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL;
225 return; 238 if (discovery_filter)
239 transport = discovery_filter->GetTransport();
240
241 if (transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC) {
242 if (!classic_discovery_manager_->StopDiscovery()) {
243 DVLOG(1) << "Failed to stop classic discovery";
244 error_callback.Run();
245 return;
246 }
247 }
248 if (transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_LE) {
249 low_energy_discovery_manager_->StopDiscovery();
226 } 250 }
227 251
228 DVLOG(1) << "Discovery stopped"; 252 DVLOG(1) << "Discovery stopped";
229 num_discovery_sessions_--; 253 num_discovery_sessions_--;
230 callback.Run(); 254 callback.Run();
231 } 255 }
232 256
233 void BluetoothAdapterMac::SetDiscoveryFilter( 257 void BluetoothAdapterMac::SetDiscoveryFilter(
234 scoped_ptr<BluetoothDiscoveryFilter> discovery_filter, 258 scoped_ptr<BluetoothDiscoveryFilter> discovery_filter,
235 const base::Closure& callback, 259 const base::Closure& callback,
236 const ErrorCallback& error_callback) { 260 const ErrorCallback& error_callback) {
237 NOTIMPLEMENTED(); 261 NOTIMPLEMENTED();
238 error_callback.Run(); 262 error_callback.Run();
239 } 263 }
240 264
241 void BluetoothAdapterMac::RemovePairingDelegateInternal( 265 bool BluetoothAdapterMac::StartDiscovery(
242 BluetoothDevice::PairingDelegate* pairing_delegate) { 266 BluetoothDiscoveryFilter* discovery_filter) {
267 // Default to dual discovery if |discovery_filter| is NULL. IOBluetooth seems
268 // allow starting low energy and classic discovery at once.
269 BluetoothDiscoveryFilter::TransportMask transport =
270 BluetoothDiscoveryFilter::Transport::TRANSPORT_DUAL;
271 if (discovery_filter)
272 transport = discovery_filter->GetTransport();
273
274 if ((transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_CLASSIC) &&
275 !classic_discovery_manager_->IsDiscovering()) {
276 // TODO(krstnmnlsn): If a classic discovery session is already running then
277 // we should update its filter. crbug.com/498056
278 if (!classic_discovery_manager_->StartDiscovery()) {
279 DVLOG(1) << "Failed to add a classic discovery session";
280 return false;
281 }
282 }
283 if (transport & BluetoothDiscoveryFilter::Transport::TRANSPORT_LE) {
284 // Begin a low energy discovery session or update it if one is already
285 // running.
286 low_energy_discovery_manager_->StartDiscovery(BluetoothDevice::UUIDList());
287 }
288 return true;
243 } 289 }
244 290
245 void BluetoothAdapterMac::Init() { 291 void BluetoothAdapterMac::Init() {
246 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 292 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
247 PollAdapter(); 293 PollAdapter();
248 } 294 }
249 295
250 void BluetoothAdapterMac::InitForTest( 296 void BluetoothAdapterMac::InitForTest(
251 scoped_refptr<base::SequencedTaskRunner> ui_task_runner) { 297 scoped_refptr<base::SequencedTaskRunner> ui_task_runner) {
252 ui_task_runner_ = ui_task_runner; 298 ui_task_runner_ = ui_task_runner;
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
316 "461181 BluetoothAdapterMac::PollAdapter::UpdateDevices")); 362 "461181 BluetoothAdapterMac::PollAdapter::UpdateDevices"));
317 UpdateDevices(); 363 UpdateDevices();
318 364
319 ui_task_runner_->PostDelayedTask( 365 ui_task_runner_->PostDelayedTask(
320 FROM_HERE, 366 FROM_HERE,
321 base::Bind(&BluetoothAdapterMac::PollAdapter, 367 base::Bind(&BluetoothAdapterMac::PollAdapter,
322 weak_ptr_factory_.GetWeakPtr()), 368 weak_ptr_factory_.GetWeakPtr()),
323 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); 369 base::TimeDelta::FromMilliseconds(kPollIntervalMs));
324 } 370 }
325 371
326 void BluetoothAdapterMac::DeviceAdded(IOBluetoothDevice* device) { 372 void BluetoothAdapterMac::ClassicDeviceAdded(IOBluetoothDevice* device) {
327 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); 373 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
328 374
329 // Only notify observers once per device. 375 // Only notify observers once per device.
330 if (devices_.count(device_address)) 376 if (devices_.count(device_address))
331 return; 377 return;
332 378
333 devices_[device_address] = new BluetoothDeviceMac(device); 379 devices_[device_address] = new BluetoothDeviceMac(device);
334 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, 380 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
335 observers_, 381 observers_,
336 DeviceAdded(this, devices_[device_address])); 382 DeviceAdded(this, devices_[device_address]));
337 } 383 }
338 384
385 // TODO(krstnmnlsn): This method to be implemented as soon as UpdateDevices can
386 // handle instances of LowEnergyBluetoothDevice in |devices_|. crbug.com/498009
387 void BluetoothAdapterMac::LowEnergyDeviceUpdated(
388 CBPeripheral* peripheral,
389 NSDictionary* advertisementData,
390 int rssi) {
391 }
392
393 // TODO(krstnmnlsn): This method assumes all BluetoothDevices in devices_ are
394 // instances of BluetoothDeviceMac. Add support for low energy devices.
395 // crbug.com/498009
339 void BluetoothAdapterMac::UpdateDevices() { 396 void BluetoothAdapterMac::UpdateDevices() {
340 // Notify observers if any previously seen devices are no longer available, 397 // 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 398 // i.e. if they are no longer paired, connected, nor recently discovered via
342 // an inquiry. 399 // an inquiry.
343 std::set<std::string> removed_devices; 400 std::set<std::string> removed_devices;
344 for (DevicesMap::iterator it = devices_.begin(); it != devices_.end(); ++it) { 401 for (DevicesMap::iterator it = devices_.begin(); it != devices_.end(); ++it) {
345 BluetoothDevice* device = it->second; 402 BluetoothDevice* device = it->second;
346 if (device->IsPaired() || device->IsConnected()) 403 if (device->IsPaired() || device->IsConnected())
347 continue; 404 continue;
348 405
349 NSDate* last_inquiry_update = 406 NSDate* last_inquiry_update =
350 static_cast<BluetoothDeviceMac*>(device)->GetLastInquiryUpdate(); 407 static_cast<BluetoothDeviceMac*>(device)->GetLastInquiryUpdate();
351 if (last_inquiry_update && 408 if (last_inquiry_update &&
352 -[last_inquiry_update timeIntervalSinceNow] < kDiscoveryTimeoutSec) 409 -[last_inquiry_update timeIntervalSinceNow] < kDiscoveryTimeoutSec)
353 continue; 410 continue;
354 411
355 FOR_EACH_OBSERVER( 412 FOR_EACH_OBSERVER(
356 BluetoothAdapter::Observer, observers_, DeviceRemoved(this, device)); 413 BluetoothAdapter::Observer, observers_, DeviceRemoved(this, device));
357 delete device; 414 delete device;
358 removed_devices.insert(it->first); 415 removed_devices.insert(it->first);
359 // The device will be erased from the map in the loop immediately below. 416 // The device will be erased from the map in the loop immediately below.
360 } 417 }
361 for (const std::string& device_address : removed_devices) { 418 for (const std::string& device_address : removed_devices) {
362 size_t num_removed = devices_.erase(device_address); 419 size_t num_removed = devices_.erase(device_address);
363 DCHECK_EQ(num_removed, 1U); 420 DCHECK_EQ(num_removed, 1U);
364 } 421 }
365 422
366 // Add any new paired devices. 423 // Add any new paired devices.
367 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { 424 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) {
368 DeviceAdded(device); 425 ClassicDeviceAdded(device);
369 } 426 }
370 } 427 }
371 428
372 } // namespace device 429 } // namespace device
OLDNEW
« no previous file with comments | « device/bluetooth/bluetooth_adapter_mac.h ('k') | device/bluetooth/bluetooth_adapter_mac_unittest.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698