| OLD | NEW |
| (Empty) |
| 1 // Copyright 2013 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/nfc/nfc_adapter_chromeos.h" | |
| 6 | |
| 7 #include <vector> | |
| 8 | |
| 9 #include "base/callback.h" | |
| 10 #include "base/logging.h" | |
| 11 #include "chromeos/dbus/dbus_thread_manager.h" | |
| 12 #include "device/nfc/nfc_peer_chromeos.h" | |
| 13 #include "device/nfc/nfc_tag_chromeos.h" | |
| 14 #include "third_party/cros_system_api/dbus/service_constants.h" | |
| 15 | |
| 16 namespace chromeos { | |
| 17 | |
| 18 namespace { | |
| 19 | |
| 20 typedef std::vector<dbus::ObjectPath> ObjectPathVector; | |
| 21 | |
| 22 } // namespace | |
| 23 | |
| 24 NfcAdapterChromeOS::NfcAdapterChromeOS() | |
| 25 : weak_ptr_factory_(this) { | |
| 26 DBusThreadManager::Get()->GetNfcAdapterClient()->AddObserver(this); | |
| 27 DBusThreadManager::Get()->GetNfcDeviceClient()->AddObserver(this); | |
| 28 DBusThreadManager::Get()->GetNfcTagClient()->AddObserver(this); | |
| 29 | |
| 30 const ObjectPathVector& object_paths = | |
| 31 DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters(); | |
| 32 if (!object_paths.empty()) { | |
| 33 VLOG(1) << object_paths.size() << " NFC adapter(s) available."; | |
| 34 SetAdapter(object_paths[0]); | |
| 35 } | |
| 36 } | |
| 37 | |
| 38 NfcAdapterChromeOS::~NfcAdapterChromeOS() { | |
| 39 DBusThreadManager::Get()->GetNfcAdapterClient()->RemoveObserver(this); | |
| 40 DBusThreadManager::Get()->GetNfcDeviceClient()->RemoveObserver(this); | |
| 41 DBusThreadManager::Get()->GetNfcTagClient()->RemoveObserver(this); | |
| 42 } | |
| 43 | |
| 44 void NfcAdapterChromeOS::AddObserver(NfcAdapter::Observer* observer) { | |
| 45 DCHECK(observer); | |
| 46 observers_.AddObserver(observer); | |
| 47 } | |
| 48 | |
| 49 void NfcAdapterChromeOS::RemoveObserver(NfcAdapter::Observer* observer) { | |
| 50 DCHECK(observer); | |
| 51 observers_.RemoveObserver(observer); | |
| 52 } | |
| 53 | |
| 54 bool NfcAdapterChromeOS::IsPresent() const { | |
| 55 return !object_path_.value().empty(); | |
| 56 } | |
| 57 | |
| 58 bool NfcAdapterChromeOS::IsPowered() const { | |
| 59 if (!IsPresent()) | |
| 60 return false; | |
| 61 return DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 62 GetProperties(object_path_)->powered.value(); | |
| 63 } | |
| 64 | |
| 65 bool NfcAdapterChromeOS::IsPolling() const { | |
| 66 if (!IsPresent()) | |
| 67 return false; | |
| 68 return DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 69 GetProperties(object_path_)->polling.value(); | |
| 70 } | |
| 71 | |
| 72 bool NfcAdapterChromeOS::IsInitialized() const { | |
| 73 return true; | |
| 74 } | |
| 75 | |
| 76 void NfcAdapterChromeOS::SetPowered(bool powered, | |
| 77 const base::Closure& callback, | |
| 78 const ErrorCallback& error_callback) { | |
| 79 if (!IsPresent()) { | |
| 80 LOG(WARNING) << "Adapter not present. Cannot power up the antenna."; | |
| 81 error_callback.Run(); | |
| 82 return; | |
| 83 } | |
| 84 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 85 GetProperties(object_path_)->powered.Set( | |
| 86 powered, | |
| 87 base::Bind(&NfcAdapterChromeOS::OnSetPowered, | |
| 88 weak_ptr_factory_.GetWeakPtr(), | |
| 89 callback, | |
| 90 error_callback)); | |
| 91 } | |
| 92 | |
| 93 void NfcAdapterChromeOS::StartPolling(const base::Closure& callback, | |
| 94 const ErrorCallback& error_callback) { | |
| 95 // Always poll in "Initiator" mode. | |
| 96 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 97 StartPollLoop(object_path_, | |
| 98 nfc_adapter::kModeInitiator, | |
| 99 base::Bind(&NfcAdapterChromeOS::OnStartPolling, | |
| 100 weak_ptr_factory_.GetWeakPtr(), | |
| 101 callback), | |
| 102 base::Bind(&NfcAdapterChromeOS::OnStartPollingError, | |
| 103 weak_ptr_factory_.GetWeakPtr(), | |
| 104 error_callback)); | |
| 105 } | |
| 106 | |
| 107 void NfcAdapterChromeOS::StopPolling(const base::Closure& callback, | |
| 108 const ErrorCallback& error_callback) { | |
| 109 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 110 StopPollLoop(object_path_, | |
| 111 base::Bind(&NfcAdapterChromeOS::OnStopPolling, | |
| 112 weak_ptr_factory_.GetWeakPtr(), | |
| 113 callback), | |
| 114 base::Bind(&NfcAdapterChromeOS::OnStopPollingError, | |
| 115 weak_ptr_factory_.GetWeakPtr(), | |
| 116 error_callback)); | |
| 117 } | |
| 118 | |
| 119 void NfcAdapterChromeOS::AdapterAdded(const dbus::ObjectPath& object_path) { | |
| 120 // Set the adapter to the newly added adapter only if no adapter is present. | |
| 121 if (!IsPresent()) | |
| 122 SetAdapter(object_path); | |
| 123 } | |
| 124 | |
| 125 void NfcAdapterChromeOS::AdapterRemoved(const dbus::ObjectPath& object_path) { | |
| 126 if (object_path != object_path_) | |
| 127 return; | |
| 128 | |
| 129 // The current adapter was removed, so mark us as not present and clean up | |
| 130 // peers and tags. | |
| 131 RemoveAdapter(); | |
| 132 | |
| 133 // There may still be other adapters present on the system. Set the next | |
| 134 // available adapter as the current one. | |
| 135 const ObjectPathVector& object_paths = | |
| 136 DBusThreadManager::Get()->GetNfcAdapterClient()->GetAdapters(); | |
| 137 for (ObjectPathVector::const_iterator iter = | |
| 138 object_paths.begin(); | |
| 139 iter != object_paths.end(); ++iter) { | |
| 140 // The removed object will still be available until the call to | |
| 141 // AdapterRemoved returns. Make sure that we are not re-adding the | |
| 142 // removed adapter. | |
| 143 if (*iter == object_path) | |
| 144 continue; | |
| 145 SetAdapter(*iter); | |
| 146 } | |
| 147 } | |
| 148 | |
| 149 void NfcAdapterChromeOS::AdapterPropertyChanged( | |
| 150 const dbus::ObjectPath& object_path, | |
| 151 const std::string& property_name) { | |
| 152 if (object_path != object_path_) | |
| 153 return; | |
| 154 NfcAdapterClient::Properties* properties = | |
| 155 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 156 GetProperties(object_path_); | |
| 157 if (property_name == properties->powered.name()) | |
| 158 PoweredChanged(properties->powered.value()); | |
| 159 else if (property_name == properties->polling.name()) | |
| 160 PollingChanged(properties->polling.value()); | |
| 161 } | |
| 162 | |
| 163 void NfcAdapterChromeOS::DeviceAdded(const dbus::ObjectPath& object_path) { | |
| 164 if (!IsPresent()) | |
| 165 return; | |
| 166 | |
| 167 if (GetPeer(object_path.value())) | |
| 168 return; | |
| 169 | |
| 170 VLOG(1) << "NFC device found: " << object_path.value(); | |
| 171 | |
| 172 // Check to see if the device belongs to this adapter. | |
| 173 const ObjectPathVector& devices = | |
| 174 DBusThreadManager::Get()->GetNfcDeviceClient()-> | |
| 175 GetDevicesForAdapter(object_path_); | |
| 176 bool device_found = false; | |
| 177 for (ObjectPathVector::const_iterator iter = devices.begin(); | |
| 178 iter != devices.end(); ++iter) { | |
| 179 if (*iter == object_path) { | |
| 180 device_found = true; | |
| 181 break; | |
| 182 } | |
| 183 } | |
| 184 if (!device_found) { | |
| 185 VLOG(1) << "Found peer device does not belong to the current adapter."; | |
| 186 return; | |
| 187 } | |
| 188 | |
| 189 // Create the peer object. | |
| 190 NfcPeerChromeOS* peer_chromeos = new NfcPeerChromeOS(object_path); | |
| 191 SetPeer(object_path.value(), peer_chromeos); | |
| 192 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 193 PeerFound(this, peer_chromeos)); | |
| 194 } | |
| 195 | |
| 196 void NfcAdapterChromeOS::DeviceRemoved(const dbus::ObjectPath& object_path) { | |
| 197 VLOG(1) << "NFC device lost: " << object_path.value(); | |
| 198 device::NfcPeer* peer = RemovePeer(object_path.value()); | |
| 199 if (!peer) { | |
| 200 VLOG(1) << "Removed peer device does not belong to the current adapter."; | |
| 201 return; | |
| 202 } | |
| 203 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, PeerLost(this, peer)); | |
| 204 delete peer; | |
| 205 } | |
| 206 | |
| 207 void NfcAdapterChromeOS::TagAdded(const dbus::ObjectPath& object_path) { | |
| 208 if (!IsPresent()) | |
| 209 return; | |
| 210 | |
| 211 if (GetTag(object_path.value())) | |
| 212 return; | |
| 213 | |
| 214 VLOG(1) << "NFC tag found: " << object_path.value(); | |
| 215 | |
| 216 // Check to see if the tag belongs to this adapter. | |
| 217 const std::vector<dbus::ObjectPath>& tags = | |
| 218 DBusThreadManager::Get()->GetNfcTagClient()-> | |
| 219 GetTagsForAdapter(object_path_); | |
| 220 bool tag_found = false; | |
| 221 for (std::vector<dbus::ObjectPath>::const_iterator iter = tags.begin(); | |
| 222 iter != tags.end(); ++iter) { | |
| 223 if (*iter == object_path) { | |
| 224 tag_found = true; | |
| 225 break; | |
| 226 } | |
| 227 } | |
| 228 if (!tag_found) { | |
| 229 VLOG(1) << "Found tag does not belong to the current adapter."; | |
| 230 return; | |
| 231 } | |
| 232 | |
| 233 // Create the tag object. | |
| 234 NfcTagChromeOS* tag_chromeos = new NfcTagChromeOS(object_path); | |
| 235 SetTag(object_path.value(), tag_chromeos); | |
| 236 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 237 TagFound(this, tag_chromeos)); | |
| 238 } | |
| 239 | |
| 240 void NfcAdapterChromeOS::TagRemoved(const dbus::ObjectPath& object_path) { | |
| 241 VLOG(1) << "NFC tag lost : " << object_path.value(); | |
| 242 device::NfcTag* tag = RemoveTag(object_path.value()); | |
| 243 if (!tag) { | |
| 244 VLOG(1) << "Removed tag does not belong to the current adapter."; | |
| 245 return; | |
| 246 } | |
| 247 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, TagLost(this, tag)); | |
| 248 delete tag; | |
| 249 } | |
| 250 | |
| 251 void NfcAdapterChromeOS::SetAdapter(const dbus::ObjectPath& object_path) { | |
| 252 DCHECK(!IsPresent()); | |
| 253 object_path_ = object_path; | |
| 254 VLOG(1) << "Using NFC adapter: " << object_path.value(); | |
| 255 | |
| 256 NfcAdapterClient::Properties* properties = | |
| 257 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 258 GetProperties(object_path_); | |
| 259 PresentChanged(true); | |
| 260 if (properties->powered.value()) | |
| 261 PoweredChanged(true); | |
| 262 if (properties->polling.value()) | |
| 263 PollingChanged(true); | |
| 264 | |
| 265 // Create peer objects for peers that were added before the adapter was set. | |
| 266 const ObjectPathVector& devices = | |
| 267 DBusThreadManager::Get()->GetNfcDeviceClient()-> | |
| 268 GetDevicesForAdapter(object_path_); | |
| 269 for (ObjectPathVector::const_iterator iter = devices.begin(); | |
| 270 iter != devices.end(); ++iter) { | |
| 271 const dbus::ObjectPath& object_path = *iter; | |
| 272 if (GetPeer(object_path.value())) | |
| 273 continue; | |
| 274 NfcPeerChromeOS* peer_chromeos = new NfcPeerChromeOS(object_path); | |
| 275 SetPeer(object_path.value(), peer_chromeos); | |
| 276 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 277 PeerFound(this, peer_chromeos)); | |
| 278 } | |
| 279 | |
| 280 // Create tag objects for tags that were added before the adapter was set. | |
| 281 const std::vector<dbus::ObjectPath>& tags = | |
| 282 DBusThreadManager::Get()->GetNfcTagClient()-> | |
| 283 GetTagsForAdapter(object_path_); | |
| 284 for (std::vector<dbus::ObjectPath>::const_iterator iter = tags.begin(); | |
| 285 iter != tags.end(); ++iter) { | |
| 286 const dbus::ObjectPath& object_path = *iter; | |
| 287 if (GetTag(object_path.value())) | |
| 288 continue; | |
| 289 NfcTagChromeOS* tag_chromeos = new NfcTagChromeOS(object_path); | |
| 290 SetTag(object_path.value(), tag_chromeos); | |
| 291 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 292 TagFound(this, tag_chromeos)); | |
| 293 } | |
| 294 } | |
| 295 | |
| 296 void NfcAdapterChromeOS::RemoveAdapter() { | |
| 297 DCHECK(IsPresent()); | |
| 298 VLOG(1) << "NFC adapter removed: " << object_path_.value(); | |
| 299 | |
| 300 NfcAdapterClient::Properties* properties = | |
| 301 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 302 GetProperties(object_path_); | |
| 303 if (properties->powered.value()) | |
| 304 PoweredChanged(false); | |
| 305 if (properties->polling.value()) | |
| 306 PollingChanged(false); | |
| 307 | |
| 308 // Copy the tags and peers here and clear the original containers so that | |
| 309 // GetPeers and GetTags return no values during the *Removed observer calls. | |
| 310 PeerList peers; | |
| 311 TagList tags; | |
| 312 GetPeers(&peers); | |
| 313 GetTags(&tags); | |
| 314 ClearPeers(); | |
| 315 ClearTags(); | |
| 316 | |
| 317 for (PeerList::iterator iter = peers.begin(); | |
| 318 iter != peers.end(); ++iter) { | |
| 319 device::NfcPeer* peer = *iter; | |
| 320 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 321 PeerLost(this, peer)); | |
| 322 delete peer; | |
| 323 } | |
| 324 for (TagList::iterator iter = tags.begin(); | |
| 325 iter != tags.end(); ++iter) { | |
| 326 device::NfcTag* tag = *iter; | |
| 327 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 328 TagLost(this, tag)); | |
| 329 delete tag; | |
| 330 } | |
| 331 | |
| 332 object_path_ = dbus::ObjectPath(""); | |
| 333 PresentChanged(false); | |
| 334 } | |
| 335 | |
| 336 void NfcAdapterChromeOS::PoweredChanged(bool powered) { | |
| 337 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 338 AdapterPoweredChanged(this, powered)); | |
| 339 } | |
| 340 | |
| 341 void NfcAdapterChromeOS::PollingChanged(bool polling) { | |
| 342 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 343 AdapterPollingChanged(this, polling)); | |
| 344 } | |
| 345 | |
| 346 void NfcAdapterChromeOS::PresentChanged(bool present) { | |
| 347 FOR_EACH_OBSERVER(NfcAdapter::Observer, observers_, | |
| 348 AdapterPresentChanged(this, present)); | |
| 349 } | |
| 350 | |
| 351 void NfcAdapterChromeOS::OnSetPowered(const base::Closure& callback, | |
| 352 const ErrorCallback& error_callback, | |
| 353 bool success) { | |
| 354 VLOG(1) << "NfcAdapterChromeOS::OnSetPowered result: " << success; | |
| 355 if (success) { | |
| 356 // TODO(armansito): There is a bug in neard 0.13 that causes it not to emit | |
| 357 // a signal when the "Powered" property changes. Sync the properties here, | |
| 358 // but remove it in neard 0.14. | |
| 359 if (IsPresent()) { | |
| 360 DBusThreadManager::Get()->GetNfcAdapterClient()-> | |
| 361 GetProperties(object_path_)->GetAll(); | |
| 362 } | |
| 363 callback.Run(); | |
| 364 } else { | |
| 365 LOG(ERROR) << "Failed to power up the NFC antenna radio."; | |
| 366 error_callback.Run(); | |
| 367 } | |
| 368 } | |
| 369 | |
| 370 void NfcAdapterChromeOS::OnStartPolling(const base::Closure& callback) { | |
| 371 callback.Run(); | |
| 372 } | |
| 373 | |
| 374 void NfcAdapterChromeOS::OnStartPollingError( | |
| 375 const ErrorCallback& error_callback, | |
| 376 const std::string& error_name, | |
| 377 const std::string& error_message) { | |
| 378 LOG(ERROR) << object_path_.value() << ": Failed to start polling: " | |
| 379 << error_name << ": " << error_message; | |
| 380 error_callback.Run(); | |
| 381 } | |
| 382 | |
| 383 void NfcAdapterChromeOS::OnStopPolling(const base::Closure& callback) { | |
| 384 callback.Run(); | |
| 385 } | |
| 386 | |
| 387 void NfcAdapterChromeOS::OnStopPollingError( | |
| 388 const ErrorCallback& error_callback, | |
| 389 const std::string& error_name, | |
| 390 const std::string& error_message) { | |
| 391 LOG(ERROR) << object_path_.value() << ": Failed to stop polling: " | |
| 392 << error_name << ": " << error_message; | |
| 393 error_callback.Run(); | |
| 394 } | |
| 395 | |
| 396 } // namespace chromeos | |
| OLD | NEW |