API changes for NFC.

Bug: 3366009
Change-Id: Ia28e03e1501421906b640b78d4c9a59a20e9c668
diff --git a/api/current.xml b/api/current.xml
index f4e9a34..adba51b 100644
--- a/api/current.xml
+++ b/api/current.xml
@@ -102891,21 +102891,6 @@
  visibility="public"
 >
 </method>
-<method name="getTechnology"
- return="android.nfc.technology.TagTechnology"
- abstract="false"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-<parameter name="tag" type="android.nfc.Tag">
-</parameter>
-<parameter name="tech" type="int">
-</parameter>
-</method>
 <method name="isEnabled"
  return="boolean"
  abstract="false"
@@ -103118,7 +103103,7 @@
 </constructor>
 </class>
 </package>
-<package name="android.nfc.technology"
+<package name="android.nfc.tech"
 >
 <class name="BasicTagTechnology"
  extends="java.lang.Object"
@@ -103128,7 +103113,7 @@
  deprecated="not deprecated"
  visibility=""
 >
-<implements name="android.nfc.technology.TagTechnology">
+<implements name="android.nfc.tech.TagTechnology">
 </implements>
 <method name="close"
  return="void"
@@ -103202,13 +103187,26 @@
 </method>
 </class>
 <class name="IsoDep"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="get"
+ return="android.nfc.tech.IsoDep"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getHiLayerResponse"
  return="byte[]"
  abstract="false"
@@ -103261,7 +103259,7 @@
 </method>
 </class>
 <class name="MifareClassic"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
@@ -103321,6 +103319,19 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="get"
+ return="android.nfc.tech.MifareClassic"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getBlockCount"
  return="int"
  abstract="false"
@@ -103664,13 +103675,26 @@
 </field>
 </class>
 <class name="MifareUltralight"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="get"
+ return="android.nfc.tech.MifareUltralight"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getType"
  return="int"
  abstract="false"
@@ -103764,7 +103788,7 @@
 </field>
 </class>
 <class name="Ndef"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
@@ -103782,6 +103806,19 @@
  visibility="public"
 >
 </method>
+<method name="get"
+ return="android.nfc.tech.Ndef"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getCachedNdefMessage"
  return="android.nfc.NdefMessage"
  abstract="false"
@@ -103875,7 +103912,7 @@
  type="int"
  transient="false"
  volatile="false"
- value="105"
+ value="101"
  static="true"
  final="true"
  deprecated="not deprecated"
@@ -103939,7 +103976,7 @@
 </field>
 </class>
 <class name="NdefFormatable"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
@@ -103963,15 +104000,41 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
+<method name="get"
+ return="android.nfc.tech.NdefFormatable"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 </class>
 <class name="NfcA"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="get"
+ return="android.nfc.tech.NfcA"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getAtqa"
  return="byte[]"
  abstract="false"
@@ -104011,13 +104074,26 @@
 </method>
 </class>
 <class name="NfcB"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="get"
+ return="android.nfc.tech.NfcB"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getApplicationData"
  return="byte[]"
  abstract="false"
@@ -104057,13 +104133,26 @@
 </method>
 </class>
 <class name="NfcF"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="get"
+ return="android.nfc.tech.NfcF"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getManufacturer"
  return="byte[]"
  abstract="false"
@@ -104103,13 +104192,26 @@
 </method>
 </class>
 <class name="NfcV"
- extends="android.nfc.technology.BasicTagTechnology"
+ extends="android.nfc.tech.BasicTagTechnology"
  abstract="false"
  static="false"
  final="true"
  deprecated="not deprecated"
  visibility="public"
 >
+<method name="get"
+ return="android.nfc.tech.NfcV"
+ abstract="false"
+ native="false"
+ synchronized="false"
+ static="true"
+ final="false"
+ deprecated="not deprecated"
+ visibility="public"
+>
+<parameter name="tag" type="android.nfc.Tag">
+</parameter>
+</method>
 <method name="getDsfId"
  return="byte"
  abstract="false"
@@ -104190,17 +104292,6 @@
  visibility="public"
 >
 </method>
-<method name="getTechnologyId"
- return="int"
- abstract="true"
- native="false"
- synchronized="false"
- static="false"
- final="false"
- deprecated="not deprecated"
- visibility="public"
->
-</method>
 <method name="reconnect"
  return="void"
  abstract="true"
@@ -104214,105 +104305,6 @@
 <exception name="IOException" type="java.io.IOException">
 </exception>
 </method>
-<field name="ISO_DEP"
- type="int"
- transient="false"
- volatile="false"
- value="3"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MIFARE_CLASSIC"
- type="int"
- transient="false"
- volatile="false"
- value="8"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="MIFARE_ULTRALIGHT"
- type="int"
- transient="false"
- volatile="false"
- value="9"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NDEF"
- type="int"
- transient="false"
- volatile="false"
- value="6"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NDEF_FORMATABLE"
- type="int"
- transient="false"
- volatile="false"
- value="7"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NFC_A"
- type="int"
- transient="false"
- volatile="false"
- value="1"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NFC_B"
- type="int"
- transient="false"
- volatile="false"
- value="2"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NFC_F"
- type="int"
- transient="false"
- volatile="false"
- value="4"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
-<field name="NFC_V"
- type="int"
- transient="false"
- volatile="false"
- value="5"
- static="true"
- final="true"
- deprecated="not deprecated"
- visibility="public"
->
-</field>
 </interface>
 </package>
 <package name="android.opengl"
diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java
index f6605b8..b1623a5 100644
--- a/core/java/android/nfc/NfcAdapter.java
+++ b/core/java/android/nfc/NfcAdapter.java
@@ -26,7 +26,7 @@
 import android.content.IntentFilter;
 import android.content.pm.IPackageManager;
 import android.content.pm.PackageManager;
-import android.nfc.technology.TagTechnology;
+import android.nfc.tech.TagTechnology;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -532,16 +532,6 @@
     }
 
     /**
-     * Retrieve a TagTechnology object used to interact with a Tag that is
-     * in field.
-     * <p>
-     * @return TagTechnology object, or null if not present
-     */
-    public TagTechnology getTechnology(Tag tag, int tech) {
-        return tag.getTechnology(NfcAdapter.this, tech);
-    }
-
-    /**
      * Set the NDEF Message that this NFC adapter should appear as to Tag
      * readers.
      * <p>
diff --git a/core/java/android/nfc/NfcSecureElement.java b/core/java/android/nfc/NfcSecureElement.java
index 5f4c066..ea2846e 100755
--- a/core/java/android/nfc/NfcSecureElement.java
+++ b/core/java/android/nfc/NfcSecureElement.java
@@ -16,7 +16,7 @@
 
 package android.nfc;
 
-import android.nfc.technology.TagTechnology;
+import android.nfc.tech.TagTechnology;
 import android.os.RemoteException;
 import android.util.Log;
 
diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java
index 8e2360a..55a9556 100644
--- a/core/java/android/nfc/Tag.java
+++ b/core/java/android/nfc/Tag.java
@@ -16,20 +16,10 @@
 
 package android.nfc;
 
-import android.nfc.technology.IsoDep;
-import android.nfc.technology.MifareClassic;
-import android.nfc.technology.MifareUltralight;
-import android.nfc.technology.NfcV;
-import android.nfc.technology.Ndef;
-import android.nfc.technology.NdefFormatable;
-import android.nfc.technology.NfcA;
-import android.nfc.technology.NfcB;
-import android.nfc.technology.NfcF;
-import android.nfc.technology.TagTechnology;
+import android.nfc.tech.TagTechnology;
 import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.RemoteException;
 
 import java.util.Arrays;
 
@@ -44,8 +34,8 @@
  * {@link Tag} objects are passed to applications via the {@link NfcAdapter#EXTRA_TAG} extra
  * in {@link NfcAdapter#ACTION_TAG_DISCOVERED} intents. A {@link Tag} object is immutable
  * and represents the state of the tag at the time of discovery. It can be
- * directly queried for its UID and Type, or used to create a {@link TagTechnology}
- * (with {@link NfcAdapter#getTechnology}).
+ * directly queried for its UID and Type, or used to create a {@link TagTechnology} using the
+ * static <code>get()</code> methods on the varios tech classes.
  * <p>
  * A {@link Tag} can  be used to create a {@link TagTechnology} only while the tag is in
  * range. If it is removed and then returned to range, then the most recent
@@ -61,6 +51,7 @@
     /*package*/ final int[] mTechList;
     /*package*/ final Bundle[] mTechExtras;
     /*package*/ final int mServiceHandle;  // for use by NFC service, 0 indicates a mock
+    /*package*/ final INfcTag mTagService;
 
     /*package*/ int mConnectedTechnology;
 
@@ -68,7 +59,8 @@
      * Hidden constructor to be used by NFC service and internal classes.
      * @hide
      */
-    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle) {
+    public Tag(byte[] id, int[] techList, Bundle[] techListExtras, int serviceHandle,
+            INfcTag tagService) {
         if (techList == null) {
             throw new IllegalArgumentException("rawTargets cannot be null");
         }
@@ -77,15 +69,15 @@
         // Ensure mTechExtras is as long as mTechList
         mTechExtras = Arrays.copyOf(techListExtras, techList.length);
         mServiceHandle = serviceHandle;
+        mTagService = tagService;
 
         mConnectedTechnology = -1;
     }
 
     /**
      * Construct a mock Tag.
-     * <p>This is an application constructed tag, so NfcAdapter methods on this
-     * Tag such as {@link NfcAdapter#getTechnology} may fail with
-     * {@link IllegalArgumentException} since it does not represent a physical Tag.
+     * <p>This is an application constructed tag, so NfcAdapter methods on this Tag may fail
+     * with {@link IllegalArgumentException} since it does not represent a physical Tag.
      * <p>This constructor might be useful for mock testing.
      * @param id The tag identifier, can be null
      * @param techList must not be null
@@ -93,7 +85,7 @@
      */
     public static Tag createMockTag(byte[] id, int[] techList, Bundle[] techListExtras) {
         // set serviceHandle to 0 to indicate mock tag
-        return new Tag(id, techList, techListExtras, 0);
+        return new Tag(id, techList, techListExtras, 0, null);
     }
 
     /**
@@ -127,7 +119,16 @@
         return Arrays.copyOf(mTechList, mTechList.length);
     }
 
-    /*package*/ TagTechnology getTechnology(NfcAdapter adapter, int tech) {
+    /** @hide */
+    public boolean hasTech(int techType) {
+        for (int tech : mTechList) {
+            if (tech == techType) return true;
+        }
+        return false;
+    }
+    
+    /** @hide */
+    public Bundle getTechExtras(int tech) {
         int pos = -1;
         for (int idx = 0; idx < mTechList.length; idx++) {
           if (mTechList[idx] == tech) {
@@ -139,44 +140,12 @@
             return null;
         }
 
-        Bundle extras = mTechExtras[pos];
-        try {
-            switch (tech) {
-                case TagTechnology.NFC_A: {
-                    return new NfcA(adapter, this, extras);
-                }
-                case TagTechnology.NFC_B: {
-                    return new NfcB(adapter, this, extras);
-                }
-                case TagTechnology.ISO_DEP: {
-                    return new IsoDep(adapter, this, extras);
-                }
-                case TagTechnology.NFC_V: {
-                    return new NfcV(adapter, this, extras);
-                }
-                case TagTechnology.NDEF: {
-                    return new Ndef(adapter, this, tech, extras);
-                }
-                case TagTechnology.NDEF_FORMATABLE: {
-                    return new NdefFormatable(adapter, this, tech, extras);
-                }
-                case TagTechnology.NFC_F: {
-                    return new NfcF(adapter, this, extras);
-                }
-                case TagTechnology.MIFARE_CLASSIC: {
-                    return new MifareClassic(adapter, this, extras);
-                }
-                case TagTechnology.MIFARE_ULTRALIGHT: {
-                    return new MifareUltralight(adapter, this, extras);
-                }
+        return mTechExtras[pos];
+    }
 
-                default: {
-                    throw new UnsupportedOperationException("Tech " + tech + " not supported");
-                }
-            }
-        } catch (RemoteException e) {
-            return null;
-        }
+    /** @hide */
+    public INfcTag getTagService() {
+        return mTagService;
     }
 
     @Override
@@ -223,6 +192,7 @@
         dest.writeIntArray(mTechList);
         dest.writeTypedArray(mTechExtras, 0);
         dest.writeInt(mServiceHandle);
+        dest.writeStrongBinder(mTagService.asBinder());
     }
 
     public static final Parcelable.Creator<Tag> CREATOR =
@@ -235,8 +205,9 @@
             in.readIntArray(techList);
             Bundle[] techExtras = in.createTypedArray(Bundle.CREATOR);
             int serviceHandle = in.readInt();
+            INfcTag tagService = INfcTag.Stub.asInterface(in.readStrongBinder());
 
-            return new Tag(id, techList, techExtras, serviceHandle);
+            return new Tag(id, techList, techExtras, serviceHandle, tagService);
         }
 
         @Override
diff --git a/core/java/android/nfc/technology/BasicTagTechnology.java b/core/java/android/nfc/tech/BasicTagTechnology.java
similarity index 84%
rename from core/java/android/nfc/technology/BasicTagTechnology.java
rename to core/java/android/nfc/tech/BasicTagTechnology.java
index b67c607..a909631 100644
--- a/core/java/android/nfc/technology/BasicTagTechnology.java
+++ b/core/java/android/nfc/tech/BasicTagTechnology.java
@@ -14,20 +14,17 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import java.io.IOException;
-
-import android.nfc.INfcAdapter;
-import android.nfc.INfcTag;
-import android.nfc.NfcAdapter;
-import android.nfc.TransceiveResult;
-import android.nfc.Tag;
 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().
  */
@@ -37,11 +34,8 @@
     /*package*/ final Tag mTag;
     /*package*/ boolean mIsConnected;
     /*package*/ int mSelectedTechnology;
-    private final NfcAdapter mAdapter;
-    /*package*/ final INfcAdapter mService;
-    /*package*/ final INfcTag mTagService;
 
-    BasicTagTechnology(NfcAdapter adapter, Tag tag, int tech) throws RemoteException {
+    BasicTagTechnology(Tag tag, int tech) throws RemoteException {
         int[] techList = tag.getTechnologyList();
         int i;
 
@@ -56,15 +50,12 @@
             throw new IllegalArgumentException("Technology " + tech + " not present on tag " + tag);
         }
 
-        mAdapter = adapter;
-        mService = mAdapter.getService();
-        mTagService = mAdapter.getTagService();
         mTag = tag;
         mSelectedTechnology = tech;
     }
 
-    BasicTagTechnology(NfcAdapter adapter, Tag tag) throws RemoteException {
-        this(adapter, tag, tag.getTechnologyList()[0]);
+    BasicTagTechnology(Tag tag) throws RemoteException {
+        this(tag, tag.getTechnologyList()[0]);
     }
 
     @Override
@@ -100,7 +91,7 @@
         }
 
         try {
-            return mTagService.isPresent(mTag.getServiceHandle());
+            return mTag.getTagService().isPresent(mTag.getServiceHandle());
         } catch (RemoteException e) {
             Log.e(TAG, "NFC service dead", e);
             return false;
@@ -110,7 +101,7 @@
     @Override
     public void connect() throws IOException {
         try {
-            int errorCode = mTagService.connect(mTag.getServiceHandle(), getTechnologyId());
+            int errorCode = mTag.getTagService().connect(mTag.getServiceHandle(), getTechnologyId());
 
             if (errorCode == ErrorCodes.SUCCESS) {
                 // Store this in the tag object
@@ -132,7 +123,7 @@
         }
 
         try {
-            int errorCode = mTagService.reconnect(mTag.getServiceHandle());
+            int errorCode = mTag.getTagService().reconnect(mTag.getServiceHandle());
 
             if (errorCode != ErrorCodes.SUCCESS) {
                 mIsConnected = false;
@@ -153,7 +144,7 @@
             /* Note that we don't want to physically disconnect the tag,
              * but just reconnect to it to reset its state
              */
-            mTagService.reconnect(mTag.getServiceHandle());
+            mTag.getTagService().reconnect(mTag.getServiceHandle());
         } catch (RemoteException e) {
             Log.e(TAG, "NFC service dead", e);
         } finally {
@@ -167,7 +158,7 @@
         checkConnected();
 
         try {
-            TransceiveResult result = mTagService.transceive(mTag.getServiceHandle(), data, raw);
+            TransceiveResult result = mTag.getTagService().transceive(mTag.getServiceHandle(), data, raw);
             if (result == null) {
                 throw new IOException("transceive failed");
             } else {
diff --git a/core/java/android/nfc/technology/IsoDep.java b/core/java/android/nfc/tech/IsoDep.java
similarity index 81%
rename from core/java/android/nfc/technology/IsoDep.java
rename to core/java/android/nfc/tech/IsoDep.java
index c58127a..f6d141a 100644
--- a/core/java/android/nfc/technology/IsoDep.java
+++ b/core/java/android/nfc/tech/IsoDep.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -28,7 +27,7 @@
  * A low-level connection to a {@link Tag} using the ISO-DEP technology, also known as
  * ISO1443-4.
  *
- * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -49,10 +48,26 @@
     private byte[] mHiLayerResponse = null;
     private byte[] mHistBytes = null;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras)
+    public IsoDep(Tag tag)
             throws RemoteException {
-        super(adapter, tag, TagTechnology.ISO_DEP);
+        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);
@@ -70,7 +85,7 @@
      */
     public void setTimeout(int timeout) {
         try {
-            mTagService.setIsoDepTimeout(timeout);
+            mTag.getTagService().setIsoDepTimeout(timeout);
         } catch (RemoteException e) {
             Log.e(TAG, "NFC service dead", e);
         }
@@ -79,7 +94,7 @@
     @Override
     public void close() {
         try {
-            mTagService.resetIsoDepTimeout();
+            mTag.getTagService().resetIsoDepTimeout();
         } catch (RemoteException e) {
             Log.e(TAG, "NFC service dead", e);
         }
diff --git a/core/java/android/nfc/technology/MifareClassic.java b/core/java/android/nfc/tech/MifareClassic.java
similarity index 95%
rename from core/java/android/nfc/technology/MifareClassic.java
rename to core/java/android/nfc/tech/MifareClassic.java
index a2abaa3..1c52322 100644
--- a/core/java/android/nfc/technology/MifareClassic.java
+++ b/core/java/android/nfc/tech/MifareClassic.java
@@ -14,12 +14,10 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
-import android.nfc.TagLostException;
 import android.nfc.Tag;
-import android.os.Bundle;
+import android.nfc.TagLostException;
 import android.os.RemoteException;
 
 import java.io.IOException;
@@ -82,12 +80,27 @@
     private int mType;
     private int mSize;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
-        super(adapter, tag, TagTechnology.MIFARE_CLASSIC);
+    public MifareClassic(Tag tag) throws RemoteException {
+        super(tag, TagTechnology.MIFARE_CLASSIC);
 
         // Check if this could actually be a MIFARE Classic
-        NfcA a = (NfcA) adapter.getTechnology(tag, TagTechnology.NFC_A);
+        NfcA a = NfcA.get(tag);
 
         mIsEmulated = false;
         mType = TYPE_UNKNOWN;
diff --git a/core/java/android/nfc/technology/MifareUltralight.java b/core/java/android/nfc/tech/MifareUltralight.java
similarity index 82%
rename from core/java/android/nfc/technology/MifareUltralight.java
rename to core/java/android/nfc/tech/MifareUltralight.java
index 5c8cb3c..f096298 100644
--- a/core/java/android/nfc/technology/MifareUltralight.java
+++ b/core/java/android/nfc/tech/MifareUltralight.java
@@ -14,11 +14,9 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
 import android.nfc.Tag;
-import android.os.Bundle;
 import android.os.RemoteException;
 
 import java.io.IOException;
@@ -44,16 +42,31 @@
 
     private int mType;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
-        super(adapter, tag, TagTechnology.MIFARE_ULTRALIGHT);
+    public MifareUltralight(Tag tag) throws RemoteException {
+        super(tag, TagTechnology.MIFARE_ULTRALIGHT);
 
         // Check if this could actually be a Mifare
-        NfcA a = (NfcA) adapter.getTechnology(tag, TagTechnology.NFC_A);
+        NfcA a = NfcA.get(tag);
 
         mType = TYPE_UNKNOWN;
 
-        if( a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID ) {
+        if (a.getSak() == 0x00 && tag.getId()[0] == NXP_MANUFACTURER_ID) {
             // could be UL or UL-C
             mType = TYPE_ULTRALIGHT;
         }
diff --git a/core/java/android/nfc/technology/Ndef.java b/core/java/android/nfc/tech/Ndef.java
similarity index 84%
rename from core/java/android/nfc/technology/Ndef.java
rename to core/java/android/nfc/tech/Ndef.java
index f537941..03f2184 100644
--- a/core/java/android/nfc/technology/Ndef.java
+++ b/core/java/android/nfc/tech/Ndef.java
@@ -14,10 +14,11 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+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;
@@ -32,7 +33,7 @@
  * to interact with NDEF data. MiFare Classic cards that present NDEF data may also be used
  * via this class. To determine the exact technology being used call {@link #getTechnologyId()}
  *
- * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  *
  * <p class="note"><strong>Note:</strong>
  * Use of this class requires the {@link android.Manifest.permission#NFC}
@@ -60,14 +61,12 @@
     /** @hide */
     public static final String EXTRA_NDEF_TYPE = "ndeftype";
 
-    //TODO: consider removing OTHER entirely - and not allowing Ndef to
-    // enumerate for tag types outside of (NFC Forum 1-4, MifareClassic)
     public static final int OTHER = -1;
     public static final int NFC_FORUM_TYPE_1 = 1;
     public static final int NFC_FORUM_TYPE_2 = 2;
     public static final int NFC_FORUM_TYPE_3 = 3;
     public static final int NFC_FORUM_TYPE_4 = 4;
-    public static final int MIFARE_CLASSIC = 105;
+    public static final int MIFARE_CLASSIC = 101;
 
     private final int mMaxNdefSize;
     private final int mCardState;
@@ -75,11 +74,27 @@
     private final int mNdefType;
 
     /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
-        super(adapter, tag, tech);
+    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);
@@ -142,11 +157,12 @@
         checkConnected();
 
         try {
+            INfcTag tagService = mTag.getTagService();
             int serviceHandle = mTag.getServiceHandle();
-            if (mTagService.isNdef(serviceHandle)) {
-                NdefMessage msg = mTagService.ndefRead(serviceHandle);
+            if (tagService.isNdef(serviceHandle)) {
+                NdefMessage msg = tagService.ndefRead(serviceHandle);
                 if (msg == null) {
-                    int errorCode = mTagService.getLastError(serviceHandle);
+                    int errorCode = tagService.getLastError(serviceHandle);
                     switch (errorCode) {
                         case ErrorCodes.ERROR_IO:
                             throw new IOException();
@@ -175,9 +191,10 @@
         checkConnected();
 
         try {
+            INfcTag tagService = mTag.getTagService();
             int serviceHandle = mTag.getServiceHandle();
-            if (mTagService.isNdef(serviceHandle)) {
-                int errorCode = mTagService.ndefWrite(serviceHandle, msg);
+            if (tagService.isNdef(serviceHandle)) {
+                int errorCode = tagService.ndefWrite(serviceHandle, msg);
                 switch (errorCode) {
                     case ErrorCodes.SUCCESS:
                         break;
@@ -221,8 +238,9 @@
         checkConnected();
 
         try {
-            if (mTagService.isNdef(mTag.getServiceHandle())) {
-                int errorCode = mTagService.ndefMakeReadOnly(mTag.getServiceHandle());
+            INfcTag tagService = mTag.getTagService();
+            if (tagService.isNdef(mTag.getServiceHandle())) {
+                int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle());
                 switch (errorCode) {
                     case ErrorCodes.SUCCESS:
                         return true;
diff --git a/core/java/android/nfc/technology/NdefFormatable.java b/core/java/android/nfc/tech/NdefFormatable.java
similarity index 73%
rename from core/java/android/nfc/technology/NdefFormatable.java
rename to core/java/android/nfc/tech/NdefFormatable.java
index e2fd034..2919c43 100644
--- a/core/java/android/nfc/technology/NdefFormatable.java
+++ b/core/java/android/nfc/tech/NdefFormatable.java
@@ -14,14 +14,14 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+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.os.Bundle;
 import android.os.RemoteException;
 import android.util.Log;
 
@@ -30,7 +30,7 @@
 /**
  * An interface to a {@link Tag} allowing to format the tag as NDEF.
  *
- * <p>You can acquire this kind of interface with {@link NfcAdapter#getTechnology}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  *
  * <p class="note"><strong>Note:</strong>
  * Use of this class requires the {@link android.Manifest.permission#NFC}
@@ -40,11 +40,26 @@
     private static final String TAG = "NFC";
 
     /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, int tech, Bundle extras) throws RemoteException {
-        super(adapter, tag, tech);
+    public NdefFormatable(Tag tag) throws RemoteException {
+        super(tag, TagTechnology.NDEF_FORMATABLE);
     }
 
     /**
@@ -55,10 +70,9 @@
         checkConnected();
 
         try {
-            byte[] DEFAULT_KEY = {(byte)0xFF,(byte)0xFF,(byte)0xFF,
-                                  (byte)0xFF,(byte)0xFF,(byte)0xFF};
             int serviceHandle = mTag.getServiceHandle();
-            int errorCode = mTagService.formatNdef(serviceHandle, DEFAULT_KEY);
+            INfcTag tagService = mTag.getTagService();
+            int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT);
             switch (errorCode) {
                 case ErrorCodes.SUCCESS:
                     break;
@@ -71,8 +85,8 @@
                     throw new IOException();
             }
             // Now check and see if the format worked
-            if (mTagService.isNdef(serviceHandle)) {
-                errorCode = mTagService.ndefWrite(serviceHandle, firstMessage);
+            if (tagService.isNdef(serviceHandle)) {
+                errorCode = tagService.ndefWrite(serviceHandle, firstMessage);
                 switch (errorCode) {
                     case ErrorCodes.SUCCESS:
                         break;
diff --git a/core/java/android/nfc/technology/NfcA.java b/core/java/android/nfc/tech/NfcA.java
similarity index 77%
rename from core/java/android/nfc/technology/NfcA.java
rename to core/java/android/nfc/tech/NfcA.java
index 0615a10..24badc4 100644
--- a/core/java/android/nfc/technology/NfcA.java
+++ b/core/java/android/nfc/tech/NfcA.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -27,7 +26,7 @@
  * A low-level connection to a {@link Tag} using the NFC-A technology, also known as
  * ISO1443-3A.
  *
- * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -46,9 +45,25 @@
     private short mSak;
     private byte[] mAtqa;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras) throws RemoteException {
-        super(adapter, tag, TagTechnology.NFC_A);
+    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);
     }
diff --git a/core/java/android/nfc/technology/NfcB.java b/core/java/android/nfc/tech/NfcB.java
similarity index 78%
rename from core/java/android/nfc/technology/NfcB.java
rename to core/java/android/nfc/tech/NfcB.java
index c14b98d..abeef32 100644
--- a/core/java/android/nfc/technology/NfcB.java
+++ b/core/java/android/nfc/tech/NfcB.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -27,7 +26,7 @@
  * A low-level connection to a {@link Tag} using the NFC-B technology, also known as
  * ISO1443-3B.
  *
- * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -46,10 +45,25 @@
     private byte[] mAppData;
     private byte[] mProtInfo;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras)
-            throws RemoteException {
-        super(adapter, tag, TagTechnology.NFC_B);
+    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);
     }
diff --git a/core/java/android/nfc/technology/NfcF.java b/core/java/android/nfc/tech/NfcF.java
similarity index 77%
rename from core/java/android/nfc/technology/NfcF.java
rename to core/java/android/nfc/tech/NfcF.java
index 434e5df..f617739 100644
--- a/core/java/android/nfc/technology/NfcF.java
+++ b/core/java/android/nfc/tech/NfcF.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -27,7 +26,7 @@
  * A low-level connection to a {@link Tag} using the NFC-F technology, also known as
  * JIS6319-4.
  *
- * <p>You can acquire this kind of connection with {@link NfcAdapter#getTechnology}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -46,10 +45,25 @@
     private byte[] mSystemCode = null;
     private byte[] mManufacturer = null;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras)
-            throws RemoteException {
-        super(adapter, tag, TagTechnology.NFC_F);
+    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);
diff --git a/core/java/android/nfc/technology/NfcV.java b/core/java/android/nfc/tech/NfcV.java
similarity index 76%
rename from core/java/android/nfc/technology/NfcV.java
rename to core/java/android/nfc/tech/NfcV.java
index 142ef9d..8e1f066 100644
--- a/core/java/android/nfc/technology/NfcV.java
+++ b/core/java/android/nfc/tech/NfcV.java
@@ -14,9 +14,8 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
-import android.nfc.NfcAdapter;
 import android.nfc.Tag;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -27,7 +26,7 @@
  * 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}.
+ * <p>You can acquire this kind of connection with {@link #get}.
  * Use this class to send and receive data with {@link #transceive transceive()}.
  *
  * <p>Applications must implement their own protocol stack on top of
@@ -47,10 +46,25 @@
     private byte mRespFlags;
     private byte mDsfId;
 
+    /**
+     * Returns an instance of this tech for the given tag. If the tag doesn't support
+     * this tech type null is returned.
+     *
+     * @param tag The tag to get the tech from
+     */
+    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(NfcAdapter adapter, Tag tag, Bundle extras)
-            throws RemoteException {
-        super(adapter, tag, TagTechnology.NFC_V);
+    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);
     }
diff --git a/core/java/android/nfc/technology/TagTechnology.java b/core/java/android/nfc/tech/TagTechnology.java
similarity index 96%
rename from core/java/android/nfc/technology/TagTechnology.java
rename to core/java/android/nfc/tech/TagTechnology.java
index 96f1724..1331bae 100644
--- a/core/java/android/nfc/technology/TagTechnology.java
+++ b/core/java/android/nfc/tech/TagTechnology.java
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-package android.nfc.technology;
+package android.nfc.tech;
 
 import android.nfc.Tag;
 
@@ -24,42 +24,49 @@
     /**
      * 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;
 
@@ -68,6 +75,7 @@
      * <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;
 
@@ -76,11 +84,13 @@
      * <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;
 
     /**
      * Returns the technology type for this tag connection.
+     * @hide
      */
     public int getTechnologyId();