Javadoc updates for NFC.

Change-Id: Ibd91829979576297599fbcc9eb8054924af1d527
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java
index e3fa32c..162d9eb 100644
--- a/core/java/android/app/ActivityThread.java
+++ b/core/java/android/app/ActivityThread.java
@@ -1439,6 +1439,16 @@
         }
     }
 
+    public void unregisterOnActivityPausedListener(Activity activity,
+            OnActivityPausedListener listener) {
+        synchronized (mOnPauseListeners) {
+            ArrayList<OnActivityPausedListener> list = mOnPauseListeners.get(activity);
+            if (list != null) {
+                list.remove(listener);
+            }
+        }
+    }
+
     public final ActivityInfo resolveActivityInfo(Intent intent) {
         ActivityInfo aInfo = intent.resolveActivityInfo(
                 mInitialApplication.getPackageManager(), PackageManager.GET_SHARED_LIBRARY_FILES);
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index 28d53f5..f6605b8 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -436,7 +436,7 @@
         }
         try {
             ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
-                    new ForegroundDispatchPausedListener());
+                    mForegroundDispatchListener);
             sService.enableForegroundDispatch(activity.getComponentName(), intent, filters);
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
@@ -453,15 +453,17 @@
      * <p>This method must be called from the main thread.
      */
     public void disableForegroundDispatch(Activity activity) {
+        ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
+                mForegroundDispatchListener);
         disableForegroundDispatchInternal(activity, false);
     }
 
-    class ForegroundDispatchPausedListener implements OnActivityPausedListener {
+    OnActivityPausedListener mForegroundDispatchListener = new OnActivityPausedListener() {
         @Override
         public void onPaused(Activity activity) {
             disableForegroundDispatchInternal(activity, true);
         }
-    }
+    };
 
     void disableForegroundDispatchInternal(Activity activity, boolean force) {
         try {
@@ -488,7 +490,7 @@
         }
         try {
             ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
-                    new ForegroundDispatchPausedListener());
+                    mForegroundNdefPushListener);
             sService.enableForegroundNdefPush(activity.getComponentName(), msg);
         } catch (RemoteException e) {
             attemptDeadServiceRecovery(e);
@@ -504,18 +506,20 @@
      *
      * <p>This method must be called from the main thread.
      */
-    public void disableNdefPushDispatch(Activity activity) {
-        disableForegroundDispatchInternal(activity, false);
+    public void disableForegroundNdefPush(Activity activity) {
+        ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
+                mForegroundNdefPushListener);
+        disableForegroundNdefPushInternal(activity, false);
     }
 
-    class ForegroundNdefPushPausedListener implements OnActivityPausedListener {
+    OnActivityPausedListener mForegroundNdefPushListener = new OnActivityPausedListener() {
         @Override
         public void onPaused(Activity activity) {
-            disableNdefPushDispatchInternal(activity, true);
+            disableForegroundNdefPushInternal(activity, true);
         }
-    }
+    };
 
-    void disableNdefPushDispatchInternal(Activity activity, boolean force) {
+    void disableForegroundNdefPushInternal(Activity activity, boolean force) {
         try {
             sService.disableForegroundNdefPush(activity.getComponentName());
             if (!force && !activity.isResumed()) {
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 7bd2289..8e2360a 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -36,8 +36,8 @@
 /**
  * Represents a (generic) discovered tag.
  * <p>
- * A tag is a passive NFC element, such as NFC Forum Tag's, Mifare class Tags,
- * Sony Felica Tags.
+ * A tag is a passive NFC element, such as NFC Forum Tag's, MIFARE class Tags,
+ * Sony FeliCa Tags, etc.
  * <p>
  * Tag's have a type and usually have a UID.
  * <p>
diff --git a/core/java/android/nfc/technology/BasicTagTechnology.java b/core/java/android/nfc/technology/BasicTagTechnology.java
index f529ee5..6d3292b 100644
--- a/core/java/android/nfc/technology/BasicTagTechnology.java
+++ b/core/java/android/nfc/technology/BasicTagTechnology.java
@@ -39,10 +39,7 @@
     /*package*/ final INfcAdapter mService;
     /*package*/ final INfcTag mTagService;
 
-    /**
-     * @hide
-     */
-    public BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException {
+    BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException {
         int[] techList = tag.getTechnologyList();
         int i;
 
@@ -64,46 +61,36 @@
         mSelectedTechnology = tech;
     }
 
-    /**
-     * @hide
-     */
-    public BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException {
+    BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException {
         this(adapter, tag, tag.getTechnologyList()[0]);
     }
 
-    /**
-     * Get the {@link Tag} this connection is associated with.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     */
     @Override
     public Tag getTag() {
         return mTag;
     }
 
-    public void checkConnected() {
+    /** Internal helper to throw IllegalStateException if the technology isn't connected */
+    void checkConnected() {
        if ((mTag.getConnectedTechnology() != getTechnologyId()) ||
                (mTag.getConnectedTechnology() == -1)) {
            throw new IllegalStateException("Call connect() first!");
        }
     }
 
-    /**
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     */
     @Override
     public int getTechnologyId() {
         return mSelectedTechnology;
     }
 
     /**
-     * Helper to indicate if {@link #transceive transceive()} calls might succeed.
+     * Helper to indicate if {@link #connect} has succeeded.
      * <p>
      * Does not cause RF activity, and does not block.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
      * @return true if {@link #connect} has completed successfully and the {@link Tag} is believed
      * to be within range. Applications must still handle {@link java.io.IOException}
-     * while using {@link #transceive transceive()}, in case connection is lost after this method
-     * returns true.
+     * while using methods that require a connection in case the connection is lost after this
+     * method returns.
      */
     public boolean isConnected() {
         if (!mIsConnected) {
@@ -118,16 +105,6 @@
         }
     }
 
-    /**
-     * Connect to the {@link Tag} associated with this connection.
-     * <p>
-     * This method blocks until the connection is established.
-     * <p>
-     * {@link #close} can be called from another thread to cancel this connection
-     * attempt.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     * @throws IOException if the target is lost, or connect canceled
-     */
     @Override
     public void connect() throws IOException {
         try {
@@ -146,17 +123,6 @@
         }
     }
 
-    /**
-     * Re-connect to the {@link Tag} associated with this connection.
-     * <p>
-     * Reconnecting to a tag can be used to reset the state of the tag itself.
-     * This method blocks until the connection is re-established.
-     * <p>
-     * {@link #close} can be called from another thread to cancel this connection
-     * attempt.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     * @throws IOException if the target is lost, or connect canceled
-     */
     @Override
     public void reconnect() throws IOException {
         if (!mIsConnected) {
@@ -179,16 +145,6 @@
         }
     }
 
-    /**
-     * Close this connection.
-     * <p>
-     * Causes blocking operations such as {@link #transceive transceive()} or {@link #connect} to
-     * be canceled and immediately throw {@link java.io.IOException}.
-     * <p>
-     * Once this method is called, this object cannot be re-used and should be discarded. Further
-     * calls to {@link #transceive transceive()} or {@link #connect} will fail.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     */
     @Override
     public void close() {
         try {
@@ -204,7 +160,7 @@
         }
     }
 
-    /** internal transceive */
+    /** Internal transceive */
     /*package*/ byte[] transceive(byte[] data, boolean raw) throws IOException {
         checkConnected();
 
@@ -219,19 +175,4 @@
             throw new IOException("NFC service died");
         }
     }
-
-    /**
-     * Send data to a tag and receive the response.
-     * <p>
-     * This method will block until the response is received. It can be canceled
-     * with {@link #close}.
-     * <p>Requires {@link android.Manifest.permission#NFC} permission.
-     *
-     * @param data bytes to send
-     * @return bytes received in response
-     * @throws IOException if the target is lost or connection closed
-     */
-    public byte[] transceive(byte[] data) throws IOException {
-        return transceive(data, true);
-    }
 }
diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/technology/IsoDep.java
index 03c518e..0a5b1b1 100644
--- a/core/java/android/nfc/technology/IsoDep.java
+++ b/core/java/android/nfc/technology/IsoDep.java
@@ -46,6 +46,7 @@
     private byte[] mHiLayerResponse = null;
     private byte[] mHistBytes = null;
 
+    /** @hide */
     public IsoDep(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.ISO_DEP);
@@ -56,16 +57,31 @@
     }
 
     /**
-     * 3A only
+     * Return the historical bytes if the tag is using {@link NfcA}, null otherwise.
      */
     public byte[] getHistoricalBytes() {
         return mHistBytes;
     }
 
     /**
-     * 3B only
+     * Return the hi layer response bytes if the tag is using {@link NfcB}, null otherwise.
      */
     public byte[] getHiLayerResponse() {
         return mHiLayerResponse;
     }
+
+    /**
+     * Send data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
+    }
 }
diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/technology/MifareClassic.java
index 3be38fe..fc3e8b3 100644
--- a/core/java/android/nfc/technology/MifareClassic.java
+++ b/core/java/android/nfc/technology/MifareClassic.java
@@ -24,21 +24,22 @@
 import java.io.IOException;
 
 /**
- * Concrete class for TagTechnology.MIFARE_CLASSIC
+ * Technology class representing MIFARE Classic tags (also known as MIFARE Standard).
  *
- * 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.
+ * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology
+ * MIFARE Classic tags will still be scanned, but will only show the NfcA technology.
  *
- * Each sector has k blocks.
- * Block size is constant across the whole MIFARE classic family.
+ * <p>MIFARE Classic tags have sectors that each contain blocks. The block size is constant at
+ * 16 bytes, but the number of sectors and the sector size varies by product. MIFARE has encryption
+ * built in and each sector has two keys associated with it, as well as ACLs to determine what
+ * level acess each key grants. Before operating on a sector you must call either
+ * {@link #authenticateSector(int, byte[], boolean)} or
+ * {@link #authenticateBlock(int, byte[], boolean)} to gain authorize your request.
  */
 public final class MifareClassic extends BasicTagTechnology {
     /**
-     * The well-known, default MIFARE read key.
-     * Use this key to effectively make the payload in this sector
-     * public.
+     * The well-known default MIFARE read key. All keys are set to this at the factory.
+     * Using this key will effectively make the payload in the sector public.
      */
     public static final byte[] KEY_DEFAULT =
             {(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF,(byte)0xFF};
@@ -53,39 +54,45 @@
     public static final byte[] KEY_NFC_FORUM =
             {(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7,(byte)0xD3,(byte)0xF7};
 
+    /** 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;
-    public static final int TYPE_DESFIRE = 3;
-    public static final int TYPE_ULTRALIGHT = 4;
+    /** The tag type is unknown */
     public static final int TYPE_UNKNOWN = 5;
 
+    /** The tag contains 16 sectors, each holding 4 blocks. */
     public static final int SIZE_1K = 1024;
+    /** The tag contains 32 sectors, each holding 4 blocks. */
     public static final int SIZE_2K = 2048;
+    /**
+     * The 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;
+    /** The tag contains 5 sectors, each holding 4 blocks. */
     public static final int SIZE_MINI = 320;
+    /** The capacity is unknown */
     public static final int SIZE_UNKNOWN = 0;
 
     private boolean mIsEmulated;
     private int mType;
     private int mSize;
 
+    /** @hide */
     public MifareClassic(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
         super(adapter, tag, TagTechnology.MIFARE_CLASSIC);
 
-        // Check if this could actually be a Mifare
+        // Check if this could actually be a MIFARE Classic
         NfcA a = (NfcA) adapter.getTechnology(tag, 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
@@ -122,7 +129,7 @@
                 // TODO this really should be a short, not byte
                 if (a.getAtqa()[0] == 0x03) {
                     // Type == DESFIRE
-                    mType = TYPE_DESFIRE;
+                    break;
                 } else {
                     // Type == MF+
                     // SL = SL3
@@ -160,27 +167,25 @@
                 mType = TYPE_PRO;
                 mSize = SIZE_4K;
                 break;
-            default:
-                // Unknown mifare
-                mType = TYPE_UNKNOWN;
-                mSize = SIZE_UNKNOWN;
-                break;
         }
     }
 
-    // Immutable data known at discovery time
+    /** Returns the size of the tag, determined at discovery time */
     public int getSize() {
         return mSize;
     }
 
+    /** Returns the size of the tag, determined at discovery time */
     public int getType() {
         return mType;
     }
 
+    /** Returns true if the tag is emulated, determined at discovery time */
     public boolean isEmulated() {
         return mIsEmulated;
     }
 
+    /** Returns the number of sectors on this tag, determined at discovery time */
     public int getSectorCount() {
         switch (mSize) {
             case SIZE_1K: {
@@ -201,10 +206,12 @@
         }
     }
 
+    /** Returns the sector size, determined at discovery time */
     public int getSectorSize(int sector) {
         return getBlockCount(sector) * 16;
     }
 
+    /** Returns the total block count, determined at discovery time */
     public int getTotalBlockCount() {
         int totalBlocks = 0;
         for (int sec = 0; sec < getSectorCount(); sec++) {
@@ -214,6 +221,7 @@
         return totalBlocks;
     }
 
+    /** Returns the block count for the given sector, determined at discovery time */
     public int getBlockCount(int sector) {
         if (sector >= getSectorCount()) {
             throw new IllegalArgumentException("this card only has " + getSectorCount() +
@@ -237,8 +245,8 @@
 
     // Methods that require connect()
     /**
-     * Authenticate for a given block.
-     * Note that this will authenticate the entire sector the block belongs to.
+     * Authenticate the entire sector that the given block resides in.
+     * <p>This requires a that the tag be connected.
      */
     public boolean authenticateBlock(int block, byte[] key, boolean keyA) {
         checkConnected();
@@ -274,6 +282,7 @@
 
     /**
      * Authenticate for a given sector.
+     * <p>This requires a that the tag be connected.
      */
     public boolean authenticateSector(int sector, byte[] key, boolean keyA) {
         checkConnected();
@@ -288,6 +297,7 @@
     /**
      * Sector indexing starts at 0.
      * Block indexing starts at 0, and resets in each sector.
+     * <p>This requires a that the tag be connected.
      * @throws IOException
      */
     public byte[] readBlock(int sector, int block) throws IOException {
@@ -295,11 +305,11 @@
 
         byte addr = (byte) ((firstBlockInSector(sector) + block) & 0xff);
         return readBlock(addr);
-
     }
 
     /**
      * Reads absolute block index.
+     * <p>This requires a that the tag be connected.
      * @throws IOException
      */
     public byte[] readBlock(int block) throws IOException {
@@ -313,6 +323,7 @@
 
     /**
      * Writes absolute block index.
+     * <p>This requires a that the tag be connected.
      * @throws IOException
      */
     public void writeBlock(int block, byte[] data) throws IOException {
@@ -329,6 +340,7 @@
 
     /**
      * Writes relative block in sector.
+     * <p>This requires a that the tag be connected.
      * @throws IOException
      */
     public void writeBlock(int sector, int block, byte[] data) throws IOException {
@@ -342,7 +354,6 @@
     public void increment(int block) throws IOException {
         checkConnected();
 
-        byte addr = (byte) block;
         byte[] incr_cmd = { (byte) 0xC1, (byte) block };
 
         transceive(incr_cmd, false);
@@ -351,7 +362,6 @@
     public void decrement(int block) throws IOException {
         checkConnected();
 
-        byte addr = (byte) block;
         byte[] decr_cmd = { (byte) 0xC0, (byte) block };
 
         transceive(decr_cmd, false);
@@ -360,7 +370,6 @@
     public void transfer(int block) throws IOException {
         checkConnected();
 
-        byte addr = (byte) block;
         byte[] trans_cmd = { (byte) 0xB0, (byte) block };
 
         transceive(trans_cmd, false);
@@ -369,9 +378,24 @@
     public void restore(int block) throws IOException {
         checkConnected();
 
-        byte addr = (byte) block;
         byte[] rest_cmd = { (byte) 0xC2, (byte) block };
 
         transceive(rest_cmd, false);
     }
+
+    /**
+     * Send raw NfcA data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * <p>This requires a that the tag be connected.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
+    }
 }
diff --git a/core/java/android/nfc/technology/MifareUltralight.java b/core/java/android/nfc/technology/MifareUltralight.java
index 525b85b..5c8cb3c 100644
--- a/core/java/android/nfc/technology/MifareUltralight.java
+++ b/core/java/android/nfc/technology/MifareUltralight.java
@@ -16,33 +16,35 @@
 
 package android.nfc.technology;
 
-import java.io.IOException;
-
 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_ULTRALIGHT
+ * Technology class representing MIFARE Ultralight and MIFARE Ultralight C tags.
  *
- * MIFARE Ultralight has n sectors, with varying sizes, although
- * they are at least the same pattern for any one MIFARE Ultralight
- * product. Each sector has two keys. Authentication with the correct
- * key is needed before access to any sector.
+ * <p>Support for this technology type is optional. If the NFC stack doesn't support this technology
+ * MIFARE Ultralight class tags will still be scanned, but will only show the NfcA technology.
  *
- * Each sector has k blocks.
- * Block size is constant across the whole MIFARE Ultralight family.
+ * <p>MIFARE Ultralight class tags have a series of 4 bytes pages that can be individually written
+ * and read in chunks of 4 for a total read of 16 bytes.
  */
 public final class MifareUltralight extends BasicTagTechnology {
+    /** A MIFARE Ultralight tag */
     public static final int TYPE_ULTRALIGHT = 1;
+    /** A MIFARE Ultralight C tag */
     public static final int TYPE_ULTRALIGHT_C = 2;
+    /** The tag type is unknown */
     public static final int TYPE_UNKNOWN = 10;
 
     private static final int NXP_MANUFACTURER_ID = 0x04;
 
     private int mType;
 
+    /** @hide */
     public MifareUltralight(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
         super(adapter, tag, TagTechnology.MIFARE_ULTRALIGHT);
 
@@ -57,49 +59,59 @@
         }
     }
 
+    /** Returns the type of the tag */
     public int getType() {
         return mType;
     }
 
     // Methods that require connect()
     /**
+     * Reads a single 16 byte block from the given page offset.
+     *
+     * <p>This requires a that the tag be connected.
+     *
      * @throws IOException
      */
-    public byte[] readBlock(int block) throws IOException {
+    public byte[] readBlock(int page) throws IOException {
         checkConnected();
 
-        byte[] blockread_cmd = { 0x30, (byte)block }; // phHal_eMifareRead
+        byte[] blockread_cmd = { 0x30, (byte) page}; // phHal_eMifareRead
         return transceive(blockread_cmd, false);
     }
 
     /**
+     * Writes a 4 byte page to the tag.
+     *
+     * <p>This requires a that the tag be connected.
+     *
+     * @param page The offset of the page to write
+     * @param data The data to write
      * @throws IOException
      */
-    public byte[] readOTP() throws IOException {
-        checkConnected();
-
-        return readBlock(3); // OTP is at page 3
-    }
-
-    public void writePage(int block, byte[] data) throws IOException {
+    public void writePage(int page, byte[] data) throws IOException {
         checkConnected();
 
         byte[] pagewrite_cmd = new byte[data.length + 2];
         pagewrite_cmd[0] = (byte) 0xA2;
-        pagewrite_cmd[1] = (byte) block;
+        pagewrite_cmd[1] = (byte) page;
         System.arraycopy(data, 0, pagewrite_cmd, 2, data.length);
 
         transceive(pagewrite_cmd, false);
     }
 
-    public void writeBlock(int block, byte[] data) throws IOException {
-        checkConnected();
-
-        byte[] blockwrite_cmd = new byte[data.length + 2];
-        blockwrite_cmd[0] = (byte) 0xA0;
-        blockwrite_cmd[1] = (byte) block;
-        System.arraycopy(data, 0, blockwrite_cmd, 2, data.length);
-
-        transceive(blockwrite_cmd, false);
+    /**
+     * Send raw NfcA data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     * <p>This requires a that the tag be connected.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
     }
 }
diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/technology/Ndef.java
index 5f05b58..1c0afde 100644
--- a/core/java/android/nfc/technology/Ndef.java
+++ b/core/java/android/nfc/technology/Ndef.java
@@ -100,15 +100,6 @@
     }
 
     /**
-     * Get optional extra NDEF messages.
-     * Some tags may contain extra NDEF messages, but not all
-     * implementations will be able to read them.
-     */
-    public NdefMessage[] getExtraNdefMessage() throws IOException, FormatException {
-        throw new UnsupportedOperationException();
-    }
-
-    /**
      * Get 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},
@@ -208,22 +199,6 @@
     }
 
     /**
-     * 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 void writeExtraNdefMessage(int i, NdefMessage msg) throws IOException, FormatException {
-        checkConnected();
-
-        throw new UnsupportedOperationException();
-    }
-
-    /**
      * Indicates whether a tag can be made read-only with
      * {@link #makeReadonly()}
      */
@@ -263,11 +238,4 @@
             return false;
         }
     }
-
-    @Override
-    public byte[] transceive(byte[] data) {
-        checkConnected();
-
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/technology/NdefFormatable.java
index 0901607..e2fd034 100644
--- a/core/java/android/nfc/technology/NdefFormatable.java
+++ b/core/java/android/nfc/technology/NdefFormatable.java
@@ -91,11 +91,4 @@
             Log.e(TAG, "NFC service dead", e);
         }
     }
-
-    @Override
-    public byte[] transceive(byte[] data) {
-        checkConnected();
-
-        throw new UnsupportedOperationException();
-    }
 }
diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/technology/NfcA.java
index 20fe09e..0615a10 100644
--- a/core/java/android/nfc/technology/NfcA.java
+++ b/core/java/android/nfc/technology/NfcA.java
@@ -21,6 +21,8 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+import java.io.IOException;
+
 /**
  * A low-level connection to a {@link Tag} using the NFC-A technology, also known as
  * ISO1443-3A.
@@ -44,6 +46,7 @@
     private short mSak;
     private byte[] mAtqa;
 
+    /** @hide */
     public NfcA(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
         super(adapter, tag, TagTechnology.NFC_A);
         mSak = extras.getShort(EXTRA_SAK);
@@ -63,4 +66,19 @@
     public short getSak() {
         return mSak;
     }
+
+    /**
+     * Send data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
+    }
 }
diff --git a/core/java/android/nfc/technology/NfcB.java b/core/java/android/nfc/technology/NfcB.java
index 767558e..c14b98d 100644
--- a/core/java/android/nfc/technology/NfcB.java
+++ b/core/java/android/nfc/technology/NfcB.java
@@ -21,6 +21,8 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+import java.io.IOException;
+
 /**
  * A low-level connection to a {@link Tag} using the NFC-B technology, also known as
  * ISO1443-3B.
@@ -44,6 +46,7 @@
     private byte[] mAppData;
     private byte[] mProtInfo;
 
+    /** @hide */
     public NfcB(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.NFC_B);
@@ -67,4 +70,18 @@
         return mProtInfo;
     }
 
+    /**
+     * Send data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
+    }
 }
diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/technology/NfcF.java
index f7f1fd3..434e5df 100644
--- a/core/java/android/nfc/technology/NfcF.java
+++ b/core/java/android/nfc/technology/NfcF.java
@@ -21,6 +21,8 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+import java.io.IOException;
+
 /**
  * A low-level connection to a {@link Tag} using the NFC-F technology, also known as
  * JIS6319-4.
@@ -44,6 +46,7 @@
     private byte[] mSystemCode = null;
     private byte[] mManufacturer = null;
 
+    /** @hide */
     public NfcF(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.NFC_F);
@@ -60,4 +63,19 @@
     public byte[] getManufacturer() {
       return mManufacturer;
     }
+
+    /**
+     * Send data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
+    }
 }
diff --git a/core/java/android/nfc/technology/NfcV.java b/core/java/android/nfc/technology/NfcV.java
index 4b51119..142ef9d 100644
--- a/core/java/android/nfc/technology/NfcV.java
+++ b/core/java/android/nfc/technology/NfcV.java
@@ -21,8 +21,10 @@
 import android.os.Bundle;
 import android.os.RemoteException;
 
+import java.io.IOException;
+
 /**
- * A low-level connection to a {@link Tag} using the NFC-V technology, also known as
+ * A low-level connection to a {@link Tag} using NFC vicinity technology, also known as
  * ISO15693.
  *
  * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
@@ -45,6 +47,7 @@
     private byte mRespFlags;
     private byte mDsfId;
 
+    /** @hide */
     public NfcV(NfcAdapter adapter, Tag tag, Bundle extras)
             throws RemoteException {
         super(adapter, tag, TagTechnology.NFC_V);
@@ -59,4 +62,19 @@
     public byte getDsfId() {
         return mDsfId;
     }
+
+    /**
+     * Send data to a tag and receive the response.
+     * <p>
+     * This method will block until the response is received. It can be canceled
+     * with {@link #close}.
+     * <p>Requires {@link android.Manifest.permission#NFC} permission.
+     *
+     * @param data bytes to send
+     * @return bytes received in response
+     * @throws IOException if the target is lost or connection closed
+     */
+    public byte[] transceive(byte[] data) throws IOException {
+        return transceive(data, true);
+    }
 }
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/technology/TagTechnology.java
index 62216c1..96f1724 100644
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ b/core/java/android/nfc/technology/TagTechnology.java
@@ -22,47 +22,60 @@
 
 public interface TagTechnology {
     /**
-     * This object is an instance of {@link NfcA}
+     * This technology is an instance of {@link NfcA}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int NFC_A = 1;
 
     /**
-     * This object is an instance of {@link NfcB}
+     * This technology is an instance of {@link NfcB}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int NFC_B = 2;
 
     /**
-     * This object is an instance of {@link IsoDep}
+     * This technology is an instance of {@link IsoDep}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int ISO_DEP = 3;
 
     /**
-     * This object is an instance of {@link NfcF}
+     * This technology is an instance of {@link NfcF}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int NFC_F = 4;
 
     /**
-     * This object is an instance of {@link NfcV}
+     * This technology is an instance of {@link NfcV}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int NFC_V = 5;
 
     /**
-     * This object is an instance of {@link Ndef}
+     * This technology is an instance of {@link Ndef}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int NDEF = 6;
 
     /**
-     * This object is an instance of {@link NdefFormatable}
+     * This technology is an instance of {@link NdefFormatable}.
+     * <p>Support for this technology type is mandatory.
      */
     public static final int NDEF_FORMATABLE = 7;
 
     /**
-     * This object is an instance of {@link MifareClassic}
+     * 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.
      */
     public static final int MIFARE_CLASSIC = 8;
 
     /**
-     * This object is an instance of {@link MifareUltralight}
+     * 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.
      */
     public static final int MIFARE_ULTRALIGHT = 9;
 
@@ -72,23 +85,51 @@
     public int getTechnologyId();
 
     /**
-     * Get the backing tag object.
+     * Get the {@link Tag} object this technology came from.
      */
     public Tag getTag();
 
     /**
-     * @throws IOException
+     * Opens a connection to the {@link Tag} enabling interactive commands. The command set
+     * varies by the technology type.
+     *
+     * <p>This method blocks until the connection has been established.
+     *
+     * <p>A call to {@link #close} from another thread will cancel a blocked call and cause an
+     * IOException to be thrown on the thread that is blocked.
+     *
+     * @see #reconnect()
+     * @see #close()
+     * @throws IOException if the target is lost, or connect 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>This method blocks until the connection is re-established.
+     *
+     * <p>A call to {@link #close} from another thread will cancel a blocked call and cause an
+     * IOException to be thrown on the thread that is blocked.
+     *
+     * @see #connect()
+     * @see #close()
      * @throws IOException
      */
     public void reconnect() throws IOException;
 
     /**
-     * Non-blocking. Immediately causes all blocking calls
-     * to throw IOException.
+     * Closes the connection to the {@link Tag}. This call is non-blocking and causes all blocking
+     * operations such as {@link #connect} to be canceled and immediately throw
+     * {@link java.io.IOException} on the thread that is blocked.
+     *
+     * <p>
+     * Once this method is called, this object cannot be re-used and should be discarded. Further
+     * calls to {@link #connect} will fail.
+     *
+     * @see #connect()
+     * @see #reconnect()
      */
     public void close();
 }