| 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/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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |