am d8c32332: Merge "Merge branch gingerbread-nfc into gingerbread." into gingerbread

* commit 'd8c323321c28a0a5ff70c6e0694aa822edca4005':
  Fixed technology name typo's.
  Implement historical bytes / attrib on IsoDep
  Provide system code and manufacturer code for Felica tech.
  Fixed NfcAdapter init and getTechnology().
  Secure Element access implementation
  Rough first pass at the NFC technology API.
  Revert "Merge "Remove the My Tag feature." into gingerbread"
This commit is contained in:
Nick Pelly
2010-12-05 14:49:00 -08:00
committed by Android Git Automerger
20 changed files with 1162 additions and 579 deletions

View File

@ -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 \

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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.
* <p>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.
* <p>
* {@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.
* <p>{@link NfcAdapter#createNdefTagConnection createNdefTagConnection()} can be used to modify the
* contents of some tags.
* <p>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.
* <p>This is based on Jewel/Topaz technology
*/
public static final String TARGET_TYPE_1 = "type_1";
/**
* Target for NFC Forum Type 2 compliant tag.
* <p>This is based on Mifare Ultralight technology.
*/
public static final String TARGET_TYPE_2 = "type_2";
/**
* Target for NFC Forum Type 3 compliant tag.
* <p>This is based on Felica technology.
*/
public static final String TARGET_TYPE_3 = "type_3";
/**
* Target for NFC Forum Type 4 compliant tag.
* <p>This is based on Mifare Desfire technology.
*/
public static final String TARGET_TYPE_4 = "type_4";
/**
* Target for NFC Forum Enabled: Mifare Classic tag.
* <p>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.
* <p>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.
* <p>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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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.
* <p>
* 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<mNdefTargets.length; i++) {
if (target.equals(mNdefTargets[i])) {
return mMessages[i];
}
}
throw new IllegalArgumentException("target (" + target + ") not found");
}
/**
* Return the NDEF targets on this Tag that support NDEF messages.
*
* @return
*/
public String[] getNdefTargets() {
return mNdefTargets;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
// Tag fields
dest.writeInt(mIsNdef ? 1 : 0);
writeBytesWithNull(dest, mId);
dest.writeInt(mRawTargets.length);
dest.writeStringArray(mRawTargets);
writeBytesWithNull(dest, mPollBytes);
writeBytesWithNull(dest, mActivationBytes);
dest.writeInt(mServiceHandle);
// NdefTag fields
dest.writeInt(mNdefTargets.length);
dest.writeStringArray(mNdefTargets);
dest.writeInt(mMessages.length);
for (NdefMessage[] ms : mMessages) {
dest.writeInt(ms.length);
dest.writeTypedArray(ms, flags);
}
}
public static final Parcelable.Creator<NdefTag> CREATOR =
new Parcelable.Creator<NdefTag>() {
public NdefTag createFromParcel(Parcel in) {
boolean isNdef = (in.readInt() == 1);
if (!isNdef) {
throw new IllegalArgumentException("Creating NdefTag from Tag parcel");
}
// Tag fields
byte[] id = readBytesWithNull(in);
String[] rawTargets = new String[in.readInt()];
in.readStringArray(rawTargets);
byte[] pollBytes = readBytesWithNull(in);
byte[] activationBytes = readBytesWithNull(in);
int serviceHandle = in.readInt();
// NdefTag fields
String[] ndefTargets = new String[in.readInt()];
in.readStringArray(ndefTargets);
NdefMessage[][] messages = new NdefMessage[in.readInt()][];
for (int i=0; i<messages.length; i++) {
messages[i] = new NdefMessage[in.readInt()];
in.readTypedArray(messages[i], NdefMessage.CREATOR);
}
return new NdefTag(id, rawTargets, pollBytes, activationBytes, serviceHandle,
ndefTargets, messages);
}
public NdefTag[] newArray(int size) {
return new NdefTag[size];
}
};
}

View File

@ -1,25 +1,26 @@
/*
* 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.
* 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 java.lang.UnsupportedOperationException;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.app.ActivityThread;
import android.content.Context;
import android.content.pm.IPackageManager;
import android.content.pm.PackageManager;
import android.nfc.INfcAdapter;
import android.os.IBinder;
import android.os.RemoteException;
import android.os.ServiceManager;
@ -39,6 +40,12 @@ public final class NfcAdapter {
@SdkConstant(SdkConstantType.ACTIVITY_INTENT_ACTION)
public static final String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED";
/**
* Broadcast to only the activity that handles ACTION_TAG_DISCOVERED
* @hide
*/
public static final String ACTION_TAG_LEFT_FIELD = "android.nfc.action.TAG_LOST";
/**
* Mandatory Tag extra for the ACTION_TAG intents.
* @hide
@ -169,6 +176,14 @@ public final class NfcAdapter {
mService = service;
}
/**
* Returns the binder interface to the service.
* @hide
*/
public INfcAdapter getService() {
return mService;
}
/**
* Helper to check if this device has FEATURE_NFC, but without using
* a context.
@ -230,8 +245,11 @@ public final class NfcAdapter {
}
}
/** NFC service dead - attempt best effort recovery */
/*package*/ void attemptDeadServiceRecovery(Exception e) {
/**
* NFC service dead - attempt best effort recovery
* @hide
*/
public void attemptDeadServiceRecovery(Exception e) {
Log.e(TAG, "NFC service dead - attempting to recover", e);
INfcAdapter service = getServiceInterface();
if (service == null) {
@ -301,16 +319,41 @@ public final class NfcAdapter {
}
/**
* Create a raw tag connection to the default Target
* Set the NDEF Message that this NFC adapter should appear as to Tag
* readers.
* <p>
* Any Tag reader can read the contents of the local tag when it is in
* proximity, without any further user confirmation.
* <p>
* The implementation of this method must either
* <ul>
* <li>act as a passive tag containing this NDEF message
* <li>provide the NDEF message on over LLCP to peer NFC adapters
* </ul>
* The NDEF message is preserved across reboot.
* <p>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.
* <p>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
* <p>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
* <p>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
* <p>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;
}
}

View File

@ -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;
}
}
}

View File

@ -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)}).
* <p>
* 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}.
* <p>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.
* <p>
* 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.
* <p>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.
* <p>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).
* <p>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.
* <p>These can be used to help with advanced identification of a Tag.
* <p>The meaning of these bytes depends on the Tag technology.
* <p>ISO14443-3A: ATQA/SENS_RES
* <p>ISO14443-3B: Application data (4 bytes) and Protocol Info (3 bytes) from ATQB/SENSB_RES
* <p>JIS_X_6319_4: PAD0 (2 byte), PAD1 (2 byte), MRTI(2 byte), PAD2 (1 byte), RC (2 byte)
* <p>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.
* <p>These can be used to help with advanced identification of a Tag.
* <p>The meaning of these bytes depends on the Tag technology.
* <p>ISO14443-3A: SAK/SEL_RES
* <p>ISO14443-3B: null
* <p>ISO14443-3A & ISO14443-4: SAK/SEL_RES, historical bytes from ATS <TODO: confirm>
* <p>ISO14443-3B & ISO14443-4: ATTRIB response
* <p>JIS_X_6319_4: null
* <p>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,35 +207,30 @@ 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<Tag> CREATOR =
new Parcelable.Creator<Tag>() {
@Override
public Tag createFromParcel(Parcel in) {
boolean isNdef = (in.readInt() == 1);
if (isNdef) {
throw new IllegalArgumentException("Creating Tag from NdefTag parcel");
}
// Tag fields
byte[] id = Tag.readBytesWithNull(in);
String[] rawTargets = new String[in.readInt()];
in.readStringArray(rawTargets);
byte[] pollBytes = Tag.readBytesWithNull(in);
byte[] activationBytes = Tag.readBytesWithNull(in);
int[] techList = new int[in.readInt()];
in.readIntArray(techList);
Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
int serviceHandle = in.readInt();
return new Tag(id, isNdef, rawTargets, pollBytes, activationBytes, serviceHandle);
return new Tag(id, techList, techExtras, serviceHandle);
}
@Override
public Tag[] newArray(int size) {
return new Tag[size];
}

View File

@ -14,31 +14,25 @@
* limitations under the License.
*/
package android.nfc;
package android.nfc.technology;
import java.io.IOException;
import android.nfc.INfcAdapter;
import android.nfc.INfcTag;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.RemoteException;
import android.util.Log;
/**
* A low-level connection to a {@link Tag} target.
* <p>You can acquire this kind of connection with {@link NfcAdapter#createRawTagConnection
* createRawTagConnection()}. Use the connection to send and receive data with {@link #transceive
* transceive()}.
* <p>
* Applications must implement their own protocol stack on top of {@link #transceive transceive()}.
*
* <p class="note"><strong>Note:</strong>
* 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<targets.length;i++) {
if (target.equals(targets[i])) {
for (i = 0; i < techList.length; i++) {
if (tech == techList[i]) {
break;
}
}
if (i >= targets.length) {
// Target not found
throw new IllegalArgumentException();
if (i >= techList.length) {
// Technology not found
throw new IllegalArgumentException("Technology " + tech + " not present on tag " + tag);
}
mAdapter = adapter;
mService = mAdapter.mService;
mService = mAdapter.getService();
try {
mTagService = mService.getNfcTagInterface();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}
mTag = tag;
mSelectedTarget = target;
mSelectedTechnology = tech;
}
/*package*/ RawTagConnection(NfcAdapter adapter, Tag tag) throws RemoteException {
this(adapter, tag, tag.getRawTargets()[0]);
/**
* @hide
*/
public BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException {
this(adapter, tag, tag.getTechnologyList()[0]);
}
/** NFC service dead - attempt best effort recovery */
@ -80,7 +84,7 @@ public class RawTagConnection {
mAdapter.attemptDeadServiceRecovery(e);
/* assigning to mService is not thread-safe, but this is best-effort code
* and on a well-behaved system should never happen */
mService = mAdapter.mService;
mService = mAdapter.getService();
try {
mTagService = mService.getNfcTagInterface();
} catch (RemoteException e2) {
@ -92,6 +96,7 @@ public class RawTagConnection {
* Get the {@link Tag} this connection is associated with.
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*/
@Override
public Tag getTag() {
return mTag;
}
@ -99,8 +104,9 @@ public class RawTagConnection {
/**
* <p>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 {
* <p>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.
* <p>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");
}

View File

@ -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.
*
* <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
* Use this class to send and receive data with {@link #transceive transceive()}.
*
* <p>Applications must implement their own protocol stack on top of
* {@link #transceive transceive()}.
*
* <p class="note"><strong>Note:</strong>
* 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();
}
}

View File

@ -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);
*/
}

View File

@ -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}.
* <p>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()}
*
* <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
*
* <p class="note"><strong>Note:</strong>
* 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<targets.length; i++) {
if (target.equals(targets[i])) {
break;
}
}
if (i >= targets.length) {
// Target not found
throw new IllegalArgumentException();
}
public Ndef(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
super(adapter, tag, tech);
}
/**
* Internal constructor, to be used by NfcAdapter
* @hide
* Get the primary NDEF message on this tag. This data is read at discovery time
* and does not require a connection.
*/
/* package private */ NdefTagConnection(NfcAdapter adapter, NdefTag tag) throws RemoteException {
this(adapter, tag, tag.getNdefTargets()[0]);
}
/**
* Read NDEF message(s).
* This will always return the most up to date payload, and can block.
* It can be canceled with {@link RawTagConnection#close}.
* Most NDEF tags will contain just one NDEF message.
* <p>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.
* <p>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.
* <p>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}.
* <p>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.
* <p>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();
}
}

View File

@ -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.
*
* <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
* Use this class to send and receive data with {@link #transceive transceive()}.
*
* <p>Applications must implement their own protocol stack on top of
* {@link #transceive transceive()}.
*
* <p class="note"><strong>Note:</strong>
* 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;
}
}

View File

@ -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.
*
* <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
* Use this class to send and receive data with {@link #transceive transceive()}.
*
* <p>Applications must implement their own protocol stack on top of
* {@link #transceive transceive()}.
*
* <p class="note"><strong>Note:</strong>
* 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;
}
}

View File

@ -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.
*
* <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
* Use this class to send and receive data with {@link #transceive transceive()}.
*
* <p>Applications must implement their own protocol stack on top of
* {@link #transceive transceive()}.
*
* <p class="note"><strong>Note:</strong>
* 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;
}
}

View File

@ -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.
*
* <p>You can acquire this kind of connection with {@link Tag#getTechnology(int)}.
* Use this class to send and receive data with {@link #transceive transceive()}.
*
* <p>Applications must implement their own protocol stack on top of
* {@link #transceive transceive()}.
*
* <p class="note"><strong>Note:</strong>
* 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);
}
}

View File

@ -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();
}

View File

@ -0,0 +1,5 @@
<HTML>
<BODY>
{@hide}
</BODY>
</HTML>