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

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: Addressed comments 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/mac/sdk_forward_declarations.h" 16 #include "base/mac/sdk_forward_declarations.h"
18 #include "base/memory/scoped_ptr.h" 17 #include "base/memory/scoped_ptr.h"
19 #include "base/sequenced_task_runner.h" 18 #include "base/sequenced_task_runner.h"
20 #include "base/single_thread_task_runner.h" 19 #include "base/single_thread_task_runner.h"
21 #include "base/strings/sys_string_conversions.h" 20 #include "base/strings/sys_string_conversions.h"
22 #include "base/thread_task_runner_handle.h" 21 #include "base/thread_task_runner_handle.h"
23 #include "base/time/time.h" 22 #include "base/time/time.h"
24 #include "device/bluetooth/bluetooth_device_mac.h" 23 #include "device/bluetooth/bluetooth_device_mac.h"
25 #include "device/bluetooth/bluetooth_socket_mac.h" 24 #include "device/bluetooth/bluetooth_socket_mac.h"
26 #include "device/bluetooth/bluetooth_uuid.h" 25 #include "device/bluetooth/bluetooth_uuid.h"
27 26
28 @interface BluetoothAdapterMacDelegate
29 : NSObject <IOBluetoothDeviceInquiryDelegate> {
30 @private
31 device::BluetoothAdapterMac* adapter_; // weak
32 }
33
34 - (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter;
35
36 @end
37
38 @implementation BluetoothAdapterMacDelegate
39
40 - (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter {
41 if ((self = [super init]))
42 adapter_ = adapter;
43
44 return self;
45 }
46
47 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender {
48 adapter_->DeviceInquiryStarted(sender);
49 }
50
51 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender
52 device:(IOBluetoothDevice*)device {
53 adapter_->DeviceFound(sender, device);
54 }
55
56 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender
57 error:(IOReturn)error
58 aborted:(BOOL)aborted {
59 adapter_->DeviceInquiryComplete(sender, error, aborted);
60 }
61
62 @end
63
64 namespace { 27 namespace {
65 28
66 const int kPollIntervalMs = 500; 29 const int kPollIntervalMs = 500;
67 30
68 } // namespace 31 } // namespace
69 32
70 namespace device { 33 namespace device {
71 34
72 // static 35 // static
73 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter( 36 base::WeakPtr<BluetoothAdapter> BluetoothAdapter::CreateAdapter(
74 const InitCallback& init_callback) { 37 const InitCallback& init_callback) {
75 return BluetoothAdapterMac::CreateAdapter(); 38 return BluetoothAdapterMac::CreateAdapter();
76 } 39 }
77 40
78 // static 41 // static
79 base::WeakPtr<BluetoothAdapter> BluetoothAdapterMac::CreateAdapter() { 42 base::WeakPtr<BluetoothAdapter> BluetoothAdapterMac::CreateAdapter() {
80 BluetoothAdapterMac* adapter = new BluetoothAdapterMac(); 43 BluetoothAdapterMac* adapter = new BluetoothAdapterMac();
81 adapter->Init(); 44 adapter->Init();
82 return adapter->weak_ptr_factory_.GetWeakPtr(); 45 return adapter->weak_ptr_factory_.GetWeakPtr();
83 } 46 }
84 47
85 BluetoothAdapterMac::BluetoothAdapterMac() 48 BluetoothAdapterMac::BluetoothAdapterMac()
86 : BluetoothAdapter(), 49 : BluetoothAdapter(),
87 powered_(false), 50 powered_(false),
88 discovery_status_(NOT_DISCOVERING), 51 num_discovery_sessions_(0),
89 adapter_delegate_( 52 classic_discovery_manager_(
90 [[BluetoothAdapterMacDelegate alloc] initWithAdapter:this]), 53 BluetoothDiscoveryManagerMac::CreateClassic(this)),
91 device_inquiry_(
92 [[IOBluetoothDeviceInquiry
93 inquiryWithDelegate:adapter_delegate_] retain]),
94 weak_ptr_factory_(this) { 54 weak_ptr_factory_(this) {
55 DCHECK(classic_discovery_manager_.get());
95 } 56 }
96 57
97 BluetoothAdapterMac::~BluetoothAdapterMac() { 58 BluetoothAdapterMac::~BluetoothAdapterMac() {
98 } 59 }
99 60
100 void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) { 61 void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) {
101 DCHECK(observer); 62 DCHECK(observer);
102 observers_.AddObserver(observer); 63 observers_.AddObserver(observer);
103 } 64 }
104 65
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
145 } 106 }
146 107
147 void BluetoothAdapterMac::SetDiscoverable( 108 void BluetoothAdapterMac::SetDiscoverable(
148 bool discoverable, 109 bool discoverable,
149 const base::Closure& callback, 110 const base::Closure& callback,
150 const ErrorCallback& error_callback) { 111 const ErrorCallback& error_callback) {
151 NOTIMPLEMENTED(); 112 NOTIMPLEMENTED();
152 } 113 }
153 114
154 bool BluetoothAdapterMac::IsDiscovering() const { 115 bool BluetoothAdapterMac::IsDiscovering() const {
155 return discovery_status_ == DISCOVERING || 116 return classic_discovery_manager_->IsDiscovering();
156 discovery_status_ == DISCOVERY_STOPPING;
157 } 117 }
158 118
159 void BluetoothAdapterMac::CreateRfcommService( 119 void BluetoothAdapterMac::CreateRfcommService(
160 const BluetoothUUID& uuid, 120 const BluetoothUUID& uuid,
161 int channel, 121 int channel,
162 const CreateServiceCallback& callback, 122 const CreateServiceCallback& callback,
163 const CreateServiceErrorCallback& error_callback) { 123 const CreateServiceErrorCallback& error_callback) {
164 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket(); 124 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
165 socket->ListenUsingRfcomm( 125 socket->ListenUsingRfcomm(
166 this, uuid, channel, base::Bind(callback, socket), error_callback); 126 this, uuid, channel, base::Bind(callback, socket), error_callback);
167 } 127 }
168 128
169 void BluetoothAdapterMac::CreateL2capService( 129 void BluetoothAdapterMac::CreateL2capService(
170 const BluetoothUUID& uuid, 130 const BluetoothUUID& uuid,
171 int psm, 131 int psm,
172 const CreateServiceCallback& callback, 132 const CreateServiceCallback& callback,
173 const CreateServiceErrorCallback& error_callback) { 133 const CreateServiceErrorCallback& error_callback) {
174 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket(); 134 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket();
175 socket->ListenUsingL2cap( 135 socket->ListenUsingL2cap(
176 this, uuid, psm, base::Bind(callback, socket), error_callback); 136 this, uuid, psm, base::Bind(callback, socket), error_callback);
177 } 137 }
178 138
139 void BluetoothAdapterMac::DeviceFound(BluetoothDiscoveryManagerMac* manager,
140 IOBluetoothDevice* device) {
141 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
142 if (discovered_devices_.find(device_address) == discovered_devices_.end()) {
143 BluetoothDeviceMac device_mac(device);
144 FOR_EACH_OBSERVER(
145 BluetoothAdapter::Observer, observers_, DeviceAdded(this, &device_mac));
146 discovered_devices_.insert(device_address);
147 }
148 }
149
150 void BluetoothAdapterMac::DiscoveryStopped(
151 BluetoothDiscoveryManagerMac* manager,
152 bool unexpected) {
153 DCHECK_EQ(manager, classic_discovery_manager_.get());
154 if (unexpected) {
155 DVLOG(1) << "Discovery stopped unexpectedly";
156 num_discovery_sessions_ = 0;
157 MarkDiscoverySessionsAsInactive();
158 }
159 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
160 observers_,
161 AdapterDiscoveringChanged(this, false));
162 }
163
179 void BluetoothAdapterMac::AddDiscoverySession( 164 void BluetoothAdapterMac::AddDiscoverySession(
180 const base::Closure& callback, 165 const base::Closure& callback,
181 const ErrorCallback& error_callback) { 166 const ErrorCallback& error_callback) {
182 if (discovery_status_ == DISCOVERING) { 167 DVLOG(1) << __func__;
183 num_discovery_listeners_++; 168 if (num_discovery_sessions_ > 0) {
169 DCHECK(IsDiscovering());
170 num_discovery_sessions_++;
184 callback.Run(); 171 callback.Run();
185 return; 172 return;
186 } 173 }
187 on_start_discovery_callbacks_.push_back( 174
188 std::make_pair(callback, error_callback)); 175 DCHECK_EQ(0, num_discovery_sessions_);
189 MaybeStartDeviceInquiry(); 176
177 if (!classic_discovery_manager_->StartDiscovery()) {
178 DVLOG(1) << "Failed to add a discovery session";
179 error_callback.Run();
180 return;
181 }
182
183 DVLOG(1) << "Added a discovery session";
184 num_discovery_sessions_++;
185 FOR_EACH_OBSERVER(BluetoothAdapter::Observer,
186 observers_,
187 AdapterDiscoveringChanged(this, true));
188 callback.Run();
190 } 189 }
191 190
192 void BluetoothAdapterMac::RemoveDiscoverySession( 191 void BluetoothAdapterMac::RemoveDiscoverySession(
193 const base::Closure& callback, 192 const base::Closure& callback,
194 const ErrorCallback& error_callback) { 193 const ErrorCallback& error_callback) {
195 if (discovery_status_ == NOT_DISCOVERING) { 194 DVLOG(1) << __func__;
195
196 if (num_discovery_sessions_ > 1) {
197 // There are active sessions other than the one currently being removed.
198 DCHECK(IsDiscovering());
199 num_discovery_sessions_--;
200 callback.Run();
201 return;
202 }
203
204 if (num_discovery_sessions_ == 0) {
205 DVLOG(1) << "No active discovery sessions. Returning error.";
196 error_callback.Run(); 206 error_callback.Run();
197 return; 207 return;
198 } 208 }
199 on_stop_discovery_callbacks_.push_back( 209
200 std::make_pair(callback, error_callback)); 210 if (!classic_discovery_manager_->StopDiscovery()) {
201 MaybeStopDeviceInquiry(); 211 DVLOG(1) << "Failed to stop discovery";
212 error_callback.Run();
213 return;
214 }
215
216 DVLOG(1) << "Discovery stopped";
217 num_discovery_sessions_--;
218 callback.Run();
202 } 219 }
203 220
204 void BluetoothAdapterMac::RemovePairingDelegateInternal( 221 void BluetoothAdapterMac::RemovePairingDelegateInternal(
205 BluetoothDevice::PairingDelegate* pairing_delegate) { 222 BluetoothDevice::PairingDelegate* pairing_delegate) {
206 } 223 }
207 224
208 void BluetoothAdapterMac::Init() { 225 void BluetoothAdapterMac::Init() {
209 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get(); 226 ui_task_runner_ = base::ThreadTaskRunnerHandle::Get();
210 PollAdapter(); 227 PollAdapter();
211 } 228 }
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
257 } 274 }
258 275
259 ui_task_runner_->PostDelayedTask( 276 ui_task_runner_->PostDelayedTask(
260 FROM_HERE, 277 FROM_HERE,
261 base::Bind(&BluetoothAdapterMac::PollAdapter, 278 base::Bind(&BluetoothAdapterMac::PollAdapter,
262 weak_ptr_factory_.GetWeakPtr()), 279 weak_ptr_factory_.GetWeakPtr()),
263 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); 280 base::TimeDelta::FromMilliseconds(kPollIntervalMs));
264 } 281 }
265 282
266 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) { 283 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) {
284 // TODO(armansito): This code never calls
285 // BluetoothAdapter::Observer::DeviceRemoved. It should, if a device
286 // no longer exists.
267 STLDeleteValues(&devices_); 287 STLDeleteValues(&devices_);
268 for (IOBluetoothDevice* device in devices) { 288 for (IOBluetoothDevice* device in devices) {
269 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); 289 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
270 devices_[device_address] = new BluetoothDeviceMac(device); 290 devices_[device_address] = new BluetoothDeviceMac(device);
271 } 291 }
272 } 292 }
273 293
274 void BluetoothAdapterMac::DeviceInquiryStarted(
275 IOBluetoothDeviceInquiry* inquiry) {
276 DCHECK_EQ(device_inquiry_, inquiry);
277 if (discovery_status_ == DISCOVERING)
278 return;
279
280 discovery_status_ = DISCOVERING;
281 RunCallbacks(on_start_discovery_callbacks_, true);
282 num_discovery_listeners_ = on_start_discovery_callbacks_.size();
283 on_start_discovery_callbacks_.clear();
284
285 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
286 AdapterDiscoveringChanged(this, true));
287 MaybeStopDeviceInquiry();
288 }
289
290 void BluetoothAdapterMac::DeviceFound(IOBluetoothDeviceInquiry* inquiry,
291 IOBluetoothDevice* device) {
292 DCHECK_EQ(device_inquiry_, inquiry);
293 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device);
294 if (discovered_devices_.find(device_address) == discovered_devices_.end()) {
295 BluetoothDeviceMac device_mac(device);
296 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
297 DeviceAdded(this, &device_mac));
298 discovered_devices_.insert(device_address);
299 }
300 }
301
302 void BluetoothAdapterMac::DeviceInquiryComplete(
303 IOBluetoothDeviceInquiry* inquiry,
304 IOReturn error,
305 bool aborted) {
306 DCHECK_EQ(device_inquiry_, inquiry);
307 if (discovery_status_ == DISCOVERING &&
308 [device_inquiry_ start] == kIOReturnSuccess) {
309 return;
310 }
311
312 // Device discovery is done.
313 discovered_devices_.clear();
314 discovery_status_ = NOT_DISCOVERING;
315 RunCallbacks(on_stop_discovery_callbacks_, error == kIOReturnSuccess);
316 num_discovery_listeners_ = 0;
317 on_stop_discovery_callbacks_.clear();
318 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_,
319 AdapterDiscoveringChanged(this, false));
320 MaybeStartDeviceInquiry();
321 }
322
323 void BluetoothAdapterMac::MaybeStartDeviceInquiry() {
324 if (discovery_status_ == NOT_DISCOVERING &&
325 !on_start_discovery_callbacks_.empty()) {
326 discovery_status_ = DISCOVERY_STARTING;
327 if ([device_inquiry_ start] != kIOReturnSuccess) {
328 discovery_status_ = NOT_DISCOVERING;
329 RunCallbacks(on_start_discovery_callbacks_, false);
330 on_start_discovery_callbacks_.clear();
331 }
332 }
333 }
334
335 void BluetoothAdapterMac::MaybeStopDeviceInquiry() {
336 if (discovery_status_ != DISCOVERING)
337 return;
338
339 if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) {
340 RunCallbacks(on_stop_discovery_callbacks_, true);
341 num_discovery_listeners_ -= on_stop_discovery_callbacks_.size();
342 on_stop_discovery_callbacks_.clear();
343 return;
344 }
345
346 discovery_status_ = DISCOVERY_STOPPING;
347 if ([device_inquiry_ stop] != kIOReturnSuccess) {
348 RunCallbacks(on_stop_discovery_callbacks_, false);
349 on_stop_discovery_callbacks_.clear();
350 }
351 }
352
353 void BluetoothAdapterMac::RunCallbacks(
354 const DiscoveryCallbackList& callback_list, bool success) const {
355 for (DiscoveryCallbackList::const_iterator iter = callback_list.begin();
356 iter != callback_list.end();
357 ++iter) {
358 if (success)
359 ui_task_runner_->PostTask(FROM_HERE, iter->first);
360 else
361 ui_task_runner_->PostTask(FROM_HERE, iter->second);
362 }
363 }
364
365 } // namespace device 294 } // namespace device
OLDNEW
« no previous file with comments | « device/bluetooth/bluetooth_adapter_mac.h ('k') | device/bluetooth/bluetooth_discovery_manager_mac.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698