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

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: Moved discovery manager to its own file. 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>
9 #import <IOBluetooth/objc/IOBluetoothHostController.h> 8 #import <IOBluetooth/objc/IOBluetoothHostController.h>
10 9
11 #include <string> 10 #include <string>
12 11
13 #include "base/bind.h" 12 #include "base/bind.h"
14 #include "base/compiler_specific.h" 13 #include "base/compiler_specific.h"
15 #include "base/containers/hash_tables.h" 14 #include "base/containers/hash_tables.h"
16 #include "base/location.h" 15 #include "base/location.h"
17 #include "base/memory/scoped_ptr.h" 16 #include "base/memory/scoped_ptr.h"
18 #include "base/sequenced_task_runner.h" 17 #include "base/sequenced_task_runner.h"
19 #include "base/single_thread_task_runner.h" 18 #include "base/single_thread_task_runner.h"
20 #include "base/strings/sys_string_conversions.h" 19 #include "base/strings/sys_string_conversions.h"
21 #include "base/thread_task_runner_handle.h" 20 #include "base/thread_task_runner_handle.h"
22 #include "base/time/time.h" 21 #include "base/time/time.h"
23 #include "device/bluetooth/bluetooth_device_mac.h" 22 #include "device/bluetooth/bluetooth_device_mac.h"
24 #include "device/bluetooth/bluetooth_socket_mac.h" 23 #include "device/bluetooth/bluetooth_socket_mac.h"
25 #include "device/bluetooth/bluetooth_uuid.h" 24 #include "device/bluetooth/bluetooth_uuid.h"
26 25
27 // Replicate specific 10.7 SDK declarations for building with prior SDKs. 26 // Replicate specific 10.7 SDK declarations for building with prior SDKs.
28 #if !defined(MAC_OS_X_VERSION_10_7) || \ 27 #if !defined(MAC_OS_X_VERSION_10_7) || \
29 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 28 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
30 29
31 @interface IOBluetoothHostController (LionSDKDeclarations) 30 @interface IOBluetoothHostController (LionSDKDeclarations)
32 - (NSString*)nameAsString; 31 - (NSString*)nameAsString;
33 - (BluetoothHCIPowerState)powerState; 32 - (BluetoothHCIPowerState)powerState;
34 @end 33 @end
35 34
36 @protocol IOBluetoothDeviceInquiryDelegate
37 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender;
38 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender
39 device:(IOBluetoothDevice*)device;
40 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender
41 error:(IOReturn)error
42 aborted:(BOOL)aborted;
43 @end
44
45 #endif // MAC_OS_X_VERSION_10_7 35 #endif // MAC_OS_X_VERSION_10_7
46 36
47 @interface BluetoothAdapterMacDelegate
48 : NSObject <IOBluetoothDeviceInquiryDelegate> {
49 @private
50 device::BluetoothAdapterMac* adapter_; // weak
51 }
52
53 - (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter;
54
55 @end
56
57 @implementation BluetoothAdapterMacDelegate
58
59 - (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter {
60 if ((self = [super init]))
61 adapter_ = adapter;
62
63 return self;
64 }
65
66 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender {
67 adapter_->DeviceInquiryStarted(sender);
68 }
69
70 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender
71 device:(IOBluetoothDevice*)device {
72 adapter_->DeviceFound(sender, device);
73 }
74
75 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender
76 error:(IOReturn)error
77 aborted:(BOOL)aborted {
78 adapter_->DeviceInquiryComplete(sender, error, aborted);
79 }
80
81 @end
82
83 namespace { 37 namespace {
84 38
85 const int kPollIntervalMs = 500; 39 const int kPollIntervalMs = 500;
86 40
87 } // namespace 41 } // namespace
88 42
89 namespace device { 43 namespace device {
90 44
91 // static 45 // static
92 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( 46 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
93 const InitCallback& init_callback) { 47 const InitCallback& init_callback) {
94 return BluetoothAdapterMac::CreateAdapter(); 48 return BluetoothAdapterMac::CreateAdapter();
95 } 49 }
96 50
97 // static 51 // static
98 base::WeakPtr<BluetoothAdapter> BluetoothAdapterMac::CreateAdapter() { 52 base::WeakPtr<BluetoothAdapter> BluetoothAdapterMac::CreateAdapter() {
99 BluetoothAdapterMac* adapter = new BluetoothAdapterMac(); 53 BluetoothAdapterMac* adapter = new BluetoothAdapterMac();
100 adapter->Init(); 54 adapter->Init();
101 return adapter->weak_ptr_factory_.GetWeakPtr(); 55 return adapter->weak_ptr_factory_.GetWeakPtr();
102 } 56 }
103 57
104 BluetoothAdapterMac::BluetoothAdapterMac() 58 BluetoothAdapterMac::BluetoothAdapterMac()
105 : BluetoothAdapter(), 59 : BluetoothAdapter(),
106 powered_(false), 60 powered_(false),
107 discovery_status_(NOT_DISCOVERING), 61 num_discovery_sessions_(0),
108 adapter_delegate_( 62 classic_discovery_manager_(BluetoothMacDiscoveryManager::CreateClassic()),
109 [[BluetoothAdapterMacDelegate alloc] initWithAdapter:this]),
110 device_inquiry_(
111 [[IOBluetoothDeviceInquiry
112 inquiryWithDelegate:adapter_delegate_] retain]),
113 weak_ptr_factory_(this) { 63 weak_ptr_factory_(this) {
64 DCHECK(classic_discovery_manager_.get());
65 classic_discovery_manager_->AddObserver(this);
114 } 66 }
115 67
116 BluetoothAdapterMac::~BluetoothAdapterMac() { 68 BluetoothAdapterMac::~BluetoothAdapterMac() {
69 classic_discovery_manager_->RemoveObserver(this);
117 } 70 }
118 71
119 void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) { 72 void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) {
120 DCHECK(observer); 73 DCHECK(observer);
121 observers_.AddObserver(observer); 74 observers_.AddObserver(observer);
122 } 75 }
123 76
124 void BluetoothAdapterMac::RemoveObserver(BluetoothAdapter::Observer* observer) { 77 void BluetoothAdapterMac::RemoveObserver(BluetoothAdapter::Observer* observer) {
125 DCHECK(observer); 78 DCHECK(observer);
126 observers_.RemoveObserver(observer); 79 observers_.RemoveObserver(observer);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
164 } 117 }
165 118
166 void BluetoothAdapterMac::SetDiscoverable( 119 void BluetoothAdapterMac::SetDiscoverable(
167 bool discoverable, 120 bool discoverable,
168 const base::Closure& callback, 121 const base::Closure& callback,
169 const ErrorCallback& error_callback) { 122 const ErrorCallback& error_callback) {
170 NOTIMPLEMENTED(); 123 NOTIMPLEMENTED();
171 } 124 }
172 125
173 bool BluetoothAdapterMac::IsDiscovering() const { 126 bool BluetoothAdapterMac::IsDiscovering() const {
174 return discovery_status_ == DISCOVERING || 127 return classic_discovery_manager_->IsDiscovering();
175 discovery_status_ == DISCOVERY_STOPPING;
176 } 128 }
177 129
178 void BluetoothAdapterMac::CreateRfcommService( 130 void BluetoothAdapterMac::CreateRfcommService(
179 const BluetoothUUID& uuid, 131 const BluetoothUUID& uuid,
180 int channel, 132 int channel,
181 bool insecure, 133 bool insecure,
182 const CreateServiceCallback& callback, 134 const CreateServiceCallback& callback,
183 const CreateServiceErrorCallback& error_callback) { 135 const CreateServiceErrorCallback& error_callback) {
184 // TODO(keybuk): implement. 136 // TODO(keybuk): implement.
185 NOTIMPLEMENTED(); 137 NOTIMPLEMENTED();
186 } 138 }
187 139
188 void BluetoothAdapterMac::CreateL2capService( 140 void BluetoothAdapterMac::CreateL2capService(
189 const BluetoothUUID& uuid, 141 const BluetoothUUID& uuid,
190 int psm, 142 int psm,
191 const CreateServiceCallback& callback, 143 const CreateServiceCallback& callback,
192 const CreateServiceErrorCallback& error_callback) { 144 const CreateServiceErrorCallback& error_callback) {
193 // TODO(keybuk): implement. 145 // TODO(keybuk): implement.
194 NOTIMPLEMENTED(); 146 NOTIMPLEMENTED();
195 } 147 }
196 148
149 void BluetoothAdapterMac::DeviceFound(BluetoothMacDiscoveryManager* manager,
150 IOBluetoothDevice* device) {
151 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
152 if (discovered_devices_.find(device_address) == discovered_devices_.end()) {
153 BluetoothDeviceMac device_mac(device);
154 FOR_EACH_OBSERVER(
155 BluetoothAdapter::Observer, observers_, DeviceAdded(this, &device_mac));
156 discovered_devices_.insert(device_address);
157 }
158 }
159
160 void BluetoothAdapterMac::DiscoveryStopped(
161 BluetoothMacDiscoveryManager* manager,
162 bool unexpected) {
163 if (manager != classic_discovery_manager_.get()) {
164 VLOG(1) << "Received \"DiscoveryStopped\" from unknown discovery manager.";
165 return;
166 }
Ilya Sherman 2014/06/10 01:10:59 Can this be a DCHECK rather than a VLOG?
armansito 2014/06/10 21:56:50 Done.
167 if (unexpected) {
168 VLOG(1) << "Discovery stopped unexpectedly";
Ilya Sherman 2014/06/10 01:10:59 Out of curiousity, why do we use VLOG rather than
keybuk 2014/06/10 01:13:12 CHROME OS debug builds haven't worked for somethin
Ilya Sherman 2014/06/10 01:14:04 Ok, good to know -- thanks :)
keybuk 2014/06/10 01:21:03 but this is _mac, so doesn't really apply, I was j
armansito 2014/06/10 21:56:50 Done.
169 num_discovery_sessions_ = 0;
170 MarkDiscoverySessionsAsInactive();
171 }
172 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
173 observers_,
174 AdapterDiscoveringChanged(this, false));
175 }
176
197 void BluetoothAdapterMac::AddDiscoverySession( 177 void BluetoothAdapterMac::AddDiscoverySession(
198 const base::Closure& callback, 178 const base::Closure& callback,
199 const ErrorCallback& error_callback) { 179 const ErrorCallback& error_callback) {
200 if (discovery_status_ == DISCOVERING) { 180 VLOG(1) << __func__;
201 num_discovery_listeners_++; 181 if (num_discovery_sessions_ > 0) {
182 DCHECK(IsDiscovering());
183 num_discovery_sessions_++;
202 callback.Run(); 184 callback.Run();
203 return; 185 return;
204 } 186 }
205 on_start_discovery_callbacks_.push_back( 187
206 std::make_pair(callback, error_callback)); 188 DCHECK(num_discovery_sessions_ == 0);
Ilya Sherman 2014/06/10 01:10:59 nit: DCHECK_EQ
armansito 2014/06/10 21:56:50 Done.
207 MaybeStartDeviceInquiry(); 189
190 if (!classic_discovery_manager_->StartDiscovery()) {
191 VLOG(1) << "Failed to add a discovery session";
192 error_callback.Run();
193 return;
194 }
195
196 VLOG(1) << "Added a discovery session";
197 num_discovery_sessions_++;
198 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
199 observers_,
200 AdapterDiscoveringChanged(this, true));
201 callback.Run();
208 } 202 }
209 203
210 void BluetoothAdapterMac::RemoveDiscoverySession( 204 void BluetoothAdapterMac::RemoveDiscoverySession(
211 const base::Closure& callback, 205 const base::Closure& callback,
212 const ErrorCallback& error_callback) { 206 const ErrorCallback& error_callback) {
213 if (discovery_status_ == NOT_DISCOVERING) { 207 VLOG(1) << __func__;
208
209 // There are active sessions other than the one currently being removed.
Ilya Sherman 2014/06/10 01:10:59 nit: Please move this into the if-stmt. Typically
armansito 2014/06/10 21:56:50 Done.
210 if (num_discovery_sessions_ > 1) {
211 DCHECK(IsDiscovering());
212 num_discovery_sessions_--;
213 callback.Run();
214 return;
215 }
216
217 if (num_discovery_sessions_ == 0) {
218 VLOG(1) << "No active discovery sessions. Returning error.";
214 error_callback.Run(); 219 error_callback.Run();
215 return; 220 return;
216 } 221 }
217 on_stop_discovery_callbacks_.push_back( 222
218 std::make_pair(callback, error_callback)); 223 if (!classic_discovery_manager_->StopDiscovery()) {
219 MaybeStopDeviceInquiry(); 224 VLOG(1) << "Failed to stop discovery";
225 error_callback.Run();
226 return;
227 }
228
229 VLOG(1) << "Discovery stopped";
230 num_discovery_sessions_--;
231 callback.Run();
220 } 232 }
221 233
222 void BluetoothAdapterMac::RemovePairingDelegateInternal( 234 void BluetoothAdapterMac::RemovePairingDelegateInternal(
223 BluetoothDevice::PairingDelegate* pairing_delegate) { 235 BluetoothDevice::PairingDelegate* pairing_delegate) {
224 } 236 }
225 237
226 void BluetoothAdapterMac::Init() { 238 void BluetoothAdapterMac::Init() {
227 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 239 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
228 PollAdapter(); 240 PollAdapter();
229 } 241 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
275 } 287 }
276 288
277 ui_task_runner_->PostDelayedTask( 289 ui_task_runner_->PostDelayedTask(
278 FROM_HERE, 290 FROM_HERE,
279 base::Bind(&BluetoothAdapterMac::PollAdapter, 291 base::Bind(&BluetoothAdapterMac::PollAdapter,
280 weak_ptr_factory_.GetWeakPtr()), 292 weak_ptr_factory_.GetWeakPtr()),
281 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); 293 base::TimeDelta::FromMilliseconds(kPollIntervalMs));
282 } 294 }
283 295
284 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) { 296 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) {
297 // TODO(armansito): This code never calls
298 // BluetoothAdapter::Observer::DeviceRemoved. It should, if a device
299 // no longer exists.
285 STLDeleteValues(&devices_); 300 STLDeleteValues(&devices_);
286 for (IOBluetoothDevice* device in devices) { 301 for (IOBluetoothDevice* device in devices) {
287 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); 302 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
288 devices_[device_address] = new BluetoothDeviceMac(device); 303 devices_[device_address] = new BluetoothDeviceMac(device);
289 } 304 }
290 } 305 }
291 306
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 307 } // namespace device
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698