diff options
author | youngki@chromium.org <youngki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-29 14:43:09 +0000 |
---|---|---|
committer | youngki@chromium.org <youngki@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-03-29 14:43:09 +0000 |
commit | a86d4f2857de0b0a47db915f6ed4a21089044f65 (patch) | |
tree | bcb666f6834193655c183d4baa807bf34af595fb /device | |
parent | d9eb60ae1231e9b7e8dd9a6f749bce99e7324cd4 (diff) | |
download | chromium_src-a86d4f2857de0b0a47db915f6ed4a21089044f65.zip chromium_src-a86d4f2857de0b0a47db915f6ed4a21089044f65.tar.gz chromium_src-a86d4f2857de0b0a47db915f6ed4a21089044f65.tar.bz2 |
Implemented Device Inquiry.
I haven't added unittests here, because this file will soon be refactored according to the new API proposal. So for now I am submitting this then will add unittests when we refactor the file.
BUG=135472
Review URL: https://chromiumcodereview.appspot.com/13199002
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@191354 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'device')
-rw-r--r-- | device/bluetooth/bluetooth_adapter_mac.h | 46 | ||||
-rw-r--r-- | device/bluetooth/bluetooth_adapter_mac.mm | 166 |
2 files changed, 210 insertions, 2 deletions
diff --git a/device/bluetooth/bluetooth_adapter_mac.h b/device/bluetooth/bluetooth_adapter_mac.h index a8202b5..abbd6cc 100644 --- a/device/bluetooth/bluetooth_adapter_mac.h +++ b/device/bluetooth/bluetooth_adapter_mac.h @@ -5,16 +5,26 @@ #ifndef DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_MAC_H_ #define DEVICE_BLUETOOTH_BLUETOOTH_ADAPTER_MAC_H_ +#include <IOKit/IOReturn.h> + #include <string> +#include <vector> +#include "base/hash_tables.h" #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/observer_list.h" #include "device/bluetooth/bluetooth_adapter.h" #ifdef __OBJC__ +@class BluetoothAdapterMacDelegate; +@class IOBluetoothDevice; +@class IOBluetoothDeviceInquiry; @class NSArray; #else +class BluetoothAdapterMacDelegate; +class IOBluetoothDevice; +class IOBluetoothDeviceInquiry; class NSArray; #endif @@ -52,10 +62,25 @@ class BluetoothAdapterMac : public BluetoothAdapter { const BluetoothOutOfBandPairingDataCallback& callback, const ErrorCallback& error_callback) OVERRIDE; + // called by BluetoothAdapterMacDelegate. + void DeviceInquiryStarted(IOBluetoothDeviceInquiry* inquiry); + void DeviceFound(IOBluetoothDeviceInquiry* inquiry, + IOBluetoothDevice* device); + void DeviceInquiryComplete(IOBluetoothDeviceInquiry* inquiry, + IOReturn error, + bool aborted); + private: friend class BluetoothAdapterFactory; friend class BluetoothAdapterMacTest; + enum DiscoveryStatus { + NOT_DISCOVERING, + DISCOVERY_STARTING, + DISCOVERING, + DISCOVERY_STOPPING + }; + BluetoothAdapterMac(); virtual ~BluetoothAdapterMac(); @@ -74,7 +99,28 @@ class BluetoothAdapterMac : public BluetoothAdapter { // |devices| is an array of pointers to paired |IOBluetoothDevice| objects. void RemoveUnpairedDevices(NSArray* paired_devices); + void MaybeStartDeviceInquiry(); + void MaybeStopDeviceInquiry(); + + typedef std::vector<std::pair<base::Closure, ErrorCallback> > + DiscoveryCallbackList; + void RunCallbacks(const DiscoveryCallbackList& callback_list, + bool success) const; + bool powered_; + DiscoveryStatus discovery_status_; + + DiscoveryCallbackList on_start_discovery_callbacks_; + DiscoveryCallbackList on_stop_discovery_callbacks_; + size_t num_discovery_listeners_; + + BluetoothAdapterMacDelegate* adapter_delegate_; + IOBluetoothDeviceInquiry* device_inquiry_; + + // A list of discovered device addresses. + // This list is used to check if the same device is discovered twice during + // the discovery between consecutive inquiries. + base::hash_set<std::string> discovered_devices_; scoped_refptr<base::SequencedTaskRunner> ui_task_runner_; diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm index 8977ab6..994a7c4 100644 --- a/device/bluetooth/bluetooth_adapter_mac.mm +++ b/device/bluetooth/bluetooth_adapter_mac.mm @@ -4,6 +4,7 @@ #include "device/bluetooth/bluetooth_adapter_mac.h" +#import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h> #import <IOBluetooth/objc/IOBluetoothDevice.h> #import <IOBluetooth/objc/IOBluetoothHostController.h> @@ -13,6 +14,7 @@ #include "base/compiler_specific.h" #include "base/hash_tables.h" #include "base/location.h" +#include "base/memory/scoped_ptr.h" #include "base/sequenced_task_runner.h" #include "base/single_thread_task_runner.h" #include "base/thread_task_runner_handle.h" @@ -33,8 +35,53 @@ MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 - (NSString*)addressString; @end +@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 +@interface BluetoothAdapterMacDelegate + : NSObject <IOBluetoothDeviceInquiryDelegate> { + @private + device::BluetoothAdapterMac* adapter_; // weak +} + +- (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter; + +@end + +@implementation BluetoothAdapterMacDelegate + +- (id)initWithAdapter:(device::BluetoothAdapterMac*)adapter { + if ((self = [super init])) + adapter_ = adapter; + + return self; +} + +- (void)deviceInquiryStarted:(IOBluetoothDeviceInquiry*)sender { + adapter_->DeviceInquiryStarted(sender); +} + +- (void)deviceInquiryDeviceFound:(IOBluetoothDeviceInquiry*)sender + device:(IOBluetoothDevice*)device { + adapter_->DeviceFound(sender, device); +} + +- (void)deviceInquiryComplete:(IOBluetoothDeviceInquiry*)sender + error:(IOReturn)error + aborted:(BOOL)aborted { + adapter_->DeviceInquiryComplete(sender, error, aborted); +} + +@end + namespace { const int kPollIntervalMs = 500; @@ -46,10 +93,18 @@ namespace device { BluetoothAdapterMac::BluetoothAdapterMac() : BluetoothAdapter(), powered_(false), - ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) { + discovery_status_(NOT_DISCOVERING), + adapter_delegate_( + [[BluetoothAdapterMacDelegate alloc] initWithAdapter:this]), + device_inquiry_( + [[IOBluetoothDeviceInquiry + inquiryWithDelegate:adapter_delegate_] retain]), + weak_ptr_factory_(this) { } BluetoothAdapterMac::~BluetoothAdapterMac() { + [device_inquiry_ release]; + [adapter_delegate_ release]; } void BluetoothAdapterMac::AddObserver(BluetoothAdapter::Observer* observer) { @@ -80,16 +135,32 @@ void BluetoothAdapterMac::SetPowered(bool powered, } bool BluetoothAdapterMac::IsDiscovering() const { - return false; + return discovery_status_ == DISCOVERING || + discovery_status_ == DISCOVERY_STOPPING; } void BluetoothAdapterMac::StartDiscovering( const base::Closure& callback, const ErrorCallback& error_callback) { + if (discovery_status_ == DISCOVERING) { + num_discovery_listeners_++; + callback.Run(); + return; + } + on_start_discovery_callbacks_.push_back( + std::make_pair(callback, error_callback)); + MaybeStartDeviceInquiry(); } void BluetoothAdapterMac::StopDiscovering(const base::Closure& callback, const ErrorCallback& error_callback) { + if (discovery_status_ == NOT_DISCOVERING) { + error_callback.Run(); + return; + } + on_stop_discovery_callbacks_.push_back( + std::make_pair(callback, error_callback)); + MaybeStopDeviceInquiry(); } void BluetoothAdapterMac::ReadLocalOutOfBandPairingData( @@ -196,4 +267,95 @@ void BluetoothAdapterMac::RemoveUnpairedDevices(NSArray* paired_devices) { } } +void BluetoothAdapterMac::DeviceInquiryStarted( + IOBluetoothDeviceInquiry* inquiry) { + DCHECK(device_inquiry_ == inquiry); + if (discovery_status_ == DISCOVERING) + return; + + discovery_status_ = DISCOVERING; + RunCallbacks(on_start_discovery_callbacks_, true); + num_discovery_listeners_ = on_start_discovery_callbacks_.size(); + on_start_discovery_callbacks_.clear(); + + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, + AdapterDiscoveringChanged(this, true)); + MaybeStopDeviceInquiry(); +} + +void BluetoothAdapterMac::DeviceFound(IOBluetoothDeviceInquiry* inquiry, + IOBluetoothDevice* device) { + DCHECK(device_inquiry_ == inquiry); + std::string device_address = base::SysNSStringToUTF8([device addressString]); + if (discovered_devices_.find(device_address) == discovered_devices_.end()) { + scoped_ptr<BluetoothDeviceMac> device_mac(new BluetoothDeviceMac(device)); + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, + DeviceAdded(this, device_mac.get())); + discovered_devices_.insert(device_address); + } +} + +void BluetoothAdapterMac::DeviceInquiryComplete( + IOBluetoothDeviceInquiry* inquiry, + IOReturn error, + bool aborted) { + DCHECK(device_inquiry_ == inquiry); + if (discovery_status_ == DISCOVERING && + [device_inquiry_ start] == kIOReturnSuccess) { + return; + } + + // Device discovery is done. + discovered_devices_.clear(); + discovery_status_ = NOT_DISCOVERING; + RunCallbacks(on_stop_discovery_callbacks_, error == kIOReturnSuccess); + num_discovery_listeners_ = 0; + on_stop_discovery_callbacks_.clear(); + FOR_EACH_OBSERVER(BluetoothAdapter::Observer, observers_, + AdapterDiscoveringChanged(this, false)); + MaybeStartDeviceInquiry(); +} + +void BluetoothAdapterMac::MaybeStartDeviceInquiry() { + if (discovery_status_ == NOT_DISCOVERING && + !on_start_discovery_callbacks_.empty()) { + discovery_status_ = DISCOVERY_STARTING; + if ([device_inquiry_ start] != kIOReturnSuccess) { + discovery_status_ = NOT_DISCOVERING; + RunCallbacks(on_start_discovery_callbacks_, false); + on_start_discovery_callbacks_.clear(); + } + } +} + +void BluetoothAdapterMac::MaybeStopDeviceInquiry() { + if (discovery_status_ != DISCOVERING) + return; + + if (on_stop_discovery_callbacks_.size() < num_discovery_listeners_) { + RunCallbacks(on_stop_discovery_callbacks_, true); + num_discovery_listeners_ -= on_stop_discovery_callbacks_.size(); + on_stop_discovery_callbacks_.clear(); + return; + } + + discovery_status_ = DISCOVERY_STOPPING; + if ([device_inquiry_ stop] != kIOReturnSuccess) { + RunCallbacks(on_stop_discovery_callbacks_, false); + on_stop_discovery_callbacks_.clear(); + } +} + +void BluetoothAdapterMac::RunCallbacks( + const DiscoveryCallbackList& callback_list, bool success) const { + for (DiscoveryCallbackList::const_iterator iter = callback_list.begin(); + iter != callback_list.end(); + ++iter) { + if (success) + ui_task_runner_->PostTask(FROM_HERE, iter->first); + else + ui_task_runner_->PostTask(FROM_HERE, iter->second); + } +} + } // namespace device |