1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
|
/*
* 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.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 {
int err = mTag.getTagService().setTimeout(TagTechnology.ISO_DEP, timeout);
if (err != ErrorCodes.SUCCESS) {
throw new IllegalArgumentException("The supplied timeout is not valid");
}
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
}
}
/**
* Get the current timeout for {@link #transceive} in milliseconds.
*
* <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
*
* @return timeout value in milliseconds
*/
public int getTimeout() {
try {
return mTag.getTagService().getTimeout(TagTechnology.ISO_DEP);
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
return 0;
}
}
/**
* 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>Use {@link #getMaxTransceiveLength} to retrieve the maximum number of bytes
* that can be sent with {@link #transceive}.
*
* <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);
}
/**
* Return the maximum number of bytes that can be sent with {@link #transceive}.
* @return the maximum number of bytes that can be sent with {@link #transceive}.
*/
public int getMaxTransceiveLength() {
return getMaxTransceiveLengthInternal();
}
/**
* <p>Standard APDUs have a 1-byte length field, allowing a maximum of
* 255 payload bytes, which results in a maximum APDU length of 261 bytes.
*
* <p>Extended length APDUs have a 3-byte length field, allowing 65535
* payload bytes.
*
* <p>Some NFC adapters, like the one used in the Nexus S and the Galaxy Nexus
* do not support extended length APDUs. They are expected to be well-supported
* in the future though. Use this method to check for extended length APDU
* support.
*
* @return whether the NFC adapter on this device supports extended length APDUs.
*/
public boolean isExtendedLengthApduSupported() {
try {
return mTag.getTagService().getExtendedLengthApdusSupported();
} catch (RemoteException e) {
Log.e(TAG, "NFC service dead", e);
return false;
}
}
}
|