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