M7350v1_en_gpl

This commit is contained in:
T
2024-09-09 08:52:07 +00:00
commit f9cc65cfda
65988 changed files with 26357421 additions and 0 deletions

View File

@@ -0,0 +1,153 @@
/*
* 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.tech;
import android.nfc.ErrorCodes;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.nfc.TransceiveResult;
import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
/**
* A base class for tag technologies that are built on top of transceive().
*/
/* package */ abstract class BasicTagTechnology implements TagTechnology {
private static final String TAG = "NFC";
/*package*/ final Tag mTag;
/*package*/ boolean mIsConnected;
/*package*/ int mSelectedTechnology;
BasicTagTechnology(Tag tag, int tech) throws RemoteException {
mTag = tag;
mSelectedTechnology = tech;
}
@Override
public Tag getTag() {
return mTag;
}
/** Internal helper to throw IllegalStateException if the technology isn't connected */
void checkConnected() {
if ((mTag.getConnectedTechnology() != mSelectedTechnology) ||
(mTag.getConnectedTechnology() == -1)) {
throw new IllegalStateException("Call connect() first!");
}
}
@Override
public boolean isConnected() {
if (!mIsConnected) {
return false;
}
try {
return mTag.getTagService().isPresent(mTag.getServiceHandle());
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
return false;
}
}
@Override
public void connect() throws IOException {
try {
int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(),
mSelectedTechnology);
if (errorCode == ErrorCodes.SUCCESS) {
// Store this in the tag object
mTag.setConnectedTechnology(mSelectedTechnology);
mIsConnected = true;
} else {
throw new IOException();
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
throw new IOException("NFC service died");
}
}
/** @hide */
@Override
public void reconnect() throws IOException {
if (!mIsConnected) {
throw new IllegalStateException("Technology not connected yet");
}
try {
int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
if (errorCode != ErrorCodes.SUCCESS) {
mIsConnected = false;
mTag.setTechnologyDisconnected();
throw new IOException();
}
} catch (RemoteException e) {
mIsConnected = false;
mTag.setTechnologyDisconnected();
Log.e(TAG, "NFC service dead", e);
throw new IOException("NFC service died");
}
}
@Override
public void close() throws IOException {
try {
/* Note that we don't want to physically disconnect the tag,
* but just reconnect to it to reset its state
*/
mTag.getTagService().reconnect(mTag.getServiceHandle());
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
} finally {
mIsConnected = false;
mTag.setTechnologyDisconnected();
}
}
/** Internal transceive */
/*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException {
checkConnected();
try {
TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(),
data, raw);
if (result == null) {
throw new IOException("transceive failed");
} else {
if (result.isSuccessful()) {
return result.getResponseData();
} else {
if (result.isTagLost()) {
throw new TagLostException("Tag was lost.");
}
else {
throw new IOException("transceive failed");
}
}
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
throw new IOException("NFC service died");
}
}
}

View File

@@ -0,0 +1,161 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
/**
* Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations on a {@link Tag}.
*
* <p>Acquire an {@link IsoDep} object using {@link #get}.
* <p>The primary ISO-DEP I/O operation is {@link #transceive}. Applications must
* implement their own protocol stack on top of {@link #transceive}.
* <p>Tags that enumerate the {@link IsoDep} technology in {@link Tag#getTechList}
* will also enumerate
* {@link NfcA} or {@link NfcB} (since IsoDep builds on top of either of these).
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class IsoDep extends BasicTagTechnology {
private static final String TAG = "NFC";
/** @hide */
public static final String EXTRA_HI_LAYER_RESP = "hiresp";
/** @hide */
public static final String EXTRA_HIST_BYTES = "histbytes";
private byte[] mHiLayerResponse = null;
private byte[] mHistBytes = null;
/**
* Get an instance of {@link IsoDep} for the given tag.
* <p>Does not cause any RF activity and does not block.
* <p>Returns null if {@link IsoDep} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag does not support ISO-DEP.
*
* @param tag an ISO-DEP compatible tag
* @return ISO-DEP object
*/
public static IsoDep get(Tag tag) {
if (!tag.hasTech(TagTechnology.ISO_DEP)) return null;
try {
return new IsoDep(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public IsoDep(Tag tag)
throws RemoteException {
super(tag, TagTechnology.ISO_DEP);
Bundle extras = tag.getTechExtras(TagTechnology.ISO_DEP);
if (extras != null) {
mHiLayerResponse = extras.getByteArray(EXTRA_HI_LAYER_RESP);
mHistBytes = extras.getByteArray(EXTRA_HIST_BYTES);
}
}
/**
* Set the timeout of {@link #transceive} in milliseconds.
* <p>The timeout only applies to ISO-DEP {@link #transceive}, and is
* reset to a default value when {@link #close} is called.
* <p>Setting a longer timeout may be useful when performing
* transactions that require a long processing time on the tag
* such as key generation.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param timeout timeout value in milliseconds
*/
public void setTimeout(int timeout) {
try {
mTag.getTagService().setIsoDepTimeout(timeout);
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
}
@Override
public void close() throws IOException {
try {
mTag.getTagService().resetIsoDepTimeout();
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
super.close();
}
/**
* Return the ISO-DEP historical bytes for {@link NfcA} tags.
* <p>Does not cause any RF activity and does not block.
* <p>The historical bytes can be used to help identify a tag. They are present
* only on {@link IsoDep} tags that are based on {@link NfcA} RF technology.
* If this tag is not {@link NfcA} then null is returned.
* <p>In ISO 14443-4 terminology, the historical bytes are a subset of the RATS
* response.
*
* @return ISO-DEP historical bytes, or null if this is not a {@link NfcA} tag
*/
public byte[] getHistoricalBytes() {
return mHistBytes;
}
/**
* Return the higher layer response bytes for {@link NfcB} tags.
* <p>Does not cause any RF activity and does not block.
* <p>The higher layer response bytes can be used to help identify a tag.
* They are present only on {@link IsoDep} tags that are based on {@link NfcB}
* RF technology. If this tag is not {@link NfcB} then null is returned.
* <p>In ISO 14443-4 terminology, the higher layer bytes are a subset of the
* ATTRIB response.
*
* @return ISO-DEP historical bytes, or null if this is not a {@link NfcB} tag
*/
public byte[] getHiLayerResponse() {
return mHiLayerResponse;
}
/**
* Send raw ISO-DEP data to the tag and receive the response.
*
* <p>Applications must only send the INF payload, and not the start of frame and
* end of frame indicators. Applications do not need to fragment the payload, it
* will be automatically fragmented and defragmented by {@link #transceive} if
* it exceeds FSD/FSC limits.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param data command bytes to send, must not be null
* @return response bytes received, will not be null
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or this operation is canceled
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
}

View File

@@ -0,0 +1,596 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.os.RemoteException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
/**
* Provides access to MIFARE Classic properties and I/O operations on a {@link Tag}.
*
* <p>Acquire a {@link MifareClassic} object using {@link #get}.
*
* <p>MIFARE Classic is also known as MIFARE Standard.
* <p>MIFARE Classic tags are divided into sectors, and each sector is sub-divided into
* blocks. Block size is always 16 bytes ({@link #BLOCK_SIZE}. Sector size varies.
* <ul>
* <li>MIFARE Classic Mini are 320 bytes ({@link #SIZE_MINI}), with 5 sectors each of 4 blocks.
* <li>MIFARE Classic 1k are 1024 bytes ({@link #SIZE_1K}), with 16 sectors each of 4 blocks.
* <li>MIFARE Classic 2k are 2048 bytes ({@link #SIZE_2K}), with 32 sectors each of 4 blocks.
* <li>MIFARE Classic 4k} are 4096 bytes ({@link #SIZE_4K}). The first 32 sectors contain 4 blocks
* and the last 8 sectors contain 16 blocks.
* </ul>
*
* <p>MIFARE Classic tags require authentication on a per-sector basis before any
* other I/O operations on that sector can be performed. There are two keys per sector,
* and ACL bits determine what I/O operations are allowed on that sector after
* authenticating with a key. {@see #authenticateSectorWithKeyA} and
* {@see #authenticateSectorWithKeyB}.
*
* <p>Three well-known authentication keys are defined in this class:
* {@link #KEY_DEFAULT}, {@link #KEY_MIFARE_APPLICATION_DIRECTORY},
* {@link #KEY_NFC_FORUM}.
* <ul>
* <li>{@link #KEY_DEFAULT} is the default factory key for MIFARE Classic.
* <li>{@link #KEY_MIFARE_APPLICATION_DIRECTORY} is the well-known key for
* MIFARE Classic cards that have been formatted according to the
* MIFARE Application Directory (MAD) specification.
* <li>{@link #KEY_NFC_FORUM} is the well-known key for MIFARE Classic cards that
* have been formatted according to the NXP specification for NDEF on MIFARE Classic.
*
* <p>Implementation of this class on a Android NFC device is optional.
* If it is not implemented, then
* {@link MifareClassic} will never be enumerated in {@link Tag#getTechList}.
* If it is enumerated, then all {@link MifareClassic} I/O operations will be supported,
* and {@link Ndef#MIFARE_CLASSIC} NDEF tags will also be supported. In either case,
* {@link NfcA} will also be enumerated on the tag, because all MIFARE Classic tags are also
* {@link NfcA}.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class MifareClassic extends BasicTagTechnology {
/**
* The default factory key.
*/
public static final byte[] KEY_DEFAULT =
{(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
/**
* The well-known key for tags formatted according to the
* MIFARE Application Directory (MAD) specification.
*/
public static final byte[] KEY_MIFARE_APPLICATION_DIRECTORY =
{(byte)0xA0,(byte)0xA1,(byte)0xA2,(byte)0xA3,(byte)0xA4,(byte)0xA5};
/**
* The well-known key for tags formatted according to the
* NDEF on Mifare Classic specification.
*/
public static final byte[] KEY_NFC_FORUM =
{(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
/** A Mifare Classic compatible card of unknown type */
public static final int TYPE_UNKNOWN = -1;
/** A MIFARE Classic tag */
public static final int TYPE_CLASSIC = 0;
/** A MIFARE Plus tag */
public static final int TYPE_PLUS = 1;
/** A MIFARE Pro tag */
public static final int TYPE_PRO = 2;
/** Tag contains 16 sectors, each with 4 blocks. */
public static final int SIZE_1K = 1024;
/** Tag contains 32 sectors, each with 4 blocks. */
public static final int SIZE_2K = 2048;
/**
* Tag contains 40 sectors. The first 32 sectors contain 4 blocks and the last 8 sectors
* contain 16 blocks.
*/
public static final int SIZE_4K = 4096;
/** Tag contains 5 sectors, each with 4 blocks. */
public static final int SIZE_MINI = 320;
/** Size of a MIFARE Classic block (in bytes) */
public static final int BLOCK_SIZE = 16;
private static final int MAX_BLOCK_COUNT = 256;
private static final int MAX_SECTOR_COUNT = 40;
private boolean mIsEmulated;
private int mType;
private int mSize;
/**
* Get an instance of {@link MifareClassic} for the given tag.
* <p>Does not cause any RF activity and does not block.
* <p>Returns null if {@link MifareClassic} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag is not MIFARE Classic compatible, or this Android
* device does not support MIFARE Classic.
*
* @param tag an MIFARE Classic compatible tag
* @return MIFARE Classic object
*/
public static MifareClassic get(Tag tag) {
if (!tag.hasTech(TagTechnology.MIFARE_CLASSIC)) return null;
try {
return new MifareClassic(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public MifareClassic(Tag tag) throws RemoteException {
super(tag, TagTechnology.MIFARE_CLASSIC);
NfcA a = NfcA.get(tag); // Mifare Classic is always based on NFC a
mIsEmulated = false;
switch (a.getSak()) {
case 0x08:
mType = TYPE_CLASSIC;
mSize = SIZE_1K;
break;
case 0x09:
mType = TYPE_CLASSIC;
mSize = SIZE_MINI;
break;
case 0x10:
mType = TYPE_PLUS;
mSize = SIZE_2K;
// SecLevel = SL2
break;
case 0x11:
mType = TYPE_PLUS;
mSize = SIZE_4K;
// Seclevel = SL2
break;
case 0x18:
mType = TYPE_CLASSIC;
mSize = SIZE_4K;
break;
case 0x28:
mType = TYPE_CLASSIC;
mSize = SIZE_1K;
mIsEmulated = true;
break;
case 0x38:
mType = TYPE_CLASSIC;
mSize = SIZE_4K;
mIsEmulated = true;
break;
case 0x88:
mType = TYPE_CLASSIC;
mSize = SIZE_1K;
// NXP-tag: false
break;
case 0x98:
case 0xB8:
mType = TYPE_PRO;
mSize = SIZE_4K;
break;
default:
// Stack incorrectly reported a MifareClassic. We cannot handle this
// gracefully - we have no idea of the memory layout. Bail.
throw new RuntimeException(
"Tag incorrectly enumerated as Mifare Classic, SAK = " + a.getSak());
}
}
/**
* Return the type of this MIFARE Classic compatible tag.
* <p>One of {@link #TYPE_UNKNOWN}, {@link #TYPE_CLASSIC}, {@link #TYPE_PLUS} or
* {@link #TYPE_PRO}.
* <p>Does not cause any RF activity and does not block.
*
* @return type
*/
public int getType() {
return mType;
}
/**
* Return the size of the tag in bytes
* <p>One of {@link #SIZE_MINI}, {@link #SIZE_1K}, {@link #SIZE_2K}, {@link #SIZE_4K}.
* These constants are equal to their respective size in bytes.
* <p>Does not cause any RF activity and does not block.
* @return size in bytes
*/
public int getSize() {
return mSize;
}
/**
* Return true if the tag is emulated, determined at discovery time.
* These are actually smart-cards that emulate a Mifare Classic interface.
* They can be treated identically to a Mifare Classic tag.
* @hide
*/
public boolean isEmulated() {
return mIsEmulated;
}
/**
* Return the number of MIFARE Classic sectors.
* <p>Does not cause any RF activity and does not block.
* @return number of sectors
*/
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;
}
}
/**
* Return the total number of MIFARE Classic blocks.
* <p>Does not cause any RF activity and does not block.
* @return total number of blocks
*/
public int getBlockCount() {
return mSize / BLOCK_SIZE;
}
/**
* Return the number of blocks in the given sector.
* <p>Does not cause any RF activity and does not block.
*
* @param sectorIndex index of sector, starting from 0
* @return number of blocks in the sector
*/
public int getBlockCountInSector(int sectorIndex) {
validateSector(sectorIndex);
if (sectorIndex < 32) {
return 4;
} else {
return 16;
}
}
/**
* Return the sector that contains a given block.
* <p>Does not cause any RF activity and does not block.
*
* @param blockIndex index of block to lookup, starting from 0
* @return sector index that contains the block
*/
public int blockToSector(int blockIndex) {
validateBlock(blockIndex);
if (blockIndex < 32 * 4) {
return blockIndex / 4;
} else {
return 32 + (blockIndex - 32 * 4) / 16;
}
}
/**
* Return the first block of a given sector.
* <p>Does not cause any RF activity and does not block.
*
* @param sectorIndex index of sector to lookup, starting from 0
* @return block index of first block in sector
*/
public int sectorToBlock(int sectorIndex) {
if (sectorIndex < 32) {
return sectorIndex * 4;
} else {
return 32 * 4 + (sectorIndex - 32) * 16;
}
}
/**
* Authenticate a sector with key A.
*
* <p>Successful authentication of a sector with key A enables other
* I/O operations on that sector. The set of operations granted by key A
* key depends on the ACL bits set in that sector. For more information
* see the MIFARE Classic specification on {@see http://www.nxp.com}.
*
* <p>A failed authentication attempt causes an implicit reconnection to the
* tag, so authentication to other sectors will be lost.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param sectorIndex index of sector to authenticate, starting from 0
* @param key 6-byte authentication key
* @return true on success, false on authentication failure
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public boolean authenticateSectorWithKeyA(int sectorIndex, byte[] key) throws IOException {
return authenticate(sectorIndex, key, true);
}
/**
* Authenticate a sector with key B.
*
* <p>Successful authentication of a sector with key B enables other
* I/O operations on that sector. The set of operations granted by key B
* depends on the ACL bits set in that sector. For more information
* see the MIFARE Classic specification on {@see http://www.nxp.com}.
*
* <p>A failed authentication attempt causes an implicit reconnection to the
* tag, so authentication to other sectors will be lost.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param sectorIndex index of sector to authenticate, starting from 0
* @param key 6-byte authentication key
* @return true on success, false on authentication failure
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public boolean authenticateSectorWithKeyB(int sectorIndex, byte[] key) throws IOException {
return authenticate(sectorIndex, key, false);
}
private boolean authenticate(int sector, byte[] key, boolean keyA) throws IOException {
validateSector(sector);
checkConnected();
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
// Authenticate command takes a block address. Authenticating a block
// of a sector will authenticate the entire sector.
cmd[1] = (byte) sectorToBlock(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, false) != null) {
return true;
}
} catch (TagLostException e) {
throw e;
} catch (IOException e) {
// No need to deal with, will return false anyway
}
return false;
}
/**
* Read 16-byte block.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param blockIndex index of block to read, starting from 0
* @return 16 byte block
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public byte[] readBlock(int blockIndex) throws IOException {
validateBlock(blockIndex);
checkConnected();
byte[] cmd = { 0x30, (byte) blockIndex };
return transceive(cmd, false);
}
/**
* Write 16-byte block.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param blockIndex index of block to write, starting from 0
* @param data 16 bytes of data to write
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public void writeBlock(int blockIndex, byte[] data) throws IOException {
validateBlock(blockIndex);
checkConnected();
if (data.length != 16) {
throw new IllegalArgumentException("must write 16-bytes");
}
byte[] cmd = new byte[data.length + 2];
cmd[0] = (byte) 0xA0; // MF write command
cmd[1] = (byte) blockIndex;
System.arraycopy(data, 0, cmd, 2, data.length);
transceive(cmd, false);
}
/**
* Increment a value block, storing the result in the temporary block on the tag.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param blockIndex index of block to increment, starting from 0
* @param value non-negative to increment by
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public void increment(int blockIndex, int value) throws IOException {
validateBlock(blockIndex);
validateValueOperand(value);
checkConnected();
ByteBuffer cmd = ByteBuffer.allocate(6);
cmd.order(ByteOrder.LITTLE_ENDIAN);
cmd.put( (byte) 0xC1 );
cmd.put( (byte) blockIndex );
cmd.putInt(value);
transceive(cmd.array(), false);
}
/**
* Decrement a value block, storing the result in the temporary block on the tag.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param blockIndex index of block to decrement, starting from 0
* @param value non-negative to decrement by
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public void decrement(int blockIndex, int value) throws IOException {
validateBlock(blockIndex);
validateValueOperand(value);
checkConnected();
ByteBuffer cmd = ByteBuffer.allocate(6);
cmd.order(ByteOrder.LITTLE_ENDIAN);
cmd.put( (byte) 0xC0 );
cmd.put( (byte) blockIndex );
cmd.putInt(value);
transceive(cmd.array(), false);
}
/**
* Copy from the temporary block to a value block.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param blockIndex index of block to copy to
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public void transfer(int blockIndex) throws IOException {
validateBlock(blockIndex);
checkConnected();
byte[] cmd = { (byte) 0xB0, (byte) blockIndex };
transceive(cmd, false);
}
/**
* Copy from a value block to the temporary block.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param blockIndex index of block to copy from
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public void restore(int blockIndex) throws IOException {
validateBlock(blockIndex);
checkConnected();
byte[] cmd = { (byte) 0xC2, (byte) blockIndex };
transceive(cmd, false);
}
/**
* Send raw NfcA data to a tag and receive the response.
*
* <p>This is equivalent to connecting to this tag via {@link NfcA}
* and calling {@link NfcA#transceive}. Note that all MIFARE Classic
* tags are based on {@link NfcA} technology.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see NfcA#transceive
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
private static void validateSector(int sector) {
// Do not be too strict on upper bounds checking, since some cards
// have more addressable memory than they report. For example,
// Mifare Plus 2k cards will appear as Mifare Classic 1k cards when in
// Mifare Classic compatibility mode.
// Note that issuing a command to an out-of-bounds block is safe - the
// tag should report error causing IOException. This validation is a
// helper to guard against obvious programming mistakes.
if (sector < 0 || sector >= MAX_SECTOR_COUNT) {
throw new IndexOutOfBoundsException("sector out of bounds: " + sector);
}
}
private static void validateBlock(int block) {
// Just looking for obvious out of bounds...
if (block < 0 || block >= MAX_BLOCK_COUNT) {
throw new IndexOutOfBoundsException("block out of bounds: " + block);
}
}
private static void validateValueOperand(int value) {
if (value < 0) {
throw new IllegalArgumentException("value operand negative");
}
}
}

View File

@@ -0,0 +1,215 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.os.RemoteException;
import java.io.IOException;
//TOOD: Ultralight C 3-DES authentication, one-way counter
/**
* Provides access to MIFARE Ultralight properties and I/O operations on a {@link Tag}.
*
* <p>Acquire a {@link MifareUltralight} object using {@link #get}.
*
* <p>MIFARE Ultralight compatible tags have 4 byte pages {@link #PAGE_SIZE}.
* The primary operations on an Ultralight tag are {@link #readPages} and
* {@link #writePage}.
*
* <p>The original MIFARE Ultralight consists of a 64 byte EEPROM. The first
* 4 pages are for the OTP area, manufacturer data, and locking bits. They are
* readable and some bits are writable. The final 12 pages are the user
* read/write area. For more information see the NXP data sheet MF0ICU1.
*
* <p>The MIFARE Ultralight C consists of a 192 byte EEPROM. The first 4 pages
* are for OTP, manufacturer data, and locking bits. The next 36 pages are the
* user read/write area. The next 4 pages are additional locking bits, counters
* and authentication configuration and are readable. The final 4 pages are for
* the authentication key and are not readable. For more information see the
* NXP data sheet MF0ICU2.
*
* <p>Implementation of this class on a Android NFC device is optional.
* If it is not implemented, then
* {@link MifareUltralight} will never be enumerated in {@link Tag#getTechList}.
* If it is enumerated, then all {@link MifareUltralight} I/O operations will be supported.
* In either case, {@link NfcA} will also be enumerated on the tag,
* because all MIFARE Ultralight tags are also {@link NfcA} tags.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class MifareUltralight extends BasicTagTechnology {
/** A MIFARE Ultralight compatible tag of unknown type */
public static final int TYPE_UNKNOWN = -1;
/** A MIFARE Ultralight tag */
public static final int TYPE_ULTRALIGHT = 1;
/** A MIFARE Ultralight C tag */
public static final int TYPE_ULTRALIGHT_C = 2;
/** Size of a MIFARE Ultralight page in bytes */
public static final int PAGE_SIZE = 4;
private static final int NXP_MANUFACTURER_ID = 0x04;
private static final int MAX_PAGE_COUNT = 256;
private int mType;
/**
* Get an instance of {@link MifareUltralight} for the given tag.
* <p>Returns null if {@link MifareUltralight} was not enumerated in
* {@link Tag#getTechList} - this indicates the tag is not MIFARE
* Ultralight compatible, or that this Android
* device does not implement MIFARE Ultralight.
* <p>Does not cause any RF activity and does not block.
*
* @param tag an MIFARE Ultralight compatible tag
* @return MIFARE Ultralight object
*/
public static MifareUltralight get(Tag tag) {
if (!tag.hasTech(TagTechnology.MIFARE_ULTRALIGHT)) return null;
try {
return new MifareUltralight(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public MifareUltralight(Tag tag) throws RemoteException {
super(tag, TagTechnology.MIFARE_ULTRALIGHT);
// Check if this could actually be a Mifare
NfcA a = NfcA.get(tag);
mType = TYPE_UNKNOWN;
if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) {
// could be UL or UL-C
//TODO: stack should use NXP AN1303 procedure to make a best guess
// attempt at classifying Ultralight vs Ultralight C.
mType = TYPE_ULTRALIGHT;
}
}
/**
* Return the MIFARE Ultralight type of the tag.
* <p>One of {@link #TYPE_ULTRALIGHT} or {@link #TYPE_ULTRALIGHT_C} or
* {@link #TYPE_UNKNOWN}.
* <p>Depending on how the tag has been formatted, it can be impossible
* to accurately classify between original MIFARE Ultralight and
* Ultralight C. So treat this method as a hint.
* <p>Does not cause any RF activity and does not block.
*
* @return the type
*/
public int getType() {
return mType;
}
/**
* Read 4 pages (16 bytes).
*
* <p>The MIFARE Ultralight protocol always reads 4 pages at a time, to
* reduce the number of commands required to read an entire tag.
* <p>If a read spans past the last readable block, then the tag will
* return pages that have been wrapped back to the first blocks. MIFARE
* Ultralight tags have readable blocks 0x00 through 0x0F. So a read to
* block offset 0x0E would return blocks 0x0E, 0x0F, 0x00, 0x01. MIFARE
* Ultralight C tags have readable blocks 0x00 through 0x2B. So a read to
* block 0x2A would return blocks 0x2A, 0x2B, 0x00, 0x01.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param pageOffset index of first page to read, starting from 0
* @return 4 pages (16 bytes)
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public byte[] readPages(int pageOffset) throws IOException {
validatePageIndex(pageOffset);
checkConnected();
byte[] cmd = { 0x30, (byte) pageOffset};
return transceive(cmd, false);
}
/**
* Write 1 page (4 bytes).
*
* <p>The MIFARE Ultralight protocol always writes 1 page at a time, to
* minimize EEPROM write cycles.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param pageOffset index of page to write, starting from 0
* @param data 4 bytes to write
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public void writePage(int pageOffset, byte[] data) throws IOException {
validatePageIndex(pageOffset);
checkConnected();
byte[] cmd = new byte[data.length + 2];
cmd[0] = (byte) 0xA2;
cmd[1] = (byte) pageOffset;
System.arraycopy(data, 0, cmd, 2, data.length);
transceive(cmd, false);
}
/**
* Send raw NfcA data to a tag and receive the response.
*
* <p>This is equivalent to connecting to this tag via {@link NfcA}
* and calling {@link NfcA#transceive}. Note that all MIFARE Classic
* tags are based on {@link NfcA} technology.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see NfcA#transceive
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
private static void validatePageIndex(int pageIndex) {
// Do not be too strict on upper bounds checking, since some cards
// may have more addressable memory than they report.
// Note that issuing a command to an out-of-bounds block is safe - the
// tag will wrap the read to an addressable area. This validation is a
// helper to guard against obvious programming mistakes.
if (pageIndex < 0 || pageIndex >= MAX_PAGE_COUNT) {
throw new IndexOutOfBoundsException("page out of bounds: " + pageIndex);
}
}
}

View File

@@ -0,0 +1,389 @@
/*
* 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.tech;
import android.nfc.ErrorCodes;
import android.nfc.FormatException;
import android.nfc.INfcTag;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
/**
* Provides access to NDEF content and operations on a {@link Tag}.
*
* <p>Acquire a {@link Ndef} object using {@link #get}.
*
* <p>NDEF is an NFC Forum data format. The data formats are implemented in
* {@link android.nfc.NdefMessage} and
* {@link android.nfc.NdefRecord}. This class provides methods to
* retrieve and modify the {@link android.nfc.NdefMessage}
* on a tag.
*
* <p>There are currently four NFC Forum standardized tag types that can be
* formatted to contain NDEF data.
* <ul>
* <li>NFC Forum Type 1 Tag ({@link #NFC_FORUM_TYPE_1}), such as the Innovision Topaz
* <li>NFC Forum Type 2 Tag ({@link #NFC_FORUM_TYPE_2}), such as the NXP MIFARE Ultralight
* <li>NFC Forum Type 3 Tag ({@link #NFC_FORUM_TYPE_3}), such as Sony Felica
* <li>NFC Forum Type 4 Tag ({@link #NFC_FORUM_TYPE_4}), such as NXP MIFARE Desfire
* </ul>
* It is mandatory for all Android devices with NFC to correctly enumerate
* {@link Ndef} on NFC Forum Tag Types 1-4, and implement all NDEF operations
* as defined in this class.
*
* <p>Some vendors have there own well defined specifications for storing NDEF data
* on tags that do not fall into the above categories. Android devices with NFC
* should enumerate and implement {@link Ndef} under these vendor specifications
* where possible, but it is not mandatory. {@link #getType} returns a String
* describing this specification, for example {@link #MIFARE_CLASSIC} is
* <code>com.nxp.ndef.mifareclassic</code>.
*
* <p>Android devices that support MIFARE Classic must also correctly
* implement {@link Ndef} on MIFARE Classic tags formatted to NDEF.
*
* <p>For guaranteed compatibility across all Android devices with NFC, it is
* recommended to use NFC Forum Types 1-4 in new deployments of NFC tags
* with NDEF payload. Vendor NDEF formats will not work on all Android devices.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class Ndef extends BasicTagTechnology {
private static final String TAG = "NFC";
/** @hide */
public static final int NDEF_MODE_READ_ONLY = 1;
/** @hide */
public static final int NDEF_MODE_READ_WRITE = 2;
/** @hide */
public static final int NDEF_MODE_UNKNOWN = 3;
/** @hide */
public static final String EXTRA_NDEF_MSG = "ndefmsg";
/** @hide */
public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";
/** @hide */
public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate";
/** @hide */
public static final String EXTRA_NDEF_TYPE = "ndeftype";
/** @hide */
public static final int TYPE_OTHER = -1;
/** @hide */
public static final int TYPE_1 = 1;
/** @hide */
public static final int TYPE_2 = 2;
/** @hide */
public static final int TYPE_3 = 3;
/** @hide */
public static final int TYPE_4 = 4;
/** @hide */
public static final int TYPE_MIFARE_CLASSIC = 101;
/** @hide */
public static final int TYPE_ICODE_SLI = 102;
/** @hide */
public static final String UNKNOWN = "android.ndef.unknown";
/** NFC Forum Tag Type 1 */
public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
/** NFC Forum Tag Type 2 */
public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
/** NFC Forum Tag Type 4 */
public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
/** NFC Forum Tag Type 4 */
public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
/** NDEF on MIFARE Classic */
public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
/**
* NDEF on iCODE SLI
* @hide
*/
public static final String ICODE_SLI = "com.nxp.ndef.icodesli";
private final int mMaxNdefSize;
private final int mCardState;
private final NdefMessage mNdefMsg;
private final int mNdefType;
/**
* Get an instance of {@link Ndef} for the given tag.
*
* <p>Returns null if {@link Ndef} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag is not NDEF formatted, or that this tag
* is NDEF formatted but under a vendor specification that this Android
* device does not implement.
*
* <p>Does not cause any RF activity and does not block.
*
* @param tag an MIFARE Classic compatible tag
* @return MIFARE Classic object
*/
public static Ndef get(Tag tag) {
if (!tag.hasTech(TagTechnology.NDEF)) return null;
try {
return new Ndef(tag);
} catch (RemoteException e) {
return null;
}
}
/**
* Internal constructor, to be used by NfcAdapter
* @hide
*/
public Ndef(Tag tag) throws RemoteException {
super(tag, TagTechnology.NDEF);
Bundle extras = tag.getTechExtras(TagTechnology.NDEF);
if (extras != null) {
mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);
mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG);
mNdefType = extras.getInt(EXTRA_NDEF_TYPE);
} else {
throw new NullPointerException("NDEF tech extras are null.");
}
}
/**
* Get the {@link NdefMessage} that was read from the tag at discovery time.
*
* <p>If the NDEF Message is modified by an I/O operation then it
* will not be updated here, this function only returns what was discovered
* when the tag entered the field.
* <p>Does not cause any RF activity and does not block.
* @return NDEF Message read from the tag at discovery time
*/
public NdefMessage getCachedNdefMessage() {
return mNdefMsg;
}
/**
* Get the NDEF tag type.
*
* <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
* {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
* {@link #MIFARE_CLASSIC} or another NDEF tag type that has not yet been
* formalized in this Android API.
*
* <p>Does not cause any RF activity and does not block.
*
* @return a string representing the NDEF tag type
*/
public String getType() {
switch (mNdefType) {
case TYPE_1:
return NFC_FORUM_TYPE_1;
case TYPE_2:
return NFC_FORUM_TYPE_2;
case TYPE_3:
return NFC_FORUM_TYPE_3;
case TYPE_4:
return NFC_FORUM_TYPE_4;
case TYPE_MIFARE_CLASSIC:
return MIFARE_CLASSIC;
case TYPE_ICODE_SLI:
return ICODE_SLI;
default:
return UNKNOWN;
}
}
/**
* Get the maximum NDEF message size in bytes.
*
* <p>Does not cause any RF activity and does not block.
*
* @return size in bytes
*/
public int getMaxSize() {
return mMaxNdefSize;
}
/**
* Determine if the tag is writable.
*
* <p>NFC Forum tags can be in read-only or read-write states.
*
* <p>Does not cause any RF activity and does not block.
*
* <p>Requires {@link android.Manifest.permission#NFC} permission.
*
* @return true if the tag is writable
*/
public boolean isWritable() {
return (mCardState == NDEF_MODE_READ_WRITE);
}
/**
* Read the current {@link android.nfc.NdefMessage} on this tag.
*
* <p>This always reads the current NDEF Message stored on the tag.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* @return the NDEF Message, never null
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
* @throws FormatException if the NDEF Message on the tag is malformed
*/
public NdefMessage getNdefMessage() throws IOException, FormatException {
checkConnected();
try {
INfcTag tagService = mTag.getTagService();
int serviceHandle = mTag.getServiceHandle();
if (tagService.isNdef(serviceHandle)) {
NdefMessage msg = tagService.ndefRead(serviceHandle);
if (msg == null) {
int errorCode = tagService.getLastError(serviceHandle);
switch (errorCode) {
case ErrorCodes.ERROR_IO:
throw new IOException();
case ErrorCodes.ERROR_INVALID_PARAM:
throw new FormatException();
default:
// Should not happen
throw new IOException();
}
}
return msg;
} else {
return null;
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
return null;
}
}
/**
* Overwrite the {@link NdefMessage} on this tag.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param msg the NDEF Message to write, must not be null
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
* @throws FormatException if the NDEF Message to write is malformed
*/
public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
checkConnected();
try {
INfcTag tagService = mTag.getTagService();
int serviceHandle = mTag.getServiceHandle();
if (tagService.isNdef(serviceHandle)) {
int errorCode = tagService.ndefWrite(serviceHandle, msg);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
case ErrorCodes.ERROR_IO:
throw new IOException();
case ErrorCodes.ERROR_INVALID_PARAM:
throw new FormatException();
default:
// Should not happen
throw new IOException();
}
}
else {
throw new IOException("Tag is not ndef");
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
}
/**
* Indicates whether a tag can be made read-only with {@link #makeReadOnly()}.
*
* <p>Does not cause any RF activity and does not block.
*
* @return true if it is possible to make this tag read-only
*/
public boolean canMakeReadOnly() {
if (mNdefType == TYPE_1 || mNdefType == TYPE_2) {
return true;
} else {
return false;
}
}
/**
* Make a tag read-only.
*
* <p>This sets the CC field to indicate the tag is read-only,
* and where possible permanently sets the lock bits to prevent
* any further modification of the memory.
* <p>This is a one-way process and cannot be reverted!
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @return true on success, false if it is not possible to make this tag read-only
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
*/
public boolean makeReadOnly() throws IOException {
checkConnected();
try {
INfcTag tagService = mTag.getTagService();
if (tagService.isNdef(mTag.getServiceHandle())) {
int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle());
switch (errorCode) {
case ErrorCodes.SUCCESS:
return true;
case ErrorCodes.ERROR_IO:
throw new IOException();
case ErrorCodes.ERROR_INVALID_PARAM:
return false;
default:
// Should not happen
throw new IOException();
}
}
else {
throw new IOException("Tag is not ndef");
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
return false;
}
}
}

View File

@@ -0,0 +1,175 @@
/*
* 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.tech;
import android.nfc.ErrorCodes;
import android.nfc.FormatException;
import android.nfc.INfcTag;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.TagLostException;
import android.os.RemoteException;
import android.util.Log;
import java.io.IOException;
/**
* Provide access to NDEF format operations on a {@link Tag}.
*
* <p>Acquire a {@link NdefFormatable} object using {@link #get}.
*
* <p>Android devices with NFC must only enumerate and implement this
* class for tags for which it can format to NDEF.
*
* <p>Unfortunately the procedures to convert unformated tags to NDEF formatted
* tags are not specified by NFC Forum, and are not generally well-known. So
* there is no mandatory set of tags for which all Android devices with NFC
* must support {@link NdefFormatable}.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class NdefFormatable extends BasicTagTechnology {
private static final String TAG = "NFC";
/**
* Get an instance of {@link NdefFormatable} for the given tag.
* <p>Does not cause any RF activity and does not block.
* <p>Returns null if {@link NdefFormatable} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag is not NDEF formatable by this Android device.
*
* @param tag an NDEF formatable tag
* @return NDEF formatable object
*/
public static NdefFormatable get(Tag tag) {
if (!tag.hasTech(TagTechnology.NDEF_FORMATABLE)) return null;
try {
return new NdefFormatable(tag);
} catch (RemoteException e) {
return null;
}
}
/**
* Internal constructor, to be used by NfcAdapter
* @hide
*/
public NdefFormatable(Tag tag) throws RemoteException {
super(tag, TagTechnology.NDEF_FORMATABLE);
}
/**
* Format a tag as NDEF, and write a {@link NdefMessage}.
*
* <p>This is a multi-step process, an IOException is thrown
* if any one step fails.
* <p>The card is left in a read-write state after this operation.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param firstMessage the NDEF message to write after formatting, can be null
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
* @throws FormatException if the NDEF Message to write is malformed
*/
public void format(NdefMessage firstMessage) throws IOException, FormatException {
format(firstMessage, false);
}
/**
* Formats a tag as NDEF, write a {@link NdefMessage}, and make read-only.
*
* <p>This is a multi-step process, an IOException is thrown
* if any one step fails.
* <p>The card is left in a read-only state if this method returns successfully.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param firstMessage the NDEF message to write after formatting
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or the operation is canceled
* @throws FormatException if the NDEF Message to write is malformed
*/
public void formatReadOnly(NdefMessage firstMessage) throws IOException, FormatException {
format(firstMessage, true);
}
/*package*/ void format(NdefMessage firstMessage, boolean makeReadOnly) throws IOException,
FormatException {
checkConnected();
try {
int serviceHandle = mTag.getServiceHandle();
INfcTag tagService = mTag.getTagService();
int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
case ErrorCodes.ERROR_IO:
throw new IOException();
case ErrorCodes.ERROR_INVALID_PARAM:
throw new FormatException();
default:
// Should not happen
throw new IOException();
}
// Now check and see if the format worked
if (tagService.isNdef(serviceHandle)) {
errorCode = tagService.ndefWrite(serviceHandle, firstMessage);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
case ErrorCodes.ERROR_IO:
throw new IOException();
case ErrorCodes.ERROR_INVALID_PARAM:
throw new FormatException();
default:
// Should not happen
throw new IOException();
}
} else {
throw new IOException();
}
// optionally make read-only
if (makeReadOnly) {
errorCode = tagService.ndefMakeReadOnly(serviceHandle);
switch (errorCode) {
case ErrorCodes.SUCCESS:
break;
case ErrorCodes.ERROR_IO:
throw new IOException();
case ErrorCodes.ERROR_INVALID_PARAM:
throw new IOException();
default:
// Should not happen
throw new IOException();
}
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
}
}

View File

@@ -0,0 +1,115 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
import java.io.IOException;
/**
* Provides access to NFC-A (ISO 14443-3A) properties and I/O operations on a {@link Tag}.
*
* <p>Acquire a {@link NfcA} object using {@link #get}.
* <p>The primary NFC-A I/O operation is {@link #transceive}. Applications must
* implement their own protocol stack on top of {@link #transceive}.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require 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;
/**
* Get an instance of {@link NfcA} for the given tag.
* <p>Returns null if {@link NfcA} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag does not support NFC-A.
* <p>Does not cause any RF activity and does not block.
*
* @param tag an NFC-A compatible tag
* @return NFC-A object
*/
public static NfcA get(Tag tag) {
if (!tag.hasTech(TagTechnology.NFC_A)) return null;
try {
return new NfcA(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public NfcA(Tag tag) throws RemoteException {
super(tag, TagTechnology.NFC_A);
Bundle extras = tag.getTechExtras(TagTechnology.NFC_A);
mSak = extras.getShort(EXTRA_SAK);
mAtqa = extras.getByteArray(EXTRA_ATQA);
}
/**
* Return the ATQA/SENS_RES bytes from tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return ATQA/SENS_RES bytes
*/
public byte[] getAtqa() {
return mAtqa;
}
/**
* Return the SAK/SEL_RES bytes from tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return SAK bytes
*/
public short getSak() {
return mSak;
}
/**
* Send raw NFC-A commands to the tag and receive the response.
*
* <p>Applications must not append the EoD (CRC) to the payload,
* it will be automatically calculated.
* <p>Applications must only send commands that are complete bytes,
* for example a SENS_REQ is not possible (these are used to
* manage tag polling and initialization).
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param data bytes to send
* @return bytes received in response
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or this operation is canceled
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
import java.io.IOException;
/**
* Provides access to NFC-B (ISO 14443-3B) properties and I/O operations on a {@link Tag}.
*
* <p>Acquire a {@link NfcB} object using {@link #get}.
* <p>The primary NFC-B I/O operation is {@link #transceive}. Applications must
* implement their own protocol stack on top of {@link #transceive}.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class NfcB extends BasicTagTechnology {
/** @hide */
public static final String EXTRA_APPDATA = "appdata";
/** @hide */
public static final String EXTRA_PROTINFO = "protinfo";
private byte[] mAppData;
private byte[] mProtInfo;
/**
* Get an instance of {@link NfcB} for the given tag.
* <p>Returns null if {@link NfcB} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag does not support NFC-B.
* <p>Does not cause any RF activity and does not block.
*
* @param tag an NFC-B compatible tag
* @return NFC-B object
*/
public static NfcB get(Tag tag) {
if (!tag.hasTech(TagTechnology.NFC_B)) return null;
try {
return new NfcB(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public NfcB(Tag tag) throws RemoteException {
super(tag, TagTechnology.NFC_B);
Bundle extras = tag.getTechExtras(TagTechnology.NFC_B);
mAppData = extras.getByteArray(EXTRA_APPDATA);
mProtInfo = extras.getByteArray(EXTRA_PROTINFO);
}
/**
* Return the Application Data bytes from ATQB/SENSB_RES at tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return Application Data bytes from ATQB/SENSB_RES bytes
*/
public byte[] getApplicationData() {
return mAppData;
}
/**
* Return the Protocol Info bytes from ATQB/SENSB_RES at tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return Protocol Info bytes from ATQB/SENSB_RES bytes
*/
public byte[] getProtocolInfo() {
return mProtInfo;
}
/**
* Send raw NFC-B commands to the tag and receive the response.
*
* <p>Applications must not append the EoD (CRC) to the payload,
* it will be automatically calculated.
* <p>Applications must not send commands that manage the polling
* loop and initialization (SENSB_REQ, SLOT_MARKER etc).
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param data bytes to send
* @return bytes received in response
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or this operation is canceled
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
import java.io.IOException;
/**
* Provides access to NFC-F (JIS 6319-4) properties and I/O operations on a {@link Tag}.
*
* <p>Acquire a {@link NfcF} object using {@link #get}.
* <p>The primary NFC-F I/O operation is {@link #transceive}. Applications must
* implement their own protocol stack on top of {@link #transceive}.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require 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;
/**
* Get an instance of {@link NfcF} for the given tag.
* <p>Returns null if {@link NfcF} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag does not support NFC-F.
* <p>Does not cause any RF activity and does not block.
*
* @param tag an NFC-F compatible tag
* @return NFC-F object
*/
public static NfcF get(Tag tag) {
if (!tag.hasTech(TagTechnology.NFC_F)) return null;
try {
return new NfcF(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public NfcF(Tag tag) throws RemoteException {
super(tag, TagTechnology.NFC_F);
Bundle extras = tag.getTechExtras(TagTechnology.NFC_F);
if (extras != null) {
mSystemCode = extras.getByteArray(EXTRA_SC);
mManufacturer = extras.getByteArray(EXTRA_PMM);
}
}
/**
* Return the System Code bytes from tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return System Code bytes
*/
public byte[] getSystemCode() {
return mSystemCode;
}
/**
* Return the Manufacturer bytes from tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return Manufacturer bytes
*/
public byte[] getManufacturer() {
return mManufacturer;
}
/**
* Send raw NFC-F commands to the tag and receive the response.
*
* <p>Applications must not append the SoD (length) or EoD (CRC) to the payload,
* it will be automatically calculated.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param data bytes to send
* @return bytes received in response
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or this operation is canceled
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
}

View File

@@ -0,0 +1,114 @@
/*
* 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.tech;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.RemoteException;
import java.io.IOException;
/**
* Provides access to NFC-V (ISO 15693) properties and I/O operations on a {@link Tag}.
*
* <p>Acquire a {@link NfcV} object using {@link #get}.
* <p>The primary NFC-V I/O operation is {@link #transceive}. Applications must
* implement their own protocol stack on top of {@link #transceive}.
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public final class NfcV extends BasicTagTechnology {
/** @hide */
public static final String EXTRA_RESP_FLAGS = "respflags";
/** @hide */
public static final String EXTRA_DSFID = "dsfid";
private byte mRespFlags;
private byte mDsfId;
/**
* Get an instance of {@link NfcV} for the given tag.
* <p>Returns null if {@link NfcV} was not enumerated in {@link Tag#getTechList}.
* This indicates the tag does not support NFC-V.
* <p>Does not cause any RF activity and does not block.
*
* @param tag an NFC-V compatible tag
* @return NFC-V object
*/
public static NfcV get(Tag tag) {
if (!tag.hasTech(TagTechnology.NFC_V)) return null;
try {
return new NfcV(tag);
} catch (RemoteException e) {
return null;
}
}
/** @hide */
public NfcV(Tag tag) throws RemoteException {
super(tag, TagTechnology.NFC_V);
Bundle extras = tag.getTechExtras(TagTechnology.NFC_V);
mRespFlags = extras.getByte(EXTRA_RESP_FLAGS);
mDsfId = extras.getByte(EXTRA_DSFID);
}
/**
* Return the Response Flag bytes from tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return Response Flag bytes
*/
public byte getResponseFlags() {
return mRespFlags;
}
/**
* Return the DSF ID bytes from tag discovery.
*
* <p>Does not cause any RF activity and does not block.
*
* @return DSF ID bytes
*/
public byte getDsfId() {
return mDsfId;
}
/**
* Send raw NFC-V commands to the tag and receive the response.
*
* <p>Applications must not append the CRC to the payload,
* it will be automatically calculated. The application does
* provide FLAGS, CMD and PARAMETER bytes.
*
* <p>This is an I/O operation and will block until complete. It must
* not be called from the main application thread. A blocked call will be canceled with
* {@link IOException} if {@link #close} is called from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param data bytes to send
* @return bytes received in response
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or this operation is canceled
*/
public byte[] transceive(byte[] data) throws IOException {
return transceive(data, true);
}
}

View File

@@ -0,0 +1,211 @@
/*
* 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.tech;
import android.nfc.Tag;
import java.io.Closeable;
import java.io.IOException;
/**
* {@link TagTechnology} is an interface to a technology in a {@link Tag}.
* <p>
* Obtain a {@link TagTechnology} implementation by calling the static method <code>get()</code>
* on the implementation class.
* <p>
* NFC tags are based on a number of independently developed technologies and offer a
* wide range of capabilities. The
* {@link TagTechnology} implementations provide access to these different
* technologies and capabilities. Some sub-classes map to technology
* specification (for example {@link NfcA}, {@link IsoDep}, others map to
* pseudo-technologies or capabilities (for example {@link Ndef}, {@link NdefFormatable}).
* <p>
* It is mandatory for all Android NFC devices to provide the following
* {@link TagTechnology} implementations.
* <ul>
* <li>{@link NfcA} (also known as ISO 14443-3A)
* <li>{@link NfcB} (also known as ISO 14443-3B)
* <li>{@link NfcF} (also known as JIS 6319-4)
* <li>{@link NfcV} (also known as ISO 15693)
* <li>{@link IsoDep}
* <li>{@link Ndef} on NFC Forum Type 1, Type 2, Type 3 or Type 4 compliant tags
* </ul>
* It is optional for Android NFC devices to provide the following
* {@link TagTechnology} implementations. If it is not provided, the
* Android device will never enumerate that class via {@link Tag#getTechList}.
* <ul>
* <li>{@link MifareClassic}
* <li>{@link MifareUltralight}
* <li>{@link NdefFormatable} must only be enumerated on tags for which this Android device
* is capable of formatting. Proprietary knowledge is often required to format a tag
* to make it NDEF compatible.
* </ul>
* <p>
* {@link TagTechnology} implementations provide methods that fall into two classes:
* <em>cached getters</em> and <em>I/O operations</em>.
* <h4>Cached getters</h4>
* These methods (usually prefixed by <code>get</code> or <code>is</code>) return
* properties of the tag, as determined at discovery time. These methods will never
* block or cause RF activity, and do not require {@link #connect} to have been called.
* They also never update, for example if a property is changed by an I/O operation with a tag
* then the cached getter will still return the result from tag discovery time.
* <h4>I/O operations</h4>
* I/O operations may require RF activity, and may block. They have the following semantics.
* <ul>
* <li>{@link #connect} must be called before using any other I/O operation.
* <li>{@link #close} must be called after completing I/O operations with a
* {@link TagTechnology}, and it will cancel all other blocked I/O operations on other threads
* (including {@link #connect} with {@link IOException}.
* <li>Only one {@link TagTechnology} can be connected at a time. Other calls to
* {@link #connect} will return {@link IOException}.
* <li>I/O operations may block, and should never be called on the main application
* thread.
* </ul>
*
* <p class="note"><strong>Note:</strong> Methods that perform I/O operations
* require the {@link android.Manifest.permission#NFC} permission.
*/
public interface TagTechnology extends Closeable {
/**
* This technology is an instance of {@link NfcA}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int NFC_A = 1;
/**
* This technology is an instance of {@link NfcB}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int NFC_B = 2;
/**
* This technology is an instance of {@link IsoDep}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int ISO_DEP = 3;
/**
* This technology is an instance of {@link NfcF}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int NFC_F = 4;
/**
* This technology is an instance of {@link NfcV}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int NFC_V = 5;
/**
* This technology is an instance of {@link Ndef}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int NDEF = 6;
/**
* This technology is an instance of {@link NdefFormatable}.
* <p>Support for this technology type is mandatory.
* @hide
*/
public static final int NDEF_FORMATABLE = 7;
/**
* This technology is an instance of {@link MifareClassic}.
* <p>Support for this technology type is optional. If a stack doesn't support this technology
* type tags using it must still be discovered and present the lower level radio interface
* technologies in use.
* @hide
*/
public static final int MIFARE_CLASSIC = 8;
/**
* This technology is an instance of {@link MifareUltralight}.
* <p>Support for this technology type is optional. If a stack doesn't support this technology
* type tags using it must still be discovered and present the lower level radio interface
* technologies in use.
* @hide
*/
public static final int MIFARE_ULTRALIGHT = 9;
/**
* Get the {@link Tag} object backing this {@link TagTechnology} object.
* @return the {@link Tag} backing this {@link TagTechnology} object.
*/
public Tag getTag();
/**
* Enable I/O operations to the tag from this {@link TagTechnology} object.
* <p>May cause RF activity and may block. Must not be called
* from the main application thread. A blocked call will be canceled with
* {@link IOException} by calling {@link #close} from another thread.
* <p>Only one {@link TagTechnology} object can be connected to a {@link Tag} at a time.
* <p>Applications must call {@link #close} when I/O operations are complete.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see #close()
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or connect is canceled
*/
public void connect() throws IOException;
/**
* Re-connect to the {@link Tag} associated with this connection. Reconnecting to a tag can be
* used to reset the state of the tag itself.
*
* <p>May cause RF activity and may block. Must not be called
* from the main application thread. A blocked call will be canceled with
* {@link IOException} by calling {@link #close} from another thread.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see #connect()
* @see #close()
* @throws TagLostException if the tag leaves the field
* @throws IOException if there is an I/O failure, or connect is canceled
* @hide
*/
public void reconnect() throws IOException;
/**
* Disable I/O operations to the tag from this {@link TagTechnology} object, and release resources.
* <p>Also causes all blocked I/O operations on other thread to be canceled and
* return with {@link IOException}.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @see #connect()
*/
public void close() throws IOException;
/**
* Helper to indicate if I/O operations should be possible.
*
* <p>Returns true if {@link #connect} has completed, and {@link #close} has not been
* called, and the {@link Tag} is not known to be out of range.
* <p>Does not cause RF activity, and does not block.
*
* @return true if I/O operations should be possible
*/
public boolean isConnected();
}

View File

@@ -0,0 +1,13 @@
<HTML>
<BODY>
<p>
These classes provide access to a tag technology's features, which vary by the type
of tag that is scanned. A scanned tag can support multiple technologies, and you can find
out what they are by calling {@link android.nfc.Tag#getTechList getTechList()}.</p>
<p>For more information on dealing with tag technologies and handling the ones that you care about, see
<a href="{@docRoot}guide/topics/nfc/index.html#dispatch">The Tag Dispatch System</a>.
The {@link android.nfc.tech.TagTechnology} interface provides an overview of the
supported technologies.</p>
</BODY>
</HTML>