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