Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5b1e032e authored by Martijn Coenen's avatar Martijn Coenen
Browse files

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
parent 52c10e94
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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 \
+7 −1
Original line number Diff line number Diff line
@@ -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;
  }
+3 −1
Original line number Diff line number Diff line
@@ -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);
}
+4 −3
Original line number Diff line number Diff line
@@ -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);
}
+37 −10
Original line number Diff line number Diff line
@@ -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
            }
        }
    }

}
Loading