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