diff --git a/Android.mk b/Android.mk index 6147022e35904..e299250380e2f 100644 --- a/Android.mk +++ b/Android.mk @@ -119,11 +119,11 @@ LOCAL_SRC_FILES += \ core/java/android/nfc/ILlcpConnectionlessSocket.aidl \ core/java/android/nfc/ILlcpServiceSocket.aidl \ core/java/android/nfc/ILlcpSocket.aidl \ - core/java/android/nfc/INdefTag.aidl \ core/java/android/nfc/INfcAdapter.aidl \ core/java/android/nfc/INfcTag.aidl \ core/java/android/nfc/IP2pInitiator.aidl \ core/java/android/nfc/IP2pTarget.aidl \ + core/java/android/nfc/INfcSecureElement.aidl \ core/java/android/os/IHardwareService.aidl \ core/java/android/os/IMessenger.aidl \ core/java/android/os/INetworkManagementService.aidl \ @@ -252,7 +252,6 @@ aidl_files := \ frameworks/base/core/java/android/nfc/NdefMessage.aidl \ frameworks/base/core/java/android/nfc/NdefRecord.aidl \ frameworks/base/core/java/android/nfc/Tag.aidl \ - frameworks/base/core/java/android/nfc/NdefTag.aidl \ frameworks/base/core/java/android/os/Bundle.aidl \ frameworks/base/core/java/android/os/DropBoxManager.aidl \ frameworks/base/core/java/android/os/ParcelFileDescriptor.aidl \ diff --git a/CleanSpec.mk b/CleanSpec.mk index d19f3f8c21106..2ee8f3122ec2e 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -72,6 +72,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framew $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/com/trustedlogic) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/com/trustedlogic) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/com/trustedlogic) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc/INdefTag.java) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index cd08e332d148d..a663fb84f82d0 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -24,6 +24,7 @@ import android.nfc.ILlcpConnectionlessSocket; import android.nfc.INfcTag; import android.nfc.IP2pTarget; import android.nfc.IP2pInitiator; +import android.nfc.INfcSecureElement; /** * @hide @@ -36,9 +37,12 @@ interface INfcAdapter INfcTag getNfcTagInterface(); IP2pTarget getP2pTargetInterface(); IP2pInitiator getP2pInitiatorInterface(); + INfcSecureElement getNfcSecureElementInterface(); // NfcAdapter-class related methods boolean isEnabled(); + NdefMessage localGet(); + void localSet(in NdefMessage message); void openTagConnection(in Tag tag); // Non-public methods diff --git a/core/java/android/nfc/INdefTag.aidl b/core/java/android/nfc/INfcSecureElement.aidl old mode 100644 new mode 100755 similarity index 68% rename from core/java/android/nfc/INdefTag.aidl rename to core/java/android/nfc/INfcSecureElement.aidl index d131ebe2d3d0a..aa98dd26f8f68 --- a/core/java/android/nfc/INdefTag.aidl +++ b/core/java/android/nfc/INfcSecureElement.aidl @@ -16,13 +16,13 @@ package android.nfc; -import android.nfc.NdefMessage; - /** - * @hide + * {@hide} */ -interface INdefTag -{ - NdefMessage read(int nativeHandle); - boolean write(int nativeHandle, in NdefMessage msg); +interface INfcSecureElement { + int openSecureElementConnection(); + int closeSecureElementConnection(int nativeHandle); + byte[] exchangeAPDU(int nativeHandle, in byte[] data); + int[] getSecureElementTechList(int nativeHandle); + byte[] getSecureElementUid(int nativeHandle); } \ No newline at end of file diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 13b97d6c52b26..ad3c1bb2ce993 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -25,7 +25,7 @@ interface INfcTag { int close(int nativeHandle); int connect(int nativeHandle); - String getType(int nativeHandle); + int[] getTechList(int nativeHandle); byte[] getUid(int nativeHandle); boolean isNdef(int nativeHandle); boolean isPresent(int nativeHandle); diff --git a/core/java/android/nfc/NdefTag.aidl b/core/java/android/nfc/NdefTag.aidl deleted file mode 100644 index 288f667cf4ac4..0000000000000 --- a/core/java/android/nfc/NdefTag.aidl +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -parcelable NdefTag; \ No newline at end of file diff --git a/core/java/android/nfc/NdefTag.java b/core/java/android/nfc/NdefTag.java deleted file mode 100644 index eb9d0dc92a04f..0000000000000 --- a/core/java/android/nfc/NdefTag.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.nfc; - -import android.os.Parcel; -import android.os.Parcelable; - -/** - * Represents a discovered tag that contains {@link NdefMessage}s (or a tag that can store them). - * In practice, a tag is a thing that an NFC-enabled device can communicate with. This - * class is a representation of such a tag and can contain the NDEF messages shared by the tag. - *
An NDEF tag can contain zero or more NDEF messages (represented by {@link NdefMessage} - * objects) in addition to the basic tag properties of UID and Type. - *
- * {@link NdefTag}s that have been initialized will usually contain a single {@link NdefMessage} - * (and that Message can contain multiple {@link NdefRecord}s). However it - * is possible for {@link NdefTag}s to contain multiple {@link NdefMessage}s. - *
{@link NfcAdapter#createNdefTagConnection createNdefTagConnection()} can be used to modify the - * contents of some tags. - *
This is an immutable data class. All properties are set at Tag discovery - * time and calls on this class will retrieve those read-only properties, and - * not cause any further RF activity or block. Note however that arrays passed to and - * returned by this class are *not* cloned, so be careful not to modify them. - * @hide - */ -public class NdefTag extends Tag implements Parcelable { - /** - * Target for NFC Forum Type 1 compliant tag. - *
This is based on Jewel/Topaz technology - */ - public static final String TARGET_TYPE_1 = "type_1"; - - /** - * Target for NFC Forum Type 2 compliant tag. - *
This is based on Mifare Ultralight technology. - */ - public static final String TARGET_TYPE_2 = "type_2"; - - /** - * Target for NFC Forum Type 3 compliant tag. - *
This is based on Felica technology. - */ - public static final String TARGET_TYPE_3 = "type_3"; - - /** - * Target for NFC Forum Type 4 compliant tag. - *
This is based on Mifare Desfire technology. - */ - public static final String TARGET_TYPE_4 = "type_4"; - - /** - * Target for NFC Forum Enabled: Mifare Classic tag. - *
This is not strictly a NFC Forum tag type, but is a common - * NDEF message container. - */ - public static final String TARGET_MIFARE_CLASSIC = "type_mifare_classic"; - - /** - * Any other target. - */ - public static final String TARGET_OTHER = "other"; - - private final String[] mNdefTargets; - private final NdefMessage[][] mMessages; // one NdefMessage[] per NDEF target - private NdefMessage[] mFlatMessages; // collapsed mMessages, built lazily, protected by (this) - - /** - * Hidden constructor to be used by NFC service only. - * @hide - */ - public NdefTag(byte[] id, String[] rawTargets, byte[] pollBytes, byte[] activationBytes, - int serviceHandle, String[] ndefTargets, NdefMessage[][] messages) { - super(id, true, rawTargets, pollBytes, activationBytes, serviceHandle); - if (ndefTargets == null || messages == null) { - throw new IllegalArgumentException("ndefTargets or messages cannot be null"); - } - if (ndefTargets.length != messages.length){ - throw new IllegalArgumentException("ndefTargets and messages arrays must match"); - } - for (NdefMessage[] ms : messages) { - if (ms == null) { - throw new IllegalArgumentException("messages elements cannot be null"); - } - } - mNdefTargets = ndefTargets; - mMessages = messages; - } - - /** - * Construct a mock NdefTag. - *
This is an application constructed tag, so NfcAdapter methods on this - * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with - * {@link IllegalArgumentException} since it does not represent a physical Tag. - *
This constructor might be useful for mock testing. - * @param id The tag identifier, can be null - * @param rawTargets must not be null - * @param pollBytes can be null - * @param activationBytes can be null - * @param ndefTargets NDEF target array, such as {TARGET_TYPE_2}, cannot be null - * @param messages messages, one array per NDEF target, cannot be null - * @return freshly constructed NdefTag - */ - public static NdefTag createMockNdefTag(byte[] id, String[] rawTargets, byte[] pollBytes, - byte[] activationBytes, String[] ndefTargets, NdefMessage[][] messages) { - // set serviceHandle to 0 to indicate mock tag - return new NdefTag(id, rawTargets, pollBytes, activationBytes, 0, ndefTargets, messages); - } - - /** - * Get all NDEF Messages. - *
- * This retrieves the NDEF Messages that were found on the Tag at discovery - * time. It does not cause any further RF activity, and does not block. - *
- * Most tags only contain a single NDEF message. - * - * @return NDEF Messages found at Tag discovery - */ - public NdefMessage[] getNdefMessages() { - // common-case optimization - if (mMessages.length == 1) { - return mMessages[0]; - } - - // return cached flat array - synchronized(this) { - if (mFlatMessages != null) { - return mFlatMessages; - } - // not cached - build a flat array - int sz = 0; - for (NdefMessage[] ms : mMessages) { - sz += ms.length; - } - mFlatMessages = new NdefMessage[sz]; - int i = 0; - for (NdefMessage[] ms : mMessages) { - System.arraycopy(ms, 0, mFlatMessages, i, ms.length); - i += ms.length; - } - return mFlatMessages; - } - } - - /** - * Get only the NDEF Messages from a single NDEF target on a tag. - *
- * This retrieves the NDEF Messages that were found on the Tag at discovery - * time. It does not cause any further RF activity, and does not block. - *
- * Most tags only contain a single NDEF message.
- *
- * @param target one of targets strings provided by getNdefTargets()
- * @return NDEF Messages found at Tag discovery
- */
- public NdefMessage[] getNdefMessages(String target) {
- for (int i=0; i
+ * The implementation of this method must either
+ * Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param message NDEF message to make public
* @hide
*/
- public RawTagConnection createRawTagConnection(Tag tag) {
- if (tag.mServiceHandle == 0) {
- throw new IllegalArgumentException("mock tag cannot be used for connections");
- }
+ public void setLocalNdefMessage(NdefMessage message) {
try {
- return new RawTagConnection(this, tag);
+ mService.localSet(message);
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ }
+ }
+
+ /**
+ * Get the NDEF Message that this adapter appears as to Tag readers.
+ * Requires {@link android.Manifest.permission#NFC} permission.
+ *
+ * @return NDEF Message that is publicly readable
+ * @hide
+ */
+ public NdefMessage getLocalNdefMessage() {
+ try {
+ return mService.localGet();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return null;
@@ -318,52 +361,14 @@ public final class NfcAdapter {
}
/**
- * Create a raw tag connection to the specified Target
- * Requires {@link android.Manifest.permission#NFC} permission.
+ * Create an Nfc Secure Element Connection
* @hide
*/
- public RawTagConnection createRawTagConnection(Tag tag, String target) {
- if (tag.mServiceHandle == 0) {
- throw new IllegalArgumentException("mock tag cannot be used for connections");
- }
+ public NfcSecureElement createNfcSecureElementConnection() {
try {
- return new RawTagConnection(this, tag, target);
+ return new NfcSecureElement(mService.getNfcSecureElementInterface());
} catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return null;
- }
- }
-
- /**
- * Create an NDEF tag connection to the default Target
- * Requires {@link android.Manifest.permission#NFC} permission.
- * @hide
- */
- public NdefTagConnection createNdefTagConnection(NdefTag tag) {
- if (tag.mServiceHandle == 0) {
- throw new IllegalArgumentException("mock tag cannot be used for connections");
- }
- try {
- return new NdefTagConnection(this, tag);
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return null;
- }
- }
-
- /**
- * Create an NDEF tag connection to the specified Target
- * Requires {@link android.Manifest.permission#NFC} permission.
- * @hide
- */
- public NdefTagConnection createNdefTagConnection(NdefTag tag, String target) {
- if (tag.mServiceHandle == 0) {
- throw new IllegalArgumentException("mock tag cannot be used for connections");
- }
- try {
- return new NdefTagConnection(this, tag, target);
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
+ Log.e(TAG, "createNfcSecureElementConnection failed", e);
return null;
}
}
diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java
new file mode 100755
index 0000000000000..5f4c06699903a
--- /dev/null
+++ b/core/java/android/nfc/NfcSecureElement.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import android.nfc.technology.TagTechnology;
+import android.os.RemoteException;
+import android.util.Log;
+
+import java.io.IOException;
+
+//import android.util.Log;
+
+/**
+ * This class provides the primary API for managing all aspects Secure Element.
+ * Get an instance of this class by calling
+ * Context.getSystemService(Context.NFC_SERVICE).
+ * @hide
+ */
+public final class NfcSecureElement {
+
+ private static final String TAG = "NfcSecureElement";
+
+ private INfcSecureElement mService;
+
+
+ /**
+ * @hide
+ */
+ public NfcSecureElement(INfcSecureElement mSecureElementService) {
+ mService = mSecureElementService;
+ }
+
+ public int openSecureElementConnection(String seType) throws IOException {
+ if (seType.equals("SmartMX")) {
+ try {
+ int handle = mService.openSecureElementConnection();
+ // Handle potential errors
+ if (handle != 0) {
+ return handle;
+ } else {
+ throw new IOException("SmartMX connection not allowed");
+ }
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in openSecureElementConnection(): ", e);
+ return 0;
+ }
+
+ } else if (seType.equals("UICC")) {
+ return 0;
+ } else {
+ throw new IOException("Wrong Secure Element type");
+ }
+ }
+
+
+ public byte [] exchangeAPDU(int handle,byte [] data) throws IOException {
+
+
+ // Perform exchange APDU
+ try {
+ byte[] response = mService.exchangeAPDU(handle, data);
+ // Handle potential errors
+ if (response == null) {
+ throw new IOException("Exchange APDU failed");
+ }
+ return response;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in exchangeAPDU(): ", e);
+ return null;
+ }
+ }
+
+ public void closeSecureElementConnection(int handle) throws IOException {
+
+ try {
+ int status = mService.closeSecureElementConnection(handle);
+ // Handle potential errors
+ if (ErrorCodes.isError(status)) {
+ throw new IOException("Error during the conection close");
+ };
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in closeSecureElement(): ", e);
+ }
+ }
+
+
+ /**
+ * Returns target type. constants.
+ *
+ * @return Secure Element technology type. The possible values are defined in
+ * {@link TagTechnology}
+ *
+ */
+ public int[] getSecureElementTechList(int handle) throws IOException {
+ try {
+ return mService.getSecureElementTechList(handle);
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in getType(): ", e);
+ return null;
+ }
+ }
+
+ /**
+ * Returns Secure Element UID.
+ *
+ * @return Secure Element UID.
+ */
+ public byte[] getSecureElementUid(int handle) throws IOException {
+
+ byte[] uid = null;
+ try {
+ uid = mService.getSecureElementUid(handle);
+ // Handle potential errors
+ if (uid == null) {
+ throw new IOException("Get Secure Element UID failed");
+ }
+ return uid;
+ } catch (RemoteException e) {
+ Log.e(TAG, "RemoteException in getType(): ", e);
+ return null;
+ }
+ }
+
+}
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 5d0b04cbccf3a..938e6a7d3cc66 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,8 +16,20 @@
package android.nfc;
+import android.nfc.technology.IsoDep;
+import android.nfc.technology.MifareClassic;
+import android.nfc.technology.NfcV;
+import android.nfc.technology.Ndef;
+import android.nfc.technology.NfcA;
+import android.nfc.technology.NfcB;
+import android.nfc.technology.NfcF;
+import android.nfc.technology.TagTechnology;
+import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
+import android.os.RemoteException;
+
+import java.util.Arrays;
/**
* Represents a (generic) discovered tag.
@@ -30,13 +42,13 @@ import android.os.Parcelable;
* {@link Tag} objects are passed to applications via the {@link NfcAdapter#EXTRA_TAG} extra
* in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable
* and represents the state of the tag at the time of discovery. It can be
- * directly queried for its UID and Type, or used to create a {@link RawTagConnection}
- * (with {@link NfcAdapter#createRawTagConnection createRawTagConnection()}).
+ * directly queried for its UID and Type, or used to create a {@link TagTechnology}
+ * (with {@link Tag#getTechnology(int)}).
*
- * A {@link Tag} can be used to create a {@link RawTagConnection} only while the tag is in
+ * A {@link Tag} can be used to create a {@link TagTechnology} only while the tag is in
* range. If it is removed and then returned to range, then the most recent
* {@link Tag} object (in {@link NfcAdapter#ACTION_TAG_DISCOVERED}) should be used to create a
- * {@link RawTagConnection}.
+ * {@link TagTechnology}.
* This is an immutable data class. All properties are set at Tag discovery
* time and calls on this class will retrieve those read-only properties, and
* not cause any further RF activity or block. Note however that arrays passed to and
@@ -44,78 +56,39 @@ import android.os.Parcelable;
* @hide
*/
public class Tag implements Parcelable {
- /**
- * ISO 14443-3A technology.
- *
- * Includes Topaz (which is -3A compatible)
- */
- public static final String TARGET_ISO_14443_3A = "iso14443_3a";
-
- /**
- * ISO 14443-3B technology.
- */
- public static final String TARGET_ISO_14443_3B = "iso14443_3b";
-
- /**
- * ISO 14443-4 technology.
- */
- public static final String TARGET_ISO_14443_4 = "iso14443_4";
-
- /**
- * ISO 15693 technology, commonly known as RFID.
- */
- public static final String TARGET_ISO_15693 = "iso15693";
-
- /**
- * JIS X-6319-4 technology, commonly known as Felica.
- */
- public static final String TARGET_JIS_X_6319_4 = "jis_x_6319_4";
-
- /**
- * Any other technology.
- */
- public static final String TARGET_OTHER = "other";
-
- /*package*/ final boolean mIsNdef;
/*package*/ final byte[] mId;
- /*package*/ final String[] mRawTargets;
- /*package*/ final byte[] mPollBytes;
- /*package*/ final byte[] mActivationBytes;
+ /*package*/ final int[] mTechList;
+ /*package*/ final Bundle[] mTechExtras;
/*package*/ final int mServiceHandle; // for use by NFC service, 0 indicates a mock
/**
* Hidden constructor to be used by NFC service and internal classes.
* @hide
*/
- public Tag(byte[] id, boolean isNdef, String[] rawTargets, byte[] pollBytes,
- byte[] activationBytes, int serviceHandle) {
- if (rawTargets == null) {
+ public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle) {
+ if (techList == null) {
throw new IllegalArgumentException("rawTargets cannot be null");
}
- mIsNdef = isNdef;
mId = id;
- mRawTargets = rawTargets;
- mPollBytes = pollBytes;
- mActivationBytes = activationBytes;
+ mTechList = Arrays.copyOf(techList, techList.length);
+ // Ensure mTechExtras is as long as mTechList
+ mTechExtras = Arrays.copyOf(techListExtras, techList.length);
mServiceHandle = serviceHandle;
}
/**
* Construct a mock Tag.
* This is an application constructed tag, so NfcAdapter methods on this
- * Tag such as {@link NfcAdapter#createRawTagConnection} will fail with
+ * Tag such as {@link #getTechnology} may fail with
* {@link IllegalArgumentException} since it does not represent a physical Tag.
* This constructor might be useful for mock testing.
* @param id The tag identifier, can be null
- * @param rawTargets must not be null
- * @param pollBytes can be null
- * @param activationBytes can be null
+ * @param techList must not be null
* @return freshly constructed tag
*/
- public static Tag createMockTag(byte[] id, String[] rawTargets, byte[] pollBytes,
- byte[] activationBytes) {
+ public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
// set serviceHandle to 0 to indicate mock tag
- return new Tag(id, false, rawTargets, pollBytes, activationBytes, 0);
+ return new Tag(id, techList, techListExtras, 0);
}
/**
@@ -126,16 +99,6 @@ public class Tag implements Parcelable {
return mServiceHandle;
}
- /**
- * Return the available targets that this NFC adapter can use to create
- * a RawTagConnection.
- *
- * @return raw targets, will not be null
- */
- public String[] getRawTargets() {
- return mRawTargets;
- }
-
/**
* Get the Tag Identifier (if it has one).
* Tag ID is usually a serial number for the tag.
@@ -147,37 +110,64 @@ public class Tag implements Parcelable {
}
/**
- * Get the low-level bytes returned by this Tag at poll-time.
- * These can be used to help with advanced identification of a Tag.
- * The meaning of these bytes depends on the Tag technology.
- * ISO14443-3A: ATQA/SENS_RES
- * ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES
- * JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte)
- * ISO15693: response flags (1 byte), DSFID (1 byte)
- * from SENSF_RES
- *
- * @return poll bytes, or null if they do not exist for this Tag technology
- * @hide
+ * Returns technologies present in the tag that this implementation understands,
+ * or a zero length array if there are no supported technologies on this tag.
*/
- public byte[] getPollBytes() {
- return mPollBytes;
+ public int[] getTechnologyList() {
+ return Arrays.copyOf(mTechList, mTechList.length);
}
/**
- * Get the low-level bytes returned by this Tag at activation-time.
- * These can be used to help with advanced identification of a Tag.
- * The meaning of these bytes depends on the Tag technology.
- * ISO14443-3A: SAK/SEL_RES
- * ISO14443-3B: null
- * ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS ISO14443-3B & ISO14443-4: ATTRIB response
- * JIS_X_6319_4: null
- * ISO15693: response flags (1 byte), DSFID (1 byte): null
- * @return activation bytes, or null if they do not exist for this Tag technology
- * @hide
+ * Returns the technology, or null if not present
*/
- public byte[] getActivationBytes() {
- return mActivationBytes;
+ public TagTechnology getTechnology(int tech) {
+ int pos = -1;
+ for (int idx = 0; idx < mTechList.length; idx++) {
+ if (mTechList[idx] == tech) {
+ pos = idx;
+ break;
+ }
+ }
+ if (pos < 0) {
+ return null;
+ }
+
+ Bundle extras = mTechExtras[pos];
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter();
+ try {
+ switch (tech) {
+ case TagTechnology.NFC_A: {
+ return new NfcA(adapter, this, extras);
+ }
+ case TagTechnology.NFC_B: {
+ return new NfcB(adapter, this, extras);
+ }
+ case TagTechnology.ISO_DEP: {
+ return new IsoDep(adapter, this, extras);
+ }
+ case TagTechnology.NFC_V: {
+ return new NfcV(adapter, this, extras);
+ }
+ case TagTechnology.TYPE_1:
+ case TagTechnology.TYPE_2:
+ case TagTechnology.TYPE_3:
+ case TagTechnology.TYPE_4: {
+ return new Ndef(adapter, this, tech, extras);
+ }
+ case TagTechnology.NFC_F: {
+ return new NfcF(adapter, this, extras);
+ }
+ case TagTechnology.MIFARE_CLASSIC: {
+ return new MifareClassic(adapter, this, extras);
+ }
+
+ default: {
+ throw new UnsupportedOperationException("Tech " + tech + " not supported");
+ }
+ }
+ } catch (RemoteException e) {
+ return null;
+ }
}
@Override
@@ -185,13 +175,9 @@ public class Tag implements Parcelable {
StringBuilder sb = new StringBuilder("TAG ")
.append("uid = ")
.append(mId)
- .append(" poll ")
- .append(mPollBytes)
- .append(" activation ")
- .append(mActivationBytes)
- .append(" Raw [");
- for (String s : mRawTargets) {
- sb.append(s)
+ .append(" Tech [");
+ for (int i : mTechList) {
+ sb.append(i)
.append(", ");
}
return sb.toString();
@@ -221,37 +207,32 @@ public class Tag implements Parcelable {
return 0;
}
-
@Override
public void writeToParcel(Parcel dest, int flags) {
- dest.writeInt(mIsNdef ? 1 : 0);
writeBytesWithNull(dest, mId);
- dest.writeInt(mRawTargets.length);
- dest.writeStringArray(mRawTargets);
- writeBytesWithNull(dest, mPollBytes);
- writeBytesWithNull(dest, mActivationBytes);
+ dest.writeInt(mTechList.length);
+ dest.writeIntArray(mTechList);
+ dest.writeTypedArray(mTechExtras, 0);
dest.writeInt(mServiceHandle);
}
public static final Parcelable.Creator You can acquire this kind of connection with {@link NfcAdapter#createRawTagConnection
- * createRawTagConnection()}. Use the connection to send and receive data with {@link #transceive
- * transceive()}.
- *
- * Applications must implement their own protocol stack on top of {@link #transceive transceive()}.
- *
- * Note:
- * Use of this class requires the {@link android.Manifest.permission#NFC}
- * permission.
- * @hide
+ * A base class for tag technologies that are built on top of transceive().
*/
-public class RawTagConnection {
+/* package */ abstract class BasicTagTechnology implements TagTechnology {
/*package*/ final Tag mTag;
/*package*/ boolean mIsConnected;
- /*package*/ String mSelectedTarget;
+ /*package*/ int mSelectedTechnology;
private final NfcAdapter mAdapter;
// Following fields are final after construction, except for
@@ -49,30 +43,40 @@ public class RawTagConnection {
private static final String TAG = "NFC";
- /*package*/ RawTagConnection(NfcAdapter adapter, Tag tag, String target) throws RemoteException {
- String[] targets = tag.getRawTargets();
+ /**
+ * @hide
+ */
+ public BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException {
+ int[] techList = tag.getTechnologyList();
int i;
// Check target validity
- for (i=0;i Requires {@link android.Manifest.permission#NFC} permission.
*/
+ @Override
public Tag getTag() {
return mTag;
}
@@ -99,8 +104,9 @@ public class RawTagConnection {
/**
* Requires {@link android.Manifest.permission#NFC} permission.
*/
- public String getTagTarget() {
- return mSelectedTarget;
+ @Override
+ public int getTechnologyId() {
+ return mSelectedTechnology;
}
/**
@@ -119,7 +125,7 @@ public class RawTagConnection {
}
try {
- return mTagService.isPresent(mTag.mServiceHandle);
+ return mTagService.isPresent(mTag.getServiceHandle());
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return false;
@@ -136,6 +142,7 @@ public class RawTagConnection {
* Requires {@link android.Manifest.permission#NFC} permission.
* @throws IOException if the target is lost, or connect canceled
*/
+ @Override
public void connect() throws IOException {
//TODO(nxp): enforce exclusivity
mIsConnected = true;
@@ -151,10 +158,11 @@ public class RawTagConnection {
* calls to {@link #transceive transceive()} or {@link #connect} will fail.
* Requires {@link android.Manifest.permission#NFC} permission.
*/
+ @Override
public void close() {
mIsConnected = false;
try {
- mTagService.close(mTag.mServiceHandle);
+ mTagService.close(mTag.getServiceHandle());
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}
@@ -173,7 +181,7 @@ public class RawTagConnection {
*/
public byte[] transceive(byte[] data) throws IOException {
try {
- byte[] response = mTagService.transceive(mTag.mServiceHandle, data);
+ byte[] response = mTagService.transceive(mTag.getServiceHandle(), data);
if (response == null) {
throw new IOException("transcieve failed");
}
diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/technology/IsoDep.java
new file mode 100644
index 0000000000000..5346c679f3ac0
--- /dev/null
+++ b/core/java/android/nfc/technology/IsoDep.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+/**
+ * A low-level connection to a {@link Tag} using the ISO-DEP technology, also known as
+ * ISO1443-4.
+ *
+ * You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * Note:
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class IsoDep extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_ATTRIB = "attrib";
+ /** @hide */
+ public static final String EXTRA_HIST_BYTES = "histbytes";
+
+ private byte[] mAttrib = null;
+ private byte[] mHistBytes = null;
+
+ public IsoDep(NfcAdapter adapter, Tag tag, Bundle extras)
+ throws RemoteException {
+ super(adapter, tag, TagTechnology.ISO_DEP);
+ if (extras != null) {
+ mAttrib = extras.getByteArray(EXTRA_ATTRIB);
+ mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
+ }
+ }
+
+ /**
+ * 3A only
+ */
+ public byte[] getHistoricalBytes() { return mHistBytes; }
+
+ /**
+ * 3B only
+ */
+ public byte[] getAttrib() { return mAttrib; }
+
+ /**
+ * Attempts to select the given application on the tag. Note that this only works
+ * if the tag supports ISO7816-4, which not all IsoDep tags support. If the tag doesn't
+ * support ISO7816-4 this will throw {@link UnsupportedOperationException}.
+ *
+ * This method requires that you call {@link #connect} before calling it.
+ *
+ * @throws IOException, UnsupportedOperationException
+ */
+ public void selectAid(byte[] aid) throws IOException, UnsupportedOperationException {
+ throw new UnsupportedOperationException();
+ }
+}
diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java
new file mode 100644
index 0000000000000..c25b71f94121e
--- /dev/null
+++ b/core/java/android/nfc/technology/MifareClassic.java
@@ -0,0 +1,291 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+import java.io.IOException;
+
+/**
+ * Concrete class for TagTechnology.MIFARE_CLASSIC
+ *
+ * Mifare classic has n sectors, with varying sizes, although
+ * they are at least the same pattern for any one mifare classic
+ * product. Each sector has two keys. Authentication with the correct
+ * key is needed before access to any sector.
+ *
+ * Each sector has k blocks.
+ * Block size is constant across the whole mifare classic family.
+ */
+public final class MifareClassic extends BasicTagTechnology {
+ /**
+ * The well-known, default factory MIFARE read key.
+ * Use this key to effectively make the payload in this sector
+ * public.
+ */
+ public static final byte[] DEFAULT_KEY_FACTORY =
+ {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
+ public static final byte[] DEFAULT_KEY_ZERO =
+ {(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00};
+ /**
+ * The well-known, default Mifare Application Directory read key.
+ */
+ public static final byte[] DEFAULT_KEY_MAD =
+ {(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
+ /**
+ * The well-known, default read key for NDEF data on a Mifare Classic
+ */
+ public static final byte[] DEFAULT_KEY_NFC_FORUM =
+ {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
+
+ public static final int TYPE_CLASSIC = 0;
+ public static final int TYPE_PLUS = 1;
+ public static final int TYPE_PRO = 2;
+ public static final int TYPE_DESFIRE = 3;
+ public static final int TYPE_ULTRALIGHT = 4;
+ public static final int TYPE_UNKNOWN = 5;
+
+ public static final int SIZE_1K = 1024;
+ public static final int SIZE_2K = 2048;
+ public static final int SIZE_4K = 4096;
+ public static final int SIZE_MINI = 320;
+ public static final int SIZE_UNKNOWN = 0;
+
+ private boolean mIsEmulated;
+ private int mType;
+ private int mSize;
+
+ public MifareClassic(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
+ super(adapter, tag, TagTechnology.MIFARE_CLASSIC);
+
+ // Check if this could actually be a Mifare
+ NfcA a = (NfcA) tag.getTechnology(TagTechnology.NFC_A);
+ //short[] ATQA = getATQA(tag);
+
+ mIsEmulated = false;
+ mType = TYPE_UNKNOWN;
+ mSize = SIZE_UNKNOWN;
+
+ switch (a.getSak()) {
+ case 0x00:
+ // could be UL or UL-C
+ mType = TYPE_ULTRALIGHT;
+ break;
+ case 0x08:
+ // Type == classic
+ // Size = 1K
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_1K;
+ break;
+ case 0x09:
+ // Type == classic mini
+ // Size == ?
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_MINI;
+ break;
+ case 0x10:
+ // Type == MF+
+ // Size == 2K
+ // SecLevel = SL2
+ mType = TYPE_PLUS;
+ mSize = SIZE_2K;
+ break;
+ case 0x11:
+ // Type == MF+
+ // Size == 4K
+ // Seclevel = SL2
+ mType = TYPE_PLUS;
+ mSize = SIZE_4K;
+ break;
+ case 0x18:
+ // Type == classic
+ // Size == 4k
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_4K;
+ break;
+ case 0x20:
+ // TODO this really should be a short, not byte
+ if (a.getAtqa()[0] == 0x03) {
+ // Type == DESFIRE
+ mType = TYPE_DESFIRE;
+ } else {
+ // Type == MF+
+ // SL = SL3
+ mType = TYPE_PLUS;
+ mSize = SIZE_UNKNOWN;
+ }
+ break;
+ case 0x28:
+ // Type == MF Classic
+ // Size == 1K
+ // Emulated == true
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_1K;
+ mIsEmulated = true;
+ break;
+ case 0x38:
+ // Type == MF Classic
+ // Size == 4K
+ // Emulated == true
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_4K;
+ mIsEmulated = true;
+ break;
+ case 0x88:
+ // Type == MF Classic
+ // Size == 1K
+ // NXP-tag: false
+ mType = TYPE_CLASSIC;
+ mSize = SIZE_1K;
+ break;
+ case 0x98:
+ case 0xB8:
+ // Type == MF Pro
+ // Size == 4K
+ mType = TYPE_PRO;
+ mSize = SIZE_4K;
+ break;
+ default:
+ // Unknown, not MIFARE
+ break;
+ }
+ }
+
+ // Immutable data known at discovery time
+ public int getSize() {
+ return mSize;
+ }
+
+ public int getType() {
+ return mType;
+ }
+
+ public boolean isEmulated() {
+ return mIsEmulated;
+ }
+
+ public int getSectorCount() {
+ switch (mSize) {
+ case SIZE_1K: {
+ return 16;
+ }
+ case SIZE_2K: {
+ return 32;
+ }
+ case SIZE_4K: {
+ return 40;
+ }
+ case SIZE_MINI: {
+ return 5;
+ }
+ default: {
+ return 0;
+ }
+ }
+ }
+
+ public int getSectorSize(int sector) {
+ return getBlockCount(sector) * 16;
+ }
+
+ public int getBlockCount(int sector) {
+ if (sector >= getSectorCount()) {
+ throw new IllegalArgumentException("this card only has " + getSectorCount() +
+ " sectors");
+ }
+
+ if (sector <= 32) {
+ return 4;
+ } else {
+ return 16;
+ }
+ }
+
+ private byte firstBlockInSector(int sector) {
+ if (sector < 32) {
+ return (byte) ((sector * 4) & 0xff);
+ } else {
+ return (byte) ((32 * 4 + ((sector - 32) * 16)) & 0xff);
+ }
+ }
+
+ // Methods that require connect()
+ /**
+ * Authenticate for a given sector.
+ */
+ public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
+ byte[] cmd = new byte[12];
+
+ // First byte is the command
+ if (keyA) {
+ cmd[0] = 0x60; // phHal_eMifareAuthentA
+ } else {
+ cmd[0] = 0x61; // phHal_eMifareAuthentB
+ }
+
+ // Second byte is block address
+ cmd[1] = firstBlockInSector(sector);
+
+ // Next 4 bytes are last 4 bytes of UID
+ byte[] uid = getTag().getId();
+ System.arraycopy(uid, uid.length - 4, cmd, 2, 4);
+
+ // Next 6 bytes are key
+ System.arraycopy(key, 0, cmd, 6, 6);
+
+ try {
+ if ((transceive(cmd) != null)) {
+ return true;
+ }
+ } catch (IOException e) {
+ // No need to deal with, will return false anyway
+ }
+ return false;
+ }
+
+ /**
+ * Sector indexing starts at 0.
+ * Block indexing starts at 0, and resets in each sector.
+ * @throws IOException
+ */
+ public byte[] readBlock(int sector, int block) throws IOException {
+ byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
+ byte[] blockread_cmd = { 0x30, addr }; // phHal_eMifareRead
+
+ // TODO deal with authentication problems
+ return transceive(blockread_cmd);
+ }
+
+// public byte[] readSector(int sector);
+ //TODO: define an enumeration for access control settings
+// public int readSectorAccessControl(int sector);
+
+ /**
+ * @throws IOException
+ * @throws NotAuthenticatedException
+ */
+/*
+ public void writeBlock(int block, byte[] data);
+ public void writeSector(int block, byte[] sector);
+ public void writeSectorAccessControl(int sector, int access);
+ public void increment(int block);
+ public void decrement(int block);
+*/
+}
diff --git a/core/java/android/nfc/NdefTagConnection.java b/core/java/android/nfc/technology/Ndef.java
similarity index 50%
rename from core/java/android/nfc/NdefTagConnection.java
rename to core/java/android/nfc/technology/Ndef.java
index aafdbfd945772..22460cf452762 100644
--- a/core/java/android/nfc/NdefTagConnection.java
+++ b/core/java/android/nfc/technology/Ndef.java
@@ -14,77 +14,54 @@
* limitations under the License.
*/
-package android.nfc;
+package android.nfc.technology;
+
+import android.nfc.ErrorCodes;
+import android.nfc.FormatException;
+import android.nfc.NdefMessage;
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
import java.io.IOException;
-import android.os.RemoteException;
-import android.util.Log;
-
/**
- * A connection to an NDEF target on an {@link NdefTag}.
- * You can acquire this kind of connection with {@link NfcAdapter#createNdefTagConnection
- * createNdefTagConnection()}. Use the connection to read or write {@link NdefMessage}s.
+ * A high-level connection to a {@link Tag} using one of the NFC type 1, 2, 3, or 4 technologies
+ * to interact with NDEF data. MiFare Classic cards that present NDEF data may also be used
+ * via this class. To determine the exact technology being used call {@link #getTechnologyId()}
+ *
+ * You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ *
* Note:
* Use of this class requires the {@link android.Manifest.permission#NFC}
* permission.
- * @hide
*/
-public class NdefTagConnection extends RawTagConnection {
+public final class Ndef extends BasicTagTechnology {
public static final int NDEF_MODE_READ_ONCE = 1;
public static final int NDEF_MODE_READ_ONLY = 2;
public static final int NDEF_MODE_WRITE_ONCE = 3;
public static final int NDEF_MODE_WRITE_MANY = 4;
public static final int NDEF_MODE_UNKNOWN = 5;
- private static final String TAG = "NFC";
-
/**
* Internal constructor, to be used by NfcAdapter
* @hide
*/
- /* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag, String target) throws RemoteException {
- super(adapter, tag);
- String[] targets = tag.getNdefTargets();
- int i;
-
- // Check target validity
- for (i=0; i Requires {@link android.Manifest.permission#NFC} permission.
- * @throws FormatException if the tag is not NDEF formatted
- * @throws IOException if the target is lost or connection closed
- * @throws FormatException
- */
- public NdefMessage[] readNdefMessages() throws IOException, FormatException {
- //TODO(nxp): do not use getLastError(), it is racy
+ public NdefMessage getNdefMessage() throws IOException, FormatException {
try {
- NdefMessage[] msgArray = new NdefMessage[1];
- NdefMessage msg = mTagService.read(mTag.mServiceHandle);
+ int serviceHandle = mTag.getServiceHandle();
+ NdefMessage msg = mTagService.read(serviceHandle);
if (msg == null) {
- int errorCode = mTagService.getLastError(mTag.mServiceHandle);
+ int errorCode = mTagService.getLastError(serviceHandle);
switch (errorCode) {
case ErrorCodes.ERROR_IO:
throw new IOException();
@@ -95,8 +72,7 @@ public class NdefTagConnection extends RawTagConnection {
throw new IOException();
}
}
- msgArray[0] = msg;
- return msgArray;
+ return msg;
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return null;
@@ -104,25 +80,56 @@ public class NdefTagConnection extends RawTagConnection {
}
/**
- * Attempt to write an NDEF message to a tag.
- * This method will block until the data is written. It can be canceled
- * with {@link RawTagConnection#close}.
- * Many tags are write-once, so use this method carefully.
- * Specification allows for multiple NDEF messages per NDEF tag, but it is
- * encourage to only write one message, this so API only takes a single
- * message. Use {@link NdefRecord} to write several records to a single tag.
- * For write-many tags, use {@link #makeReadOnly} after this method to attempt
- * to prevent further modification. For write-once tags this is not
- * necessary.
- * Requires {@link android.Manifest.permission#NFC} permission.
- *
- * @throws FormatException if the tag is not suitable for NDEF messages
- * @throws IOException if the target is lost or connection closed or the
- * write failed
+ * Get optional extra NDEF messages.
+ * Some tags may contain extra NDEF messages, but not all
+ * implementations will be able to read them.
*/
- public void writeNdefMessage(NdefMessage message) throws IOException, FormatException {
+ public NdefMessage[] getExtraNdefMessage() throws IOException, FormatException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Get maximum NDEF message size in bytes
+ */
+ public int getSize() {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Read/Write mode hint.
+ * Provides a hint if further reads or writes are likely to succeed.
+ * Requires {@link android.Manifest.permission#NFC} permission.
+ * @return one of NDEF_MODE
+ * @throws IOException if the target is lost or connection closed
+ */
+ public int getModeHint() throws IOException {
try {
- int errorCode = mTagService.write(mTag.mServiceHandle, message);
+ int result = mTagService.getModeHint(mTag.getServiceHandle());
+ if (ErrorCodes.isError(result)) {
+ switch (result) {
+ case ErrorCodes.ERROR_IO:
+ throw new IOException();
+ default:
+ // Should not happen
+ throw new IOException();
+ }
+ }
+ return result;
+
+ } catch (RemoteException e) {
+ attemptDeadServiceRecovery(e);
+ return NDEF_MODE_UNKNOWN;
+ }
+ }
+
+ // Methods that require connect()
+ /**
+ * Overwrite the primary NDEF message
+ * @throws IOException
+ */
+ public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
+ try {
+ int errorCode = mTagService.write(mTag.getServiceHandle(), msg);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
@@ -140,16 +147,26 @@ public class NdefTagConnection extends RawTagConnection {
}
/**
- * Attempts to make the NDEF data in this tag read-only.
- * This method will block until the action is complete. It can be canceled
- * with {@link RawTagConnection#close}.
- * Requires {@link android.Manifest.permission#NFC} permission.
- * @return true if the tag is now read-only
- * @throws IOException if the target is lost, or connection closed
+ * Attempt to write extra NDEF messages.
+ * Implementations may be able to write extra NDEF
+ * message after the first primary message, but it is not
+ * guaranteed. Even if it can be written, other implementations
+ * may not be able to read NDEF messages after the primary message.
+ * It is recommended to use additional NDEF records instead.
+ *
+ * @throws IOException
*/
- public boolean makeReadOnly() throws IOException {
+ public void writeExtraNdefMessage(int i, NdefMessage msg) throws IOException, FormatException {
+ throw new UnsupportedOperationException();
+ }
+
+ /**
+ * Set the CC field to indicate this tag is read-only
+ * @throws IOException
+ */
+ public boolean makeReadonly() throws IOException {
try {
- int errorCode = mTagService.makeReadOnly(mTag.mServiceHandle);
+ int errorCode = mTagService.makeReadOnly(mTag.getServiceHandle());
switch (errorCode) {
case ErrorCodes.SUCCESS:
return true;
@@ -168,29 +185,11 @@ public class NdefTagConnection extends RawTagConnection {
}
/**
- * Read/Write mode hint.
- * Provides a hint if further reads or writes are likely to succeed.
- * Requires {@link android.Manifest.permission#NFC} permission.
- * @return one of NDEF_MODE
- * @throws IOException if the target is lost or connection closed
+ * Attempt to use tag specific technology to really make
+ * the tag read-only
+ * For NFC Forum Type 1 and 2 only.
*/
- public int getModeHint() throws IOException {
- try {
- int result = mTagService.getModeHint(mTag.mServiceHandle);
- if (ErrorCodes.isError(result)) {
- switch (result) {
- case ErrorCodes.ERROR_IO:
- throw new IOException();
- default:
- // Should not happen
- throw new IOException();
- }
- }
- return result;
-
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- return NDEF_MODE_UNKNOWN;
- }
+ public void makeLowLevelReadonly() {
+ throw new UnsupportedOperationException();
}
-}
\ No newline at end of file
+}
diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/technology/NfcA.java
new file mode 100644
index 0000000000000..ef46762fd8933
--- /dev/null
+++ b/core/java/android/nfc/technology/NfcA.java
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * A low-level connection to a {@link Tag} using the NFC-A technology, also known as
+ * ISO1443-3A.
+ *
+ * You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * Note:
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcA extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_SAK = "sak";
+ /** @hide */
+ public static final String EXTRA_ATQA = "atqa";
+
+ private short mSak;
+ private byte[] mAtqa;
+
+ public NfcA(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
+ super(adapter, tag, TagTechnology.NFC_A);
+ mSak = extras.getShort(EXTRA_SAK);
+ mAtqa = extras.getByteArray(EXTRA_ATQA);
+ }
+
+ /**
+ * Returns the ATQA/SENS_RES bytes discovered at tag discovery.
+ */
+ public byte[] getAtqa() {
+ return mAtqa;
+ }
+
+ /**
+ * Returns the SAK/SEL_RES discovered at tag discovery.
+ */
+ public short getSak() {
+ return mSak;
+ }
+}
diff --git a/core/java/android/nfc/technology/NfcB.java b/core/java/android/nfc/technology/NfcB.java
new file mode 100644
index 0000000000000..64cb08a79501f
--- /dev/null
+++ b/core/java/android/nfc/technology/NfcB.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * A low-level connection to a {@link Tag} using the NFC-B technology, also known as
+ * ISO1443-3B.
+ *
+ * You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * Note:
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcB extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_ATQB = "atqb";
+
+ private byte[] mAtqb;
+
+ public NfcB(NfcAdapter adapter, Tag tag, Bundle extras)
+ throws RemoteException {
+ super(adapter, tag, TagTechnology.NFC_B);
+ }
+
+ /**
+ * Returns the ATQB/SENSB_RES bytes discovered at tag discovery.
+ */
+ public byte[] getAtqb() {
+ return mAtqb;
+ }
+}
diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/technology/NfcF.java
new file mode 100644
index 0000000000000..6741ac8257706
--- /dev/null
+++ b/core/java/android/nfc/technology/NfcF.java
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * A low-level connection to a {@link Tag} using the NFC-F technology, also known as
+ * JIS6319-4.
+ *
+ * You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * Note:
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcF extends BasicTagTechnology {
+ /** @hide */
+ public static final String EXTRA_SC = "systemcode";
+ /** @hide */
+ public static final String EXTRA_PMM = "pmm";
+
+ private byte[] mSystemCode = null;
+ private byte[] mManufacturer = null;
+
+ public NfcF(NfcAdapter adapter, Tag tag, Bundle extras)
+ throws RemoteException {
+ super(adapter, tag, TagTechnology.NFC_F);
+ if (extras != null) {
+ mSystemCode = extras.getByteArray(EXTRA_SC);
+ mManufacturer = extras.getByteArray(EXTRA_PMM);
+ }
+ }
+
+ public byte[] getSystemCode() {
+ return mSystemCode;
+ }
+
+ public byte[] getManufacturer() {
+ return mManufacturer;
+ }
+}
diff --git a/core/java/android/nfc/technology/NfcV.java b/core/java/android/nfc/technology/NfcV.java
new file mode 100644
index 0000000000000..9b6a16a5c9dc6
--- /dev/null
+++ b/core/java/android/nfc/technology/NfcV.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.NfcAdapter;
+import android.nfc.Tag;
+import android.os.Bundle;
+import android.os.RemoteException;
+
+/**
+ * A low-level connection to a {@link Tag} using the NFC-V technology, also known as
+ * ISO15693.
+ *
+ * You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
+ * Use this class to send and receive data with {@link #transceive transceive()}.
+ *
+ * Applications must implement their own protocol stack on top of
+ * {@link #transceive transceive()}.
+ *
+ * Note:
+ * Use of this class requires the {@link android.Manifest.permission#NFC}
+ * permission.
+ */
+public final class NfcV extends BasicTagTechnology {
+ public NfcV(NfcAdapter adapter, Tag tag, Bundle extras)
+ throws RemoteException {
+ super(adapter, tag, TagTechnology.NFC_V);
+ }
+}
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
new file mode 100644
index 0000000000000..c6c65e8dcb6f8
--- /dev/null
+++ b/core/java/android/nfc/technology/TagTechnology.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc.technology;
+
+import android.nfc.Tag;
+
+import java.io.IOException;
+
+public interface TagTechnology {
+ /**
+ * This object is an instance of {@link NfcA}
+ */
+ public static final int NFC_A = 1;
+
+ /**
+ * This object is an instance of {@link NfcB}
+ */
+ public static final int NFC_B = 2;
+
+ /**
+ * This object is an instance of {@link IsoDep}
+ */
+ public static final int ISO_DEP = 3;
+
+ /**
+ * This object is an instance of {@link NfcF}
+ */
+ public static final int NFC_F = 11;
+
+ /**
+ * This object is an instance of {@link NfcV}
+ */
+ public static final int NFC_V = 21;
+
+ /**
+ * This object is an instance of {@link Ndef}
+ */
+ public static final int TYPE_1 = 101;
+
+ /**
+ * This object is an instance of {@link Ndef}
+ */
+ public static final int TYPE_2 = 102;
+
+ /**
+ * This object is an instance of {@link Ndef}
+ */
+ public static final int TYPE_3 = 103;
+
+ /**
+ * This object is an instance of {@link Ndef}
+ */
+ public static final int TYPE_4 = 104;
+
+ /**
+ * This object is an instance of {@link MifareClassic}
+ */
+ public static final int MIFARE_CLASSIC = 200;
+
+ /**
+ * A Mifare Classic tag with NDEF data
+ */
+ public static final int MIFARE_CLASSIC_NDEF = 201;
+
+ /**
+ * A Mifare Ultralight tag
+ */
+ public static final int MIFARE_ULTRALIGHT = 202;
+
+ /**
+ * A Mifare DESFire tag
+ */
+ public static final int MIFARE_DESFIRE = 203;
+
+ /**
+ * Returns the technology type for this tag connection.
+ */
+ public int getTechnologyId();
+
+ /**
+ * Get the backing tag object.
+ */
+ public Tag getTag();
+
+ /**
+ * @throws IOException
+ */
+ public void connect() throws IOException;
+
+ /**
+ * Non-blocking. Immediately causes all blocking calls
+ * to throw IOException.
+ */
+ public void close();
+}
diff --git a/core/java/android/nfc/technology/package.html b/core/java/android/nfc/technology/package.html
new file mode 100644
index 0000000000000..26b8a328b1321
--- /dev/null
+++ b/core/java/android/nfc/technology/package.html
@@ -0,0 +1,5 @@
+
+
+ *
+ * The NDEF message is preserved across reboot.
*