Fix observer hanging after shudown because the sign in popup was not dismissed.
[chromium-blink-merge.git] / device / bluetooth / bluetooth_remote_gatt_service_chromeos.cc
blobbd243d88046e10755f18aa9fd920873526b5c8cb
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.
5 #include "device/bluetooth/bluetooth_remote_gatt_service_chromeos.h"
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"
16 namespace chromeos {
18 namespace {
20 // TODO(jamuraa) move these to cros_system_api later
21 const char kErrorFailed[] = "org.bluez.Error.Failed";
22 const char kErrorInProgress[] = "org.bluez.Error.InProgress";
23 const char kErrorInvalidValueLength[] = "org.bluez.Error.InvalidValueLength";
24 const char kErrorNotAuthorized[] = "org.bluez.Error.NotAuthorized";
25 const char kErrorNotPaired[] = "org.bluez.Error.NotPaired";
26 const char kErrorNotSupported[] = "org.bluez.Error.NotSupported";
27 const char kErrorReadNotPermitted[] = "org.bluez.Error.ReadNotPermitted";
28 const char kErrorWriteNotPermitted[] = "org.bluez.Error.WriteNotPermitted";
30 } // namespace
32 BluetoothRemoteGattServiceChromeOS::BluetoothRemoteGattServiceChromeOS(
33 BluetoothAdapterChromeOS* adapter,
34 BluetoothDeviceChromeOS* device,
35 const dbus::ObjectPath& object_path)
36 : object_path_(object_path),
37 adapter_(adapter),
38 device_(device),
39 discovery_complete_(false),
40 weak_ptr_factory_(this) {
41 VLOG(1) << "Creating remote GATT service with identifier: "
42 << object_path.value() << ", UUID: " << GetUUID().canonical_value();
43 DCHECK(adapter_);
45 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->AddObserver(this);
46 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
47 AddObserver(this);
49 // Add all known GATT characteristics.
50 const std::vector<dbus::ObjectPath>& gatt_chars =
51 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
52 GetCharacteristics();
53 for (std::vector<dbus::ObjectPath>::const_iterator iter = gatt_chars.begin();
54 iter != gatt_chars.end(); ++iter)
55 GattCharacteristicAdded(*iter);
58 BluetoothRemoteGattServiceChromeOS::~BluetoothRemoteGattServiceChromeOS() {
59 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
60 RemoveObserver(this);
61 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
62 RemoveObserver(this);
64 // Clean up all the characteristics. Copy the characteristics list here and
65 // clear the original so that when we send GattCharacteristicRemoved(),
66 // GetCharacteristics() returns no characteristics.
67 CharacteristicMap characteristics = characteristics_;
68 characteristics_.clear();
69 for (CharacteristicMap::iterator iter = characteristics.begin();
70 iter != characteristics.end(); ++iter) {
71 DCHECK(adapter_);
72 adapter_->NotifyGattCharacteristicRemoved(iter->second);
74 delete iter->second;
78 std::string BluetoothRemoteGattServiceChromeOS::GetIdentifier() const {
79 return object_path_.value();
82 device::BluetoothUUID BluetoothRemoteGattServiceChromeOS::GetUUID() const {
83 BluetoothGattServiceClient::Properties* properties =
84 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
85 GetProperties(object_path_);
86 DCHECK(properties);
87 return device::BluetoothUUID(properties->uuid.value());
90 bool BluetoothRemoteGattServiceChromeOS::IsLocal() const {
91 return false;
94 bool BluetoothRemoteGattServiceChromeOS::IsPrimary() const {
95 BluetoothGattServiceClient::Properties* properties =
96 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->
97 GetProperties(object_path_);
98 DCHECK(properties);
99 return properties->primary.value();
102 device::BluetoothDevice* BluetoothRemoteGattServiceChromeOS::GetDevice() const {
103 return device_;
106 std::vector<device::BluetoothGattCharacteristic*>
107 BluetoothRemoteGattServiceChromeOS::GetCharacteristics() const {
108 std::vector<device::BluetoothGattCharacteristic*> characteristics;
109 for (CharacteristicMap::const_iterator iter = characteristics_.begin();
110 iter != characteristics_.end(); ++iter) {
111 characteristics.push_back(iter->second);
113 return characteristics;
116 std::vector<device::BluetoothGattService*>
117 BluetoothRemoteGattServiceChromeOS::GetIncludedServices() const {
118 // TODO(armansito): Return the actual included services here.
119 return std::vector<device::BluetoothGattService*>();
122 device::BluetoothGattCharacteristic*
123 BluetoothRemoteGattServiceChromeOS::GetCharacteristic(
124 const std::string& identifier) const {
125 CharacteristicMap::const_iterator iter =
126 characteristics_.find(dbus::ObjectPath(identifier));
127 if (iter == characteristics_.end())
128 return NULL;
129 return iter->second;
132 bool BluetoothRemoteGattServiceChromeOS::AddCharacteristic(
133 device::BluetoothGattCharacteristic* characteristic) {
134 VLOG(1) << "Characteristics cannot be added to a remote GATT service.";
135 return false;
138 bool BluetoothRemoteGattServiceChromeOS::AddIncludedService(
139 device::BluetoothGattService* service) {
140 VLOG(1) << "Included services cannot be added to a remote GATT service.";
141 return false;
144 void BluetoothRemoteGattServiceChromeOS::Register(
145 const base::Closure& callback,
146 const ErrorCallback& error_callback) {
147 VLOG(1) << "A remote GATT service cannot be registered.";
148 error_callback.Run();
151 void BluetoothRemoteGattServiceChromeOS::Unregister(
152 const base::Closure& callback,
153 const ErrorCallback& error_callback) {
154 VLOG(1) << "A remote GATT service cannot be unregistered.";
155 error_callback.Run();
158 // static
159 device::BluetoothGattService::GattErrorCode
160 BluetoothRemoteGattServiceChromeOS::DBusErrorToServiceError(
161 std::string error_name) {
162 device::BluetoothGattService::GattErrorCode code = GATT_ERROR_UNKNOWN;
163 if (error_name == kErrorFailed) {
164 code = GATT_ERROR_FAILED;
165 } else if (error_name == kErrorInProgress) {
166 code = GATT_ERROR_IN_PROGRESS;
167 } else if (error_name == kErrorInvalidValueLength) {
168 code = GATT_ERROR_INVALID_LENGTH;
169 } else if (error_name == kErrorReadNotPermitted ||
170 error_name == kErrorWriteNotPermitted) {
171 code = GATT_ERROR_NOT_PERMITTED;
172 } else if (error_name == kErrorNotAuthorized) {
173 code = GATT_ERROR_NOT_AUTHORIZED;
174 } else if (error_name == kErrorNotPaired) {
175 code = GATT_ERROR_NOT_PAIRED;
176 } else if (error_name == kErrorNotSupported) {
177 code = GATT_ERROR_NOT_SUPPORTED;
179 return code;
182 BluetoothAdapterChromeOS*
183 BluetoothRemoteGattServiceChromeOS::GetAdapter() const {
184 return adapter_;
187 void BluetoothRemoteGattServiceChromeOS::NotifyServiceChanged() {
188 // Don't send service changed unless we know that all characteristics have
189 // already been discovered. This is to prevent spammy events before sending
190 // out the first Gatt
191 if (!discovery_complete_)
192 return;
194 DCHECK(adapter_);
195 adapter_->NotifyGattServiceChanged(this);
198 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorAddedOrRemoved(
199 BluetoothRemoteGattCharacteristicChromeOS* characteristic,
200 BluetoothRemoteGattDescriptorChromeOS* descriptor,
201 bool added) {
202 DCHECK(characteristic->GetService() == this);
203 DCHECK(descriptor->GetCharacteristic() == characteristic);
204 DCHECK(adapter_);
206 if (added) {
207 adapter_->NotifyGattDescriptorAdded(descriptor);
208 return;
211 adapter_->NotifyGattDescriptorRemoved(descriptor);
214 void BluetoothRemoteGattServiceChromeOS::NotifyDescriptorValueChanged(
215 BluetoothRemoteGattCharacteristicChromeOS* characteristic,
216 BluetoothRemoteGattDescriptorChromeOS* descriptor,
217 const std::vector<uint8>& value) {
218 DCHECK(characteristic->GetService() == this);
219 DCHECK(descriptor->GetCharacteristic() == characteristic);
220 DCHECK(adapter_);
221 adapter_->NotifyGattDescriptorValueChanged(descriptor, value);
224 void BluetoothRemoteGattServiceChromeOS::GattServicePropertyChanged(
225 const dbus::ObjectPath& object_path,
226 const std::string& property_name){
227 if (object_path != object_path_)
228 return;
230 VLOG(1) << "Service property changed: \"" << property_name << "\", "
231 << object_path.value();
232 BluetoothGattServiceClient::Properties* properties =
233 DBusThreadManager::Get()->GetBluetoothGattServiceClient()->GetProperties(
234 object_path);
235 DCHECK(properties);
237 if (property_name != properties->characteristics.name()) {
238 NotifyServiceChanged();
239 return;
242 if (discovery_complete_)
243 return;
245 VLOG(1) << "All characteristics were discovered for service: "
246 << object_path.value();
247 discovery_complete_ = true;
248 DCHECK(adapter_);
249 adapter_->NotifyGattDiscoveryComplete(this);
252 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicAdded(
253 const dbus::ObjectPath& object_path) {
254 if (characteristics_.find(object_path) != characteristics_.end()) {
255 VLOG(1) << "Remote GATT characteristic already exists: "
256 << object_path.value();
257 return;
260 BluetoothGattCharacteristicClient::Properties* properties =
261 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
262 GetProperties(object_path);
263 DCHECK(properties);
264 if (properties->service.value() != object_path_) {
265 VLOG(2) << "Remote GATT characteristic does not belong to this service.";
266 return;
269 VLOG(1) << "Adding new remote GATT characteristic for GATT service: "
270 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
272 BluetoothRemoteGattCharacteristicChromeOS* characteristic =
273 new BluetoothRemoteGattCharacteristicChromeOS(this, object_path);
274 characteristics_[object_path] = characteristic;
275 DCHECK(characteristic->GetIdentifier() == object_path.value());
276 DCHECK(characteristic->GetUUID().IsValid());
278 DCHECK(adapter_);
279 adapter_->NotifyGattCharacteristicAdded(characteristic);
282 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicRemoved(
283 const dbus::ObjectPath& object_path) {
284 CharacteristicMap::iterator iter = characteristics_.find(object_path);
285 if (iter == characteristics_.end()) {
286 VLOG(2) << "Unknown GATT characteristic removed: " << object_path.value();
287 return;
290 VLOG(1) << "Removing remote GATT characteristic from service: "
291 << GetIdentifier() << ", UUID: " << GetUUID().canonical_value();
293 BluetoothRemoteGattCharacteristicChromeOS* characteristic = iter->second;
294 DCHECK(characteristic->object_path() == object_path);
295 characteristics_.erase(iter);
297 DCHECK(adapter_);
298 adapter_->NotifyGattCharacteristicRemoved(characteristic);
300 delete characteristic;
303 void BluetoothRemoteGattServiceChromeOS::GattCharacteristicPropertyChanged(
304 const dbus::ObjectPath& object_path,
305 const std::string& property_name) {
306 CharacteristicMap::iterator iter = characteristics_.find(object_path);
307 if (iter == characteristics_.end()) {
308 VLOG(3) << "Properties of unknown characteristic changed";
309 return;
312 // We may receive a property changed event in certain cases, e.g. when the
313 // characteristic "Flags" property has been updated with values from the
314 // "Characteristic Extended Properties" descriptor. In this case, kick off
315 // a service changed observer event to let observers refresh the
316 // characteristics.
317 BluetoothGattCharacteristicClient::Properties* properties =
318 DBusThreadManager::Get()->GetBluetoothGattCharacteristicClient()->
319 GetProperties(object_path);
321 DCHECK(properties);
322 DCHECK(adapter_);
324 if (property_name == properties->flags.name())
325 NotifyServiceChanged();
326 else if (property_name == properties->value.name())
327 adapter_->NotifyGattCharacteristicValueChanged(iter->second,
328 properties->value.value());
331 } // namespace chromeos