summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorarmansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-08 05:18:28 +0000
committerarmansito@chromium.org <armansito@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-04-08 05:18:28 +0000
commite65bc222634ed32194386ba1c0785cc93499309d (patch)
treeebba25c995609f5a1b0ef8ec62f2cefd2df433e1
parent05e5d16199f7c4c91e4024b6b7c2f2d9f8ace930 (diff)
downloadchromium_src-e65bc222634ed32194386ba1c0785cc93499309d.zip
chromium_src-e65bc222634ed32194386ba1c0785cc93499309d.tar.gz
chromium_src-e65bc222634ed32194386ba1c0785cc93499309d.tar.bz2
device/bluetooth: Add chromeos::BluetoothRemoteGattServiceChromeOS.
Added the chromeos::BluetoothRemoteGattServiceChromeOS class which implements a remote instance of device::BluetoothGattService for the Chrome OS platform. This CL also introduces some minor changes to the GATT API, namely removing the characteristic and descriptor Observer interfaces. Addition, removal, and value changes of remote characteristics will instead be tracked via BluetoothGattService::Observer. BUG=360266,340529 TEST=device_unittests Review URL: https://codereview.chromium.org/224953003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@262327 0039d316-1c4b-4281-b951-d872f2087c98
-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',