| Index: device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
|
| diff --git a/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java b/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
|
| index 30b59b3332b96df4d62b7626d6622345216c3774..a2c5380a1111c9f15a45ad1eb12cffc07ecaa298 100644
|
| --- a/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
|
| +++ b/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
|
| @@ -17,6 +17,7 @@ import android.nfc.NfcManager;
|
| import android.nfc.Tag;
|
| import android.nfc.TagLostException;
|
| import android.os.Build;
|
| +import android.os.Handler;
|
| import android.os.Process;
|
| import android.util.SparseArray;
|
|
|
| @@ -103,6 +104,16 @@ public class NfcImpl implements Nfc {
|
| */
|
| private final SparseArray<NfcWatchOptions> mWatchers = new SparseArray<>();
|
|
|
| + /**
|
| + * Handler that runs delayed push timeout task.
|
| + */
|
| + private final Handler mPushTimeoutHandler = new Handler();
|
| +
|
| + /**
|
| + * Runnable responsible for cancelling push operation after specified timeout.
|
| + */
|
| + private Runnable mPushTimeoutRunnable;
|
| +
|
| public NfcImpl(Context context) {
|
| int permission =
|
| context.checkPermission(Manifest.permission.NFC, Process.myPid(), Process.myUid());
|
| @@ -162,7 +173,9 @@ public class NfcImpl implements Nfc {
|
| return;
|
| }
|
|
|
| - if (options.target == NfcPushTarget.PEER) {
|
| + // Check NfcPushOptions that are not supported by Android platform.
|
| + if (options.target == NfcPushTarget.PEER || options.timeout < 0
|
| + || (options.timeout > Long.MAX_VALUE && !Double.isInfinite(options.timeout))) {
|
| callback.call(createError(NfcErrorType.NOT_SUPPORTED));
|
| return;
|
| }
|
| @@ -170,9 +183,13 @@ public class NfcImpl implements Nfc {
|
| // If previous pending push operation is not completed, cancel it.
|
| if (mPendingPushOperation != null) {
|
| mPendingPushOperation.complete(createError(NfcErrorType.OPERATION_CANCELLED));
|
| + cancelPushTimeoutTask();
|
| }
|
|
|
| mPendingPushOperation = new PendingPushOperation(message, options, callback);
|
| +
|
| + // Schedule push timeout task for new #mPendingPushOperation.
|
| + schedulePushTimeoutTask(options);
|
| enableReaderModeIfNeeded();
|
| processPendingPushOperation();
|
| }
|
| @@ -196,10 +213,8 @@ public class NfcImpl implements Nfc {
|
| if (mPendingPushOperation == null) {
|
| callback.call(createError(NfcErrorType.NOT_FOUND));
|
| } else {
|
| - mPendingPushOperation.complete(createError(NfcErrorType.OPERATION_CANCELLED));
|
| - mPendingPushOperation = null;
|
| + completePendingPushOperation(createError(NfcErrorType.OPERATION_CANCELLED));
|
| callback.call(null);
|
| - disableReaderModeIfNeeded();
|
| }
|
| }
|
|
|
| @@ -432,19 +447,27 @@ public class NfcImpl implements Nfc {
|
| }
|
|
|
| /**
|
| - * Completes pending push operation. On error, invalidates #mTagHandler.
|
| + * Handles completion of pending push operation, cancels timeout task and completes push
|
| + * operation. On error, invalidates #mTagHandler.
|
| */
|
| private void pendingPushOperationCompleted(NfcError error) {
|
| - if (mPendingPushOperation != null) {
|
| - mPendingPushOperation.complete(error);
|
| - mPendingPushOperation = null;
|
| - disableReaderModeIfNeeded();
|
| - }
|
| -
|
| + completePendingPushOperation(error);
|
| if (error != null) mTagHandler = null;
|
| }
|
|
|
| /**
|
| + * Completes pending push operation and disables reader mode if needed.
|
| + */
|
| + private void completePendingPushOperation(NfcError error) {
|
| + if (mPendingPushOperation == null) return;
|
| +
|
| + cancelPushTimeoutTask();
|
| + mPendingPushOperation.complete(error);
|
| + mPendingPushOperation = null;
|
| + disableReaderModeIfNeeded();
|
| + }
|
| +
|
| + /**
|
| * Checks whether there is a #mPendingPushOperation and writes data to NFC tag. In case of
|
| * exception calls pendingPushOperationCompleted() with appropriate error object.
|
| */
|
| @@ -599,4 +622,33 @@ public class NfcImpl implements Nfc {
|
| }
|
| }
|
| }
|
| +
|
| + /**
|
| + * Schedules task that is executed after timeout and cancels pending push operation.
|
| + */
|
| + private void schedulePushTimeoutTask(NfcPushOptions options) {
|
| + assert mPushTimeoutRunnable == null;
|
| + // Default timeout value.
|
| + if (Double.isInfinite(options.timeout)) return;
|
| +
|
| + // Create and schedule timeout.
|
| + mPushTimeoutRunnable = new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + completePendingPushOperation(createError(NfcErrorType.TIMER_EXPIRED));
|
| + }
|
| + };
|
| +
|
| + mPushTimeoutHandler.postDelayed(mPushTimeoutRunnable, (long) options.timeout);
|
| + }
|
| +
|
| + /**
|
| + * Cancels push timeout task.
|
| + */
|
| + void cancelPushTimeoutTask() {
|
| + if (mPushTimeoutRunnable == null) return;
|
| +
|
| + mPushTimeoutHandler.removeCallbacks(mPushTimeoutRunnable);
|
| + mPushTimeoutRunnable = null;
|
| + }
|
| }
|
|
|