// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef DEVICE_NFC_NFC_ADAPTER_H_
#define DEVICE_NFC_NFC_ADAPTER_H_
#include <map>
#include <string>
#include <vector>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
namespace device {
class NfcPeer;
class NfcTag;
// NfcAdapter represents a local NFC adapter which may be used to interact with
// NFC tags and remote NFC adapters on platforms that support NFC. Through
// instances of this class, users can obtain important information such as if
// and/or when an adapter is present, supported NFC technologies, and the
// adapter's power and polling state. NfcAdapter instances can be used to power
// up/down the NFC adapter and its Observer interface allows users to get
// notified when new adapters are added/removed and when remote NFC tags and
// devices were detected or lost.
//
// A system can contain more than one NFC adapter (e.g. external USB adapters)
// but Chrome will have only one NfcAdapter instance. This instance will do
// its best to represent all underlying adapters but will only allow
// interacting with only one at a given time. If the currently represented
// adapter is removed from the system, the NfcAdapter instance will update to
// reflect the information from the next available adapter.
class NfcAdapter : public base::RefCounted<NfcAdapter> {
public:
// Interface for observing changes from NFC adapters.
class Observer {
public:
virtual ~Observer() {}
// Called when the presence of the adapter |adapter| changes. When |present|
// is true, this indicates that the adapter has now become present, while a
// value of false indicates that the adapter is no longer available on the
// current system.
virtual void AdapterPresentChanged(NfcAdapter* adapter, bool present) {}
// Called when the radio power state of the adapter |adapter| changes. If
// |powered| is true, the adapter radio is turned on, otherwise it's turned
// off.
virtual void AdapterPoweredChanged(NfcAdapter* adapter, bool powered) {}
// Called when the "polling" state of the adapter |adapter| changes. If
// |polling| is true, the adapter is currently polling for remote tags and
// devices. If false, the adapter isn't polling, either because a poll loop
// was never started or because a connection with a tag or peer has been
// established.
virtual void AdapterPollingChanged(NfcAdapter* adapter, bool polling) {}
// Called when an NFC tag |tag| has been found by the adapter |adapter|.
// The observer can use this method to take further action on the tag object
// |tag|, such as reading its records or writing to it. While |tag| will be
// valid within the context of this call, its life-time cannot be guaranteed
// once this call returns, as the object may get destroyed if the connection
// with the tag is lost. Instead of caching the pointer directly, observers
// should store the tag's assigned unique identifier instead, which can be
// used to obtain a pointer to the tag, as long as it exists.
virtual void TagFound(NfcAdapter* adapter, NfcTag* tag) {}
// Called when the NFC tag |tag| is no longer known by the adapter
// |adapter|. |tag| should not be cached.
virtual void TagLost(NfcAdapter* adapter, NfcTag* tag) {}
// Called when a remote NFC adapter |peer| has been detected, which is
// available for peer-to-peer communication over NFC. The observer can use
// this method to take further action on |peer| such as reading its records
// or pushing NDEFs to it. While |peer| will be valid within the context of
// this call, its life-time cannot be guaranteed once this call returns, as
// the object may get destroyed if the connection with the peer is lost.
// Instead of caching the pointer directly, observers should store the
// peer's assigned unique identifier instead, which can be used to obtain a
// pointer to the peer, as long as it exists.
virtual void PeerFound(NfcAdapter* adaper, NfcPeer* peer) {}
// Called when the remote NFC adapter |peer| is no longer known by the
// adapter |adapter|. |peer| should not be cached.
virtual void PeerLost(NfcAdapter* adapter, NfcPeer* peer) {}
};
// The ErrorCallback is used by methods to asynchronously report errors.
typedef base::Closure ErrorCallback;
// Typedefs for lists of NFC peer and NFC tag objects.
typedef std::vector<NfcPeer*> PeerList;
typedef std::vector<NfcTag*> TagList;
// Adds and removes observers for events on this NFC adapter. If monitoring
// multiple adapters, check the |adapter| parameter of observer methods to
// determine which adapter is issuing the event.
virtual void AddObserver(Observer* observer) = 0;
virtual void RemoveObserver(Observer* observer) = 0;
// Indicates whether an underlying adapter is actually present on the
// system. An adapter that was previously present can become no longer
// present, for example, if all physical adapters that can back it up were
// removed from the system.
virtual bool IsPresent() const = 0;
// Indicates whether the adapter radio is powered.
virtual bool IsPowered() const = 0;
// Indicates whether the adapter is polling for remote NFC tags and peers.
virtual bool IsPolling() const = 0;
// Indicates whether the NfcAdapter instance is initialized and ready to use.
virtual bool IsInitialized() const = 0;
// Requests a change to the adapter radio power. Setting |powered| to true
// will turn on the radio and false will turn it off. On success, |callback|
// will be invoked. On failure, |error_callback| will be invoked, which can
// happen if the radio power is already in the requested state, or if the
// underlying adapter is not present.
virtual void SetPowered(bool powered,
const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// Requests the adapter to begin its poll loop to start looking for remote
// NFC tags and peers. On success, |callback| will be invoked. On failure,
// |error_callback| will be invoked. This method can fail for various
// reasons, including:
// - The adapter radio is not powered.
// - The adapter is already polling.
// - The adapter is busy; it has already established a connection to a
// remote tag or peer.
// Bear in mind that this method may be called by multiple users of the same
// adapter.
virtual void StartPolling(const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// Requests the adapter to stop its current poll loop. On success, |callback|
// will be invoked. On failure, |error_callback| will be invoked. This method
// can fail if the adapter is not polling when this method was called. Bear
// in mind that this method may be called by multiple users of the same
// adapter and polling may not actually stop if other callers have called
// StartPolling() in the mean time.
virtual void StopPolling(const base::Closure& callback,
const ErrorCallback& error_callback) = 0;
// Returns a list containing all known peers in |peer_list|. If |peer_list|
// was non-empty at the time of the call, it will be cleared. The contents of
// |peer_list| at the end of this call are owned by the adapter.
virtual void GetPeers(PeerList* peer_list) const;
// Returns a list containing all known tags in |tag_list|. If |tag_list| was
// non-empty at the time of the call, it will be cleared. The contents of
// |tag_list| at the end of this call are owned by the adapter.
virtual void GetTags(TagList* tag_list) const;
// Returns a pointer to the peer with the given identifier |identifier| or
// NULL if no such peer is known. If a non-NULL pointer is returned, the
// instance that it points to is owned by this adapter.
virtual NfcPeer* GetPeer(const std::string& identifier) const;
// Returns a pointer to the tag with the given identifier |identifier| or
// NULL if no such tag is known. If a non-NULL pointer is returned, the
// instance that it points to is owned by this adapter.
virtual NfcTag* GetTag(const std::string& identifier) const;
protected:
friend class base::RefCounted<NfcAdapter>;
// The default constructor does nothing. The destructor deletes all known
// NfcPeer and NfcTag instances.
NfcAdapter();
virtual ~NfcAdapter();
// Peers and tags that have been found. The key is the unique identifier
// assigned to the peer or tag and the value is a pointer to the
// corresponding NfcPeer or NfcTag object, whose lifetime is managed by the
// adapter instance.
typedef std::map<const std::string, NfcPeer*> PeersMap;
typedef std::map<const std::string, NfcTag*> TagsMap;
// Set the given tag or peer for |identifier|. If a tag or peer for
// |identifier| already exists, these methods won't do anything.
void SetTag(const std::string& identifier, NfcTag* tag);
void SetPeer(const std::string& identifier, NfcPeer* peer);
// Removes the tag or peer for |identifier| and returns the removed object.
// Returns NULL, if no tag or peer for |identifier| was found.
NfcTag* RemoveTag(const std::string& identifier);
NfcPeer* RemovePeer(const std::string& identifier);
// Clear the peer and tag maps. These methods won't delete the tag and peer
// objects, however after the call to these methods, the peers and tags won't
// be returned via calls to GetPeers and GetTags.
void ClearTags();
void ClearPeers();
private:
// Peers and tags that are managed by this adapter.
PeersMap peers_;
TagsMap tags_;
DISALLOW_COPY_AND_ASSIGN(NfcAdapter);
};
} // namespace device
#endif // DEVICE_NFC_NFC_ADAPTER_H_