Index: device/bluetooth/bluetooth_discovery_manager_mac.mm |
diff --git a/device/bluetooth/bluetooth_discovery_manager_mac.mm b/device/bluetooth/bluetooth_discovery_manager_mac.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..48a3a9f34923c59249aa1e5bb0aa4df04077f268 |
--- /dev/null |
+++ b/device/bluetooth/bluetooth_discovery_manager_mac.mm |
@@ -0,0 +1,239 @@ |
+// 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_discovery_manager_mac.h" |
+ |
+#import <IOBluetooth/objc/IOBluetoothDevice.h> |
+#import <IOBluetooth/objc/IOBluetoothDeviceInquiry.h> |
+ |
+#include "base/mac/scoped_nsobject.h" |
+#include "base/mac/sdk_forward_declarations.h" |
+ |
+namespace device { |
+ |
+class BluetoothDiscoveryManagerMacClassic; |
+ |
+} // 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 23:23:01
To clarify my previous comment, the idea is that a
armansito
2014/06/13 02:14:54
Ah, I misunderstood. Done.
|
+ |
+// IOBluetoothDeviceInquiryDelegate implementation. |
+@interface BluetoothDeviceInquiryDelegate |
+ : NSObject<IOBluetoothDeviceInquiryDelegate> { |
+ @private |
+ device::BluetoothDiscoveryManagerMacClassic* manager_; // weak |
+} |
+ |
+- (id)initWithManager:(device::BluetoothDiscoveryManagerMacClassic*)manager; |
+ |
+@end |
+ |
+namespace device { |
+ |
+// ementation of BluetoothDiscoveryManagerMac for Bluetooth classic device |
+// discovery, using the IOBluetooth framework. |
+class BluetoothDiscoveryManagerMacClassic |
+ : public BluetoothDiscoveryManagerMac { |
+ public: |
+ BluetoothDiscoveryManagerMacClassic() |
+ : should_do_discovery_(false), |
+ inquiry_running_(false), |
+ inquiry_delegate_( |
+ [[BluetoothDeviceInquiryDelegate alloc] initWithManager:this]), |
+ inquiry_([[IOBluetoothDeviceInquiry alloc] |
+ initWithDelegate:inquiry_delegate_]) {} |
+ |
+ virtual ~BluetoothDiscoveryManagerMacClassic() {} |
+ |
+ // BluetoothDiscoveryManagerMac override. |
+ virtual bool IsDiscovering() const OVERRIDE { return should_do_discovery_; } |
+ |
+ // BluetoothDiscoveryManagerMac override. |
+ virtual bool StartDiscovery() OVERRIDE { |
+ DVLOG(1) << "Bluetooth Classic: StartDiscovery"; |
+ DCHECK(!should_do_discovery_); |
+ |
+ DVLOG(1) << "Discovery requested"; |
+ should_do_discovery_ = true; |
+ |
+ if (inquiry_running_) { |
+ DVLOG(1) << "Device inquiry already running"; |
+ return true; |
+ } |
+ |
+ DVLOG(1) << "Requesting to start device inquiry"; |
+ if ([inquiry_ start] != kIOReturnSuccess) { |
+ DVLOG(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; |
+ } |
+ |
+ DVLOG(1) << "Device inquiry start was successful"; |
+ return true; |
+ } |
+ |
+ // BluetoothDiscoveryManagerMac override. |
+ virtual bool StopDiscovery() OVERRIDE { |
+ DVLOG(1) << "Bluetooth Classic: StopDiscovery"; |
+ DCHECK(should_do_discovery_); |
+ |
+ should_do_discovery_ = false; |
+ |
+ if (!inquiry_running_) { |
+ DVLOG(1) << "No device inquiry running; discovery stopped"; |
+ return true; |
+ } |
+ |
+ DVLOG(1) << "Requesting to stop device inquiry"; |
+ IOReturn status = [inquiry_ stop]; |
+ if (status == kIOReturnSuccess) { |
+ DVLOG(1) << "Device inquiry stop was successful"; |
+ return true; |
+ } |
+ |
+ if (status == kIOReturnNotPermitted) { |
+ DVLOG(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_); |
+ |
+ DVLOG(1) << "Device inquiry started!"; |
+ |
+ // If discovery was requested to stop in the mean time, stop the inquiry. |
+ if (!should_do_discovery_) { |
+ DVLOG(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); |
+ DVLOG(1) << "Device inquiry complete"; |
+ inquiry_running_ = false; |
+ |
+ // If discovery is no longer desired, notify observers that discovery |
+ // has stopped and return. |
+ if (!should_do_discovery_) { |
+ FOR_EACH_OBSERVER( |
+ Observer, observers_, DiscoveryStopped(this, false /* unexpected */)); |
+ return; |
+ } |
+ |
+ // If discovery has stopped due to an unexpected reason, notify the |
+ // observers and return. |
+ if (error != kIOReturnSuccess) { |
+ DVLOG(1) << "Inquiry has stopped with an error: " << error; |
+ should_do_discovery_ = false; |
+ FOR_EACH_OBSERVER( |
+ Observer, observers_, DiscoveryStopped(this, true /* unexpected */)); |
+ return; |
+ } |
+ |
+ DVLOG(1) << "Restarting device inquiry"; |
+ |
+ if ([inquiry_ start] == kIOReturnSuccess) { |
+ DVLOG(1) << "Device inquiry restart was successful"; |
+ return; |
+ } |
+ |
+ DVLOG(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(BluetoothDiscoveryManagerMacClassic); |
+}; |
+ |
+BluetoothDiscoveryManagerMac::BluetoothDiscoveryManagerMac() { |
+} |
+BluetoothDiscoveryManagerMac::~BluetoothDiscoveryManagerMac() { |
+} |
+ |
+void BluetoothDiscoveryManagerMac::AddObserver(Observer* observer) { |
+ observers_.AddObserver(observer); |
+} |
+ |
+void BluetoothDiscoveryManagerMac::RemoveObserver(Observer* observer) { |
+ observers_.RemoveObserver(observer); |
+} |
+ |
+// static |
+BluetoothDiscoveryManagerMac* BluetoothDiscoveryManagerMac::CreateClassic() { |
+ return new BluetoothDiscoveryManagerMacClassic(); |
+} |
+ |
+} // namespace device |
+ |
+@implementation BluetoothDeviceInquiryDelegate |
+ |
+- (id)initWithManager: |
+ (device::BluetoothDiscoveryManagerMacClassic*)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 |