Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / device / bluetooth / bluetooth_remote_gatt_service_chromeos.cc
index f2ec861..b921242 100644 (file)
@@ -8,34 +8,26 @@
 #include "base/strings/stringprintf.h"
 #include "chromeos/dbus/bluetooth_gatt_service_client.h"
 #include "chromeos/dbus/dbus_thread_manager.h"
+#include "device/bluetooth/bluetooth_adapter_chromeos.h"
 #include "device/bluetooth/bluetooth_device_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
 
 namespace chromeos {
 
-namespace {
-
-// Stream operator for logging vector<uint8>.
-std::ostream& operator<<(std::ostream& out, const std::vector<uint8> bytes) {
-  out << "[";
-  for (std::vector<uint8>::const_iterator iter = bytes.begin();
-       iter != bytes.end(); ++iter) {
-    out << base::StringPrintf("%02X", *iter);
-  }
-  return out << "]";
-}
-
-}  // namespace
-
 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS(
+    BluetoothAdapterChromeOS* adapter,
     BluetoothDeviceChromeOS* device,
     const dbus::ObjectPath& object_path)
     : object_path_(object_path),
+      adapter_(adapter),
       device_(device),
+      discovery_complete_(false),
       weak_ptr_factory_(this) {
   VLOG(1) << "Creating remote GATT service with identifier: "
           << object_path.value() << ", UUID: " << GetUUID().canonical_value();
+  DCHECK(adapter_);
+
   DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
   DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
       AddObserver(this);
@@ -62,24 +54,13 @@ BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
   characteristics_.clear();
   for (CharacteristicMap::iterator iter = characteristics.begin();
        iter != characteristics.end(); ++iter) {
-    FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                      GattCharacteristicRemoved(this, iter->second));
+    DCHECK(adapter_);
+    adapter_->NotifyGattCharacteristicRemoved(iter->second);
+
     delete iter->second;
   }
 }
 
-void BluetoothRemoteGattServiceChromeOS::AddObserver(
-    device::BluetoothGattService::Observer* observer) {
-  DCHECK(observer);
-  observers_.AddObserver(observer);
-}
-
-void BluetoothRemoteGattServiceChromeOS::RemoveObserver(
-    device::BluetoothGattService::Observer* observer) {
-  DCHECK(observer);
-  observers_.RemoveObserver(observer);
-}
-
 std::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const {
   return object_path_.value();
 }
@@ -160,9 +141,28 @@ void BluetoothRemoteGattServiceChromeOS::Unregister(
   error_callback.Run();
 }
 
+BluetoothAdapterChromeOS*
+BluetoothRemoteGattServiceChromeOS::GetAdapter() const {
+  return adapter_;
+}
+
 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() {
-  FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                    GattServiceChanged(this));
+  // Don't send service changed unless we know that all characteristics have
+  // already been discovered. This is to prevent spammy events before sending
+  // out the first Gatt
+  if (!discovery_complete_)
+    return;
+
+  DCHECK(adapter_);
+  adapter_->NotifyGattServiceChanged(this);
+}
+
+void BluetoothRemoteGattServiceChromeOS::NotifyCharacteristicValueChanged(
+    BluetoothRemoteGattCharacteristicChromeOS* characteristic,
+    const std::vector<uint8>& value) {
+  DCHECK(characteristic->GetService() == this);
+  DCHECK(adapter_);
+  adapter_->NotifyGattCharacteristicValueChanged(characteristic, value);
 }
 
 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
@@ -171,13 +171,14 @@ void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
     bool added) {
   DCHECK(characteristic->GetService() == this);
   DCHECK(descriptor->GetCharacteristic() == characteristic);
+  DCHECK(adapter_);
+
   if (added) {
-    FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                      GattDescriptorAdded(characteristic, descriptor));
+    adapter_->NotifyGattDescriptorAdded(descriptor);
     return;
   }
-  FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                    GattDescriptorRemoved(characteristic, descriptor));
+
+  adapter_->NotifyGattDescriptorRemoved(descriptor);
 }
 
 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
@@ -186,15 +187,36 @@ void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
     const std::vector<uint8>& value) {
   DCHECK(characteristic->GetService() == this);
   DCHECK(descriptor->GetCharacteristic() == characteristic);
-  FOR_EACH_OBSERVER(
-      device::BluetoothGattService::Observer, observers_,
-      GattDescriptorValueChanged(characteristic, descriptor, value));
+  DCHECK(adapter_);
+  adapter_->NotifyGattDescriptorValueChanged(descriptor, value);
 }
 
 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name){
-  NotifyServiceChanged();
+  if (object_path != object_path_)
+    return;
+
+  VLOG(1) << "Service property changed: \"" << property_name << "\", "
+          << object_path.value();
+  BluetoothGattServiceClient::Properties* properties =
+      DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
+          object_path);
+  DCHECK(properties);
+
+  if (property_name != properties->characteristics.name()) {
+    NotifyServiceChanged();
+    return;
+  }
+
+  if (discovery_complete_)
+    return;
+
+  VLOG(1) << "All characteristics were discovered for service: "
+          << object_path.value();
+  discovery_complete_ = true;
+  DCHECK(adapter_);
+  adapter_->NotifyGattDiscoveryComplete(this);
 }
 
 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
@@ -223,9 +245,8 @@ void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
   DCHECK(characteristic->GetIdentifier() == object_path.value());
   DCHECK(characteristic->GetUUID().IsValid());
 
-  FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                    GattCharacteristicAdded(this, characteristic));
-  NotifyServiceChanged();
+  DCHECK(adapter_);
+  adapter_->NotifyGattCharacteristicAdded(characteristic);
 }
 
 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
@@ -243,9 +264,8 @@ void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
   DCHECK(characteristic->object_path() == object_path);
   characteristics_.erase(iter);
 
-  FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                    GattCharacteristicRemoved(this, characteristic));
-  NotifyServiceChanged();
+  DCHECK(adapter_);
+  adapter_->NotifyGattCharacteristicRemoved(characteristic);
 
   delete characteristic;
 }
@@ -253,26 +273,24 @@ void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged(
     const dbus::ObjectPath& object_path,
     const std::string& property_name) {
-  CharacteristicMap::iterator iter = characteristics_.find(object_path);
-  if (iter == characteristics_.end()) {
-    VLOG(2) << "Unknown GATT characteristic property changed: "
-            << object_path.value();
+  if (characteristics_.find(object_path) == characteristics_.end()) {
+    VLOG(3) << "Properties of unknown characteristic changed";
     return;
   }
 
-  // Ignore all property changes except for "Value".
+  // We may receive a property changed event in certain cases, e.g. when the
+  // characteristic "Flags" property has been updated with values from the
+  // "Characteristic Extended Properties" descriptor. In this case, kick off
+  // a service changed observer event to let observers refresh the
+  // characteristics.
   BluetoothGattCharacteristicClient::Properties* properties =
       DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
           GetProperties(object_path);
   DCHECK(properties);
-  if (property_name != properties->value.name())
+  if (property_name != properties->flags.name())
     return;
 
-  VLOG(1) << "GATT characteristic value has changed: " << object_path.value()
-          << ": " << properties->value.value();
-  FOR_EACH_OBSERVER(device::BluetoothGattService::Observer, observers_,
-                    GattCharacteristicValueChanged(this, iter->second,
-                                                   properties->value.value()));
+  NotifyServiceChanged();
 }
 
 }  // namespace chromeos