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 |