Add NFC reader-mode API.
Allows applications to temporarily force the NFC controller
to only do tag discovery. This will allow Android applications
to read and interact with devices that employ HCE.
Bug: 10360259
Change-Id: I709ead9a26f8e6ae8582cc295d82bd896e7c5bba
diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java
index 10183c0..d0d943c 100644
--- a/core/java/android/nfc/NfcActivityManager.java
+++ b/core/java/android/nfc/NfcActivityManager.java
@@ -19,6 +19,7 @@
import android.app.Activity;
import android.app.Application;
import android.net.Uri;
+import android.os.Binder;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
@@ -111,6 +112,9 @@
NfcAdapter.CreateBeamUrisCallback uriCallback = null;
Uri[] uris = null;
int flags = 0;
+ int readerModeFlags = 0;
+ Binder token;
+
public NfcActivityState(Activity activity) {
if (activity.getWindow().isDestroyed()) {
throw new IllegalStateException("activity is already destroyed");
@@ -120,6 +124,7 @@
resumed = activity.isResumed();
this.activity = activity;
+ this.token = new Binder();
registerApplication(activity.getApplication());
}
public void destroy() {
@@ -131,6 +136,8 @@
onNdefPushCompleteCallback = null;
uriCallback = null;
uris = null;
+ readerModeFlags = 0;
+ token = null;
}
@Override
public String toString() {
@@ -190,6 +197,44 @@
mDefaultEvent = new NfcEvent(mAdapter);
}
+ public void enableReaderMode(Activity activity, int flags) {
+ boolean isResumed;
+ Binder token;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.readerModeFlags = flags;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ setReaderMode(token, flags);
+ }
+ }
+
+ public void disableReaderMode(Activity activity) {
+ boolean isResumed;
+ Binder token;
+ synchronized (NfcActivityManager.this) {
+ NfcActivityState state = getActivityState(activity);
+ state.readerModeFlags = 0;
+ token = state.token;
+ isResumed = state.resumed;
+ }
+ if (isResumed) {
+ setReaderMode(token, 0);
+ }
+
+ }
+
+ public void setReaderMode(Binder token, int flags) {
+ if (DBG) Log.d(TAG, "Setting reader mode");
+ try {
+ NfcAdapter.sService.setReaderMode(token, flags);
+ } catch (RemoteException e) {
+ mAdapter.attemptDeadServiceRecovery(e);
+ }
+ }
+
public void setNdefPushContentUri(Activity activity, Uri[] uris) {
boolean isResumed;
synchronized (NfcActivityManager.this) {
@@ -341,11 +386,18 @@
/** Callback from Activity life-cycle, on main thread */
@Override
public void onActivityResumed(Activity activity) {
+ int readerModeFlags = 0;
+ Binder token;
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onResume() for " + activity + " " + state);
if (state == null) return;
state.resumed = true;
+ token = state.token;
+ readerModeFlags = state.readerModeFlags;
+ }
+ if (readerModeFlags != 0) {
+ setReaderMode(token, readerModeFlags);
}
requestNfcServiceCallback();
}
@@ -353,11 +405,19 @@
/** Callback from Activity life-cycle, on main thread */
@Override
public void onActivityPaused(Activity activity) {
+ boolean readerModeFlagsSet;
+ Binder token;
synchronized (NfcActivityManager.this) {
NfcActivityState state = findActivityState(activity);
if (DBG) Log.d(TAG, "onPause() for " + activity + " " + state);
if (state == null) return;
state.resumed = false;
+ token = state.token;
+ readerModeFlagsSet = state.readerModeFlags != 0;
+ }
+ if (readerModeFlagsSet) {
+ // Restore default p2p modes
+ setReaderMode(token, 0);
}
}
@@ -381,5 +441,4 @@
}
}
}
-
}