diff options
| author | 2013-09-02 20:38:47 -0700 | |
|---|---|---|
| committer | 2013-09-02 20:43:57 -0700 | |
| commit | 5b1e032ea7c06ab11d778264dd950009fcb93cc5 (patch) | |
| tree | 69b8691184cde10bbf629921a4a17e0e419f7078 | |
| parent | 52c10e94d98e32d977bfd4021136f4c9fa571bd6 (diff) | |
Reader mode NFC API: move to callback model.
Using intents for reader mode doesn't work well for 2 reasons:
1) Intents are used to resolve, but in reader mode we already
know where to resolve to. Additionally, dispatching an intent
causes additional latency.
2) Using intents with foreground dispatch was tricky; for every
call to onNewIntent() with a new tag, there was a call to
onPause(), which effectively disabled reader mode again,
causing a discovery loop.
Instead, let the app register a callback, and call that when
we discover a new tag. Also, add new flag to disable platform
sounds, and to change the presence check delay.
Bug: 10360259
Change-Id: I8373543d6cf2f7ca73c9b3e42bb8b51e3ac48cac
| -rw-r--r-- | Android.mk | 2 | ||||
| -rw-r--r-- | api/current.txt | 8 | ||||
| -rw-r--r-- | core/java/android/nfc/IAppCallback.aidl (renamed from core/java/android/nfc/INdefPushCallback.aidl) | 4 | ||||
| -rw-r--r-- | core/java/android/nfc/INfcAdapter.aidl | 7 | ||||
| -rw-r--r-- | core/java/android/nfc/NfcActivityManager.java | 47 | ||||
| -rw-r--r-- | core/java/android/nfc/NfcAdapter.java | 49 |
6 files changed, 89 insertions, 28 deletions
diff --git a/Android.mk b/Android.mk index 69d1daf9c288..eaafa875b83a 100644 --- a/Android.mk +++ b/Android.mk @@ -142,7 +142,7 @@ LOCAL_SRC_FILES += \ core/java/android/net/INetworkStatsService.aidl \ core/java/android/net/INetworkStatsSession.aidl \ core/java/android/net/nsd/INsdManager.aidl \ - core/java/android/nfc/INdefPushCallback.aidl \ + core/java/android/nfc/IAppCallback.aidl \ core/java/android/nfc/INfcAdapter.aidl \ core/java/android/nfc/INfcAdapterExtras.aidl \ core/java/android/nfc/INfcTag.aidl \ diff --git a/api/current.txt b/api/current.txt index 7aea255564fb..709fcd97b654 100644 --- a/api/current.txt +++ b/api/current.txt @@ -15182,7 +15182,7 @@ package android.nfc { method public void disableReaderMode(android.app.Activity); method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][]); method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); - method public void enableReaderMode(android.app.Activity, int); + method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); method public boolean isEnabled(); method public boolean isNdefPushEnabled(); @@ -15198,12 +15198,14 @@ package android.nfc { field public static final java.lang.String EXTRA_ADAPTER_STATE = "android.nfc.extra.ADAPTER_STATE"; field public static final java.lang.String EXTRA_ID = "android.nfc.extra.ID"; field public static final java.lang.String EXTRA_NDEF_MESSAGES = "android.nfc.extra.NDEF_MESSAGES"; + field public static final java.lang.String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG"; field public static final int FLAG_READER_KOVIO = 16; // 0x10 field public static final int FLAG_READER_NFC_A = 1; // 0x1 field public static final int FLAG_READER_NFC_B = 2; // 0x2 field public static final int FLAG_READER_NFC_F = 4; // 0x4 field public static final int FLAG_READER_NFC_V = 8; // 0x8 + field public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 256; // 0x100 field public static final int FLAG_READER_SKIP_NDEF_CHECK = 128; // 0x80 field public static final int STATE_OFF = 1; // 0x1 field public static final int STATE_ON = 3; // 0x3 @@ -15223,6 +15225,10 @@ package android.nfc { method public abstract void onNdefPushComplete(android.nfc.NfcEvent); } + public static abstract interface NfcAdapter.ReaderCallback { + method public abstract void onTagDiscovered(android.nfc.Tag); + } + public final class NfcEvent { field public final android.nfc.NfcAdapter nfcAdapter; } diff --git a/core/java/android/nfc/INdefPushCallback.aidl b/core/java/android/nfc/IAppCallback.aidl index 16771dc38dbe..95993088bb49 100644 --- a/core/java/android/nfc/INdefPushCallback.aidl +++ b/core/java/android/nfc/IAppCallback.aidl @@ -17,12 +17,14 @@ package android.nfc; import android.nfc.BeamShareData; +import android.nfc.Tag; /** * @hide */ -interface INdefPushCallback +interface IAppCallback { BeamShareData createBeamShareData(); void onNdefPushComplete(); + void onTagDiscovered(in Tag tag); } diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 15d0475fa9f3..8414738cfa44 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -21,10 +21,11 @@ import android.content.IntentFilter; import android.nfc.NdefMessage; import android.nfc.Tag; import android.nfc.TechListParcel; -import android.nfc.INdefPushCallback; +import android.nfc.IAppCallback; import android.nfc.INfcAdapterExtras; import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; +import android.os.Bundle; /** * @hide @@ -44,10 +45,10 @@ interface INfcAdapter void setForegroundDispatch(in PendingIntent intent, in IntentFilter[] filters, in TechListParcel techLists); - void setNdefPushCallback(in INdefPushCallback callback); + void setAppCallback(in IAppCallback callback); void dispatch(in Tag tag); - void setReaderMode (IBinder b, int flags); + void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras); void setP2pModes(int initatorModes, int targetModes); } diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java index d0d943c5de7e..77c023499138 100644 --- a/core/java/android/nfc/NfcActivityManager.java +++ b/core/java/android/nfc/NfcActivityManager.java @@ -19,6 +19,7 @@ package android.nfc; import android.app.Activity; import android.app.Application; import android.net.Uri; +import android.nfc.NfcAdapter.ReaderCallback; import android.os.Binder; import android.os.Bundle; import android.os.RemoteException; @@ -36,7 +37,7 @@ import java.util.List; * * @hide */ -public final class NfcActivityManager extends INdefPushCallback.Stub +public final class NfcActivityManager extends IAppCallback.Stub implements Application.ActivityLifecycleCallbacks { static final String TAG = NfcAdapter.TAG; static final Boolean DBG = false; @@ -113,6 +114,8 @@ public final class NfcActivityManager extends INdefPushCallback.Stub Uri[] uris = null; int flags = 0; int readerModeFlags = 0; + NfcAdapter.ReaderCallback readerCallback = null; + Bundle readerModeExtras = null; Binder token; public NfcActivityState(Activity activity) { @@ -197,17 +200,20 @@ public final class NfcActivityManager extends INdefPushCallback.Stub mDefaultEvent = new NfcEvent(mAdapter); } - public void enableReaderMode(Activity activity, int flags) { + public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, + Bundle extras) { boolean isResumed; Binder token; synchronized (NfcActivityManager.this) { NfcActivityState state = getActivityState(activity); + state.readerCallback = callback; state.readerModeFlags = flags; + state.readerModeExtras = extras; token = state.token; isResumed = state.resumed; } if (isResumed) { - setReaderMode(token, flags); + setReaderMode(token, flags, extras); } } @@ -216,20 +222,22 @@ public final class NfcActivityManager extends INdefPushCallback.Stub Binder token; synchronized (NfcActivityManager.this) { NfcActivityState state = getActivityState(activity); + state.readerCallback = null; state.readerModeFlags = 0; + state.readerModeExtras = null; token = state.token; isResumed = state.resumed; } if (isResumed) { - setReaderMode(token, 0); + setReaderMode(token, 0, null); } } - public void setReaderMode(Binder token, int flags) { + public void setReaderMode(Binder token, int flags, Bundle extras) { if (DBG) Log.d(TAG, "Setting reader mode"); try { - NfcAdapter.sService.setReaderMode(token, flags); + NfcAdapter.sService.setReaderMode(token, this, flags, extras); } catch (RemoteException e) { mAdapter.attemptDeadServiceRecovery(e); } @@ -302,12 +310,12 @@ public final class NfcActivityManager extends INdefPushCallback.Stub } /** - * Request or unrequest NFC service callbacks for NDEF push. + * Request or unrequest NFC service callbacks. * Makes IPC call - do not hold lock. */ void requestNfcServiceCallback() { try { - NfcAdapter.sService.setNdefPushCallback(this); + NfcAdapter.sService.setAppCallback(this); } catch (RemoteException e) { mAdapter.attemptDeadServiceRecovery(e); } @@ -375,6 +383,22 @@ public final class NfcActivityManager extends INdefPushCallback.Stub } } + @Override + public void onTagDiscovered(Tag tag) throws RemoteException { + NfcAdapter.ReaderCallback callback; + synchronized (NfcActivityManager.this) { + NfcActivityState state = findResumedActivityState(); + if (state == null) return; + + callback = state.readerCallback; + } + + // Make callback without lock + if (callback != null) { + callback.onTagDiscovered(tag); + } + + } /** Callback from Activity life-cycle, on main thread */ @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { /* NO-OP */ } @@ -387,6 +411,7 @@ public final class NfcActivityManager extends INdefPushCallback.Stub @Override public void onActivityResumed(Activity activity) { int readerModeFlags = 0; + Bundle readerModeExtras = null; Binder token; synchronized (NfcActivityManager.this) { NfcActivityState state = findActivityState(activity); @@ -395,9 +420,10 @@ public final class NfcActivityManager extends INdefPushCallback.Stub state.resumed = true; token = state.token; readerModeFlags = state.readerModeFlags; + readerModeExtras = state.readerModeExtras; } if (readerModeFlags != 0) { - setReaderMode(token, readerModeFlags); + setReaderMode(token, readerModeFlags, readerModeExtras); } requestNfcServiceCallback(); } @@ -417,7 +443,7 @@ public final class NfcActivityManager extends INdefPushCallback.Stub } if (readerModeFlagsSet) { // Restore default p2p modes - setReaderMode(token, 0); + setReaderMode(token, 0, null); } } @@ -441,4 +467,5 @@ public final class NfcActivityManager extends INdefPushCallback.Stub } } } + } diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index fa0c1f6a6354..2a1890002acc 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -33,6 +33,7 @@ import android.nfc.tech.MifareClassic; import android.nfc.tech.Ndef; import android.nfc.tech.NfcA; import android.nfc.tech.NfcF; +import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; @@ -196,42 +197,42 @@ public final class NfcAdapter { public static final int STATE_TURNING_OFF = 4; /** - * Flag for use with {@link #enableReaderMode(Activity, int)}. + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> * Setting this flag enables polling for Nfc-A technology. */ public static final int FLAG_READER_NFC_A = 0x1; /** - * Flag for use with {@link #enableReaderMode(Activity, int)}. + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> * Setting this flag enables polling for Nfc-B technology. */ public static final int FLAG_READER_NFC_B = 0x2; /** - * Flag for use with {@link #enableReaderMode(Activity, int)}. + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> * Setting this flag enables polling for Nfc-F technology. */ public static final int FLAG_READER_NFC_F = 0x4; /** - * Flag for use with {@link #enableReaderMode(Activity, int)}. + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> * Setting this flag enables polling for Nfc-V (ISO15693) technology. */ public static final int FLAG_READER_NFC_V = 0x8; /** - * Flag for use with {@link #enableReaderMode(Activity, int)}. + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> * Setting this flag enables polling for Kovio technology. */ public static final int FLAG_READER_KOVIO = 0x10; /** - * Flag for use with {@link #enableReaderMode(Activity, int)}. + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. * <p> * Setting this flag allows the caller to prevent the * platform from performing an NDEF check on the tags it @@ -239,6 +240,23 @@ public final class NfcAdapter { */ public static final int FLAG_READER_SKIP_NDEF_CHECK = 0x80; + /** + * Flag for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. + * <p> + * Setting this flag allows the caller to prevent the + * platform from playing sounds when it discovers a tag. + */ + public static final int FLAG_READER_NO_PLATFORM_SOUNDS = 0x100; + + /** + * Int Extra for use with {@link #enableReaderMode(Activity, ReaderCallback, int, Bundle)}. + * <p> + * Setting this integer extra allows the calling application to specify + * the delay that the platform will use for performing presence checks + * on any discovered tag. + */ + public static final String EXTRA_READER_PRESENCE_CHECK_DELAY = "presence"; + /** @hide */ public static final int FLAG_NDEF_PUSH_NO_CONFIRM = 0x1; @@ -291,6 +309,14 @@ public final class NfcAdapter { final Context mContext; /** + * A callback to be invoked when the system has found a tag in + * reader mode. + */ + public interface ReaderCallback { + public void onTagDiscovered(Tag tag); + } + + /** * A callback to be invoked when the system successfully delivers your {@link NdefMessage} * to another device. * @see #setOnNdefPushCompleteCallback @@ -1167,19 +1193,18 @@ public final class NfcAdapter { * {@link Ndef} tag technology from being enumerated on the tag, and that * NDEF-based tag dispatch will not be functional. * - * <p>It is recommended to combine this method with - * {@link #enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][]) - * to ensure that tags are delivered to this activity. - * * <p>For interacting with tags that are emulated on another Android device * using Android's host-based card-emulation, the recommended flags are * {@link #FLAG_READER_NFC_A} and {@link #FLAG_READER_SKIP_NDEF_CHECK}. * * @param activity the Activity that requests the adapter to be in reader mode + * @param callback the callback to be called when a tag is discovered * @param flags Flags indicating poll technologies and other optional parameters + * @param extras Additional extras for configuring reader mode. */ - public void enableReaderMode(Activity activity, int flags) { - mNfcActivityManager.enableReaderMode(activity, flags); + public void enableReaderMode(Activity activity, ReaderCallback callback, int flags, + Bundle extras) { + mNfcActivityManager.enableReaderMode(activity, callback, flags, extras); } /** |