OLD | NEW |
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> |
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
131 int psm, | 131 int psm, |
132 const CreateServiceCallback& callback, | 132 const CreateServiceCallback& callback, |
133 const CreateServiceErrorCallback& error_callback) { | 133 const CreateServiceErrorCallback& error_callback) { |
134 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket(); | 134 scoped_refptr<BluetoothSocketMac> socket = BluetoothSocketMac::CreateSocket(); |
135 socket->ListenUsingL2cap( | 135 socket->ListenUsingL2cap( |
136 this, uuid, psm, base::Bind(callback, socket), error_callback); | 136 this, uuid, psm, base::Bind(callback, socket), error_callback); |
137 } | 137 } |
138 | 138 |
139 void BluetoothAdapterMac::DeviceFound(BluetoothDiscoveryManagerMac* manager, | 139 void BluetoothAdapterMac::DeviceFound(BluetoothDiscoveryManagerMac* manager, |
140 IOBluetoothDevice* device) { | 140 IOBluetoothDevice* device) { |
| 141 // TODO(isherman): The list of discovered devices is never reset. This should |
| 142 // probably key off of |devices_| instead. Currently, if a device is paired, |
| 143 // then unpaired, then paired again, the app would never hear about the second |
| 144 // pairing. |
141 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); | 145 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); |
142 if (discovered_devices_.find(device_address) == discovered_devices_.end()) { | 146 if (discovered_devices_.find(device_address) == discovered_devices_.end()) { |
143 BluetoothDeviceMac device_mac(device); | 147 BluetoothDeviceMac device_mac(device); |
144 FOR_EACH_OBSERVER( | 148 FOR_EACH_OBSERVER( |
145 BluetoothAdapter::Observer, observers_, DeviceAdded(this, &device_mac)); | 149 BluetoothAdapter::Observer, observers_, DeviceAdded(this, &device_mac)); |
146 discovered_devices_.insert(device_address); | 150 discovered_devices_.insert(device_address); |
147 } | 151 } |
148 } | 152 } |
149 | 153 |
150 void BluetoothAdapterMac::DiscoveryStopped( | 154 void BluetoothAdapterMac::DiscoveryStopped( |
151 BluetoothDiscoveryManagerMac* manager, | 155 BluetoothDiscoveryManagerMac* manager, |
152 bool unexpected) { | 156 bool unexpected) { |
153 DCHECK_EQ(manager, classic_discovery_manager_.get()); | 157 DCHECK_EQ(manager, classic_discovery_manager_.get()); |
154 if (unexpected) { | 158 if (unexpected) { |
155 DVLOG(1) << "Discovery stopped unexpectedly"; | 159 DVLOG(1) << "Discovery stopped unexpectedly"; |
156 num_discovery_sessions_ = 0; | 160 num_discovery_sessions_ = 0; |
157 MarkDiscoverySessionsAsInactive(); | 161 MarkDiscoverySessionsAsInactive(); |
158 } | 162 } |
159 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, | 163 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, |
160 observers_, | 164 observers_, |
161 AdapterDiscoveringChanged(this, false)); | 165 AdapterDiscoveringChanged(this, false)); |
162 } | 166 } |
163 | 167 |
| 168 void BluetoothAdapterMac::DeviceConnected(IOBluetoothDevice* device) { |
| 169 // TODO(isherman): Call -registerForDisconnectNotification:selector:, and |
| 170 // investigate whether this method can be replaced with a call to |
| 171 // +registerForConnectNotifications:selector:. |
| 172 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); |
| 173 DVLOG(1) << "Adapter registered a new connection from device with address: " |
| 174 << device_address; |
| 175 |
| 176 // Only notify once per device. |
| 177 if (devices_.count(device_address)) |
| 178 return; |
| 179 |
| 180 scoped_ptr<BluetoothDeviceMac> device_mac(new BluetoothDeviceMac(device)); |
| 181 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, |
| 182 observers_, |
| 183 DeviceAdded(this, device_mac.get())); |
| 184 devices_[device_address] = device_mac.release(); |
| 185 } |
| 186 |
164 void BluetoothAdapterMac::AddDiscoverySession( | 187 void BluetoothAdapterMac::AddDiscoverySession( |
165 const base::Closure& callback, | 188 const base::Closure& callback, |
166 const ErrorCallback& error_callback) { | 189 const ErrorCallback& error_callback) { |
167 DVLOG(1) << __func__; | 190 DVLOG(1) << __func__; |
168 if (num_discovery_sessions_ > 0) { | 191 if (num_discovery_sessions_ > 0) { |
169 DCHECK(IsDiscovering()); | 192 DCHECK(IsDiscovering()); |
170 num_discovery_sessions_++; | 193 num_discovery_sessions_++; |
171 callback.Run(); | 194 callback.Run(); |
172 return; | 195 return; |
173 } | 196 } |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
255 if (was_present != is_present) { | 278 if (was_present != is_present) { |
256 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, | 279 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
257 AdapterPresentChanged(this, is_present)); | 280 AdapterPresentChanged(this, is_present)); |
258 } | 281 } |
259 if (powered_ != powered) { | 282 if (powered_ != powered) { |
260 powered_ = powered; | 283 powered_ = powered; |
261 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, | 284 FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, |
262 AdapterPoweredChanged(this, powered_)); | 285 AdapterPoweredChanged(this, powered_)); |
263 } | 286 } |
264 | 287 |
| 288 // TODO(isherman): This doesn't detect when a device is unpaired. |
265 IOBluetoothDevice* recent_device = | 289 IOBluetoothDevice* recent_device = |
266 [[IOBluetoothDevice recentDevices:1] lastObject]; | 290 [[IOBluetoothDevice recentDevices:1] lastObject]; |
267 NSDate* access_timestamp = [recent_device recentAccessDate]; | 291 NSDate* access_timestamp = [recent_device recentAccessDate]; |
268 if (recently_accessed_device_timestamp_ == nil || | 292 if (recently_accessed_device_timestamp_ == nil || |
269 access_timestamp == nil || | 293 access_timestamp == nil || |
270 [recently_accessed_device_timestamp_ compare:access_timestamp] == | 294 [recently_accessed_device_timestamp_ compare:access_timestamp] == |
271 NSOrderedAscending) { | 295 NSOrderedAscending) { |
272 UpdateDevices([IOBluetoothDevice pairedDevices]); | 296 UpdateDevices(); |
273 recently_accessed_device_timestamp_.reset([access_timestamp copy]); | 297 recently_accessed_device_timestamp_.reset([access_timestamp copy]); |
274 } | 298 } |
275 | 299 |
276 ui_task_runner_->PostDelayedTask( | 300 ui_task_runner_->PostDelayedTask( |
277 FROM_HERE, | 301 FROM_HERE, |
278 base::Bind(&BluetoothAdapterMac::PollAdapter, | 302 base::Bind(&BluetoothAdapterMac::PollAdapter, |
279 weak_ptr_factory_.GetWeakPtr()), | 303 weak_ptr_factory_.GetWeakPtr()), |
280 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); | 304 base::TimeDelta::FromMilliseconds(kPollIntervalMs)); |
281 } | 305 } |
282 | 306 |
283 void BluetoothAdapterMac::UpdateDevices(NSArray* devices) { | 307 void BluetoothAdapterMac::UpdateDevices() { |
284 // TODO(armansito): This code never calls | 308 // Snapshot the devices observers were previously notified of. |
285 // BluetoothAdapter::Observer::DeviceRemoved. It should, if a device | 309 // Note that the code below is careful to take ownership of any values that |
286 // no longer exists. | 310 // are erased from the map, since the map owns the memory for all its mapped |
287 STLDeleteValues(&devices_); | 311 // devices. |
288 for (IOBluetoothDevice* device in devices) { | 312 DevicesMap old_devices = devices_; |
| 313 |
| 314 // Add all the paired devices. |
| 315 devices_.clear(); |
| 316 for (IOBluetoothDevice* device in [IOBluetoothDevice pairedDevices]) { |
289 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); | 317 std::string device_address = BluetoothDeviceMac::GetDeviceAddress(device); |
290 devices_[device_address] = new BluetoothDeviceMac(device); | 318 scoped_ptr<BluetoothDevice> device_mac(old_devices[device_address]); |
| 319 if (!device_mac) |
| 320 device_mac.reset(new BluetoothDeviceMac(device)); |
| 321 devices_[device_address] = device_mac.release(); |
| 322 old_devices.erase(device_address); |
291 } | 323 } |
| 324 |
| 325 // Add any unpaired connected devices. |
| 326 for (const auto& old_device : old_devices) { |
| 327 if (!old_device.second->IsConnected()) |
| 328 continue; |
| 329 |
| 330 const std::string& device_address = old_device.first; |
| 331 DCHECK(!devices_.count(device_address)); |
| 332 devices_[device_address] = old_device.second; |
| 333 old_devices.erase(device_address); |
| 334 } |
| 335 |
| 336 // TODO(isherman): Notify observers of any devices that are no longer in |
| 337 // range. Note that it's possible for a device to be neither paired nor |
| 338 // connected, but to still be in range. |
| 339 STLDeleteValues(&old_devices); |
292 } | 340 } |
293 | 341 |
294 } // namespace device | 342 } // namespace device |
OLD | NEW |