diff options
26 files changed, 769 insertions, 107 deletions
diff --git a/chrome/browser/metrics/metrics_log_unittest.cc b/chrome/browser/metrics/metrics_log_unittest.cc index 69fbe22..1067385 100644 --- a/chrome/browser/metrics/metrics_log_unittest.cc +++ b/chrome/browser/metrics/metrics_log_unittest.cc @@ -46,6 +46,9 @@ #include "chromeos/dbus/fake_bluetooth_adapter_client.h" #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" #include "chromeos/dbus/fake_bluetooth_device_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" #include "chromeos/dbus/fake_bluetooth_input_client.h" #include "chromeos/dbus/fake_dbus_thread_manager.h" @@ -53,10 +56,16 @@ using chromeos::DBusThreadManager; using chromeos::BluetoothAdapterClient; using chromeos::BluetoothAgentManagerClient; using chromeos::BluetoothDeviceClient; +using chromeos::BluetoothGattCharacteristicClient; +using chromeos::BluetoothGattDescriptorClient; +using chromeos::BluetoothGattServiceClient; using chromeos::BluetoothInputClient; using chromeos::FakeBluetoothAdapterClient; using chromeos::FakeBluetoothAgentManagerClient; using chromeos::FakeBluetoothDeviceClient; +using chromeos::FakeBluetoothGattCharacteristicClient; +using chromeos::FakeBluetoothGattDescriptorClient; +using chromeos::FakeBluetoothGattServiceClient; using chromeos::FakeBluetoothInputClient; using chromeos::FakeDBusThreadManager; #endif // OS_CHROMEOS @@ -222,6 +231,15 @@ class MetricsLogTest : public testing::Test { scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); fake_dbus_thread_manager->SetBluetoothDeviceClient( scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient)); + fake_dbus_thread_manager->SetBluetoothGattCharacteristicClient( + scoped_ptr<BluetoothGattCharacteristicClient>( + new FakeBluetoothGattCharacteristicClient)); + fake_dbus_thread_manager->SetBluetoothGattDescriptorClient( + scoped_ptr<BluetoothGattDescriptorClient>( + new FakeBluetoothGattDescriptorClient)); + fake_dbus_thread_manager->SetBluetoothGattServiceClient( + scoped_ptr<BluetoothGattServiceClient>( + new FakeBluetoothGattServiceClient)); fake_dbus_thread_manager->SetBluetoothInputClient( scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); fake_dbus_thread_manager->SetBluetoothAgentManagerClient( diff --git a/chromeos/dbus/bluetooth_gatt_service_client.cc b/chromeos/dbus/bluetooth_gatt_service_client.cc index cdbcef1..1888e51 100644 --- a/chromeos/dbus/bluetooth_gatt_service_client.cc +++ b/chromeos/dbus/bluetooth_gatt_service_client.cc @@ -13,6 +13,15 @@ namespace chromeos { +namespace { + +// TODO(armansito): Add these to service_constants.h when they are defined +// in the BlueZ doc. +const char kDeviceProperty[] = "Device"; +const char kPrimaryProperty[] = "Primary"; + +} // namespace + BluetoothGattServiceClient::Properties::Properties( dbus::ObjectProxy* object_proxy, const std::string& interface_name, @@ -20,6 +29,8 @@ BluetoothGattServiceClient::Properties::Properties( : dbus::PropertySet(object_proxy, interface_name, callback) { RegisterProperty(bluetooth_gatt_service::kUUIDProperty, &uuid); RegisterProperty(bluetooth_gatt_service::kIncludesProperty, &includes); + RegisterProperty(kDeviceProperty, &device); + RegisterProperty(kPrimaryProperty, &primary); } BluetoothGattServiceClient::Properties::~Properties() { diff --git a/chromeos/dbus/bluetooth_gatt_service_client.h b/chromeos/dbus/bluetooth_gatt_service_client.h index 94eb3ce..d3ed19d 100644 --- a/chromeos/dbus/bluetooth_gatt_service_client.h +++ b/chromeos/dbus/bluetooth_gatt_service_client.h @@ -24,6 +24,12 @@ class CHROMEOS_EXPORT BluetoothGattServiceClient : public DBusClient { // The 128-bit service UUID. [read-only] dbus::Property<std::string> uuid; + // Object path of the Bluetooth device that the GATT service belongs to. + dbus::Property<dbus::ObjectPath> device; + + // Whether or not this service is a primary service. + dbus::Property<bool> primary; + // Array of object paths representing the included services of this service. // [read-only] dbus::Property<std::vector<dbus::ObjectPath> > includes; diff --git a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc index 85408b8..c25e71c 100644 --- a/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc +++ b/chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc @@ -209,21 +209,21 @@ void FakeBluetoothGattCharacteristicClient::ExposeHeartRateCharacteristics( void FakeBluetoothGattCharacteristicClient::HideHeartRateCharacteristics() { VLOG(2) << "Hiding fake Heart Rate characteristics."; + + // Notify the observers before deleting the properties structures so that they + // can be accessed from the observer method. + NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_measurement_path_)); + NotifyCharacteristicRemoved(dbus::ObjectPath(body_sensor_location_path_)); + NotifyCharacteristicRemoved(dbus::ObjectPath(heart_rate_control_point_path_)); + heart_rate_measurement_properties_.reset(); body_sensor_location_properties_.reset(); heart_rate_control_point_properties_.reset(); - std::string hrm_path = heart_rate_measurement_path_; heart_rate_measurement_path_.clear(); - std::string bsl_path = body_sensor_location_path_; body_sensor_location_path_.clear(); - std::string hrcp_path = heart_rate_control_point_path_; heart_rate_control_point_path_.clear(); heart_rate_visible_ = false; - - NotifyCharacteristicRemoved(dbus::ObjectPath(hrm_path)); - NotifyCharacteristicRemoved(dbus::ObjectPath(bsl_path)); - NotifyCharacteristicRemoved(dbus::ObjectPath(hrcp_path)); } void FakeBluetoothGattCharacteristicClient::OnPropertyChanged( diff --git a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc b/chromeos/dbus/fake_bluetooth_gatt_service_client.cc index d579a26..506ee05 100644 --- a/chromeos/dbus/fake_bluetooth_gatt_service_client.cc +++ b/chromeos/dbus/fake_bluetooth_gatt_service_client.cc @@ -94,7 +94,9 @@ void FakeBluetoothGattServiceClient::ExposeHeartRateService( &FakeBluetoothGattServiceClient::OnPropertyChanged, base::Unretained(this), dbus::ObjectPath(heart_rate_service_path_)))); - heart_rate_service_properties_->uuid.ReplaceValue(heart_rate_service_path_); + heart_rate_service_properties_->uuid.ReplaceValue(kHeartRateServiceUUID); + heart_rate_service_properties_->device.ReplaceValue(device_path); + heart_rate_service_properties_->primary.ReplaceValue(true); NotifyServiceAdded(dbus::ObjectPath(heart_rate_service_path_)); @@ -117,11 +119,12 @@ void FakeBluetoothGattServiceClient::HideHeartRateService() { DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()); char_client->HideHeartRateCharacteristics(); + // Notify observers before deleting the properties structure so that it + // can be accessed from the observer method. + NotifyServiceRemoved(dbus::ObjectPath(heart_rate_service_path_)); + heart_rate_service_properties_.reset(); - std::string hrs_path = heart_rate_service_path_; heart_rate_service_path_.clear(); - - NotifyServiceRemoved(dbus::ObjectPath(hrs_path)); } void FakeBluetoothGattServiceClient::OnPropertyChanged( diff --git a/device/bluetooth/bluetooth.gyp b/device/bluetooth/bluetooth.gyp index f819f91..a4c93a8 100644 --- a/device/bluetooth/bluetooth.gyp +++ b/device/bluetooth/bluetooth.gyp @@ -60,6 +60,8 @@ 'bluetooth_profile_mac.mm', 'bluetooth_profile_win.cc', 'bluetooth_profile_win.h', + 'bluetooth_remote_gatt_service_chromeos.cc', + 'bluetooth_remote_gatt_service_chromeos.h', 'bluetooth_service_record.cc', 'bluetooth_service_record.h', 'bluetooth_service_record_mac.h', diff --git a/device/bluetooth/bluetooth_adapter_chromeos.h b/device/bluetooth/bluetooth_adapter_chromeos.h index f9e5ea2..f1199c5 100644 --- a/device/bluetooth/bluetooth_adapter_chromeos.h +++ b/device/bluetooth/bluetooth_adapter_chromeos.h @@ -33,10 +33,10 @@ class BluetoothPairingChromeOS; // Chrome OS platform. class BluetoothAdapterChromeOS : public device::BluetoothAdapter, - private chromeos::BluetoothAdapterClient::Observer, - private chromeos::BluetoothDeviceClient::Observer, - private chromeos::BluetoothInputClient::Observer, - private chromeos::BluetoothAgentServiceProvider::Delegate { + public chromeos::BluetoothAdapterClient::Observer, + public chromeos::BluetoothDeviceClient::Observer, + public chromeos::BluetoothInputClient::Observer, + public chromeos::BluetoothAgentServiceProvider::Delegate { public: // BluetoothAdapter override virtual void AddObserver( diff --git a/device/bluetooth/bluetooth_chromeos_unittest.cc b/device/bluetooth/bluetooth_chromeos_unittest.cc index ae60eee..379d1df 100644 --- a/device/bluetooth/bluetooth_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_chromeos_unittest.cc @@ -8,6 +8,7 @@ #include "chromeos/dbus/fake_bluetooth_adapter_client.h" #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" #include "chromeos/dbus/fake_bluetooth_device_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" #include "chromeos/dbus/fake_bluetooth_input_client.h" #include "chromeos/dbus/fake_dbus_thread_manager.h" #include "dbus/object_path.h" @@ -29,6 +30,8 @@ using device::BluetoothUUID; namespace chromeos { +namespace { + class TestObserver : public BluetoothAdapter::Observer { public: TestObserver(scoped_refptr<BluetoothAdapter> adapter) @@ -140,6 +143,8 @@ class TestObserver : public BluetoothAdapter::Observer { scoped_refptr<BluetoothAdapter> adapter_; }; +} // namespace + class TestPairingDelegate : public BluetoothDevice::PairingDelegate { public: TestPairingDelegate() @@ -241,6 +246,9 @@ class BluetoothChromeOSTest : public testing::Test { fake_dbus_thread_manager->SetBluetoothAgentManagerClient( scoped_ptr<BluetoothAgentManagerClient>( new FakeBluetoothAgentManagerClient)); + fake_dbus_thread_manager->SetBluetoothGattServiceClient( + scoped_ptr<BluetoothGattServiceClient>( + new FakeBluetoothGattServiceClient)); DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager); fake_bluetooth_adapter_client_->SetSimulationIntervalMs(10); diff --git a/device/bluetooth/bluetooth_device.cc b/device/bluetooth/bluetooth_device.cc index f8cef4a..e29e34f 100644 --- a/device/bluetooth/bluetooth_device.cc +++ b/device/bluetooth/bluetooth_device.cc @@ -7,6 +7,7 @@ #include <string> #include "base/strings/utf_string_conversions.h" +#include "device/bluetooth/bluetooth_gatt_service.h" #include "grit/device_bluetooth_strings.h" #include "ui/base/l10n/l10n_util.h" @@ -16,6 +17,7 @@ BluetoothDevice::BluetoothDevice() { } BluetoothDevice::~BluetoothDevice() { + STLDeleteValues(&gatt_services_); } base::string16 BluetoothDevice::GetName() const { @@ -168,4 +170,21 @@ bool BluetoothDevice::IsPairable() const { return true; } +std::vector<BluetoothGattService*> + BluetoothDevice::GetGattServices() const { + std::vector<BluetoothGattService*> services; + for (GattServiceMap::const_iterator iter = gatt_services_.begin(); + iter != gatt_services_.end(); ++iter) + services.push_back(iter->second); + return services; +} + +BluetoothGattService* BluetoothDevice::GetGattService( + const std::string& identifier) const { + GattServiceMap::const_iterator iter = gatt_services_.find(identifier); + if (iter != gatt_services_.end()) + return iter->second; + return NULL; +} + } // namespace device diff --git a/device/bluetooth/bluetooth_device.h b/device/bluetooth/bluetooth_device.h index bfe7987..0fda335 100644 --- a/device/bluetooth/bluetooth_device.h +++ b/device/bluetooth/bluetooth_device.h @@ -5,7 +5,9 @@ #ifndef DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_H_ #define DEVICE_BLUETOOTH_BLUETOOTH_DEVICE_H_ +#include <map> #include <string> +#include <vector> #include "base/callback.h" #include "base/memory/ref_counted.h" @@ -16,6 +18,7 @@ namespace device { +class BluetoothGattService; class BluetoothProfile; class BluetoothSocket; @@ -81,6 +84,18 @@ class BluetoothDevice { public: virtual ~Observer() {} + // Called when a new GATT service |service| is added to the device |device|, + // as the service is received from the device. Don't cache |service|. Store + // its identifier instead (i.e. BluetoothGattService::GetIdentifier). + virtual void GattServiceAdded(BluetoothDevice* device, + BluetoothGattService* service) {} + + // Called when the GATT service |service| is removed from the device + // |device|. This can happen if the attribute database of the remote device + // changes or when |device| gets removed. + virtual void GattServiceRemoved(BluetoothDevice* device, + BluetoothGattService* service) {} + // TODO(keybuk): add observers for pairing and connection. }; @@ -173,6 +188,12 @@ class BluetoothDevice { virtual ~BluetoothDevice(); + // Adds and removes observers for events on this Bluetooth device. If + // monitoring multiple devices, check the |device| parameter of the observer + // methods to determine which device is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; + // Returns the Bluetooth class of the device, used by GetDeviceType() // and metrics logging, virtual uint32 GetBluetoothClass() const = 0; @@ -356,12 +377,24 @@ class BluetoothDevice { const base::Closure& callback, const ErrorCallback& error_callback) = 0; + // Returns the list of discovered GATT services. + std::vector<BluetoothGattService*> GetGattServices() const; + + // Returns the GATT service with device-specific identifier |identifier|. + // Returns NULL, if no such service exists. + BluetoothGattService* GetGattService(const std::string& identifier) const; + protected: BluetoothDevice(); // Returns the internal name of the Bluetooth device, used by GetName(). virtual std::string GetDeviceName() const = 0; + // Mapping from the platform-specific GATT service identifiers to + // BluetoothGattService objects. + typedef std::map<std::string, BluetoothGattService*> GattServiceMap; + GattServiceMap gatt_services_; + private: // Returns a localized string containing the device's bluetooth address and // a device type for display when |name_| is empty. diff --git a/device/bluetooth/bluetooth_device_chromeos.cc b/device/bluetooth/bluetooth_device_chromeos.cc index 7d37d93..47a38d8 100644 --- a/device/bluetooth/bluetooth_device_chromeos.cc +++ b/device/bluetooth/bluetooth_device_chromeos.cc @@ -12,12 +12,14 @@ #include "base/strings/string_util.h" #include "chromeos/dbus/bluetooth_adapter_client.h" #include "chromeos/dbus/bluetooth_device_client.h" +#include "chromeos/dbus/bluetooth_gatt_service_client.h" #include "chromeos/dbus/bluetooth_input_client.h" #include "chromeos/dbus/dbus_thread_manager.h" #include "dbus/bus.h" #include "device/bluetooth/bluetooth_adapter_chromeos.h" #include "device/bluetooth/bluetooth_pairing_chromeos.h" #include "device/bluetooth/bluetooth_profile_chromeos.h" +#include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h" #include "device/bluetooth/bluetooth_socket.h" #include "third_party/cros_system_api/dbus/service_constants.h" @@ -119,9 +121,43 @@ BluetoothDeviceChromeOS::BluetoothDeviceChromeOS( object_path_(object_path), num_connecting_calls_(0), weak_ptr_factory_(this) { + DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); + + // Add all known GATT services. + const std::vector<dbus::ObjectPath> gatt_services = + DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetServices(); + for (std::vector<dbus::ObjectPath>::const_iterator it = gatt_services.begin(); + it != gatt_services.end(); ++it) { + GattServiceAdded(*it); + } } BluetoothDeviceChromeOS::~BluetoothDeviceChromeOS() { + DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> + RemoveObserver(this); + + // Copy the GATT services list here and clear the original so that when we + // send GattServiceRemoved(), GetGattServices() returns no services. + GattServiceMap gatt_services = gatt_services_; + gatt_services_.clear(); + for (GattServiceMap::iterator iter = gatt_services.begin(); + iter != gatt_services.end(); ++iter) { + FOR_EACH_OBSERVER(BluetoothDevice::Observer, observers_, + GattServiceRemoved(this, iter->second)); + delete iter->second; + } +} + +void BluetoothDeviceChromeOS::AddObserver( + device::BluetoothDevice::Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void BluetoothDeviceChromeOS::RemoveObserver( + device::BluetoothDevice::Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); } uint32 BluetoothDeviceChromeOS::GetBluetoothClass() const { @@ -411,6 +447,53 @@ BluetoothPairingChromeOS* BluetoothDeviceChromeOS::GetPairing() const { return pairing_.get(); } +void BluetoothDeviceChromeOS::GattServiceAdded( + const dbus::ObjectPath& object_path) { + if (GetGattService(object_path.value())) { + VLOG(1) << "Remote GATT service already exists: " << object_path.value(); + return; + } + + BluetoothGattServiceClient::Properties* properties = + DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> + GetProperties(object_path); + DCHECK(properties); + if (properties->device.value() != object_path_) { + VLOG(2) << "Remote GATT service does not belong to this device."; + return; + } + + VLOG(1) << "Adding new remote GATT service for device: " << GetAddress(); + + BluetoothRemoteGattServiceChromeOS* service = + new BluetoothRemoteGattServiceChromeOS(this, object_path); + gatt_services_[service->GetIdentifier()] = service; + DCHECK(service->object_path() == object_path); + DCHECK(service->GetUUID().IsValid()); + + FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_, + GattServiceAdded(this, service)); +} + +void BluetoothDeviceChromeOS::GattServiceRemoved( + const dbus::ObjectPath& object_path) { + GattServiceMap::iterator iter = gatt_services_.find(object_path.value()); + if (iter == gatt_services_.end()) { + VLOG(2) << "Unknown GATT service removed: " << object_path.value(); + return; + } + + VLOG(1) << "Removing remote GATT service from device: " << GetAddress(); + + BluetoothRemoteGattServiceChromeOS* service = + static_cast<BluetoothRemoteGattServiceChromeOS*>(iter->second); + DCHECK(service->object_path() == object_path); + gatt_services_.erase(iter); + FOR_EACH_OBSERVER(device::BluetoothDevice::Observer, observers_, + GattServiceRemoved(this, service)); + delete service; +} + void BluetoothDeviceChromeOS::ConnectInternal( bool after_pairing, const base::Closure& callback, diff --git a/device/bluetooth/bluetooth_device_chromeos.h b/device/bluetooth/bluetooth_device_chromeos.h index 0dc5133..3c447b9 100644 --- a/device/bluetooth/bluetooth_device_chromeos.h +++ b/device/bluetooth/bluetooth_device_chromeos.h @@ -9,7 +9,9 @@ #include "base/memory/scoped_ptr.h" #include "base/memory/weak_ptr.h" +#include "base/observer_list.h" #include "chromeos/dbus/bluetooth_device_client.h" +#include "chromeos/dbus/bluetooth_gatt_service_client.h" #include "dbus/object_path.h" #include "device/bluetooth/bluetooth_device.h" @@ -21,9 +23,14 @@ class BluetoothPairingChromeOS; // The BluetoothDeviceChromeOS class implements BluetoothDevice for the // Chrome OS platform. class BluetoothDeviceChromeOS - : public device::BluetoothDevice { + : public device::BluetoothDevice, + public BluetoothGattServiceClient::Observer { public: // BluetoothDevice override + virtual void AddObserver( + device::BluetoothDevice::Observer* observer) OVERRIDE; + virtual void RemoveObserver( + device::BluetoothDevice::Observer* observer) OVERRIDE; virtual uint32 GetBluetoothClass() const OVERRIDE; virtual std::string GetAddress() const OVERRIDE; virtual VendorIDSource GetVendorIDSource() const OVERRIDE; @@ -90,6 +97,10 @@ class BluetoothDeviceChromeOS const dbus::ObjectPath& object_path); virtual ~BluetoothDeviceChromeOS(); + // BluetoothGattServiceClient::Observer overrides. + virtual void GattServiceAdded(const dbus::ObjectPath& object_path) OVERRIDE; + virtual void GattServiceRemoved(const dbus::ObjectPath& object_path) OVERRIDE; + // Internal method to initiate a connection to this device, and methods called // by dbus:: on completion of the D-Bus method call. void ConnectInternal(bool after_pairing, @@ -155,6 +166,9 @@ class BluetoothDeviceChromeOS // The dbus object path of the device object. dbus::ObjectPath object_path_; + // List of observers interested in event notifications from us. + ObserverList<device::BluetoothDevice::Observer> observers_; + // Number of ongoing calls to Connect(). int num_connecting_calls_; diff --git a/device/bluetooth/bluetooth_device_mac.h b/device/bluetooth/bluetooth_device_mac.h index 26b1b8f..e0ed024 100644 --- a/device/bluetooth/bluetooth_device_mac.h +++ b/device/bluetooth/bluetooth_device_mac.h @@ -8,6 +8,7 @@ #include <string> #include "base/basictypes.h" +#include "base/observer_list.h" #include "device/bluetooth/bluetooth_device.h" #ifdef __OBJC__ @@ -24,6 +25,10 @@ class BluetoothDeviceMac : public BluetoothDevice { virtual ~BluetoothDeviceMac(); // BluetoothDevice override + virtual void AddObserver( + device::BluetoothDevice::Observer* observer) OVERRIDE; + virtual void RemoveObserver( + device::BluetoothDevice::Observer* observer) OVERRIDE; virtual uint32 GetBluetoothClass() const OVERRIDE; virtual std::string GetAddress() const OVERRIDE; virtual VendorIDSource GetVendorIDSource() const OVERRIDE; @@ -73,6 +78,9 @@ class BluetoothDeviceMac : public BluetoothDevice { private: friend class BluetoothAdapterMac; + // List of observers interested in event notifications from us. + ObserverList<Observer> observers_; + IOBluetoothDevice* device_; DISALLOW_COPY_AND_ASSIGN(BluetoothDeviceMac); diff --git a/device/bluetooth/bluetooth_device_mac.mm b/device/bluetooth/bluetooth_device_mac.mm index 00ce0cf..bd25449 100644 --- a/device/bluetooth/bluetooth_device_mac.mm +++ b/device/bluetooth/bluetooth_device_mac.mm @@ -72,6 +72,18 @@ BluetoothDeviceMac::~BluetoothDeviceMac() { [device_ release]; } +void BluetoothDeviceMac::AddObserver( + device::BluetoothDevice::Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void BluetoothDeviceMac::RemoveObserver( + device::BluetoothDevice::Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + uint32 BluetoothDeviceMac::GetBluetoothClass() const { return [device_ classOfDevice]; } diff --git a/device/bluetooth/bluetooth_device_win.cc b/device/bluetooth/bluetooth_device_win.cc index 1834096..42d7fdd 100644 --- a/device/bluetooth/bluetooth_device_win.cc +++ b/device/bluetooth/bluetooth_device_win.cc @@ -69,6 +69,19 @@ void BluetoothDeviceWin::SetVisible(bool visible) { visible_ = visible; } +void BluetoothDeviceWin::AddObserver( + device::BluetoothDevice::Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void BluetoothDeviceWin::RemoveObserver( + device::BluetoothDevice::Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + + uint32 BluetoothDeviceWin::GetBluetoothClass() const { return bluetooth_class_; } diff --git a/device/bluetooth/bluetooth_device_win.h b/device/bluetooth/bluetooth_device_win.h index acbb350..367ab23 100644 --- a/device/bluetooth/bluetooth_device_win.h +++ b/device/bluetooth/bluetooth_device_win.h @@ -9,6 +9,7 @@ #include <vector> #include "base/basictypes.h" +#include "base/observer_list.h" #include "device/bluetooth/bluetooth_device.h" #include "device/bluetooth/bluetooth_task_manager_win.h" @@ -29,6 +30,10 @@ class BluetoothDeviceWin : public BluetoothDevice { virtual ~BluetoothDeviceWin(); // BluetoothDevice override + virtual void AddObserver( + device::BluetoothDevice::Observer* observer) OVERRIDE; + virtual void RemoveObserver( + device::BluetoothDevice::Observer* observer) OVERRIDE; virtual uint32 GetBluetoothClass() const OVERRIDE; virtual std::string GetAddress() const OVERRIDE; virtual VendorIDSource GetVendorIDSource() const OVERRIDE; @@ -92,6 +97,9 @@ class BluetoothDeviceWin : public BluetoothDevice { net::NetLog* net_log_; net::NetLog::Source net_log_source_; + // List of observers interested in event notifications from us. + ObserverList<Observer> observers_; + // The Bluetooth class of the device, a bitmask that may be decoded using // https://www.bluetooth.org/Technical/AssignedNumbers/baseband.htm uint32 bluetooth_class_; diff --git a/device/bluetooth/bluetooth_gatt_characteristic.h b/device/bluetooth/bluetooth_gatt_characteristic.h index 3fe5859..d199c5a 100644 --- a/device/bluetooth/bluetooth_gatt_characteristic.h +++ b/device/bluetooth/bluetooth_gatt_characteristic.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_BLUETOOTH_GATT_CHARACTERISTIC_H_ -#define DEVICE_BLUETOOTH_GATT_CHARACTERISTIC_H_ +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_GATT_CHARACTERISTIC_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_GATT_CHARACTERISTIC_H_ #include <vector> @@ -70,30 +70,6 @@ class BluetoothGattCharacteristic { }; typedef uint32 Permissions; - // Interface for observing changes from a BluetoothGattCharacteristic. - // Properties of remote characteristics are received asynchonously. The - // Observer interface can be used to be notified when the initial values of a - // characteristic are received as well as when successive changes occur during - // its life cycle. - class Observer { - public: - // Called when the UUID of |characteristic| has changed. - virtual void UuidChanged( - BluetoothGattCharacteristic* characteristic, - const BluetoothUUID& uuid) {} - - // Called when the current value of |characteristic| has changed. - virtual void ValueChanged( - BluetoothGattCharacteristic* characteristic, - const std::vector<uint8>& value) {} - - // Called when the descriptors that are associated with |characteristic| - // have changed. - virtual void DescriptorsChanged( - BluetoothGattCharacteristic* characteristic, - const std::vector<BluetoothGattDescriptor*>& descriptors) {} - }; - // The ErrorCallback is used by methods to asynchronously report errors. typedef base::Callback<void(const std::string&)> ErrorCallback; @@ -101,12 +77,6 @@ class BluetoothGattCharacteristic { // upon a read request. typedef base::Callback<void(const std::vector<uint8>&)> ValueCallback; - // Adds and removes observers for events on this GATT characteristic. If - // monitoring multiple characteristics, check the |characteristic| parameter - // of observer methods to determine which characteristic is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - // Constructs a BluetoothGattCharacteristic that can be associated with a // local GATT service when the adapter is in the peripheral role. To // associate the returned characteristic with a service, add it to a local @@ -131,12 +101,17 @@ class BluetoothGattCharacteristic { Permissions permissions); // The Bluetooth-specific UUID of the characteristic. - virtual const BluetoothUUID& GetUuid() const = 0; + virtual BluetoothUUID GetUUID() const = 0; // Returns true, if this characteristic is hosted locally. If false, then this // instance represents a remote GATT characteristic. virtual bool IsLocal() const = 0; + // Returns the value of the characteristic. For remote characteristics, this + // is the most recently cached value. For local characteristics, this is the + // most recently updated value or the value retrieved from the delegate. + virtual const std::vector<uint8>& GetValue() const = 0; + // Returns a pointer to the GATT service this characteristic belongs to. virtual const BluetoothGattService* GetService() const = 0; @@ -192,4 +167,4 @@ class BluetoothGattCharacteristic { } // namespace device -#endif // DEVICE_BLUETOOTH_GATT_CHARACTERISTIC_H_ +#endif // DEVICE_BLUETOOTH_BLUETOOTH_GATT_CHARACTERISTIC_H_ diff --git a/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc b/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc new file mode 100644 index 0000000..f93060f --- /dev/null +++ b/device/bluetooth/bluetooth_gatt_chromeos_unittest.cc @@ -0,0 +1,251 @@ +// 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 "base/message_loop/message_loop.h" +#include "chromeos/dbus/fake_bluetooth_adapter_client.h" +#include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" +#include "chromeos/dbus/fake_bluetooth_device_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_characteristic_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_descriptor_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" +#include "chromeos/dbus/fake_bluetooth_input_client.h" +#include "chromeos/dbus/fake_dbus_thread_manager.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_adapter.h" +#include "device/bluetooth/bluetooth_adapter_factory.h" +#include "device/bluetooth/bluetooth_device.h" +#include "device/bluetooth/bluetooth_gatt_service.h" +#include "device/bluetooth/bluetooth_uuid.h" +#include "testing/gtest/include/gtest/gtest.h" + +using device::BluetoothAdapter; +using device::BluetoothDevice; +using device::BluetoothGattService; +using device::BluetoothUUID; + +namespace chromeos { + +namespace { + +class TestObserver : public BluetoothDevice::Observer { + public: + TestObserver(scoped_refptr<BluetoothAdapter> adapter, + BluetoothDevice* device) + : gatt_service_added_count_(0), + gatt_service_removed_count_(0), + device_address_(device->GetAddress()), + adapter_(adapter) { + device->AddObserver(this); + } + + virtual ~TestObserver() { + BluetoothDevice* device = adapter_->GetDevice(device_address_); + if (device) + device->RemoveObserver(this); + } + + // BluetoothDevice::Observer overrides. + virtual void GattServiceAdded( + BluetoothDevice* device, + BluetoothGattService* service) OVERRIDE { + EXPECT_EQ(device_address_, device->GetAddress()); + + ++gatt_service_added_count_; + last_gatt_service_id_ = service->GetIdentifier(); + last_gatt_service_uuid_ = service->GetUUID(); + + EXPECT_FALSE(service->IsLocal()); + EXPECT_TRUE(service->IsPrimary()); + + QuitMessageLoop(); + } + + virtual void GattServiceRemoved( + BluetoothDevice* device, + BluetoothGattService* service) OVERRIDE { + EXPECT_EQ(device_address_, device->GetAddress()); + + ++gatt_service_removed_count_; + last_gatt_service_id_ = service->GetIdentifier(); + last_gatt_service_uuid_ = service->GetUUID(); + + EXPECT_FALSE(service->IsLocal()); + EXPECT_TRUE(service->IsPrimary()); + + QuitMessageLoop(); + } + + int gatt_service_added_count_; + int gatt_service_removed_count_; + std::string last_gatt_service_id_; + BluetoothUUID last_gatt_service_uuid_; + + private: + // Some tests use a message loop since background processing is simulated; + // break out of those loops. + void QuitMessageLoop() { + if (base::MessageLoop::current() && + base::MessageLoop::current()->is_running()) + base::MessageLoop::current()->Quit(); + } + + std::string device_address_; + scoped_refptr<BluetoothAdapter> adapter_; +}; + +} // namespace + +class BluetoothGattChromeOSTest : public testing::Test { + public: + BluetoothGattChromeOSTest() + : fake_bluetooth_gatt_service_client_(NULL), + last_gatt_service_(NULL) { + } + + virtual void SetUp() { + FakeDBusThreadManager* fake_dbus_thread_manager = new FakeDBusThreadManager; + fake_bluetooth_device_client_ = new FakeBluetoothDeviceClient; + fake_bluetooth_gatt_service_client_ = + new FakeBluetoothGattServiceClient; + fake_dbus_thread_manager->SetBluetoothDeviceClient( + scoped_ptr<BluetoothDeviceClient>( + fake_bluetooth_device_client_)); + fake_dbus_thread_manager->SetBluetoothGattServiceClient( + scoped_ptr<BluetoothGattServiceClient>( + fake_bluetooth_gatt_service_client_)); + fake_dbus_thread_manager->SetBluetoothGattCharacteristicClient( + scoped_ptr<BluetoothGattCharacteristicClient>( + new FakeBluetoothGattCharacteristicClient)); + fake_dbus_thread_manager->SetBluetoothGattDescriptorClient( + scoped_ptr<BluetoothGattDescriptorClient>( + new FakeBluetoothGattDescriptorClient)); + fake_dbus_thread_manager->SetBluetoothAdapterClient( + scoped_ptr<BluetoothAdapterClient>(new FakeBluetoothAdapterClient)); + fake_dbus_thread_manager->SetBluetoothInputClient( + scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); + fake_dbus_thread_manager->SetBluetoothAgentManagerClient( + scoped_ptr<BluetoothAgentManagerClient>( + new FakeBluetoothAgentManagerClient)); + DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager); + + device::BluetoothAdapterFactory::GetAdapter( + base::Bind(&BluetoothGattChromeOSTest::AdapterCallback, + base::Unretained(this))); + ASSERT_TRUE(adapter_.get() != NULL); + ASSERT_TRUE(adapter_->IsInitialized()); + ASSERT_TRUE(adapter_->IsPresent()); + + adapter_->SetPowered( + true, + base::Bind(&base::DoNothing), + base::Bind(&base::DoNothing)); + ASSERT_TRUE(adapter_->IsPowered()); + } + + virtual void TearDown() { + adapter_ = NULL; + DBusThreadManager::Shutdown(); + } + + void AdapterCallback(scoped_refptr<BluetoothAdapter> adapter) { + adapter_ = adapter; + } + + protected: + base::MessageLoop message_loop_; + + FakeBluetoothDeviceClient* fake_bluetooth_device_client_; + FakeBluetoothGattServiceClient* fake_bluetooth_gatt_service_client_; + scoped_refptr<BluetoothAdapter> adapter_; + + BluetoothGattService* last_gatt_service_; +}; + +TEST_F(BluetoothGattChromeOSTest, GattServiceAdded) { + // Create a fake LE device. We store the device pointer here because this is a + // test. It's unsafe to do this in production as the device might get deleted. + fake_bluetooth_device_client_->CreateDevice( + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + BluetoothDevice* device = adapter_->GetDevice( + FakeBluetoothDeviceClient::kLowEnergyAddress); + ASSERT_TRUE(device); + + TestObserver observer(adapter_, device); + EXPECT_EQ(0, observer.gatt_service_added_count_); + EXPECT_EQ(0, observer.gatt_service_removed_count_); + EXPECT_TRUE(observer.last_gatt_service_id_.empty()); + EXPECT_FALSE(observer.last_gatt_service_uuid_.IsValid()); + + // Expose the fake Heart Rate Service. + fake_bluetooth_gatt_service_client_->ExposeHeartRateService( + dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + EXPECT_EQ(1, observer.gatt_service_added_count_); + EXPECT_EQ(0, observer.gatt_service_removed_count_); + EXPECT_FALSE(observer.last_gatt_service_id_.empty()); + EXPECT_EQ(1U, device->GetGattServices().size()); + EXPECT_EQ( + BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid_); + + BluetoothGattService* service = + device->GetGattService(observer.last_gatt_service_id_); + EXPECT_FALSE(service->IsLocal()); + EXPECT_TRUE(service->IsPrimary()); + + EXPECT_EQ(observer.last_gatt_service_uuid_, service->GetUUID()); + + // Hide the service. + observer.last_gatt_service_uuid_ = BluetoothUUID(); + observer.last_gatt_service_id_.clear(); + fake_bluetooth_gatt_service_client_->HideHeartRateService(); + + EXPECT_EQ(1, observer.gatt_service_added_count_); + EXPECT_EQ(1, observer.gatt_service_removed_count_); + EXPECT_FALSE(observer.last_gatt_service_id_.empty()); + EXPECT_TRUE(device->GetGattServices().empty()); + EXPECT_EQ( + BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid_); + + EXPECT_EQ(NULL, device->GetGattService(observer.last_gatt_service_id_)); + + // Expose the service again. + observer.last_gatt_service_uuid_ = BluetoothUUID(); + observer.last_gatt_service_id_.clear(); + fake_bluetooth_gatt_service_client_->ExposeHeartRateService( + dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + EXPECT_EQ(2, observer.gatt_service_added_count_); + EXPECT_EQ(1, observer.gatt_service_removed_count_); + EXPECT_FALSE(observer.last_gatt_service_id_.empty()); + EXPECT_EQ(1U, device->GetGattServices().size()); + EXPECT_EQ( + BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid_); + + service = device->GetGattService(observer.last_gatt_service_id_); + EXPECT_FALSE(service->IsLocal()); + EXPECT_TRUE(service->IsPrimary()); + + EXPECT_EQ(observer.last_gatt_service_uuid_, service->GetUUID()); + + // Remove the device. The observer should be notified of the removed service. + // |device| becomes invalid after this. + observer.last_gatt_service_uuid_ = BluetoothUUID(); + observer.last_gatt_service_id_.clear(); + fake_bluetooth_device_client_->RemoveDevice( + dbus::ObjectPath(FakeBluetoothAdapterClient::kAdapterPath), + dbus::ObjectPath(FakeBluetoothDeviceClient::kLowEnergyPath)); + + EXPECT_EQ(2, observer.gatt_service_added_count_); + EXPECT_EQ(2, observer.gatt_service_removed_count_); + EXPECT_FALSE(observer.last_gatt_service_id_.empty()); + EXPECT_EQ( + BluetoothUUID(FakeBluetoothGattServiceClient::kHeartRateServiceUUID), + observer.last_gatt_service_uuid_); + EXPECT_EQ( + NULL, adapter_->GetDevice(FakeBluetoothDeviceClient::kLowEnergyAddress)); +} + +} // namespace chromeos diff --git a/device/bluetooth/bluetooth_gatt_descriptor.h b/device/bluetooth/bluetooth_gatt_descriptor.h index 45ea8f8..7c6cc83 100644 --- a/device/bluetooth/bluetooth_gatt_descriptor.h +++ b/device/bluetooth/bluetooth_gatt_descriptor.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_BLUETOOTH_GATT_DESCRIPTOR_H_ -#define DEVICE_BLUETOOTH_GATT_DESCRIPTOR_H_ +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_GATT_DESCRIPTOR_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_GATT_DESCRIPTOR_H_ #include <vector> @@ -105,24 +105,6 @@ class BluetoothGattDescriptor { // handled by the subsystem. static const BluetoothUUID kCharacteristicAggregateFormatUuid; - // Interface for observing changes from a BluetoothGattDescriptor. - // Properties of remote characteristic desciptors are received asynchonously. - // The Observer interface can be used to be notified when the initial values - // of a characteristic descriptor are received as well as when successive - // changes occur during its life cycle. - class Observer { - public: - // Called when the UUID of |descriptor| has changed. - virtual void UuidChanged( - BluetoothGattDescriptor* descriptor, - const BluetoothUUID& uuid) {} - - // Called when the current value of |descriptor| has changed. - virtual void ValueChanged( - BluetoothGattDescriptor* descriptor, - const std::vector<uint8>& value) {} - }; - // The ErrorCallback is used by methods to asynchronously report errors. typedef base::Callback<void(const std::string&)> ErrorCallback; @@ -130,13 +112,6 @@ class BluetoothGattDescriptor { // descriptor upon a read request. typedef base::Callback<void(const std::vector<uint8>&)> ValueCallback; - // Adds and removes observers for events on this GATT characteristic - // descriptor. If monitoring multiple descriptors, check the |descriptor| - // parameter of observer methods to determine which characteristic is issuing - // the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - // Constructs a BluetoothGattDescriptor that can be associated with a local // GATT characteristic when the adapter is in the peripheral role. To // associate the returned descriptor with a characteristic, add it to a local @@ -157,12 +132,18 @@ class BluetoothGattDescriptor { const std::vector<uint8>& value); // The Bluetooth-specific UUID of the characteristic descriptor. - virtual const BluetoothUUID& GetUuid() const = 0; + virtual BluetoothUUID GetUUID() const = 0; // Returns true, if this characteristic descriptor is hosted locally. If // false, then this instance represents a remote descriptor. virtual bool IsLocal() const = 0; + // Returns the value of the descriptor. For remote descriptors, this is the + // most recently cached value of the remote descriptor. For local descriptors + // this is the most recently updated value or the value retrieved from the + // delegate. + virtual const std::vector<uint8>& GetValue() const = 0; + // Returns a pointer to the GATT characteristic that this characteristic // descriptor belongs to. virtual const BluetoothGattCharacteristic* GetCharacteristic() const = 0; @@ -194,4 +175,4 @@ class BluetoothGattDescriptor { } // namespace device -#endif // DEVICE_BLUETOOTH_GATT_DESCRIPTOR_H_ +#endif // DEVICE_BLUETOOTH_BLUETOOTH_GATT_DESCRIPTOR_H_ diff --git a/device/bluetooth/bluetooth_gatt_service.h b/device/bluetooth/bluetooth_gatt_service.h index 4046a00..240772b 100644 --- a/device/bluetooth/bluetooth_gatt_service.h +++ b/device/bluetooth/bluetooth_gatt_service.h @@ -2,8 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef DEVICE_BLUETOOTH_GATT_SERVICE_H_ -#define DEVICE_BLUETOOTH_GATT_SERVICE_H_ +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_GATT_SERVICE_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_GATT_SERVICE_H_ #include <vector> @@ -130,24 +130,31 @@ class BluetoothGattService { // as well as when successive changes occur during its life cycle. class Observer { public: - // Called when the UUID of |service| have changed. - virtual void UuidChanged( + // Called when properties of the remote GATT service |service| have changed. + // This will get called for properties such as UUID, as well as for changes + // to the list of known characteristics. Observers should read all GATT + // characteristic and descriptors objects and do any necessary set up + // required for a changed service. + virtual void GattServiceChanged(BluetoothGattService* service) {} + + // Called when the value of a characteristic has been retrieved or updated + // via a notification or inidication. + virtual void CharacteristicValueChanged( BluetoothGattService* service, - const BluetoothUUID& uuid) {} - - // Called when the services included by |service| have changed. - virtual void IncludedServicesChanged( - BluetoothGattService* service, - const std::vector<BluetoothGattService*>& included_services) {} - - // Called when the characteristics that belong to |service| have changed. - virtual void CharacteristicsChanged( - BluetoothGattService* service, - const std::vector<BluetoothGattCharacteristic*>& characteristics) {} + BluetoothGattCharacteristic* characteristic, + const std::vector<uint8>& value) {} }; // The ErrorCallback is used by methods to asynchronously report errors. - typedef base::Callback<void(const std::string&)> ErrorCallback; + typedef base::Closure ErrorCallback; + + virtual ~BluetoothGattService(); + + // Adds and removes observers for events on this GATT service. If monitoring + // multiple services, check the |service| parameter of observer methods to + // determine which service is issuing the event. + virtual void AddObserver(Observer* observer) = 0; + virtual void RemoveObserver(Observer* observer) = 0; // Constructs a BluetoothGattService that can be locally hosted when the local // adapter is in the peripheral role. The resulting object can then be made @@ -161,8 +168,15 @@ class BluetoothGattService { bool is_primary, Delegate* delegate); + // Identifier used to uniquely identify a GATT service object. This different + // from the service UUID: while multiple services with the same UUID can exist + // on a Bluetooth device, the identifier returned from this method is unique + // among all services of a device. The contents of the identifier are platform + // specific. + virtual std::string GetIdentifier() const = 0; + // The Bluetooth-specific UUID of the service. - virtual const BluetoothUUID& GetUuid() const = 0; + virtual BluetoothUUID GetUUID() const = 0; // Returns true, if this service hosted locally. If false, then this service // represents a remote GATT service. @@ -183,12 +197,6 @@ class BluetoothGattService { virtual const std::vector<BluetoothGattService*>& GetIncludedServices() const = 0; - // Adds and removes observers for events on this GATT service. If monitoring - // multiple services, check the |service| parameter of observer methods to - // determine which service is issuing the event. - virtual void AddObserver(Observer* observer) = 0; - virtual void RemoveObserver(Observer* observer) = 0; - // Adds characteristics and included services to the local attribute hierarchy // represented by this service. These methods only make sense for local // services and won't have an effect if this instance represents a remote @@ -197,7 +205,7 @@ class BluetoothGattService { // service is not taken. virtual bool AddCharacteristic( BluetoothGattCharacteristic* characteristic) = 0; - virtual bool AddService(BluetoothGattService* service) = 0; + virtual bool AddIncludedService(BluetoothGattService* service) = 0; // Registers this GATT service. Calling Register will make this service and // all of its associated attributes available on the local adapters GATT @@ -215,7 +223,6 @@ class BluetoothGattService { protected: BluetoothGattService(); - virtual ~BluetoothGattService(); private: DISALLOW_COPY_AND_ASSIGN(BluetoothGattService); @@ -223,4 +230,4 @@ class BluetoothGattService { } // namespace device -#endif // DEVICE_BLUETOOTH_GATT_SERVICE_H_ +#endif // DEVICE_BLUETOOTH_BLUETOOTH_GATT_SERVICE_H_ diff --git a/device/bluetooth/bluetooth_profile_chromeos.h b/device/bluetooth/bluetooth_profile_chromeos.h index f7974f2..24e6c37 100644 --- a/device/bluetooth/bluetooth_profile_chromeos.h +++ b/device/bluetooth/bluetooth_profile_chromeos.h @@ -31,8 +31,8 @@ namespace chromeos { // Chrome OS platform. class CHROMEOS_EXPORT BluetoothProfileChromeOS : public device::BluetoothProfile, - private device::BluetoothAdapter::Observer, - private BluetoothProfileServiceProvider::Delegate { + public device::BluetoothAdapter::Observer, + public BluetoothProfileServiceProvider::Delegate { public: // BluetoothProfile override. virtual void Unregister() OVERRIDE; diff --git a/device/bluetooth/bluetooth_profile_chromeos_unittest.cc b/device/bluetooth/bluetooth_profile_chromeos_unittest.cc index 14ff3ee..63155c5 100644 --- a/device/bluetooth/bluetooth_profile_chromeos_unittest.cc +++ b/device/bluetooth/bluetooth_profile_chromeos_unittest.cc @@ -6,6 +6,7 @@ #include "chromeos/dbus/fake_bluetooth_adapter_client.h" #include "chromeos/dbus/fake_bluetooth_agent_manager_client.h" #include "chromeos/dbus/fake_bluetooth_device_client.h" +#include "chromeos/dbus/fake_bluetooth_gatt_service_client.h" #include "chromeos/dbus/fake_bluetooth_input_client.h" #include "chromeos/dbus/fake_bluetooth_profile_manager_client.h" #include "chromeos/dbus/fake_bluetooth_profile_service_provider.h" @@ -57,6 +58,9 @@ class BluetoothProfileChromeOSTest : public testing::Test { scoped_ptr<BluetoothDeviceClient>(new FakeBluetoothDeviceClient)); fake_dbus_thread_manager->SetBluetoothInputClient( scoped_ptr<BluetoothInputClient>(new FakeBluetoothInputClient)); + fake_dbus_thread_manager->SetBluetoothGattServiceClient( + scoped_ptr<BluetoothGattServiceClient>( + new FakeBluetoothGattServiceClient)); DBusThreadManager::InitializeForTesting(fake_dbus_thread_manager); device::BluetoothAdapterFactory::GetAdapter( diff --git a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc new file mode 100644 index 0000000..2c018f2 --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc @@ -0,0 +1,108 @@ +// 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_remote_gatt_service_chromeos.h" + +#include "base/logging.h" +#include "chromeos/dbus/bluetooth_gatt_service_client.h" +#include "chromeos/dbus/dbus_thread_manager.h" + +namespace chromeos { + +BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS( + BluetoothDeviceChromeOS* device, + const dbus::ObjectPath& object_path) + : object_path_(object_path), + device_(device), + weak_ptr_factory_(this) { + VLOG(1) << "Creating remote GATT service with identifier: " + << object_path.value() << ", UUID: " << GetUUID().canonical_value(); + DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this); +} + +BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() { + DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> + RemoveObserver(this); +} + +std::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const { + return object_path_.value(); +} + +device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const { + BluetoothGattServiceClient::Properties* properties = + DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> + GetProperties(object_path_); + DCHECK(properties); + return device::BluetoothUUID(properties->uuid.value()); +} + +bool BluetoothRemoteGattServiceChromeOS::IsLocal() const { + return false; +} + +bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const { + BluetoothGattServiceClient::Properties* properties = + DBusThreadManager::Get()->GetBluetoothGattServiceClient()-> + GetProperties(object_path_); + DCHECK(properties); + return properties->primary.value(); +} + +const std::vector<device::BluetoothGattCharacteristic*>& +BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const { + return characteristics_; +} + +const std::vector<device::BluetoothGattService*>& +BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const { + return includes_; +} + +void BluetoothRemoteGattServiceChromeOS::AddObserver( + device::BluetoothGattService::Observer* observer) { + DCHECK(observer); + observers_.AddObserver(observer); +} + +void BluetoothRemoteGattServiceChromeOS::RemoveObserver( + device::BluetoothGattService::Observer* observer) { + DCHECK(observer); + observers_.RemoveObserver(observer); +} + +bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic( + device::BluetoothGattCharacteristic* characteristic) { + VLOG(1) << "Characteristics cannot be added to a remote GATT service."; + return false; +} + +bool BluetoothRemoteGattServiceChromeOS::AddIncludedService( + device::BluetoothGattService* service) { + VLOG(1) << "Included services cannot be added to a remote GATT service."; + return false; +} + +void BluetoothRemoteGattServiceChromeOS::Register( + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "A remote GATT service cannot be registered."; + error_callback.Run(); +} + +void BluetoothRemoteGattServiceChromeOS::Unregister( + const base::Closure& callback, + const ErrorCallback& error_callback) { + VLOG(1) << "A remote GATT service cannot be unregistered."; + error_callback.Run(); +} + +void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name){ + FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_, + GattServiceChanged(this)); +} + +} // namespace chromeos diff --git a/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h new file mode 100644 index 0000000..d2c8c6c --- /dev/null +++ b/device/bluetooth/bluetooth_remote_gatt_service_chromeos.h @@ -0,0 +1,95 @@ +// 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. + +#ifndef DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_CHROMEOS_H_ +#define DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_CHROMEOS_H_ + +#include <string> +#include <vector> + +#include "base/memory/weak_ptr.h" +#include "base/observer_list.h" +#include "chromeos/dbus/bluetooth_gatt_service_client.h" +#include "dbus/object_path.h" +#include "device/bluetooth/bluetooth_gatt_service.h" +#include "device/bluetooth/bluetooth_uuid.h" + +namespace device { + +class BluetoothGattCharacteristic; + +} // namespace device + +namespace chromeos { + +class BluetoothDeviceChromeOS; + +// The BluetoothRemoteGattServiceChromeOS class implements BluetootGattService +// for remote GATT services on the the Chrome OS platform. +class BluetoothRemoteGattServiceChromeOS + : public device::BluetoothGattService, + public BluetoothGattServiceClient::Observer { + public: + // device::BluetoothGattService overrides. + virtual std::string GetIdentifier() const OVERRIDE; + virtual device::BluetoothUUID GetUUID() const OVERRIDE; + virtual bool IsLocal() const OVERRIDE; + virtual bool IsPrimary() const OVERRIDE; + virtual const std::vector<device::BluetoothGattCharacteristic*>& + GetCharacteristics() const OVERRIDE; + virtual const std::vector<device::BluetoothGattService*>& + GetIncludedServices() const OVERRIDE; + virtual void AddObserver( + device::BluetoothGattService::Observer* observer) OVERRIDE; + virtual void RemoveObserver( + device::BluetoothGattService::Observer* observer) OVERRIDE; + virtual bool AddCharacteristic( + device::BluetoothGattCharacteristic* characteristic) OVERRIDE; + virtual bool AddIncludedService( + device::BluetoothGattService* service) OVERRIDE; + virtual void Register(const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE; + virtual void Unregister(const base::Closure& callback, + const ErrorCallback& error_callback) OVERRIDE; + + // Object path of the underlying service. + const dbus::ObjectPath& object_path() const { return object_path_; } + + private: + friend class BluetoothDeviceChromeOS; + + BluetoothRemoteGattServiceChromeOS(BluetoothDeviceChromeOS* device, + const dbus::ObjectPath& object_path); + virtual ~BluetoothRemoteGattServiceChromeOS(); + + // BluetoothGattServiceClient::Observer override. + virtual void GattServicePropertyChanged( + const dbus::ObjectPath& object_path, + const std::string& property_name) OVERRIDE; + + // Object path of the GATT service. + dbus::ObjectPath object_path_; + + // List of observers interested in event notifications from us. + ObserverList<device::BluetoothGattService::Observer> observers_; + + // The device this GATT service belongs to. + BluetoothDeviceChromeOS* device_; + + // The list of characteristics that belong to this service. + std::vector<device::BluetoothGattCharacteristic*> characteristics_; + + // The list of GATT services included by this service. + std::vector<device::BluetoothGattService*> includes_; + + // Note: This should remain the last member so it'll be destroyed and + // invalidate its weak pointers before any other members are destroyed. + base::WeakPtrFactory<BluetoothRemoteGattServiceChromeOS> weak_ptr_factory_; + + DISALLOW_COPY_AND_ASSIGN(BluetoothRemoteGattServiceChromeOS); +}; + +} // namespace chromeos + +#endif // DEVICE_BLUETOOTH_BLUETOOTH_REMOTE_GATT_SERVICE_CHROMEOS_H_ diff --git a/device/bluetooth/test/mock_bluetooth_device.h b/device/bluetooth/test/mock_bluetooth_device.h index 675610a..56e426f 100644 --- a/device/bluetooth/test/mock_bluetooth_device.h +++ b/device/bluetooth/test/mock_bluetooth_device.h @@ -27,6 +27,8 @@ class MockBluetoothDevice : public BluetoothDevice { bool connected); virtual ~MockBluetoothDevice(); + MOCK_METHOD1(AddObserver, void(BluetoothDevice::Observer*)); + MOCK_METHOD1(RemoveObserver, void(BluetoothDevice::Observer*)); MOCK_CONST_METHOD0(GetBluetoothClass, uint32()); MOCK_CONST_METHOD0(GetDeviceName, std::string()); MOCK_CONST_METHOD0(GetAddress, std::string()); diff --git a/device/device_tests.gyp b/device/device_tests.gyp index 36b5826..db86a48 100644 --- a/device/device_tests.gyp +++ b/device/device_tests.gyp @@ -27,6 +27,7 @@ 'bluetooth/bluetooth_adapter_win_unittest.cc', 'bluetooth/bluetooth_device_win_unittest.cc', 'bluetooth/bluetooth_chromeos_unittest.cc', + 'bluetooth/bluetooth_gatt_chromeos_unittest.cc', 'bluetooth/bluetooth_profile_chromeos_unittest.cc', 'bluetooth/bluetooth_service_record_mac_unittest.mm', 'bluetooth/bluetooth_service_record_win_unittest.cc', |