#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);
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();
}
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(
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(
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(
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(
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;
}
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