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

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

Issue 319183010: device/bluetooth: Clean up classic discovery in BluetoothAdapterMac. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 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 | Annotate | Revision Log
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/IOBluetoothDeviceInquiry.h> 8 #import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h>
9 #import <IOBluetooth/objc/IOBluetoothHostController.h> 9 #import <IOBluetooth/objc/IOBluetoothHostController.h>
10 10
(...skipping 26 matching lines...) Expand all
37 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender; 37 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender;
38 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender 38 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender
39 device:(IOBluetoothDevice*)device; 39 device:(IOBluetoothDevice*)device;
40 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender 40 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender
41 error:(IOReturn)error 41 error:(IOReturn)error
42 aborted:(BOOL)aborted; 42 aborted:(BOOL)aborted;
43 @end 43 @end
44 44
45 #endif // MAC_OS_X_VERSION_10_7 45 #endif // MAC_OS_X_VERSION_10_7
46 46
47 @interface BluetoothAdapterMacDelegate 47 @interface BluetoothDeviceInquiryDelegate
48 : NSObject <IOBluetoothDeviceInquiryDelegate> { 48 : NSObject<IOBluetoothDeviceInquiryDelegate> {
49 @private 49 @private
50 device::BluetoothAdapterMac* adapter_; // weak 50 device::BluetoothMacClassicDiscoveryManager* manager_; // weak
51 } 51 }
52 52
53 - (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter; 53 - (id)initWithManager:(device::BluetoothMacClassicDiscoveryManager*)manager;
54 54
55 @end 55 @end
56 56
57 @implementation BluetoothAdapterMacDelegate 57 @implementation BluetoothDeviceInquiryDelegate
58 58
59 - (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter { 59 - (id)initWithManager:(device::BluetoothMacClassicDiscoveryManager*)manager {
60 if ((self = [super init])) 60 if ((self = [super init]))
61 adapter_ = adapter; 61 manager_ = manager;
62 62
63 return self; 63 return self;
64 } 64 }
65 65
66 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender { 66 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender {
67 adapter_->DeviceInquiryStarted(sender); 67 manager_->DeviceInquiryStarted(sender);
68 } 68 }
69 69
70 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender 70 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender
71 device:(IOBluetoothDevice*)device { 71 device:(IOBluetoothDevice*)device {
72 adapter_->DeviceFound(sender, device); 72 manager_->DeviceFound(sender, device);
73 } 73 }
74 74
75 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender 75 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender
76 error:(IOReturn)error 76 error:(IOReturn)error
77 aborted:(BOOL)aborted { 77 aborted:(BOOL)aborted {
78 adapter_->DeviceInquiryComplete(sender, error, aborted); 78 manager_->DeviceInquiryComplete(sender, error, aborted);
79 } 79 }
80 80
81 @end 81 @end
82 82
83 namespace { 83 namespace {
84 84
85 const int kPollIntervalMs = 500; 85 const int kPollIntervalMs = 500;
86 86
87 } // namespace 87 } // namespace
88 88
89 namespace device { 89 namespace device {
90 90
91 // static 91 // static
92 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( 92 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
93 const InitCallback& init_callback) { 93 const InitCallback& init_callback) {
94 return BluetoothAdapterMac::CreateAdapter(); 94 return BluetoothAdapterMac::CreateAdapter();
95 } 95 }
96 96
97 // static 97 // static
98 base::WeakPtr<BluetoothAdapter> BluetoothAdapterMac::CreateAdapter() { 98 base::WeakPtr<BluetoothAdapter> BluetoothAdapterMac::CreateAdapter() {
99 BluetoothAdapterMac* adapter = new BluetoothAdapterMac(); 99 BluetoothAdapterMac* adapter = new BluetoothAdapterMac();
100 adapter->Init(); 100 adapter->Init();
101 return adapter->weak_ptr_factory_.GetWeakPtr(); 101 return adapter->weak_ptr_factory_.GetWeakPtr();
102 } 102 }
103 103
104 BluetoothMacClassicDiscoveryManager::BluetoothMacClassicDiscoveryManager(
105 BluetoothAdapterMac* adapter)
106 : should_do_discovery_(false),
107 inquiry_running_(false),
108 adapter_(adapter),
109 inquiry_delegate_(
110 [[BluetoothDeviceInquiryDelegate alloc] initWithManager:this]),
111 inquiry_([[IOBluetoothDeviceInquiry alloc]
112 initWithDelegate:inquiry_delegate_]) {
113 }
114
115 BluetoothMacClassicDiscoveryManager::~BluetoothMacClassicDiscoveryManager() {
116 }
117
118 bool BluetoothMacClassicDiscoveryManager::IsDiscovering() const {
119 return should_do_discovery_;
120 }
121
122 bool BluetoothMacClassicDiscoveryManager::StartDiscovery() {
123 VLOG(1) << "Bluetooth Classic: StartDiscovery";
124 if (should_do_discovery_) {
125 VLOG(1) << "Already discovering";
126 return true;
127 }
128
129 VLOG(1) << "Discovery requested";
130 should_do_discovery_ = true;
131
132 if (inquiry_running_) {
133 VLOG(1) << "Device inquiry already running";
134 return true;
135 }
136
137 VLOG(1) << "Requesting to start device inquiry";
138 if ([inquiry_ start] != kIOReturnSuccess) {
139 VLOG(1) << "Failed to start device inquiry";
140
141 // Set |should_do_discovery_| to false here. Since we're reporting an
142 // error, we're indicating that the adapter call StartDiscovery again
143 // if needed.
144 should_do_discovery_ = false;
145 return false;
146 }
147
148 VLOG(1) << "Device inquiry start was successful";
149 return true;
150 }
151
152 bool BluetoothMacClassicDiscoveryManager::StopDiscovery() {
153 VLOG(1) << "Bluetooth Classic: StopDiscovery";
154 if (!should_do_discovery_) {
155 VLOG(1) << "Discovery already stopped";
156 return true;
157 }
158
159 should_do_discovery_ = false;
160
161 if (!inquiry_running_) {
162 VLOG(1) << "No device inquiry running; discovery stopped";
163 return true;
164 }
165
166 VLOG(1) << "Requesting to stop device inquiry";
167 IOReturn status = [inquiry_ stop];
168 if (status == kIOReturnSuccess) {
169 VLOG(1) << "Device inquiry stop was successful";
170 return true;
171 }
172
173 if (status == kIOReturnNotPermitted) {
174 VLOG(1) << "Device inquiry was already stopped";
175 return true;
176 }
177
178 LOG(WARNING) << "Failed to stop device inquiry";
179 return false;
180 }
181
182 void BluetoothMacClassicDiscoveryManager::DeviceInquiryStarted(
183 IOBluetoothDeviceInquiry* inquiry) {
184 DCHECK(!inquiry_running_);
185
186 VLOG(1) << "Device inquiry started!";
187
188 // If discovery was requested to stop in the mean time, stop the inquiry.
189 if (!should_do_discovery_) {
190 VLOG(1) << "Discovery stop was requested earlier. Stopping inquiry";
191 [inquiry stop];
192 return;
193 }
194
195 inquiry_running_ = true;
196 }
197
198 void BluetoothMacClassicDiscoveryManager::DeviceFound(
199 IOBluetoothDeviceInquiry* inquiry,
200 IOBluetoothDevice* device) {
201 adapter_->DeviceFound(device);
202 }
203
204 void BluetoothMacClassicDiscoveryManager::DeviceInquiryComplete(
205 IOBluetoothDeviceInquiry* inquiry,
206 IOReturn error,
207 bool aborted) {
208 DCHECK_EQ(inquiry_, inquiry);
209 VLOG(1) << "Device inquiry complete";
210 inquiry_running_ = false;
211
212 // Automatically restart device inquiry if discovery is still desired.
213 if (!should_do_discovery_) {
214 adapter_->ClassicDiscoveryStopped(false /* unexpected */);
215 return;
216 }
217
218 if (error != kIOReturnSuccess) {
219 VLOG(1) << "Inquiry has stopped with an error: " << error;
220 should_do_discovery_ = false;
221 adapter_->ClassicDiscoveryStopped(true /* unexpected */);
222 return;
223 }
224
225 VLOG(1) << "Restarting device inquiry";
226
227 if ([inquiry_ start] == kIOReturnSuccess) {
228 VLOG(1) << "Device inquiry restart was successful";
229 return;
230 }
231
232 VLOG(1) << "Failed to restart discovery";
233 should_do_discovery_ = false;
234 adapter_->ClassicDiscoveryStopped(true /* unexpected */);
235 }
236
104 BluetoothAdapterMac::BluetoothAdapterMac() 237 BluetoothAdapterMac::BluetoothAdapterMac()
105 : BluetoothAdapter(), 238 : BluetoothAdapter(),
106 powered_(false), 239 powered_(false),
107 discovery_status_(NOT_DISCOVERING), 240 num_discovery_sessions_(0),
108 adapter_delegate_( 241 classic_discovery_session_manager_(
109 [[BluetoothAdapterMacDelegate alloc] initWithAdapter:this]), 242 new BluetoothMacClassicDiscoveryManager(this)),
110 device_inquiry_(
111 [[IOBluetoothDeviceInquiry
112 inquiryWithDelegate:adapter_delegate_] retain]),
113 weak_ptr_factory_(this) { 243 weak_ptr_factory_(this) {
114 } 244 }
115 245
116 BluetoothAdapterMac::~BluetoothAdapterMac() { 246 BluetoothAdapterMac::~BluetoothAdapterMac() {
117 } 247 }
118 248
119 void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) { 249 void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) {
120 DCHECK(observer); 250 DCHECK(observer);
121 observers_.AddObserver(observer); 251 observers_.AddObserver(observer);
122 } 252 }
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } 294 }
165 295
166 void BluetoothAdapterMac::SetDiscoverable( 296 void BluetoothAdapterMac::SetDiscoverable(
167 bool discoverable, 297 bool discoverable,
168 const base::Closure& callback, 298 const base::Closure& callback,
169 const ErrorCallback& error_callback) { 299 const ErrorCallback& error_callback) {
170 NOTIMPLEMENTED(); 300 NOTIMPLEMENTED();
171 } 301 }
172 302
173 bool BluetoothAdapterMac::IsDiscovering() const { 303 bool BluetoothAdapterMac::IsDiscovering() const {
174 return discovery_status_ == DISCOVERING || 304 return classic_discovery_session_manager_->IsDiscovering();
175 discovery_status_ == DISCOVERY_STOPPING;
176 } 305 }
177 306
178 void BluetoothAdapterMac::CreateRfcommService( 307 void BluetoothAdapterMac::CreateRfcommService(
179 const BluetoothUUID& uuid, 308 const BluetoothUUID& uuid,
180 int channel, 309 int channel,
181 bool insecure, 310 bool insecure,
182 const CreateServiceCallback& callback, 311 const CreateServiceCallback& callback,
183 const CreateServiceErrorCallback& error_callback) { 312 const CreateServiceErrorCallback& error_callback) {
184 // TODO(keybuk): implement. 313 // TODO(keybuk): implement.
185 NOTIMPLEMENTED(); 314 NOTIMPLEMENTED();
186 } 315 }
187 316
188 void BluetoothAdapterMac::CreateL2capService( 317 void BluetoothAdapterMac::CreateL2capService(
189 const BluetoothUUID& uuid, 318 const BluetoothUUID& uuid,
190 int psm, 319 int psm,
191 const CreateServiceCallback& callback, 320 const CreateServiceCallback& callback,
192 const CreateServiceErrorCallback& error_callback) { 321 const CreateServiceErrorCallback& error_callback) {
193 // TODO(keybuk): implement. 322 // TODO(keybuk): implement.
194 NOTIMPLEMENTED(); 323 NOTIMPLEMENTED();
195 } 324 }
196 325
326 void BluetoothAdapterMac::DeviceFound(IOBluetoothDevice* device) {
327 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
328 if (discovered_devices_.find(device_address) == discovered_devices_.end()) {
329 BluetoothDeviceMac device_mac(device);
330 FOR_EACH_OBSERVER(
331 BluetoothAdapter::Observer, observers_, DeviceAdded(this, &device_mac));
332 discovered_devices_.insert(device_address);
333 }
334 }
335
336 void BluetoothAdapterMac::ClassicDiscoveryStopped(bool unexpected) {
337 if (unexpected) {
338 VLOG(1) << "Discovery stopped unexpectedly";
339 num_discovery_sessions_ = 0;
340 MarkDiscoverySessionsAsInactive();
341 }
342 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
343 observers_,
344 AdapterDiscoveringChanged(this, false));
345 }
346
197 void BluetoothAdapterMac::AddDiscoverySession( 347 void BluetoothAdapterMac::AddDiscoverySession(
198 const base::Closure& callback, 348 const base::Closure& callback,
199 const ErrorCallback& error_callback) { 349 const ErrorCallback& error_callback) {
200 if (discovery_status_ == DISCOVERING) { 350 VLOG(1) << __func__;
201 num_discovery_listeners_++; 351 if (num_discovery_sessions_ > 0) {
352 DCHECK(IsDiscovering());
353 num_discovery_sessions_++;
202 callback.Run(); 354 callback.Run();
203 return; 355 return;
204 } 356 }
205 on_start_discovery_callbacks_.push_back( 357
206 std::make_pair(callback, error_callback)); 358 DCHECK(num_discovery_sessions_ == 0);
207 MaybeStartDeviceInquiry(); 359
360 if (!classic_discovery_session_manager_->StartDiscovery()) {
361 VLOG(1) << "Failed to add a discovery session";
362 error_callback.Run();
363 return;
364 }
365
366 VLOG(1) << "Added a discovery session";
367 num_discovery_sessions_++;
368 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
369 observers_,
370 AdapterDiscoveringChanged(this, true));
371 callback.Run();
208 } 372 }
209 373
210 void BluetoothAdapterMac::RemoveDiscoverySession( 374 void BluetoothAdapterMac::RemoveDiscoverySession(
211 const base::Closure& callback, 375 const base::Closure& callback,
212 const ErrorCallback& error_callback) { 376 const ErrorCallback& error_callback) {
213 if (discovery_status_ == NOT_DISCOVERING) { 377 VLOG(1) << __func__;
378
379 // There are active sessions other than the one currently being removed.
380 if (num_discovery_sessions_ > 1) {
381 DCHECK(IsDiscovering());
382 num_discovery_sessions_--;
383 callback.Run();
384 return;
385 }
386
387 if (num_discovery_sessions_ == 0) {
388 VLOG(1) << "No active discovery sessions. Returning error.";
214 error_callback.Run(); 389 error_callback.Run();
215 return; 390 return;
216 } 391 }
217 on_stop_discovery_callbacks_.push_back( 392
218 std::make_pair(callback, error_callback)); 393 if (!classic_discovery_session_manager_->StopDiscovery()) {
219 MaybeStopDeviceInquiry(); 394 VLOG(1) << "Failed to stop discovery";
395 error_callback.Run();
396 return;
397 }
398
399 VLOG(1) << "Discovery stopped";
400 num_discovery_sessions_--;
401 callback.Run();
220 } 402 }
221 403
222 void BluetoothAdapterMac::RemovePairingDelegateInternal( 404 void BluetoothAdapterMac::RemovePairingDelegateInternal(
223 BluetoothDevice::PairingDelegate* pairing_delegate) { 405 BluetoothDevice::PairingDelegate* pairing_delegate) {
224 } 406 }
225 407
226 void BluetoothAdapterMac::Init() { 408 void BluetoothAdapterMac::Init() {
227 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 409 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
228 PollAdapter(); 410 PollAdapter();
229 } 411 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } 457 }
276 458
277 ui_task_runner_->PostDelayedTask( 459 ui_task_runner_->PostDelayedTask(
278 FROM_HERE, 460 FROM_HERE,
279 base::Bind(&BluetoothAdapterMac::PollAdapter, 461 base::Bind(&BluetoothAdapterMac::PollAdapter,
280 weak_ptr_factory_.GetWeakPtr()), 462 weak_ptr_factory_.GetWeakPtr()),
281 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); 463 base::TimeDelta::FromMilliseconds(kPollIntervalMs));
282 } 464 }
283 465
284 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) { 466 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) {
467 // TODO(armansito): This code never calls
468 // BluetoothAdapter::Observer::DeviceRemoved. It should, if a device
469 // no longer exists.
285 STLDeleteValues(&devices_); 470 STLDeleteValues(&devices_);
286 for (IOBluetoothDevice* device in devices) { 471 for (IOBluetoothDevice* device in devices) {
287 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); 472 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
288 devices_[device_address] = new BluetoothDeviceMac(device); 473 devices_[device_address] = new BluetoothDeviceMac(device);
289 } 474 }
290 } 475 }
291 476
292 void BluetoothAdapterMac::DeviceInquiryStarted(
293 IOBluetoothDeviceInquiry* inquiry) {
294 DCHECK_EQ(device_inquiry_, inquiry);
295 if (discovery_status_ == DISCOVERING)
296 return;
297
298 discovery_status_ = DISCOVERING;
299 RunCallbacks(on_start_discovery_callbacks_, true);
300 num_discovery_listeners_ = on_start_discovery_callbacks_.size();
301 on_start_discovery_callbacks_.clear();
302
303 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
304 AdapterDiscoveringChanged(this, true));
305 MaybeStopDeviceInquiry();
306 }
307
308 void BluetoothAdapterMac::DeviceFound(IOBluetoothDeviceInquiry* inquiry,
309 IOBluetoothDevice* device) {
310 DCHECK_EQ(device_inquiry_, inquiry);
311 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
312 if (discovered_devices_.find(device_address) == discovered_devices_.end()) {
313 BluetoothDeviceMac device_mac(device);
314 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
315 DeviceAdded(this, &device_mac));
316 discovered_devices_.insert(device_address);
317 }
318 }
319
320 void BluetoothAdapterMac::DeviceInquiryComplete(
321 IOBluetoothDeviceInquiry* inquiry,
322 IOReturn error,
323 bool aborted) {
324 DCHECK_EQ(device_inquiry_, inquiry);
325 if (discovery_status_ == DISCOVERING &&
326 [device_inquiry_ start] == kIOReturnSuccess) {
327 return;
328 }
329
330 // Device discovery is done.
331 discovered_devices_.clear();
332 discovery_status_ = NOT_DISCOVERING;
333 RunCallbacks(on_stop_discovery_callbacks_, error == kIOReturnSuccess);
334 num_discovery_listeners_ = 0;
335 on_stop_discovery_callbacks_.clear();
336 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
337 AdapterDiscoveringChanged(this, false));
338 MaybeStartDeviceInquiry();
339 }
340
341 void BluetoothAdapterMac::MaybeStartDeviceInquiry() {
342 if (discovery_status_ == NOT_DISCOVERING &&
343 !on_start_discovery_callbacks_.empty()) {
344 discovery_status_ = DISCOVERY_STARTING;
345 if ([device_inquiry_ start] != kIOReturnSuccess) {
346 discovery_status_ = NOT_DISCOVERING;
347 RunCallbacks(on_start_discovery_callbacks_, false);
348 on_start_discovery_callbacks_.clear();
349 }
350 }
351 }
352
353 void BluetoothAdapterMac::MaybeStopDeviceInquiry() {
354 if (discovery_status_ != DISCOVERING)
355 return;
356
357 if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) {
358 RunCallbacks(on_stop_discovery_callbacks_, true);
359 num_discovery_listeners_ -= on_stop_discovery_callbacks_.size();
360 on_stop_discovery_callbacks_.clear();
361 return;
362 }
363
364 discovery_status_ = DISCOVERY_STOPPING;
365 if ([device_inquiry_ stop] != kIOReturnSuccess) {
366 RunCallbacks(on_stop_discovery_callbacks_, false);
367 on_stop_discovery_callbacks_.clear();
368 }
369 }
370
371 void BluetoothAdapterMac::RunCallbacks(
372 const DiscoveryCallbackList& callback_list, bool success) const {
373 for (DiscoveryCallbackList::const_iterator iter = callback_list.begin();
374 iter != callback_list.end();
375 ++iter) {
376 if (success)
377 ui_task_runner_->PostTask(FROM_HERE, iter->first);
378 else
379 ui_task_runner_->PostTask(FROM_HERE, iter->second);
380 }
381 }
382
383 } // namespace device 477 } // namespace device
OLDNEW
« device/bluetooth/bluetooth_adapter_mac.h ('K') | « device/bluetooth/bluetooth_adapter_mac.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698