Chromium Code Reviews| Index: device/bluetooth/bluetooth_mac_discovery_manager.mm |
| diff --git a/device/bluetooth/bluetooth_mac_discovery_manager.mm b/device/bluetooth/bluetooth_mac_discovery_manager.mm |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..836fd62f26bcaaa3a015d988d14e11e4d36d6f55 |
| --- /dev/null |
| +++ b/device/bluetooth/bluetooth_mac_discovery_manager.mm |
| @@ -0,0 +1,241 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "device/bluetooth/bluetooth_mac_discovery_manager.h" |
| + |
| +#import <IOBluetooth/objc/IOBluetoothDevice.h> |
| +#import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h> |
| + |
| +#include "base/mac/scoped_nsobject.h" |
| + |
| +namespace device { |
| + |
| +class BluetoothMacDiscoveryManagerClassicImpl; |
| + |
| +} // namespace device |
| + |
| +// Replicate specific 10.7 SDK declarations for building with prior SDKs. |
| +#if !defined(MAC_OS_X_VERSION_10_7) || \ |
| + MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 |
| + |
| +@protocol IOBluetoothDeviceInquiryDelegate |
| +- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender; |
| +- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender |
| + device:(IOBluetoothDevice*)device; |
| +- (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender |
| + error:(IOReturn)error |
| + aborted:(BOOL)aborted; |
| +@end |
| + |
| +#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.
|
| + |
| +// IOBluetoothDeviceInquiryDelegate implementation. |
| +@interface BluetoothDeviceInquiryDelegate |
| + : NSObject<IOBluetoothDeviceInquiryDelegate> { |
| + @private |
| + device::BluetoothMacDiscoveryManagerClassicImpl* manager_; // weak |
| +} |
| + |
| +- (id)initWithManager:(device::BluetoothMacDiscoveryManagerClassicImpl*)manager; |
| + |
| +@end |
| + |
| +namespace device { |
| + |
| +// Implementation of BluetoothMacDiscoveryManager for Bluetooth classic device |
| +// discovery, using the IOBluetooth framework. |
| +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.
|
| + : public BluetoothMacDiscoveryManager { |
| + public: |
| + BluetoothMacDiscoveryManagerClassicImpl() |
| + : should_do_discovery_(false), |
| + inquiry_running_(false), |
| + inquiry_delegate_( |
| + [[BluetoothDeviceInquiryDelegate alloc] initWithManager:this]), |
| + inquiry_([[IOBluetoothDeviceInquiry alloc] |
| + initWithDelegate:inquiry_delegate_]) {} |
| + |
| + virtual ~BluetoothMacDiscoveryManagerClassicImpl() {} |
| + |
| + // BluetoothMacDiscoveryManager override. |
| + virtual bool IsDiscovering() const OVERRIDE { return should_do_discovery_; } |
| + |
| + // BluetoothMacDiscoveryManager override. |
| + virtual bool StartDiscovery() OVERRIDE { |
| + VLOG(1) << "Bluetooth Classic: StartDiscovery"; |
| + if (should_do_discovery_) { |
| + VLOG(1) << "Already discovering"; |
| + return true; |
| + } |
|
Ilya Sherman
2014/06/10 01:11:00
Could this be a DCHECK instead?
armansito
2014/06/10 21:56:50
Done.
|
| + |
| + VLOG(1) << "Discovery requested"; |
| + should_do_discovery_ = true; |
| + |
| + if (inquiry_running_) { |
| + VLOG(1) << "Device inquiry already running"; |
| + return true; |
| + } |
|
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.
|
| + |
| + VLOG(1) << "Requesting to start device inquiry"; |
| + if ([inquiry_ start] != kIOReturnSuccess) { |
| + VLOG(1) << "Failed to start device inquiry"; |
| + |
| + // Set |should_do_discovery_| to false here. Since we're reporting an |
| + // error, we're indicating that the adapter call StartDiscovery again |
| + // if needed. |
| + should_do_discovery_ = false; |
| + return false; |
| + } |
| + |
| + VLOG(1) << "Device inquiry start was successful"; |
| + return true; |
| + } |
| + |
| + // BluetoothMacDiscoveryManager override. |
| + virtual bool StopDiscovery() OVERRIDE { |
| + VLOG(1) << "Bluetooth Classic: StopDiscovery"; |
| + if (!should_do_discovery_) { |
| + VLOG(1) << "Discovery already stopped"; |
| + return true; |
| + } |
|
Ilya Sherman
2014/06/10 01:10:59
Ditto.
armansito
2014/06/10 21:56:50
Done.
|
| + |
| + should_do_discovery_ = false; |
| + |
| + if (!inquiry_running_) { |
| + VLOG(1) << "No device inquiry running; discovery stopped"; |
| + return true; |
| + } |
|
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
|
| + |
| + VLOG(1) << "Requesting to stop device inquiry"; |
| + IOReturn status = [inquiry_ stop]; |
| + if (status == kIOReturnSuccess) { |
| + VLOG(1) << "Device inquiry stop was successful"; |
| + return true; |
| + } |
| + |
| + if (status == kIOReturnNotPermitted) { |
| + VLOG(1) << "Device inquiry was already stopped"; |
| + return true; |
| + } |
| + |
| + LOG(WARNING) << "Failed to stop device inquiry"; |
| + return false; |
| + } |
| + |
| + // Called by BluetoothDeviceInquiryDelegate. |
| + void DeviceInquiryStarted(IOBluetoothDeviceInquiry* inquiry) { |
| + DCHECK(!inquiry_running_); |
| + |
| + VLOG(1) << "Device inquiry started!"; |
| + |
| + // If discovery was requested to stop in the mean time, stop the inquiry. |
| + if (!should_do_discovery_) { |
| + VLOG(1) << "Discovery stop was requested earlier. Stopping inquiry"; |
| + [inquiry stop]; |
| + return; |
| + } |
| + |
| + inquiry_running_ = true; |
| + } |
| + |
| + void DeviceFound(IOBluetoothDeviceInquiry* inquiry, |
| + IOBluetoothDevice* device) { |
| + FOR_EACH_OBSERVER(Observer, observers_, DeviceFound(this, device)); |
| + } |
| + |
| + void DeviceInquiryComplete(IOBluetoothDeviceInquiry* inquiry, |
| + IOReturn error, |
| + bool aborted) { |
| + DCHECK_EQ(inquiry_, inquiry); |
| + VLOG(1) << "Device inquiry complete"; |
| + inquiry_running_ = false; |
| + |
| + // 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.
|
| + if (!should_do_discovery_) { |
| + FOR_EACH_OBSERVER( |
| + Observer, observers_, DiscoveryStopped(this, false /* unexpected */)); |
| + return; |
| + } |
| + |
| + if (error != kIOReturnSuccess) { |
| + VLOG(1) << "Inquiry has stopped with an error: " << error; |
| + should_do_discovery_ = false; |
| + FOR_EACH_OBSERVER( |
| + Observer, observers_, DiscoveryStopped(this, true /* unexpected */)); |
| + return; |
| + } |
| + |
| + VLOG(1) << "Restarting device inquiry"; |
| + |
| + if ([inquiry_ start] == kIOReturnSuccess) { |
| + VLOG(1) << "Device inquiry restart was successful"; |
| + return; |
| + } |
| + |
| + VLOG(1) << "Failed to restart discovery"; |
| + should_do_discovery_ = false; |
| + FOR_EACH_OBSERVER( |
| + Observer, observers_, DiscoveryStopped(this, true /* unexpected */)); |
| + } |
| + |
| + private: |
| + // The requested discovery state. |
| + bool should_do_discovery_; |
| + |
| + // The current inquiry state. |
| + bool inquiry_running_; |
| + |
| + // Objective-C objects for running and tracking device inquiry. |
| + base::scoped_nsobject<BluetoothDeviceInquiryDelegate> inquiry_delegate_; |
| + base::scoped_nsobject<IOBluetoothDeviceInquiry> inquiry_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(BluetoothMacDiscoveryManagerClassicImpl); |
| +}; |
| + |
| +BluetoothMacDiscoveryManager::BluetoothMacDiscoveryManager() { |
| +} |
| +BluetoothMacDiscoveryManager::~BluetoothMacDiscoveryManager() { |
| +} |
| + |
| +void BluetoothMacDiscoveryManager::AddObserver(Observer* observer) { |
| + observers_.AddObserver(observer); |
| +} |
| + |
| +void BluetoothMacDiscoveryManager::RemoveObserver(Observer* observer) { |
| + observers_.RemoveObserver(observer); |
| +} |
| + |
| +// static |
| +BluetoothMacDiscoveryManager* BluetoothMacDiscoveryManager::CreateClassic() { |
| + return new BluetoothMacDiscoveryManagerClassicImpl(); |
| +} |
| + |
| +} // namespace device |
| + |
| +@implementation BluetoothDeviceInquiryDelegate |
| + |
| +- (id)initWithManager: |
| + (device::BluetoothMacDiscoveryManagerClassicImpl*)manager { |
| + if ((self = [super init])) |
| + manager_ = manager; |
| + |
| + return self; |
| +} |
| + |
| +- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender { |
| + manager_->DeviceInquiryStarted(sender); |
| +} |
| + |
| +- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender |
| + device:(IOBluetoothDevice*)device { |
| + manager_->DeviceFound(sender, device); |
| +} |
| + |
| +- (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender |
| + error:(IOReturn)error |
| + aborted:(BOOL)aborted { |
| + manager_->DeviceInquiryComplete(sender, error, aborted); |
| +} |
| + |
| +@end |