OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "device/bluetooth/bluetooth_mac_discovery_manager.h" | |
6 | |
7 #import <IOBluetooth/objc/IOBluetoothDevice.h> | |
8 #import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h> | |
9 | |
10 #include "base/mac/scoped_nsobject.h" | |
11 | |
12 namespace device { | |
13 | |
14 class BluetoothMacDiscoveryManagerClassicImpl; | |
15 | |
16 } // namespace device | |
17 | |
18 // Replicate specific 10.7 SDK declarations for building with prior SDKs. | |
19 #if !defined(MAC_OS_X_VERSION_10_7) || \ | |
20 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 | |
21 | |
22 @protocol IOBluetoothDeviceInquiryDelegate | |
23 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender; | |
24 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender | |
25 device:(IOBluetoothDevice*)device; | |
26 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender | |
27 error:(IOReturn)error | |
28 aborted:(BOOL)aborted; | |
29 @end | |
30 | |
31 #endif // MAC_OS_X_VERSION_10_7 | |
Ilya Sherman
2014/06/10 01:25:13
I discovered while rebasing a CL today that appare
armansito
2014/06/10 21:56:50
Done.
| |
32 | |
33 // IOBluetoothDeviceInquiryDelegate implementation. | |
34 @interface BluetoothDeviceInquiryDelegate | |
35 : NSObject<IOBluetoothDeviceInquiryDelegate> { | |
36 @private | |
37 device::BluetoothMacDiscoveryManagerClassicImpl* manager_; // weak | |
38 } | |
39 | |
40 - (id)initWithManager:(device::BluetoothMacDiscoveryManagerClassicImpl*)manager; | |
41 | |
42 @end | |
43 | |
44 namespace device { | |
45 | |
46 // Implementation of BluetoothMacDiscoveryManager for Bluetooth classic device | |
47 // discovery, using the IOBluetooth framework. | |
48 class BluetoothMacDiscoveryManagerClassicImpl | |
Ilya Sherman
2014/06/10 01:10:59
nit: "Impl" seems unnecessary, since there's no no
armansito
2014/06/10 21:56:50
You assumed correctly. Done.
| |
49 : public BluetoothMacDiscoveryManager { | |
50 public: | |
51 BluetoothMacDiscoveryManagerClassicImpl() | |
52 : should_do_discovery_(false), | |
53 inquiry_running_(false), | |
54 inquiry_delegate_( | |
55 [[BluetoothDeviceInquiryDelegate alloc] initWithManager:this]), | |
56 inquiry_([[IOBluetoothDeviceInquiry alloc] | |
57 initWithDelegate:inquiry_delegate_]) {} | |
58 | |
59 virtual ~BluetoothMacDiscoveryManagerClassicImpl() {} | |
60 | |
61 // BluetoothMacDiscoveryManager override. | |
62 virtual bool IsDiscovering() const OVERRIDE { return should_do_discovery_; } | |
63 | |
64 // BluetoothMacDiscoveryManager override. | |
65 virtual bool StartDiscovery() OVERRIDE { | |
66 VLOG(1) << "Bluetooth Classic: StartDiscovery"; | |
67 if (should_do_discovery_) { | |
68 VLOG(1) << "Already discovering"; | |
69 return true; | |
70 } | |
Ilya Sherman
2014/06/10 01:11:00
Could this be a DCHECK instead?
armansito
2014/06/10 21:56:50
Done.
| |
71 | |
72 VLOG(1) << "Discovery requested"; | |
73 should_do_discovery_ = true; | |
74 | |
75 if (inquiry_running_) { | |
76 VLOG(1) << "Device inquiry already running"; | |
77 return true; | |
78 } | |
Ilya Sherman
2014/06/10 01:10:59
Why is this reachable? Could this be a DCHECK ins
armansito
2014/06/10 21:56:51
No, please see my comment below.
| |
79 | |
80 VLOG(1) << "Requesting to start device inquiry"; | |
81 if ([inquiry_ start] != kIOReturnSuccess) { | |
82 VLOG(1) << "Failed to start device inquiry"; | |
83 | |
84 // Set |should_do_discovery_| to false here. Since we're reporting an | |
85 // error, we're indicating that the adapter call StartDiscovery again | |
86 // if needed. | |
87 should_do_discovery_ = false; | |
88 return false; | |
89 } | |
90 | |
91 VLOG(1) << "Device inquiry start was successful"; | |
92 return true; | |
93 } | |
94 | |
95 // BluetoothMacDiscoveryManager override. | |
96 virtual bool StopDiscovery() OVERRIDE { | |
97 VLOG(1) << "Bluetooth Classic: StopDiscovery"; | |
98 if (!should_do_discovery_) { | |
99 VLOG(1) << "Discovery already stopped"; | |
100 return true; | |
101 } | |
Ilya Sherman
2014/06/10 01:10:59
Ditto.
armansito
2014/06/10 21:56:50
Done.
| |
102 | |
103 should_do_discovery_ = false; | |
104 | |
105 if (!inquiry_running_) { | |
106 VLOG(1) << "No device inquiry running; discovery stopped"; | |
107 return true; | |
108 } | |
Ilya Sherman
2014/06/10 01:10:59
This seems wrong, since inquiry_running_ can be se
armansito
2014/06/10 21:56:51
[inquiry_ start] and [inquiry_ stop] are synchrono
| |
109 | |
110 VLOG(1) << "Requesting to stop device inquiry"; | |
111 IOReturn status = [inquiry_ stop]; | |
112 if (status == kIOReturnSuccess) { | |
113 VLOG(1) << "Device inquiry stop was successful"; | |
114 return true; | |
115 } | |
116 | |
117 if (status == kIOReturnNotPermitted) { | |
118 VLOG(1) << "Device inquiry was already stopped"; | |
119 return true; | |
120 } | |
121 | |
122 LOG(WARNING) << "Failed to stop device inquiry"; | |
123 return false; | |
124 } | |
125 | |
126 // Called by BluetoothDeviceInquiryDelegate. | |
127 void DeviceInquiryStarted(IOBluetoothDeviceInquiry* inquiry) { | |
128 DCHECK(!inquiry_running_); | |
129 | |
130 VLOG(1) << "Device inquiry started!"; | |
131 | |
132 // If discovery was requested to stop in the mean time, stop the inquiry. | |
133 if (!should_do_discovery_) { | |
134 VLOG(1) << "Discovery stop was requested earlier. Stopping inquiry"; | |
135 [inquiry stop]; | |
136 return; | |
137 } | |
138 | |
139 inquiry_running_ = true; | |
140 } | |
141 | |
142 void DeviceFound(IOBluetoothDeviceInquiry* inquiry, | |
143 IOBluetoothDevice* device) { | |
144 FOR_EACH_OBSERVER(Observer, observers_, DeviceFound(this, device)); | |
145 } | |
146 | |
147 void DeviceInquiryComplete(IOBluetoothDeviceInquiry* inquiry, | |
148 IOReturn error, | |
149 bool aborted) { | |
150 DCHECK_EQ(inquiry_, inquiry); | |
151 VLOG(1) << "Device inquiry complete"; | |
152 inquiry_running_ = false; | |
153 | |
154 // Automatically restart device inquiry if discovery is still desired. | |
Ilya Sherman
2014/06/10 01:10:59
nit: This comment seems either misplaced, or like
armansito
2014/06/10 21:56:51
Done.
| |
155 if (!should_do_discovery_) { | |
156 FOR_EACH_OBSERVER( | |
157 Observer, observers_, DiscoveryStopped(this, false /* unexpected */)); | |
158 return; | |
159 } | |
160 | |
161 if (error != kIOReturnSuccess) { | |
162 VLOG(1) << "Inquiry has stopped with an error: " << error; | |
163 should_do_discovery_ = false; | |
164 FOR_EACH_OBSERVER( | |
165 Observer, observers_, DiscoveryStopped(this, true /* unexpected */)); | |
166 return; | |
167 } | |
168 | |
169 VLOG(1) << "Restarting device inquiry"; | |
170 | |
171 if ([inquiry_ start] == kIOReturnSuccess) { | |
172 VLOG(1) << "Device inquiry restart was successful"; | |
173 return; | |
174 } | |
175 | |
176 VLOG(1) << "Failed to restart discovery"; | |
177 should_do_discovery_ = false; | |
178 FOR_EACH_OBSERVER( | |
179 Observer, observers_, DiscoveryStopped(this, true /* unexpected */)); | |
180 } | |
181 | |
182 private: | |
183 // The requested discovery state. | |
184 bool should_do_discovery_; | |
185 | |
186 // The current inquiry state. | |
187 bool inquiry_running_; | |
188 | |
189 // Objective-C objects for running and tracking device inquiry. | |
190 base::scoped_nsobject<BluetoothDeviceInquiryDelegate> inquiry_delegate_; | |
191 base::scoped_nsobject<IOBluetoothDeviceInquiry> inquiry_; | |
192 | |
193 DISALLOW_COPY_AND_ASSIGN(BluetoothMacDiscoveryManagerClassicImpl); | |
194 }; | |
195 | |
196 BluetoothMacDiscoveryManager::BluetoothMacDiscoveryManager() { | |
197 } | |
198 BluetoothMacDiscoveryManager::~BluetoothMacDiscoveryManager() { | |
199 } | |
200 | |
201 void BluetoothMacDiscoveryManager::AddObserver(Observer* observer) { | |
202 observers_.AddObserver(observer); | |
203 } | |
204 | |
205 void BluetoothMacDiscoveryManager::RemoveObserver(Observer* observer) { | |
206 observers_.RemoveObserver(observer); | |
207 } | |
208 | |
209 // static | |
210 BluetoothMacDiscoveryManager* BluetoothMacDiscoveryManager::CreateClassic() { | |
211 return new BluetoothMacDiscoveryManagerClassicImpl(); | |
212 } | |
213 | |
214 } // namespace device | |
215 | |
216 @implementation BluetoothDeviceInquiryDelegate | |
217 | |
218 - (id)initWithManager: | |
219 (device::BluetoothMacDiscoveryManagerClassicImpl*)manager { | |
220 if ((self = [super init])) | |
221 manager_ = manager; | |
222 | |
223 return self; | |
224 } | |
225 | |
226 - (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender { | |
227 manager_->DeviceInquiryStarted(sender); | |
228 } | |
229 | |
230 - (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender | |
231 device:(IOBluetoothDevice*)device { | |
232 manager_->DeviceFound(sender, device); | |
233 } | |
234 | |
235 - (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender | |
236 error:(IOReturn)error | |
237 aborted:(BOOL)aborted { | |
238 manager_->DeviceInquiryComplete(sender, error, aborted); | |
239 } | |
240 | |
241 @end | |
OLD | NEW |