Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(164)

Unified Diff: device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java

Issue 2894373002: [DeviceService] Move //device/nfc to be part of the internal impl of Device Service (Closed)
Patch Set: Modify code comment Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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
deleted file mode 100644
index e4efd51023c4061666279aa11a3d6cd2794cf3bd..0000000000000000000000000000000000000000
--- a/device/nfc/android/java/src/org/chromium/device/nfc/NfcImpl.java
+++ /dev/null
@@ -1,668 +0,0 @@
-// Copyright 2016 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.
-
-package org.chromium.device.nfc;
-
-import android.Manifest;
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.content.Context;
-import android.content.pm.PackageManager;
-import android.nfc.FormatException;
-import android.nfc.NdefMessage;
-import android.nfc.NfcAdapter;
-import android.nfc.NfcAdapter.ReaderCallback;
-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;
-
-import org.chromium.base.Callback;
-import org.chromium.base.Log;
-import org.chromium.device.nfc.mojom.Nfc;
-import org.chromium.device.nfc.mojom.NfcClient;
-import org.chromium.device.nfc.mojom.NfcError;
-import org.chromium.device.nfc.mojom.NfcErrorType;
-import org.chromium.device.nfc.mojom.NfcMessage;
-import org.chromium.device.nfc.mojom.NfcPushOptions;
-import org.chromium.device.nfc.mojom.NfcPushTarget;
-import org.chromium.device.nfc.mojom.NfcWatchMode;
-import org.chromium.device.nfc.mojom.NfcWatchOptions;
-import org.chromium.mojo.bindings.Callbacks;
-import org.chromium.mojo.system.MojoException;
-
-import java.io.IOException;
-import java.io.UnsupportedEncodingException;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Android implementation of the NFC mojo service defined in device/nfc/nfc.mojom.
- */
-public class NfcImpl implements Nfc {
- private static final String TAG = "NfcImpl";
-
- private final int mHostId;
-
- private final NfcDelegate mDelegate;
-
- /**
- * Used to get instance of NFC adapter, @see android.nfc.NfcManager
- */
- private final NfcManager mNfcManager;
-
- /**
- * NFC adapter. @see android.nfc.NfcAdapter
- */
- private final NfcAdapter mNfcAdapter;
-
- /**
- * Activity that is in foreground and is used to enable / disable NFC reader mode operations.
- * Can be updated when activity associated with web page is changed. @see #setActivity
- */
- private Activity mActivity;
-
- /**
- * Flag that indicates whether NFC permission is granted.
- */
- private final boolean mHasPermission;
-
- /**
- * Implementation of android.nfc.NfcAdapter.ReaderCallback. @see ReaderCallbackHandler
- */
- private ReaderCallbackHandler mReaderCallbackHandler;
-
- /**
- * Object that contains data that was passed to method
- * #push(NfcMessage message, NfcPushOptions options, PushResponse callback)
- * @see PendingPushOperation
- */
- private PendingPushOperation mPendingPushOperation;
-
- /**
- * Utility that provides I/O operations for a Tag. Created on demand when Tag is found.
- * @see NfcTagHandler
- */
- private NfcTagHandler mTagHandler;
-
- /**
- * Client interface used to deliver NFCMessages for registered watch operations.
- * @see #watch
- */
- private NfcClient mClient;
-
- /**
- * Watcher id that is incremented for each #watch call.
- */
- private int mWatcherId;
-
- /**
- * Map of watchId <-> NfcWatchOptions. All NfcWatchOptions are matched against tag that is in
- * proximity, when match algorithm (@see #matchesWatchOptions) returns true, watcher with
- * corresponding ID would be notified using NfcClient interface.
- * @see NfcClient#onWatch(int[] id, NfcMessage message)
- */
- 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 hostId, NfcDelegate delegate) {
- mHostId = hostId;
- mDelegate = delegate;
- int permission =
- context.checkPermission(Manifest.permission.NFC, Process.myPid(), Process.myUid());
- mHasPermission = permission == PackageManager.PERMISSION_GRANTED;
- Callback<Activity> onActivityUpdatedCallback = new Callback<Activity>() {
- @Override
- public void onResult(Activity activity) {
- setActivity(activity);
- }
- };
-
- mDelegate.trackActivityForHost(mHostId, onActivityUpdatedCallback);
-
- if (!mHasPermission || Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
- Log.w(TAG, "NFC operations are not permitted.");
- mNfcAdapter = null;
- mNfcManager = null;
- } else {
- mNfcManager = (NfcManager) context.getSystemService(Context.NFC_SERVICE);
- if (mNfcManager == null) {
- Log.w(TAG, "NFC is not supported.");
- mNfcAdapter = null;
- } else {
- mNfcAdapter = mNfcManager.getDefaultAdapter();
- }
- }
- }
-
- /**
- * Sets Activity that is used to enable / disable NFC reader mode. When Activity is set,
- * reader mode is disabled for old Activity and enabled for the new Activity.
- */
- protected void setActivity(Activity activity) {
- disableReaderMode();
- mActivity = activity;
- enableReaderModeIfNeeded();
- }
-
- /**
- * Sets NfcClient. NfcClient interface is used to notify mojo NFC service client when NFC
- * device is in proximity and has NfcMessage that matches NfcWatchOptions criteria.
- * @see Nfc#watch(NfcWatchOptions options, WatchResponse callback)
- *
- * @param client @see NfcClient
- */
- @Override
- public void setClient(NfcClient client) {
- mClient = client;
- }
-
- /**
- * Pushes NfcMessage to Tag or Peer, whenever NFC device is in proximity. At the moment, only
- * passive NFC devices are supported (NfcPushTarget.TAG).
- *
- * @param message that should be pushed to NFC device.
- * @param options that contain information about timeout and target device type.
- * @param callback that is used to notify when push operation is completed.
- */
- @Override
- public void push(NfcMessage message, NfcPushOptions options, PushResponse callback) {
- if (!checkIfReady(callback)) return;
-
- if (!NfcMessageValidator.isValid(message)) {
- callback.call(createError(NfcErrorType.INVALID_MESSAGE));
- return;
- }
-
- // 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;
- }
-
- // 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();
- }
-
- /**
- * Cancels pending push operation.
- * At the moment, only passive NFC devices are supported (NfcPushTarget.TAG).
- *
- * @param target @see NfcPushTarget
- * @param callback that is used to notify caller when cancelPush() is completed.
- */
- @Override
- public void cancelPush(int target, CancelPushResponse callback) {
- if (!checkIfReady(callback)) return;
-
- if (target == NfcPushTarget.PEER) {
- callback.call(createError(NfcErrorType.NOT_SUPPORTED));
- return;
- }
-
- if (mPendingPushOperation == null) {
- callback.call(createError(NfcErrorType.NOT_FOUND));
- } else {
- completePendingPushOperation(createError(NfcErrorType.OPERATION_CANCELLED));
- callback.call(null);
- }
- }
-
- /**
- * Watch method allows to set filtering criteria for NfcMessages that are found when NFC device
- * is within proximity. On success, watch ID is returned to caller through WatchResponse
- * callback. When NfcMessage that matches NfcWatchOptions is found, it is passed to NfcClient
- * interface together with corresponding watch ID.
- * @see NfcClient#onWatch(int[] id, NfcMessage message)
- *
- * @param options used to filter NfcMessages, @see NfcWatchOptions.
- * @param callback that is used to notify caller when watch() is completed and return watch ID.
- */
- @Override
- public void watch(NfcWatchOptions options, WatchResponse callback) {
- if (!checkIfReady(callback)) return;
- int watcherId = ++mWatcherId;
- mWatchers.put(watcherId, options);
- callback.call(watcherId, null);
- enableReaderModeIfNeeded();
- processPendingWatchOperations();
- }
-
- /**
- * Cancels NFC watch operation.
- *
- * @param id of watch operation.
- * @param callback that is used to notify caller when cancelWatch() is completed.
- */
- @Override
- public void cancelWatch(int id, CancelWatchResponse callback) {
- if (!checkIfReady(callback)) return;
-
- if (mWatchers.indexOfKey(id) < 0) {
- callback.call(createError(NfcErrorType.NOT_FOUND));
- } else {
- mWatchers.remove(id);
- callback.call(null);
- disableReaderModeIfNeeded();
- }
- }
-
- /**
- * Cancels all NFC watch operations.
- *
- * @param callback that is used to notify caller when cancelAllWatches() is completed.
- */
- @Override
- public void cancelAllWatches(CancelAllWatchesResponse callback) {
- if (!checkIfReady(callback)) return;
-
- if (mWatchers.size() == 0) {
- callback.call(createError(NfcErrorType.NOT_FOUND));
- } else {
- mWatchers.clear();
- callback.call(null);
- disableReaderModeIfNeeded();
- }
- }
-
- /**
- * Suspends all pending operations. Should be called when web page visibility is lost.
- */
- @Override
- public void suspendNfcOperations() {
- disableReaderMode();
- }
-
- /**
- * Resumes all pending watch / push operations. Should be called when web page becomes visible.
- */
- @Override
- public void resumeNfcOperations() {
- enableReaderModeIfNeeded();
- }
-
- @Override
- public void close() {
- mDelegate.stopTrackingActivityForHost(mHostId);
- disableReaderMode();
- }
-
- @Override
- public void onConnectionError(MojoException e) {
- close();
- }
-
- /**
- * Holds information about pending push operation.
- */
- private static class PendingPushOperation {
- public final NfcMessage nfcMessage;
- public final NfcPushOptions nfcPushOptions;
- private final PushResponse mPushResponseCallback;
-
- public PendingPushOperation(
- NfcMessage message, NfcPushOptions options, PushResponse callback) {
- nfcMessage = message;
- nfcPushOptions = options;
- mPushResponseCallback = callback;
- }
-
- /**
- * Completes pending push operation.
- *
- * @param error should be null when operation is completed successfully, otherwise,
- * error object with corresponding NfcErrorType should be provided.
- */
- public void complete(NfcError error) {
- if (mPushResponseCallback != null) mPushResponseCallback.call(error);
- }
- }
-
- /**
- * Helper method that creates NfcError object from NfcErrorType.
- */
- private NfcError createError(int errorType) {
- NfcError error = new NfcError();
- error.errorType = errorType;
- return error;
- }
-
- /**
- * Checks if NFC funcionality can be used by the mojo service. If permission to use NFC is
- * granted and hardware is enabled, returns null.
- */
- private NfcError checkIfReady() {
- if (!mHasPermission || mActivity == null) {
- return createError(NfcErrorType.SECURITY);
- } else if (mNfcManager == null || mNfcAdapter == null) {
- return createError(NfcErrorType.NOT_SUPPORTED);
- } else if (!mNfcAdapter.isEnabled()) {
- return createError(NfcErrorType.DEVICE_DISABLED);
- }
- return null;
- }
-
- /**
- * Uses checkIfReady() method and if NFC cannot be used, calls mojo callback with NfcError.
- *
- * @param WatchResponse Callback that is provided to watch() method.
- * @return boolean true if NFC functionality can be used, false otherwise.
- */
- private boolean checkIfReady(WatchResponse callback) {
- NfcError error = checkIfReady();
- if (error == null) return true;
-
- callback.call(0, error);
- return false;
- }
-
- /**
- * Uses checkIfReady() method and if NFC cannot be used, calls mojo callback with NfcError.
- *
- * @param callback Generic callback that is provided to push(), cancelPush(),
- * cancelWatch() and cancelAllWatches() methods.
- * @return boolean true if NFC functionality can be used, false otherwise.
- */
- private boolean checkIfReady(Callbacks.Callback1<NfcError> callback) {
- NfcError error = checkIfReady();
- if (error == null) return true;
-
- callback.call(error);
- return false;
- }
-
- /**
- * Implementation of android.nfc.NfcAdapter.ReaderCallback. Callback is called when NFC tag is
- * discovered, Tag object is delegated to mojo service implementation method
- * NfcImpl.onTagDiscovered().
- */
- @TargetApi(Build.VERSION_CODES.KITKAT)
- private static class ReaderCallbackHandler implements ReaderCallback {
- private final NfcImpl mNfcImpl;
-
- public ReaderCallbackHandler(NfcImpl impl) {
- mNfcImpl = impl;
- }
-
- @Override
- public void onTagDiscovered(Tag tag) {
- mNfcImpl.onTagDiscovered(tag);
- }
- }
-
- /**
- * Enables reader mode, allowing NFC device to read / write NFC tags.
- * @see android.nfc.NfcAdapter#enableReaderMode
- */
- private void enableReaderModeIfNeeded() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
-
- if (mReaderCallbackHandler != null || mActivity == null || mNfcAdapter == null) return;
-
- // Do not enable reader mode, if there are no active push / watch operations.
- if (mPendingPushOperation == null && mWatchers.size() == 0) return;
-
- mReaderCallbackHandler = new ReaderCallbackHandler(this);
- mNfcAdapter.enableReaderMode(mActivity, mReaderCallbackHandler,
- NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B
- | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_NFC_V,
- null);
- }
-
- /**
- * Disables reader mode.
- * @see android.nfc.NfcAdapter#disableReaderMode
- */
- @TargetApi(Build.VERSION_CODES.KITKAT)
- private void disableReaderMode() {
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return;
-
- // There is no API that could query whether reader mode is enabled for adapter.
- // If mReaderCallbackHandler is null, reader mode is not enabled.
- if (mReaderCallbackHandler == null) return;
-
- mReaderCallbackHandler = null;
- if (mActivity != null && mNfcAdapter != null && !mActivity.isDestroyed()) {
- mNfcAdapter.disableReaderMode(mActivity);
- }
- }
-
- /**
- * Checks if there are pending push / watch operations and disables readre mode
- * whenever necessary.
- */
- private void disableReaderModeIfNeeded() {
- if (mPendingPushOperation == null && mWatchers.size() == 0) {
- disableReaderMode();
- }
- }
-
- /**
- * Handles completion of pending push operation, cancels timeout task and completes push
- * operation. On error, invalidates #mTagHandler.
- */
- private void pendingPushOperationCompleted(NfcError error) {
- 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.
- */
- private void processPendingPushOperation() {
- if (mTagHandler == null || mPendingPushOperation == null) return;
-
- if (mTagHandler.isTagOutOfRange()) {
- mTagHandler = null;
- return;
- }
-
- try {
- mTagHandler.connect();
- mTagHandler.write(NfcTypeConverter.toNdefMessage(mPendingPushOperation.nfcMessage));
- pendingPushOperationCompleted(null);
- } catch (InvalidNfcMessageException e) {
- Log.w(TAG, "Cannot write data to NFC tag. Invalid NfcMessage.");
- pendingPushOperationCompleted(createError(NfcErrorType.INVALID_MESSAGE));
- } catch (TagLostException e) {
- Log.w(TAG, "Cannot write data to NFC tag. Tag is lost.");
- pendingPushOperationCompleted(createError(NfcErrorType.IO_ERROR));
- } catch (FormatException | IllegalStateException | IOException e) {
- Log.w(TAG, "Cannot write data to NFC tag. IO_ERROR.");
- pendingPushOperationCompleted(createError(NfcErrorType.IO_ERROR));
- }
- }
-
- /**
- * Reads NfcMessage from a tag and forwards message to matching method.
- */
- private void processPendingWatchOperations() {
- if (mTagHandler == null || mClient == null || mWatchers.size() == 0) return;
-
- // Skip reading if there is a pending push operation and ignoreRead flag is set.
- if (mPendingPushOperation != null && mPendingPushOperation.nfcPushOptions.ignoreRead) {
- return;
- }
-
- if (mTagHandler.isTagOutOfRange()) {
- mTagHandler = null;
- return;
- }
-
- NdefMessage message = null;
-
- try {
- mTagHandler.connect();
- message = mTagHandler.read();
- if (message.getByteArrayLength() > NfcMessage.MAX_SIZE) {
- Log.w(TAG, "Cannot read data from NFC tag. NfcMessage exceeds allowed size.");
- return;
- }
- } catch (TagLostException e) {
- Log.w(TAG, "Cannot read data from NFC tag. Tag is lost.");
- } catch (FormatException | IllegalStateException | IOException e) {
- Log.w(TAG, "Cannot read data from NFC tag. IO_ERROR.");
- }
-
- if (message != null) notifyMatchingWatchers(message);
- }
-
- /**
- * Iterates through active watchers and if any of those match NfcWatchOptions criteria,
- * delivers NfcMessage to the client.
- */
- private void notifyMatchingWatchers(NdefMessage message) {
- try {
- NfcMessage nfcMessage = NfcTypeConverter.toNfcMessage(message);
- List<Integer> watchIds = new ArrayList<Integer>();
- for (int i = 0; i < mWatchers.size(); i++) {
- NfcWatchOptions options = mWatchers.valueAt(i);
- if (matchesWatchOptions(nfcMessage, options)) watchIds.add(mWatchers.keyAt(i));
- }
-
- if (watchIds.size() != 0) {
- int[] ids = new int[watchIds.size()];
- for (int i = 0; i < watchIds.size(); ++i) {
- ids[i] = watchIds.get(i).intValue();
- }
- mClient.onWatch(ids, nfcMessage);
- }
- } catch (UnsupportedEncodingException e) {
- Log.w(TAG, "Cannot convert NdefMessage to NfcMessage.");
- }
- }
-
- /**
- * Implements matching algorithm.
- */
- private boolean matchesWatchOptions(NfcMessage message, NfcWatchOptions options) {
- // Valid WebNFC message must have non-empty url.
- if (options.mode == NfcWatchMode.WEBNFC_ONLY
- && (message.url == null || message.url.isEmpty())) {
- return false;
- }
-
- // Filter by NfcMessage.url
- if (options.url != null && !options.url.isEmpty() && !options.url.equals(message.url)) {
- return false;
- }
-
- // Matches any record / media type.
- if ((options.mediaType == null || options.mediaType.isEmpty())
- && options.recordFilter == null) {
- return true;
- }
-
- // Filter by mediaType and recordType
- for (int i = 0; i < message.data.length; i++) {
- boolean matchedMediaType;
- boolean matchedRecordType;
-
- if (options.mediaType == null || options.mediaType.isEmpty()) {
- // If media type for the watch options is empty, match all media types.
- matchedMediaType = true;
- } else {
- matchedMediaType = options.mediaType.equals(message.data[i].mediaType);
- }
-
- if (options.recordFilter == null) {
- // If record type filter for the watch options is null, match all record types.
- matchedRecordType = true;
- } else {
- matchedRecordType = options.recordFilter.recordType == message.data[i].recordType;
- }
-
- if (matchedMediaType && matchedRecordType) return true;
- }
-
- return false;
- }
-
- /**
- * Called by ReaderCallbackHandler when NFC tag is in proximity.
- */
- public void onTagDiscovered(Tag tag) {
- processPendingOperations(NfcTagHandler.create(tag));
- }
-
- /**
- * Processes pending operation when NFC tag is in proximity.
- */
- protected void processPendingOperations(NfcTagHandler tagHandler) {
- mTagHandler = tagHandler;
- processPendingWatchOperations();
- processPendingPushOperation();
- if (mTagHandler != null && mTagHandler.isConnected()) {
- try {
- mTagHandler.close();
- } catch (IOException e) {
- Log.w(TAG, "Cannot close NFC tag connection.");
- }
- }
- }
-
- /**
- * 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;
- }
-}

Powered by Google App Engine
This is Rietveld 408576698