Home | History | Annotate | Download | only in bluetooth
      1 // Copyright 2014 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/strings/stringprintf.h"
      9 #include "chromeos/dbus/bluetooth_gatt_service_client.h"
     10 #include "chromeos/dbus/dbus_thread_manager.h"
     11 #include "device/bluetooth/bluetooth_adapter_chromeos.h"
     12 #include "device/bluetooth/bluetooth_device_chromeos.h"
     13 #include "device/bluetooth/bluetooth_remote_gatt_characteristic_chromeos.h"
     14 #include "device/bluetooth/bluetooth_remote_gatt_descriptor_chromeos.h"
     15 
     16 namespace chromeos {
     17 
     18 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS(
     19     BluetoothAdapterChromeOS* adapter,
     20     BluetoothDeviceChromeOS* device,
     21     const dbus::ObjectPath& object_path)
     22     : object_path_(object_path),
     23       adapter_(adapter),
     24       device_(device),
     25       discovery_complete_(false),
     26       weak_ptr_factory_(this) {
     27   VLOG(1) << "Creating remote GATT service with identifier: "
     28           << object_path.value() << ", UUID: " << GetUUID().canonical_value();
     29   DCHECK(adapter_);
     30 
     31   DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
     32   DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
     33       AddObserver(this);
     34 
     35   // Add all known GATT characteristics.
     36   const std::vector<dbus::ObjectPath>& gatt_chars =
     37       DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
     38           GetCharacteristics();
     39   for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin();
     40        iter != gatt_chars.end(); ++iter)
     41     GattCharacteristicAdded(*iter);
     42 }
     43 
     44 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
     45   DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
     46       RemoveObserver(this);
     47   DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
     48       RemoveObserver(this);
     49 
     50   // Clean up all the characteristics. Copy the characteristics list here and
     51   // clear the original so that when we send GattCharacteristicRemoved(),
     52   // GetCharacteristics() returns no characteristics.
     53   CharacteristicMap characteristics = characteristics_;
     54   characteristics_.clear();
     55   for (CharacteristicMap::iterator iter = characteristics.begin();
     56        iter != characteristics.end(); ++iter) {
     57     DCHECK(adapter_);
     58     adapter_->NotifyGattCharacteristicRemoved(iter->second);
     59 
     60     delete iter->second;
     61   }
     62 }
     63 
     64 std::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const {
     65   return object_path_.value();
     66 }
     67 
     68 device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const {
     69   BluetoothGattServiceClient::Properties* properties =
     70       DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
     71           GetProperties(object_path_);
     72   DCHECK(properties);
     73   return device::BluetoothUUID(properties->uuid.value());
     74 }
     75 
     76 bool BluetoothRemoteGattServiceChromeOS::IsLocal() const {
     77   return false;
     78 }
     79 
     80 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const {
     81   BluetoothGattServiceClient::Properties* properties =
     82       DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
     83           GetProperties(object_path_);
     84   DCHECK(properties);
     85   return properties->primary.value();
     86 }
     87 
     88 device::BluetoothDevice* BluetoothRemoteGattServiceChromeOS::GetDevice() const {
     89   return device_;
     90 }
     91 
     92 std::vector<device::BluetoothGattCharacteristic*>
     93 BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const {
     94   std::vector<device::BluetoothGattCharacteristic*> characteristics;
     95   for (CharacteristicMap::const_iterator iter = characteristics_.begin();
     96        iter != characteristics_.end(); ++iter) {
     97     characteristics.push_back(iter->second);
     98   }
     99   return characteristics;
    100 }
    101 
    102 std::vector<device::BluetoothGattService*>
    103 BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const {
    104   // TODO(armansito): Return the actual included services here.
    105   return std::vector<device::BluetoothGattService*>();
    106 }
    107 
    108 device::BluetoothGattCharacteristic*
    109 BluetoothRemoteGattServiceChromeOS::GetCharacteristic(
    110     const std::string& identifier) const {
    111   CharacteristicMap::const_iterator iter =
    112       characteristics_.find(dbus::ObjectPath(identifier));
    113   if (iter == characteristics_.end())
    114     return NULL;
    115   return iter->second;
    116 }
    117 
    118 bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic(
    119     device::BluetoothGattCharacteristic* characteristic) {
    120   VLOG(1) << "Characteristics cannot be added to a remote GATT service.";
    121   return false;
    122 }
    123 
    124 bool BluetoothRemoteGattServiceChromeOS::AddIncludedService(
    125     device::BluetoothGattService* service) {
    126   VLOG(1) << "Included services cannot be added to a remote GATT service.";
    127   return false;
    128 }
    129 
    130 void BluetoothRemoteGattServiceChromeOS::Register(
    131     const base::Closure& callback,
    132     const ErrorCallback& error_callback) {
    133   VLOG(1) << "A remote GATT service cannot be registered.";
    134   error_callback.Run();
    135 }
    136 
    137 void BluetoothRemoteGattServiceChromeOS::Unregister(
    138     const base::Closure& callback,
    139     const ErrorCallback& error_callback) {
    140   VLOG(1) << "A remote GATT service cannot be unregistered.";
    141   error_callback.Run();
    142 }
    143 
    144 BluetoothAdapterChromeOS*
    145 BluetoothRemoteGattServiceChromeOS::GetAdapter() const {
    146   return adapter_;
    147 }
    148 
    149 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() {
    150   // Don't send service changed unless we know that all characteristics have
    151   // already been discovered. This is to prevent spammy events before sending
    152   // out the first Gatt
    153   if (!discovery_complete_)
    154     return;
    155 
    156   DCHECK(adapter_);
    157   adapter_->NotifyGattServiceChanged(this);
    158 }
    159 
    160 void BluetoothRemoteGattServiceChromeOS::NotifyCharacteristicValueChanged(
    161     BluetoothRemoteGattCharacteristicChromeOS* characteristic,
    162     const std::vector<uint8>& value) {
    163   DCHECK(characteristic->GetService() == this);
    164   DCHECK(adapter_);
    165   adapter_->NotifyGattCharacteristicValueChanged(characteristic, value);
    166 }
    167 
    168 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
    169     BluetoothRemoteGattCharacteristicChromeOS* characteristic,
    170     BluetoothRemoteGattDescriptorChromeOS* descriptor,
    171     bool added) {
    172   DCHECK(characteristic->GetService() == this);
    173   DCHECK(descriptor->GetCharacteristic() == characteristic);
    174   DCHECK(adapter_);
    175 
    176   if (added) {
    177     adapter_->NotifyGattDescriptorAdded(descriptor);
    178     return;
    179   }
    180 
    181   adapter_->NotifyGattDescriptorRemoved(descriptor);
    182 }
    183 
    184 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
    185     BluetoothRemoteGattCharacteristicChromeOS* characteristic,
    186     BluetoothRemoteGattDescriptorChromeOS* descriptor,
    187     const std::vector<uint8>& value) {
    188   DCHECK(characteristic->GetService() == this);
    189   DCHECK(descriptor->GetCharacteristic() == characteristic);
    190   DCHECK(adapter_);
    191   adapter_->NotifyGattDescriptorValueChanged(descriptor, value);
    192 }
    193 
    194 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged(
    195     const dbus::ObjectPath& object_path,
    196     const std::string& property_name){
    197   if (object_path != object_path_)
    198     return;
    199 
    200   VLOG(1) << "Service property changed: \"" << property_name << "\", "
    201           << object_path.value();
    202   BluetoothGattServiceClient::Properties* properties =
    203       DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
    204           object_path);
    205   DCHECK(properties);
    206 
    207   if (property_name != properties->characteristics.name()) {
    208     NotifyServiceChanged();
    209     return;
    210   }
    211 
    212   if (discovery_complete_)
    213     return;
    214 
    215   VLOG(1) << "All characteristics were discovered for service: "
    216           << object_path.value();
    217   discovery_complete_ = true;
    218   DCHECK(adapter_);
    219   adapter_->NotifyGattDiscoveryComplete(this);
    220 }
    221 
    222 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
    223     const dbus::ObjectPath& object_path) {
    224   if (characteristics_.find(object_path) != characteristics_.end()) {
    225     VLOG(1) << "Remote GATT characteristic already exists: "
    226             << object_path.value();
    227     return;
    228   }
    229 
    230   BluetoothGattCharacteristicClient::Properties* properties =
    231       DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
    232           GetProperties(object_path);
    233   DCHECK(properties);
    234   if (properties->service.value() != object_path_) {
    235     VLOG(2) << "Remote GATT characteristic does not belong to this service.";
    236     return;
    237   }
    238 
    239   VLOG(1) << "Adding new remote GATT characteristic for GATT service: "
    240           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
    241 
    242   BluetoothRemoteGattCharacteristicChromeOS* characteristic =
    243       new BluetoothRemoteGattCharacteristicChromeOS(this, object_path);
    244   characteristics_[object_path] = characteristic;
    245   DCHECK(characteristic->GetIdentifier() == object_path.value());
    246   DCHECK(characteristic->GetUUID().IsValid());
    247 
    248   DCHECK(adapter_);
    249   adapter_->NotifyGattCharacteristicAdded(characteristic);
    250 }
    251 
    252 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
    253     const dbus::ObjectPath& object_path) {
    254   CharacteristicMap::iterator iter = characteristics_.find(object_path);
    255   if (iter == characteristics_.end()) {
    256     VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value();
    257     return;
    258   }
    259 
    260   VLOG(1) << "Removing remote GATT characteristic from service: "
    261           << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
    262 
    263   BluetoothRemoteGattCharacteristicChromeOS* characteristic = iter->second;
    264   DCHECK(characteristic->object_path() == object_path);
    265   characteristics_.erase(iter);
    266 
    267   DCHECK(adapter_);
    268   adapter_->NotifyGattCharacteristicRemoved(characteristic);
    269 
    270   delete characteristic;
    271 }
    272 
    273 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged(
    274     const dbus::ObjectPath& object_path,
    275     const std::string& property_name) {
    276   if (characteristics_.find(object_path) == characteristics_.end()) {
    277     VLOG(3) << "Properties of unknown characteristic changed";
    278     return;
    279   }
    280 
    281   // We may receive a property changed event in certain cases, e.g. when the
    282   // characteristic "Flags" property has been updated with values from the
    283   // "Characteristic Extended Properties" descriptor. In this case, kick off
    284   // a service changed observer event to let observers refresh the
    285   // characteristics.
    286   BluetoothGattCharacteristicClient::Properties* properties =
    287       DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
    288           GetProperties(object_path);
    289   DCHECK(properties);
    290   if (property_name != properties->flags.name())
    291     return;
    292 
    293   NotifyServiceChanged();
    294 }
    295 
    296 }  // namespace chromeos
    297