summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/metrics/metrics_log_unittest.cc18
-rw-r--r--chromeos/dbus/bluetooth_gatt_service_client.cc11
-rw-r--r--chromeos/dbus/bluetooth_gatt_service_client.h6
-rw-r--r--chromeos/dbus/fake_bluetooth_gatt_characteristic_client.cc14
-rw-r--r--chromeos/dbus/fake_bluetooth_gatt_service_client.cc11
-rw-r--r--device/bluetooth/bluetooth.gyp2
-rw-r--r--device/bluetooth/bluetooth_adapter_chromeos.h8
-rw-r--r--device/bluetooth/bluetooth_chromeos_unittest.cc8
-rw-r--r--device/bluetooth/bluetooth_device.cc19
-rw-r--r--device/bluetooth/bluetooth_device.h33
-rw-r--r--device/bluetooth/bluetooth_device_chromeos.cc83
-rw-r--r--device/bluetooth/bluetooth_device_chromeos.h16
-rw-r--r--device/bluetooth/bluetooth_device_mac.h8
-rw-r--r--device/bluetooth/bluetooth_device_mac.mm12
-rw-r--r--device/bluetooth/bluetooth_device_win.cc13
-rw-r--r--device/bluetooth/bluetooth_device_win.h8
-rw-r--r--device/bluetooth/bluetooth_gatt_characteristic.h43
-rw-r--r--device/bluetooth/bluetooth_gatt_chromeos_unittest.cc251
-rw-r--r--device/bluetooth/bluetooth_gatt_descriptor.h39
-rw-r--r--device/bluetooth/bluetooth_gatt_service.h59
-rw-r--r--device/bluetooth/bluetooth_profile_chromeos.h4
-rw-r--r--device/bluetooth/bluetooth_profile_chromeos_unittest.cc4
-rw-r--r--device/bluetooth/bluetooth_remote_gatt_service_chromeos.cc108
-rw-r--r--device/bluetooth/bluetooth_remote_gatt_service_chromeos.h95
-rw-r--r--device/bluetooth/test/mock_bluetooth_device.h2
-rw-r--r--device/device_tests.gyp1
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',