Merge "More robust attribute binding Adding attribute and uniform debug logging. Checking to see if aniso filtering is available."
diff --git a/Android.mk b/Android.mk
index 9492167..570fbf8 100644
--- a/Android.mk
+++ b/Android.mk
@@ -161,6 +161,14 @@
 	core/java/com/android/internal/view/IInputMethodManager.aidl \
 	core/java/com/android/internal/view/IInputMethodSession.aidl \
 	core/java/com/android/internal/widget/IRemoteViewsFactory.aidl \
+	core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl \
+	core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl \
+	core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl \
+	core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl \
+	core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl \
+	core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl \
+	core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl \
+	core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl \
 	location/java/android/location/ICountryDetector.aidl \
 	location/java/android/location/ICountryListener.aidl \
 	location/java/android/location/IGeocodeProvider.aidl \
diff --git a/core/java/android/app/ContextImpl.java b/core/java/android/app/ContextImpl.java
index 3174f55..918ecf1 100644
--- a/core/java/android/app/ContextImpl.java
+++ b/core/java/android/app/ContextImpl.java
@@ -103,6 +103,8 @@
 import android.accounts.AccountManager;
 import android.accounts.IAccountManager;
 import android.app.admin.DevicePolicyManager;
+import com.trustedlogic.trustednfc.android.NfcManager;
+import com.trustedlogic.trustednfc.android.INfcManager;
 
 import com.android.internal.os.IDropBoxManagerService;
 
@@ -173,6 +175,7 @@
     private static WifiManager sWifiManager;
     private static LocationManager sLocationManager;
     private static CountryDetector sCountryDetector;
+    private static NfcManager sNfcManager;
     private static final HashMap<String, SharedPreferencesImpl> sSharedPrefs =
             new HashMap<String, SharedPreferencesImpl>();
 
@@ -968,6 +971,8 @@
             return getClipboardManager();
         } else if (WALLPAPER_SERVICE.equals(name)) {
             return getWallpaperManager();
+        } else if (NFC_SERVICE.equals(name)) {
+            return getNfcManager();
         } else if (DROPBOX_SERVICE.equals(name)) {
             return getDropBoxManager();
         } else if (DEVICE_POLICY_SERVICE.equals(name)) {
@@ -1219,6 +1224,21 @@
         return mDownloadManager;
     }
 
+    private NfcManager getNfcManager()
+    {
+        synchronized (sSync) {
+            if (sNfcManager == null) {
+                IBinder b = ServiceManager.getService(NFC_SERVICE);
+                if (b == null) {
+                    return null;
+                }
+                INfcManager service = INfcManager.Stub.asInterface(b);
+                sNfcManager = new NfcManager(service, mMainThread.getHandler());
+            }
+        }
+        return sNfcManager;
+    }
+
     @Override
     public int checkPermission(String permission, int pid, int uid) {
         if (permission == null) {
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 3a56afb..9c8d698 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -1592,6 +1592,16 @@
     public static final String SIP_SERVICE = "sip";
 
     /**
+     * Use with {@link #getSystemService} to retrieve an
+     * {@link com.trustedlogic.trustednfc.android.INfcManager.INfcManager} for
+     * accessing NFC methods.
+     *
+     * @see #getSystemService
+     * @hide
+     */
+    public static final String NFC_SERVICE = "nfc";
+
+    /**
      * Determine whether the given permission is allowed for a particular
      * process and user ID running in the system.
      *
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index d8fb658..cf95872 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -1642,6 +1642,86 @@
         public static final String NOTIFICATION_LIGHT_PULSE = "notification_light_pulse";
 
         /**
+         * Whether nfc is enabled/disabled
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_ON = "nfc_on";
+
+        /**
+         * Whether nfc secure element is enabled/disabled
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_SECURE_ELEMENT_ON = "nfc_secure_element_on";
+
+        /**
+         * Whether nfc secure element is enabled/disabled
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_SECURE_ELEMENT_ID = "nfc_secure_element_id";
+
+        /**
+         * LLCP LTO value
+         * @hide
+         */
+        public static final String NFC_LLCP_LTO = "nfc_llcp_lto";
+
+        /**
+         * LLCP MIU value
+         * @hide
+         */
+        public static final String NFC_LLCP_MIU = "nfc_llcp_miu";
+
+        /**
+         * LLCP WKS value
+         * @hide
+         */
+        public static final String NFC_LLCP_WKS = "nfc_llcp_wks";
+
+        /**
+         * LLCP OPT value
+         * @hide
+         */
+        public static final String NFC_LLCP_OPT = "nfc_llcp_opt";
+
+        /**
+         * NFC Discovery Reader A
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_DISCOVERY_A = "nfc_discovery_a";
+
+        /**
+         * NFC Discovery Reader B
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_DISCOVERY_B = "nfc_discovery_b";
+
+        /**
+         * NFC Discovery Reader Felica
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_DISCOVERY_F = "nfc_discovery_felica";
+
+        /**
+         * NFC Discovery Reader 15693
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_DISCOVERY_15693 = "nfc_discovery_15693";
+
+        /**
+         * NFC Discovery NFCIP
+         * 0=disabled. 1=enabled.
+         * @hide
+         */
+        public static final String NFC_DISCOVERY_NFCIP = "nfc_discovery_nfcip";
+
+        /**
          * Show pointer location on screen?
          * 0 = no
          * 1 = yes
@@ -1814,7 +1894,19 @@
             NOTIFICATION_LIGHT_PULSE,
             USE_PTP_INTERFACE,
             SIP_CALL_OPTIONS,
-            SIP_RECEIVE_CALLS
+            SIP_RECEIVE_CALLS,
+            NFC_ON,
+            NFC_SECURE_ELEMENT_ON,
+            NFC_SECURE_ELEMENT_ID,
+            NFC_LLCP_LTO,
+            NFC_LLCP_MIU,
+            NFC_LLCP_WKS,
+            NFC_LLCP_OPT,
+            NFC_DISCOVERY_A,
+            NFC_DISCOVERY_B,
+            NFC_DISCOVERY_F,
+            NFC_DISCOVERY_15693,
+            NFC_DISCOVERY_NFCIP,
         };
 
         // Settings moved to Settings.Secure
diff --git a/core/java/android/view/DisplayList.java b/core/java/android/view/DisplayList.java
new file mode 100644
index 0000000..b1160f0
--- /dev/null
+++ b/core/java/android/view/DisplayList.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+/**
+ * A display lists records a series of graphics related operation and can replay
+ * them later. Display lists are usually built by recording operations on a
+ * {@link android.graphics.Canvas}. Replaying the operations from a display list
+ * avoids executing views drawing code on every frame, and is thus much more
+ * efficient. 
+ */
+abstract class DisplayList {
+    /**
+     * Starts recording the display list. All operations performed on the
+     * returned canvas are recorded and stored in this display list.
+     * 
+     * @return A canvas to record drawing operations.
+     */
+    abstract HardwareCanvas start();
+
+    /**
+     * Ends the recording for this display list. A display list cannot be
+     * replayed if recording is not finished. 
+     */
+    abstract void end();
+
+    /**
+     * Frees resources taken by this display list. This method must be called
+     * before releasing all references.
+     */
+    abstract void destroy();
+
+    /**
+     * Indicates whether this display list can be replayed or not.
+     * 
+     * @return True if the display list can be replayed, false otherwise.
+     * 
+     * @see android.view.HardwareCanvas#drawDisplayList(DisplayList) 
+     */
+    abstract boolean isReady();
+}
diff --git a/core/java/android/view/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index f917001..f0b00dd 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -35,14 +35,10 @@
 import android.text.SpannedString;
 import android.text.TextUtils;
 
-import javax.microedition.khronos.opengles.GL;
-
 /**
  * An implementation of Canvas on top of OpenGL ES 2.0.
  */
-class GLES20Canvas extends Canvas {
-    @SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"})
-    private final GL mGl;
+class GLES20Canvas extends HardwareCanvas {
     private final boolean mOpaque;
     private int mRenderer;
     
@@ -72,27 +68,29 @@
     ///////////////////////////////////////////////////////////////////////////
     // Constructors
     ///////////////////////////////////////////////////////////////////////////
+
+    GLES20Canvas(boolean translucent) {
+        this(false, translucent);
+    }
     
-    GLES20Canvas(GL gl, boolean translucent) {
-        mGl = gl;
+    GLES20Canvas(boolean record, boolean translucent) {
         mOpaque = !translucent;
 
-        mRenderer = nCreateRenderer();
+        if (record) {
+            mRenderer = nCreateDisplayListRenderer();
+        } else {
+            mRenderer = nCreateRenderer();
+        }
+       
         if (mRenderer == 0) {
             throw new IllegalStateException("Could not create GLES20Canvas renderer");
         }
     }
-    
-    private native int nCreateRenderer();
 
-    /**
-     * This method <strong>must</strong> be called before releasing a
-     * reference to a GLES20Canvas. This method is responsible for freeing
-     * native resources associated with the hardware. Not invoking this
-     * method properly can result in memory leaks.
-     * 
-     * @hide
-     */
+    private native int nCreateRenderer();    
+    private native int nCreateDisplayListRenderer();    
+
+    @Override
     public synchronized void destroy() {
         if (mRenderer != 0) {
             nDestroyRenderer(mRenderer);
@@ -105,16 +103,6 @@
     ///////////////////////////////////////////////////////////////////////////
     // Canvas management
     ///////////////////////////////////////////////////////////////////////////
-    
-    @Override
-    public boolean isHardwareAccelerated() {
-        return true;
-    }
-
-    @Override
-    public void setBitmap(Bitmap bitmap) {
-        throw new UnsupportedOperationException();
-    }
 
     @Override
     public boolean isOpaque() {
@@ -145,12 +133,14 @@
     
     private native void nSetViewport(int renderer, int width, int height);
 
+    @Override
     void onPreDraw() {
         nPrepare(mRenderer);
     }
 
     private native void nPrepare(int renderer);
 
+    @Override
     void onPostDraw() {
         nFinish(mRenderer);
     }
@@ -177,6 +167,29 @@
     }
 
     private native void nReleaseContext(int renderer);
+    
+    ///////////////////////////////////////////////////////////////////////////
+    // Display list
+    ///////////////////////////////////////////////////////////////////////////
+
+    int getDisplayList() {
+        return nCreateDisplayList(mRenderer);
+    }
+
+    private native int nCreateDisplayList(int renderer);
+    
+    void destroyDisplayList(int displayList) {
+        nDestroyDisplayList(displayList);
+    }
+
+    private native void nDestroyDisplayList(int displayList);
+
+    @Override
+    public void drawDisplayList(DisplayList displayList) {
+        nDrawDisplayList(mRenderer, ((GLES20DisplayList) displayList).mNativeDisplayList);
+    }
+
+    private native void nDrawDisplayList(int renderer, int displayList);
 
     ///////////////////////////////////////////////////////////////////////////
     // Clipping
diff --git a/core/java/android/view/GLES20DisplayList.java b/core/java/android/view/GLES20DisplayList.java
new file mode 100644
index 0000000..2886bf3
--- /dev/null
+++ b/core/java/android/view/GLES20DisplayList.java
@@ -0,0 +1,74 @@
+/*
+ * 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.view;
+
+/**
+ * An implementation of display list for OpenGL ES 2.0.
+ */
+class GLES20DisplayList extends DisplayList {
+    private GLES20Canvas mCanvas;
+
+    private boolean mStarted = false;
+    private boolean mRecorded = false;
+
+    int mNativeDisplayList;
+
+    @Override
+    HardwareCanvas start() {
+        if (mStarted) {
+            throw new IllegalStateException("Recording has already started");
+        }
+
+        destroyCanvas();
+
+        mCanvas = new GLES20Canvas(true, true);
+        mStarted = true;
+        mRecorded = false;
+
+        return mCanvas;
+    }
+
+    private void destroyCanvas() {
+        if (mCanvas != null) {
+            mCanvas.destroyDisplayList(mNativeDisplayList);
+            mCanvas.destroy();
+
+            mCanvas = null;
+            mNativeDisplayList = 0;
+        }
+    }
+
+    @Override
+    void end() {
+        if (mCanvas != null) {
+            mStarted = false;
+            mRecorded = true;
+
+            mNativeDisplayList = mCanvas.getDisplayList();
+        }
+    }
+
+    @Override
+    void destroy() {
+        destroyCanvas();
+    }
+
+    @Override
+    boolean isReady() {
+        return !mStarted && mRecorded;
+    }
+}
diff --git a/core/java/android/view/HardwareCanvas.java b/core/java/android/view/HardwareCanvas.java
new file mode 100644
index 0000000..22d2fe6
--- /dev/null
+++ b/core/java/android/view/HardwareCanvas.java
@@ -0,0 +1,60 @@
+/*
+ * 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.view;
+
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+
+/**
+ * Hardware accelerated canvas. 
+ */
+abstract class HardwareCanvas extends Canvas {
+    @Override
+    public boolean isHardwareAccelerated() {
+        return true;
+    }
+
+    @Override
+    public void setBitmap(Bitmap bitmap) {
+        throw new UnsupportedOperationException();
+    }
+    
+    /**
+     * This method <strong>must</strong> be called before releasing a
+     * reference to a hardware canvas. This method is responsible for
+     * freeing native resources associated with the hardware. Not
+     * invoking this method properly can result in memory leaks.
+     */    
+    public abstract void destroy();
+
+    /**
+     * Invoked before any drawing operation is performed in this canvas.
+     */
+    abstract void onPreDraw();
+
+    /**
+     * Invoked after all drawing operation have been performed.
+     */
+    abstract void onPostDraw();
+    
+    /**
+     * Draws the specified display list onto this canvas.
+     * 
+     * @param displayList The display list to replay.
+     */
+    public abstract void drawDisplayList(DisplayList displayList);
+}
diff --git a/core/java/android/view/HardwareRenderer.java b/core/java/android/view/HardwareRenderer.java
index fbb13af..2cc4052 100644
--- a/core/java/android/view/HardwareRenderer.java
+++ b/core/java/android/view/HardwareRenderer.java
@@ -103,6 +103,14 @@
     abstract void draw(View view, View.AttachInfo attachInfo, int yOffset);
 
     /**
+     * Creates a new canvas that can be used to record drawing operations
+     * in the specified display list.
+     * 
+     * @return A new recording canvas.
+     */
+    abstract DisplayList createDisplayList();
+
+    /**
      * Initializes the hardware renderer for the specified surface and setup the
      * renderer for drawing, if needed. This is invoked when the ViewRoot has
      * potentially lost the hardware renderer. The hardware renderer should be
@@ -577,7 +585,7 @@
 
         @Override
         GLES20Canvas createCanvas() {
-            return mGlCanvas = new GLES20Canvas(mGl, true);
+            return mGlCanvas = new GLES20Canvas(true);
         }
 
         @Override
@@ -590,6 +598,11 @@
             mGlCanvas.onPostDraw();
         }
 
+        @Override
+        DisplayList createDisplayList() {
+            return new GLES20DisplayList();
+        }
+
         static HardwareRenderer create(boolean translucent) {
             if (GLES20Canvas.isAvailable()) {
                 return new Gl20Renderer(translucent);
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index 96066b7..3b10437 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -1250,12 +1250,12 @@
      */
     private static final int[][] VIEW_STATE_SETS;
 
-    static final int VIEW_STATE_WINDOW_FOCUSED = 1<<0;
-    static final int VIEW_STATE_SELECTED = 1<<1;
-    static final int VIEW_STATE_FOCUSED = 1<<2;
-    static final int VIEW_STATE_ENABLED = 1<<3;
-    static final int VIEW_STATE_PRESSED = 1<<4;
-    static final int VIEW_STATE_ACTIVATED = 1<<5;
+    static final int VIEW_STATE_WINDOW_FOCUSED = 1;
+    static final int VIEW_STATE_SELECTED = 1 << 1;
+    static final int VIEW_STATE_FOCUSED = 1 << 2;
+    static final int VIEW_STATE_ENABLED = 1 << 3;
+    static final int VIEW_STATE_PRESSED = 1 << 4;
+    static final int VIEW_STATE_ACTIVATED = 1 << 5;
 
     static final int[] VIEW_STATE_IDS = new int[] {
         R.attr.state_window_focused,    VIEW_STATE_WINDOW_FOCUSED,
@@ -1268,28 +1268,23 @@
 
     static {
         int[] orderedIds = new int[VIEW_STATE_IDS.length];
-        for (int i=0; i<R.styleable.ViewDrawableStates.length; i++) {
+        for (int i = 0; i < R.styleable.ViewDrawableStates.length; i++) {
             int viewState = R.styleable.ViewDrawableStates[i];
-            for (int j=0; j<VIEW_STATE_IDS.length; j+=2) {
+            for (int j = 0; j<VIEW_STATE_IDS.length; j += 2) {
                 if (VIEW_STATE_IDS[j] == viewState) {
-                    orderedIds[i*2] = viewState;
-                    orderedIds[i*2+1] = VIEW_STATE_IDS[j+1];
+                    orderedIds[i * 2] = viewState;
+                    orderedIds[i * 2 + 1] = VIEW_STATE_IDS[j + 1];
                 }
             }
         }
-        final int NUM_BITS = VIEW_STATE_IDS.length/2;
-        VIEW_STATE_SETS = new int[1<<NUM_BITS][];
-        for (int i=0; i<VIEW_STATE_SETS.length; i++) {
+        final int NUM_BITS = VIEW_STATE_IDS.length / 2;
+        VIEW_STATE_SETS = new int[1 << NUM_BITS][];
+        for (int i = 0; i < VIEW_STATE_SETS.length; i++) {
             int numBits = Integer.bitCount(i);
             int[] set = new int[numBits];
             int pos = 0;
-            for (int j=0; j<orderedIds.length; j+=2) {
-                if ((i&orderedIds[j+1]) != 0) {
-                    if (false) {
-                        Log.i("View", "Index #" + i + " @ ordered #" + j
-                                + " resid=0x" + Integer.toHexString(orderedIds[j])
-                                + " mask " + orderedIds[j+1]);
-                    }
+            for (int j = 0; j < orderedIds.length; j += 2) {
+                if ((i & orderedIds[j+1]) != 0) {
                     set[pos++] = orderedIds[j];
                 }
             }
@@ -1958,6 +1953,7 @@
 
     private Bitmap mDrawingCache;
     private Bitmap mUnscaledDrawingCache;
+    private DisplayList mDisplayList;
 
     /**
      * When this view has focus and the next focus is {@link #FOCUS_LEFT},
@@ -7317,6 +7313,64 @@
     }
 
     /**
+     * <p>Returns a display list that can be used to draw this view again
+     * without executing its draw method.</p>
+     * 
+     * @return A DisplayList ready to replay, or null if caching is not enabled.
+     */
+    DisplayList getDisplayList() {
+        if ((mViewFlags & WILL_NOT_CACHE_DRAWING) == WILL_NOT_CACHE_DRAWING) {
+            return null;
+        }
+        
+        if (mAttachInfo == null || mAttachInfo.mHardwareRenderer == null) {
+            return null;
+        }
+
+        if ((mViewFlags & DRAWING_CACHE_ENABLED) == DRAWING_CACHE_ENABLED &&
+                ((mPrivateFlags & DRAWING_CACHE_VALID) == 0 || mDisplayList == null)) {
+
+            if (mDisplayList != null) {
+                mDisplayList.destroy();
+            }
+
+            mDisplayList = mAttachInfo.mHardwareRenderer.createDisplayList();
+
+            final HardwareCanvas canvas = mDisplayList.start();
+            try {
+                int width = mRight - mLeft;
+                int height = mBottom - mTop;
+
+                canvas.setViewport(width, height);
+                canvas.onPreDraw();
+
+                final int restoreCount = canvas.save();
+
+                mPrivateFlags |= DRAWN;
+                mPrivateFlags |= DRAWING_CACHE_VALID;
+    
+                // Fast path for layouts with no backgrounds
+                if ((mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                    mPrivateFlags &= ~DIRTY_MASK;
+                    dispatchDraw(canvas);
+                } else {
+                    draw(canvas);
+                }
+    
+                canvas.restoreToCount(restoreCount);
+            } finally {
+                canvas.onPostDraw();
+
+                mDisplayList.end();
+
+                canvas.destroy();                
+            }
+        }
+
+        return mDisplayList;
+    }
+
+    /**
      * <p>Calling this method is equivalent to calling <code>getDrawingCache(false)</code>.</p>
      * 
      * @return A non-scaled bitmap representing this view or null if cache is disabled.
@@ -7383,6 +7437,10 @@
             mUnscaledDrawingCache.recycle();
             mUnscaledDrawingCache = null;
         }
+        if (mDisplayList != null) {
+            mDisplayList.destroy();
+            mDisplayList = null;
+        }
     }
 
     /**
@@ -10167,7 +10225,8 @@
         IBinder mPanelParentWindowToken;
         Surface mSurface;
 
-        boolean mHardwareAccelerated;        
+        boolean mHardwareAccelerated;
+        HardwareRenderer mHardwareRenderer;
         
         /**
          * Scale factor used by the compatibility mode
diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java
index 12c49c4..570e288 100644
--- a/core/java/android/view/ViewGroup.java
+++ b/core/java/android/view/ViewGroup.java
@@ -1830,8 +1830,7 @@
 
         boolean scalingRequired = false;
         boolean caching = false;
-        if (!canvas.isHardwareAccelerated() &&
-                (flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
+        if ((flags & FLAG_CHILDREN_DRAWN_WITH_CACHE) == FLAG_CHILDREN_DRAWN_WITH_CACHE ||
                 (flags & FLAG_ALWAYS_DRAWN_WITH_CACHE) == FLAG_ALWAYS_DRAWN_WITH_CACHE) {
             caching = true;
             if (mAttachInfo != null) scalingRequired = mAttachInfo.mScalingRequired;
@@ -1914,12 +1913,18 @@
         final int sx = child.mScrollX;
         final int sy = child.mScrollY;
 
+        DisplayList displayList = null;
         Bitmap cache = null;
         if (caching) {
-            cache = child.getDrawingCache(true);
+            if (!canvas.isHardwareAccelerated()) {
+                cache = child.getDrawingCache(true);
+            } else {
+                displayList = child.getDisplayList();
+            }
         }
 
-        final boolean hasNoCache = cache == null;
+        final boolean hasDisplayList = displayList != null && displayList.isReady();
+        final boolean hasNoCache = cache == null || hasDisplayList;
 
         final int restoreTo = canvas.save();
         if (hasNoCache) {
@@ -2002,17 +2007,21 @@
         }
 
         if (hasNoCache) {
-            // Fast path for layouts with no backgrounds
-            if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
-                if (ViewDebug.TRACE_HIERARCHY) {
-                    ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
+            if (!hasDisplayList) {
+                // Fast path for layouts with no backgrounds
+                if ((child.mPrivateFlags & SKIP_DRAW) == SKIP_DRAW) {
+                    if (ViewDebug.TRACE_HIERARCHY) {
+                        ViewDebug.trace(this, ViewDebug.HierarchyTraceType.DRAW);
+                    }
+                    child.mPrivateFlags &= ~DIRTY_MASK;
+                    child.dispatchDraw(canvas);
+                } else {
+                    child.draw(canvas);
                 }
-                child.mPrivateFlags &= ~DIRTY_MASK;
-                child.dispatchDraw(canvas);
             } else {
-                child.draw(canvas);
+                ((HardwareCanvas) canvas).drawDisplayList(displayList);
             }
-        } else {
+        } else if (cache != null) {
             final Paint cachePaint = mCachePaint;
             if (alpha < 1.0f) {
                 cachePaint.setAlpha((int) (alpha * 255));
diff --git a/core/java/android/view/ViewRoot.java b/core/java/android/view/ViewRoot.java
index f6a06ce..77ba6fe 100644
--- a/core/java/android/view/ViewRoot.java
+++ b/core/java/android/view/ViewRoot.java
@@ -196,8 +196,6 @@
     int mCurScrollY;
     Scroller mScroller;
 
-    HardwareRenderer mHwRenderer;
-
     final ViewConfiguration mViewConfiguration;
 
     /**
@@ -451,10 +449,10 @@
             if (attrs != null &&
                     (attrs.flags & WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0) {
                 final boolean translucent = attrs.format != PixelFormat.OPAQUE;
-                if (mHwRenderer != null) {
-                    mHwRenderer.destroy(true);
+                if (mAttachInfo.mHardwareRenderer != null) {
+                    mAttachInfo.mHardwareRenderer.destroy(true);
                 }                
-                mHwRenderer = HardwareRenderer.createGlRenderer(2, translucent);
+                mAttachInfo.mHardwareRenderer = HardwareRenderer.createGlRenderer(2, translucent);
                 mAttachInfo.mHardwareAccelerated = true;
             }
         }
@@ -663,8 +661,8 @@
             attachInfo.mWindowVisibility = viewVisibility;
             host.dispatchWindowVisibilityChanged(viewVisibility);
             if (viewVisibility != View.VISIBLE || mNewSurfaceNeeded) {
-                if (mHwRenderer != null) {
-                    mHwRenderer.destroy(false);
+                if (mAttachInfo.mHardwareRenderer != null) {
+                    mAttachInfo.mHardwareRenderer.destroy(false);
                 }                
             }
             if (viewVisibility == View.GONE) {
@@ -869,8 +867,8 @@
                         fullRedrawNeeded = true;
                         mPreviousTransparentRegion.setEmpty();
 
-                        if (mHwRenderer != null) {
-                            hwIntialized = mHwRenderer.initialize(mHolder);
+                        if (mAttachInfo.mHardwareRenderer != null) {
+                            hwIntialized = mAttachInfo.mHardwareRenderer.initialize(mHolder);
                         }
                     }
                 } else if (!mSurface.isValid()) {
@@ -948,8 +946,8 @@
                 }
             }
 
-            if (hwIntialized || (windowShouldResize && mHwRenderer != null)) {
-                mHwRenderer.setup(mWidth, mHeight);
+            if (hwIntialized || (windowShouldResize && mAttachInfo.mHardwareRenderer != null)) {
+                mAttachInfo.mHardwareRenderer.setup(mWidth, mHeight);
             }
 
             boolean focusChangedDueToTouchMode = ensureTouchModeLocally(
@@ -1262,9 +1260,9 @@
             dirty.union(0, 0, (int) (mWidth * appScale + 0.5f), (int) (mHeight * appScale + 0.5f));
         }
         
-        if (mHwRenderer != null && mHwRenderer.isEnabled()) {
+        if (mAttachInfo.mHardwareRenderer != null && mAttachInfo.mHardwareRenderer.isEnabled()) {
             if (!dirty.isEmpty()) {
-                mHwRenderer.draw(mView, mAttachInfo, yoff);
+                mAttachInfo.mHardwareRenderer.draw(mView, mAttachInfo, yoff);
             }
 
             if (scrolling) {
@@ -1774,8 +1772,9 @@
                     boolean inTouchMode = msg.arg2 != 0;
                     ensureTouchModeLocally(inTouchMode);
 
-                    if (mHwRenderer != null) {
-                        mHwRenderer.initializeIfNeeded(mWidth, mHeight, mAttachInfo, mHolder);
+                    if (mAttachInfo.mHardwareRenderer != null) {
+                        mAttachInfo.mHardwareRenderer.initializeIfNeeded(mWidth, mHeight,
+                                mAttachInfo, mHolder);
                     }
                 }
 
@@ -2582,9 +2581,9 @@
     }
 
     private void destroyHardwareRenderer() {
-        if (mHwRenderer != null) {
-            mHwRenderer.destroy(true);
-            mHwRenderer = null;
+        if (mAttachInfo.mHardwareRenderer != null) {
+            mAttachInfo.mHardwareRenderer.destroy(true);
+            mAttachInfo.mHardwareRenderer = null;
             mAttachInfo.mHardwareAccelerated = false;
         }
     }
diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl
new file mode 100644
index 0000000..35746ad
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/ILlcpConnectionlessSocket.aidl
@@ -0,0 +1,34 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+import com.trustedlogic.trustednfc.android.LlcpPacket;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface ILlcpConnectionlessSocket
+{
+
+    void        close(int nativeHandle);
+    int         getSap(int nativeHandle);
+    LlcpPacket  receiveFrom(int nativeHandle);
+    int        sendTo(int nativeHandle, in LlcpPacket packet);
+    
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl
new file mode 100644
index 0000000..5eb1f3c
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/ILlcpServiceSocket.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface ILlcpServiceSocket
+{
+
+    int     accept(int nativeHandle);
+    void    close(int nativeHandle);
+    int     getAcceptTimeout(int nativeHandle);
+    void    setAcceptTimeout(int nativeHandle, int timeout);
+    
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl b/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl
new file mode 100644
index 0000000..e9169d8
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/ILlcpSocket.aidl
@@ -0,0 +1,41 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface ILlcpSocket
+{
+ 
+    int     close(int nativeHandle);
+    int     connect(int nativeHandle, int sap);
+    int     connectByName(int nativeHandle, String sn);
+    int     getConnectTimeout(int nativeHandle);
+    int     getLocalSap(int nativeHandle);
+    int     getLocalSocketMiu(int nativeHandle);
+    int     getLocalSocketRw(int nativeHandle);
+    int     getRemoteSocketMiu(int nativeHandle);
+    int     getRemoteSocketRw(int nativeHandle);
+    int     receive(int nativeHandle, out byte[] receiveBuffer);
+    int     send(int nativeHandle, in byte[] data);
+    void    setConnectTimeout(int nativeHandle, int timeout);
+    
+}
+
diff --git a/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl b/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl
new file mode 100644
index 0000000..1f8d1a4
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/INdefTag.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+import com.trustedlogic.trustednfc.android.NdefMessage;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface INdefTag
+{
+
+    NdefMessage read(int nativeHandle);
+    boolean     write(int nativeHandle, in NdefMessage msg);
+
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl b/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl
new file mode 100644
index 0000000..ce36ab2
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/INfcManager.aidl
@@ -0,0 +1,61 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+import com.trustedlogic.trustednfc.android.ILlcpSocket;
+import com.trustedlogic.trustednfc.android.ILlcpServiceSocket;
+import com.trustedlogic.trustednfc.android.ILlcpConnectionlessSocket;
+import com.trustedlogic.trustednfc.android.INfcTag;
+import com.trustedlogic.trustednfc.android.IP2pTarget;
+import com.trustedlogic.trustednfc.android.IP2pInitiator;
+
+
+/**
+ * Interface that allows controlling NFC activity.
+ *
+ * {@hide}
+ */
+interface INfcManager
+{
+
+    ILlcpSocket                 getLlcpInterface();
+    ILlcpConnectionlessSocket   getLlcpConnectionlessInterface();
+    ILlcpServiceSocket          getLlcpServiceInterface();
+    INfcTag                     getNfcTagInterface();
+    IP2pTarget                  getP2pTargetInterface();
+    IP2pInitiator               getP2pInitiatorInterface();
+    
+    void    cancel();
+    int     createLlcpConnectionlessSocket(int sap);
+    int     createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength);
+    int     createLlcpSocket(int sap, int miu, int rw, int linearBufferLength);
+    int     deselectSecureElement();
+    boolean disable();
+    boolean enable();
+    int     getOpenTimeout();
+    String  getProperties(String param);
+    int[]   getSecureElementList();
+    int     getSelectedSecureElement();
+    boolean isEnabled();
+    int     openP2pConnection();
+    int     openTagConnection();
+    int     selectSecureElement(int seId);
+    void    setOpenTimeout(int timeout);
+    int     setProperties(String param, String value);
+
+}
+
diff --git a/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl b/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl
new file mode 100644
index 0000000..79543c4
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/INfcTag.aidl
@@ -0,0 +1,38 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+import com.trustedlogic.trustednfc.android.NdefMessage;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface INfcTag
+{
+
+    int     close(int nativeHandle);
+    int     connect(int nativeHandle);
+    String  getType(int nativeHandle);
+    byte[]  getUid(int nativeHandle);
+    boolean isNdef(int nativeHandle);
+    byte[]  transceive(int nativeHandle, in byte[] data);
+    
+    NdefMessage read(int nativeHandle);
+    boolean     write(int nativeHandle, in NdefMessage msg);
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl b/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
new file mode 100644
index 0000000..96819ae
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/IP2pInitiator.aidl
@@ -0,0 +1,32 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface IP2pInitiator
+{
+
+    byte[]   getGeneralBytes(int nativeHandle);
+    int      getMode(int nativeHandle);
+    byte[]   receive(int nativeHandle);
+    boolean  send(int nativeHandle, in byte[] data);
+
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl b/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl
new file mode 100644
index 0000000..8dcdf18
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/IP2pTarget.aidl
@@ -0,0 +1,33 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+/**
+ * TODO
+ *
+ * {@hide}
+ */
+interface IP2pTarget
+{
+
+    byte[]     getGeneralBytes(int nativeHandle);
+    int        getMode(int nativeHandle);
+    int    	   connect(int nativeHandle);
+    boolean    disconnect(int nativeHandle);
+    byte[]     transceive(int nativeHandle, in byte[] data);
+ 
+}
\ No newline at end of file
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java
new file mode 100644
index 0000000..0270626
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpConnectionlessSocket.java
@@ -0,0 +1,148 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : LlcpConnectionLessSocket.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used
+ * in a connectionless communication
+ * 
+ * @since AA02.01
+ * @hide
+ */
+public class LlcpConnectionlessSocket {
+	
+	
+    private static final String TAG = "LlcpConnectionlessSocket";
+
+    /**
+     * The handle returned by the NFC service and used to identify the LLCP connectionless socket in
+     * every call of this class.
+     * 
+     * @hide
+     */
+    protected int mHandle;
+
+
+    /**
+     * The entry point for LLCP Connectionless socket operations.
+     * 
+     * @hide
+     */
+    protected ILlcpConnectionlessSocket mService;
+	
+	
+    /**
+     * Internal constructor for the LlcpConnectionlessSocket class.
+     * 
+     * @param service The entry point to the Nfc Service for  LLCP Connectionless socket  class.
+     * @param handle The handle returned by the NFC service and used to identify
+     *            the socket in subsequent calls.
+     * @hide
+     */
+	LlcpConnectionlessSocket(ILlcpConnectionlessSocket service, int handle) {
+        this.mService = service;
+        this.mHandle = handle;
+    }
+
+    /**
+     * Send data to a specific LLCP Connectionless client
+     * 
+     * @param packet Service Access Point number related to a LLCP
+     *            Connectionless client and a data buffer to send
+     * @throws IOException if the LLCP link has been lost or deactivated.
+     * @since AA02.01
+     */
+    public void sendTo(LlcpPacket packet) throws IOException {
+		try {
+			int result = mService.sendTo(mHandle, packet);
+			// Handle potential errors
+			if (ErrorCodes.isError(result)) {
+				throw new IOException();
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in sendTo(): ", e);
+		}
+    }
+
+    /**
+     * Receive data from a LLCP Connectionless client
+     * 
+     * @return data data received from a specific LLCP Connectionless client
+     * @throws IOException if the LLCP link has been lost or deactivated.
+     * @see LlcpPacket
+     * @since AA02.01
+     */
+    public LlcpPacket receiveFrom() throws IOException {
+		try {
+			LlcpPacket packet = mService.receiveFrom(mHandle);
+			if (packet != null) {
+				return packet;
+			}else{
+				// Handle potential errors
+				throw new IOException();			
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in receiveFrom(): ", e);
+		}
+        return null;
+    }
+
+    /**
+     * Close the created Connectionless socket.
+     * 
+     * @since AA02.01
+     */
+    public void close() {
+		try {
+			mService.close(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in close(): ", e);
+		}
+    }
+
+    /**
+     * Returns the local Service Access Point number of the socket
+     * 
+     * @return sap
+     * @since AA02.01
+     */
+    public int getSap() {
+    	int sap = 0;
+    	
+    	try {
+			sap = mService.getSap(mHandle);
+
+		} catch (RemoteException e) {
+
+			e.printStackTrace();
+		}
+    	return sap;
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpException.java b/core/java/com/trustedlogic/trustednfc/android/LlcpException.java
new file mode 100644
index 0000000..1e2e2da
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : LLCPException.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 24-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+/**
+ * Generic exception thrown in case something unexpected happened during a 
+ * LLCP communication.
+ *
+ * @since AA02.01
+ * @hide
+ */
+public class LlcpException extends Exception {
+   /**
+    * Constructs a new LlcpException with the current stack trace and the
+    * specified detail message.
+    *
+    * @param s the detail message for this exception.
+    */
+   public LlcpException(String s) {
+      super(s);
+   }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl
new file mode 100644
index 0000000..297a1fe
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+parcelable LlcpPacket;
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java
new file mode 100644
index 0000000..af79023
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpPacket.java
@@ -0,0 +1,119 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : LLCPPacket.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 25-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents a LLCP packet received in a LLCP Connectionless communication;
+ * 
+ * @since AA02.01
+ * @hide
+ */
+public class LlcpPacket implements Parcelable {
+
+    private int mRemoteSap;
+
+    private byte[] mDataBuffer;
+
+    /**
+     * Creator class, needed when implementing from Parcelable
+     * {@hide}
+     */
+    public static final Parcelable.Creator<LlcpPacket> CREATOR = new Parcelable.Creator<LlcpPacket>() {
+        public LlcpPacket createFromParcel(Parcel in) {
+            // Remote SAP
+            short sap = (short)in.readInt();
+            
+            // Data Buffer
+            int dataLength = in.readInt();
+            byte[] data = new byte[dataLength];
+            in.readByteArray(data);
+            
+            return new LlcpPacket(sap, data);
+        }
+
+        public LlcpPacket[] newArray(int size) {
+            return new LlcpPacket[size];
+        }
+    };
+    
+
+    /**
+     * Creates a LlcpPacket to be sent to a remote Service Access Point number
+     * (SAP)
+     * 
+     * @param sap Remote Service Access Point number
+     * @param data Data buffer
+     * @since AA02.01
+     */
+    public LlcpPacket(int sap, byte[] data) {
+    	mRemoteSap = sap;
+        mDataBuffer = data;
+    }
+    
+    /**
+     * @hide
+     */
+    public LlcpPacket() {
+    }
+
+    /**
+     * Returns the remote Service Access Point number
+     * 
+     * @return remoteSap
+     * @since AA02.01
+     */
+    public int getRemoteSap() {
+        return mRemoteSap;
+    }
+
+    /**
+     * Returns the data buffer
+     * 
+     * @return data
+     * @since AA02.01
+     */
+    public byte[] getDataBuffer() {
+        return mDataBuffer;
+    }
+
+    /**
+     * (Parcelable) Describe the parcel
+     * {@hide}
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * (Parcelable) Convert current object to a Parcel
+     * {@hide}
+     */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mRemoteSap);
+        dest.writeInt(mDataBuffer.length);
+        dest.writeByteArray(mDataBuffer);      
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java
new file mode 100644
index 0000000..a152ecb1
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpServiceSocket.java
@@ -0,0 +1,180 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : LLCPServerSocket.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * LlcpServiceSocket represents a LLCP Service to be used in a
+ * Connection-oriented communication
+ * 
+ * @since AA02.01
+ * @hide
+ */
+public class LlcpServiceSocket {
+
+	private static final String TAG = "LlcpServiceSocket";
+
+	/**
+	 * The handle returned by the NFC service and used to identify the LLCP
+	 * Service socket in every call of this class.
+	 * 
+	 * @hide
+	 */
+	protected int mHandle;
+
+	/**
+	 * The entry point for LLCP Service socket operations.
+	 * 
+	 * @hide
+	 */
+	protected ILlcpServiceSocket mService;
+	
+    private ILlcpSocket mLlcpSocketService;
+
+	static LlcpException convertErrorToLlcpException(int errorCode) {
+		return convertErrorToLlcpException(errorCode, null);
+	}
+
+	static LlcpException convertErrorToLlcpException(int errorCode,
+			String message) {
+		if (message == null) {
+			message = "";
+		} else {
+			message = " (" + message + ")";
+		}
+
+		switch (errorCode) {
+		case ErrorCodes.ERROR_SOCKET_CREATION:
+			return new LlcpException(
+					"Error during the creation of an Llcp socket" + message);
+		case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
+			return new LlcpException("Not enough ressources are available"
+					+ message);
+		default:
+			return new LlcpException("Unkown error code " + errorCode + message);
+		}
+	}
+
+	/**
+	 * Internal constructor for the LlcpServiceSocket class.
+	 * 
+	 * @param service
+	 *            The entry point to the Nfc Service for LlcpServiceSocket
+	 *            class.
+	 * @param handle
+	 *            The handle returned by the NFC service and used to identify
+	 *            the socket in subsequent calls.
+	 * @hide
+	 */
+	LlcpServiceSocket(ILlcpServiceSocket service, ILlcpSocket socketService, int handle) {
+		this.mService = service;
+		this.mHandle = handle;
+		this.mLlcpSocketService = socketService;
+	}
+
+	/**
+	 * Wait for incomming connection request from a LLCP client and accept this
+	 * request
+	 * 
+	 * @return socket object to be used to communicate with a LLCP client
+	 * 
+	 * @throws IOException
+	 *             if the llcp link is lost or deactivated
+	 * @throws LlcpException
+	 *             if not enough ressources are available
+	 * 
+	 * @see LlcpSocket
+	 * @since AA02.01
+	 */
+	public LlcpSocket accept() throws IOException, LlcpException {
+
+		try {
+			int handle = mService.accept(mHandle);
+			// Handle potential errors
+			if (ErrorCodes.isError(handle)) {
+				if (handle == ErrorCodes.ERROR_IO) {
+					throw new IOException();
+				} else {
+					throw convertErrorToLlcpException(handle);
+				}
+			}
+	        
+			// Build the public LlcpSocket object
+			return new LlcpSocket(mLlcpSocketService, handle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in accept(): ", e);
+			return null;
+		}
+
+	}
+
+	/**
+	 * Set the timeout for the accept request
+	 * 
+	 * @param timeout
+	 *            value of the timeout for the accept request
+	 * @since AA02.01
+	 */
+	public void setAcceptTimeout(int timeout) {
+		try {
+			mService.setAcceptTimeout(mHandle, timeout);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in setAcceptTimeout(): ", e);
+		}
+	}
+
+	/**
+	 * Get the timeout value of the accept request
+	 * 
+	 * @return mTimeout
+	 * @since AA02.01
+	 */
+	public int getAcceptTimeout() {
+		try {
+			return mService.getAcceptTimeout(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getAcceptTimeout(): ", e);
+			return 0;
+		}
+	}
+
+	/**
+	 * Close the created Llcp Service socket
+	 * 
+	 * @since AA02.01
+	 */
+	public void close() {
+		try {
+			mService.close(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in close(): ", e);
+		}
+	}
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java b/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java
new file mode 100644
index 0000000..e47160c
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/LlcpSocket.java
@@ -0,0 +1,344 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : LlcpClientSocket.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a
+ * connection-oriented communication
+ * 
+ * @since AA02.01
+ * @hide
+ */
+public class LlcpSocket {
+
+	private static final String TAG = "LlcpSocket";
+
+	/**
+	 * The handle returned by the NFC service and used to identify the LLCP
+	 * socket in every call of this class.
+	 * 
+	 * @hide
+	 */
+	protected int mHandle;
+
+	/**
+	 * The entry point for LLCP socket operations.
+	 * 
+	 * @hide
+	 */
+	protected ILlcpSocket mService;
+
+	static LlcpException convertErrorToLlcpException(int errorCode) {
+		return convertErrorToLlcpException(errorCode, null);
+	}
+
+	static LlcpException convertErrorToLlcpException(int errorCode,
+			String message) {
+		if (message == null) {
+			message = "";
+		} else {
+			message = " (" + message + ")";
+		}
+
+		switch (errorCode) {
+		case ErrorCodes.ERROR_SOCKET_CREATION:
+			return new LlcpException(
+					"Error during the creation of an Llcp socket" + message);
+		case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
+			return new LlcpException("Not enough ressources are available"
+					+ message);
+		case ErrorCodes.ERROR_SOCKET_NOT_CONNECTED:
+			return new LlcpException("Socket not connected to an Llcp Service"
+					+ message);
+		default:
+			return new LlcpException("Unkown error code " + errorCode + message);
+		}
+	}
+
+	/**
+	 * Internal constructor for the LlcpSocket class.
+	 * 
+	 * @param service
+	 *            The entry point to the Nfc Service for LlcpServiceSocket
+	 *            class.
+	 * @param handle
+	 *            The handle returned by the NFC service and used to identify
+	 *            the socket in subsequent calls.
+	 * @hide
+	 */
+	LlcpSocket(ILlcpSocket service, int handle) {
+		this.mService = service;
+		this.mHandle = handle;
+	}
+
+	/**
+	 * Connect request to a specific LLCP Service by its SAP.
+	 * 
+	 * @param sap
+	 *            Service Access Point number of the LLCP Service
+	 * @throws IOException
+	 *             if the LLCP has been lost or deactivated.
+	 * @throws LlcpException
+	 *             if the connection request is rejected by the remote LLCP
+	 *             Service
+	 * @since AA02.01
+	 */
+	public void connect(int sap) throws IOException, LlcpException {
+		try {
+			int result = mService.connect(mHandle, sap);
+			// Handle potential errors
+			if (ErrorCodes.isError(result)) {
+				if (result == ErrorCodes.ERROR_IO) {
+					throw new IOException();
+				} else {
+					throw convertErrorToLlcpException(result);
+				}
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in accept(): ", e);
+		}
+	}
+
+	/**
+	 * Connect request to a specific LLCP Service by its Service Name.
+	 * 
+	 * @param sn
+	 *            Service Name of the LLCP Service
+	 * @throws IOException
+	 *             if the LLCP has been lost or deactivated.
+	 * @throws LlcpException
+	 *             if the connection request is rejected by the remote LLCP
+	 *             Service
+	 * @since AA02.01
+	 */
+	public void connect(String sn) throws IOException, LlcpException {
+		try {
+			int result = mService.connectByName(mHandle, sn);
+			// Handle potential errors
+			if (ErrorCodes.isError(result)) {
+				if (result == ErrorCodes.ERROR_IO) {
+					throw new IOException();
+				} else {
+					throw convertErrorToLlcpException(result);
+				}
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in accept(): ", e);
+		}
+	}
+
+	/**
+	 * Set the timeout for the connect request
+	 * 
+	 * @param timeout
+	 *            timeout value for the connect request
+	 * @since AA02.01
+	 */
+	public void setConnectTimeout(int timeout) {
+		try {
+			mService.setConnectTimeout(mHandle, timeout);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in setConnectTimeout(): ", e);
+		}
+	}
+
+	/**
+	 * Get the timeout value of the connect request
+	 * 
+	 * @return mTimeout
+	 * @since AA02.01
+	 */
+	public int getConnectTimeout() {
+		try {
+			return mService.getConnectTimeout(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getConnectTimeout(): ", e);
+			return 0;
+		}
+	}
+
+	/**
+	 * Disconnect request to the connected LLCP socket and close the created
+	 * socket.
+	 * 
+	 * @throws IOException
+	 *             if the LLCP has been lost or deactivated.
+	 * @since AA02.01
+	 */
+	public void close() throws IOException {
+		try {
+			int result = mService.close(mHandle);
+			// Handle potential errors
+			if (ErrorCodes.isError(result)) {
+				throw new IOException();
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in close(): ", e);
+		}
+	}
+
+	/**
+	 * Send data to the connected LLCP Socket.
+	 * 
+	 * @throws IOException
+	 *             if the LLCP has been lost or deactivated.
+	 * @since AA02.01
+	 */
+	public void send(byte[] data) throws IOException {
+		try {
+			int result = mService.send(mHandle, data);
+			// Handle potential errors
+			if (ErrorCodes.isError(result)) {
+				throw new IOException();
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in send(): ", e);
+		}		
+	}
+
+	/**
+	 * Receive data from the connected LLCP socket
+	 * 
+	 * @param receiveBuffer
+	 *            a buffer for the received data
+	 * @return length length of the data received
+	 * @throws IOException
+	 *             if the LLCP has been lost or deactivated.
+	 * @since AA02.01
+	 */
+	public int receive(byte[] receiveBuffer) throws IOException {
+		int receivedLength = 0;
+		try {
+			receivedLength = mService.receive(mHandle, receiveBuffer);
+			if(receivedLength == 0){
+				throw new IOException();
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in send(): ", e);
+		}	
+		
+		return receivedLength;
+	}
+	
+	/**
+	 * Returns the local Service Access Point number of the socket
+	 * 
+	 * @return localSap
+	 * @since AA02.01
+	 */
+	public int getLocalSap() {
+		try {
+			return  mService.getLocalSap(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getLocalSap(): ", e);
+			return 0;
+		}
+	}
+
+	/**
+	 * Returns the local Maximum Information Unit(MIU) of the socket
+	 * 
+	 * @return miu
+	 * @since AA02.01
+	 */
+	public int getLocalSocketMiu() {
+		try {
+			return  mService.getLocalSocketMiu(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getLocalSocketMiu(): ", e);
+			return 0;
+		}
+	}
+
+	/**
+	 * Returns the local Receive Window(RW) of the socket
+	 * 
+	 * @return rw
+	 * @since AA02.01
+	 */
+	public int getLocalSocketRw() {
+		try {
+			return  mService.getLocalSocketRw(mHandle);
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getLocalSocketRw(): ", e);
+			return 0;
+		}
+	}
+
+	/**
+	 * Returns the remote Maximum Information Unit(MIU) of the socket.
+	 * <p>
+	 * This method must be called when the socket is in CONNECTED_STATE
+	 * 
+	 * @return remoteMiu
+	 * @throws LlcpException
+	 *             if the LlcpClientSocket is not in a CONNECTED_STATE
+	 * @since AA02.01
+	 */
+	public int getRemoteSocketMiu() throws LlcpException {
+		try {
+			int result = mService.getRemoteSocketMiu(mHandle);
+			if(result != ErrorCodes.ERROR_SOCKET_NOT_CONNECTED){
+				return result;
+			}else{
+				throw convertErrorToLlcpException(result);
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getRemoteSocketMiu(): ", e);
+			return 0;
+		}
+	}
+
+	/**
+	 * Returns the remote Receive Window(RW) of the connected remote socket.
+	 * <p>
+	 * This method must be called when the socket is in CONNECTED_STATE
+	 * 
+	 * @return rw
+	 * @throws LlcpException
+	 *             if the LlcpClientSocket is not in a CONNECTED_STATE
+	 * @since AA02.01
+	 */
+	public int getRemoteSocketRw() throws LlcpException {
+		try {
+			int result = mService.getRemoteSocketRw(mHandle);
+			if( result != ErrorCodes.ERROR_SOCKET_NOT_CONNECTED){
+				return result;
+			}else{
+				throw convertErrorToLlcpException(result);
+			}
+		} catch (RemoteException e) {
+			Log.e(TAG, "RemoteException in getRemoteSocketRw(): ", e);
+			return 0;
+		}
+	}
+
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
new file mode 100644
index 0000000..e60f4e8
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+parcelable NdefMessage;
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java
new file mode 100644
index 0000000..f03b604
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NdefMessage.java
@@ -0,0 +1,160 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NDEFMessage.java
+ * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
+ * Created         : 05-10-2009
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.util.LinkedList;
+import java.util.ListIterator;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * Represents an NDEF message as specified by the <a
+ * href="http://www.nfc-forum.org/">NFC Forum</a>.
+ * 
+ * @see NdefRecord
+ * 
+ * @since AA01.04
+ * @hide
+ */
+public class NdefMessage implements Parcelable {
+	/* Flag values */
+	private static final int FLAG_MB = 0x80;
+	private static final int FLAG_ME = 0x40;
+	private static final int FLAG_CF = 0x20;
+	private static final int FLAG_SR = 0x10;
+	private static final int FLAG_IL = 0x08;
+
+	/**
+	 * Array of {@link NdefRecord} composing this message.
+	 */
+	private NdefRecord[] mRecords;
+
+	/**
+	 * Builds an NDEF message.
+	 * 
+	 * @param data raw NDEF message data
+	 * 
+	 * @throws NFCException
+	 */
+	public NdefMessage(byte[] data) throws NfcException {
+		if (parseNdefMessage(data) == -1)
+			throw new NfcException("Error while parsing NDEF message");
+	}
+
+	/**
+	 * Builds an NDEF message.
+	 * 
+	 * @param records
+	 *            an array of already created NDEF records
+	 */
+	public NdefMessage(NdefRecord[] records) {
+		mRecords = new NdefRecord[records.length];
+
+		System.arraycopy(records, 0, mRecords, 0, records.length);
+	}
+
+	/**
+	 * Returns the NDEF message as a byte array.
+	 * 
+	 * @return the message as a byte array
+	 */
+	public byte[] toByteArray() {
+		if ((mRecords == null) || (mRecords.length == 0))
+			return null;
+
+		byte[] msg = {};
+
+		for (int i = 0; i < mRecords.length; i++) {
+			byte[] record = mRecords[i].toByteArray();
+			byte[] tmp = new byte[msg.length + record.length];
+
+			/* Make sure the Message Begin flag is set only for the first record */
+			if (i == 0)
+				record[0] |= FLAG_MB;
+			else
+				record[0] &= ~FLAG_MB;
+
+			/* Make sure the Message End flag is set only for the last record */
+			if (i == (mRecords.length - 1))
+				record[0] |= FLAG_ME;
+			else
+				record[0] &= ~FLAG_ME;
+
+			System.arraycopy(msg, 0, tmp, 0, msg.length);
+			System.arraycopy(record, 0, tmp, msg.length, record.length);
+
+			msg = tmp;
+		}
+
+		return msg;
+	}
+	
+	/**
+	* Returns an array of {@link NdefRecord} composing this message.
+	*
+	* @return mRecords
+	* 
+	* @since AA02.01
+	*/
+	public NdefRecord[] getRecords(){
+		return mRecords;
+	}
+	
+	private native int parseNdefMessage(byte[] data);
+
+    /**
+     * (Parcelable) Describe the parcel
+     * {@hide}
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * (Parcelable) Convert current object to a Parcel
+     * {@hide}
+     */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mRecords.length);
+        dest.writeTypedArray(mRecords, 0);
+    }
+
+    /**
+     * Creator class, needed when implementing from Parcelable
+     * {@hide}
+     */
+    public static final Parcelable.Creator<NdefMessage> CREATOR = new Parcelable.Creator<NdefMessage>() {
+        public NdefMessage createFromParcel(Parcel in) {
+            int recordsLength = in.readInt();
+            NdefRecord[] records = new NdefRecord[recordsLength];
+            in.readTypedArray(records, NdefRecord.CREATOR);
+            return new NdefMessage(records);
+        }
+
+        public NdefMessage[] newArray(int size) {
+            return new NdefMessage[size];
+        }
+    };
+    
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl
new file mode 100644
index 0000000..9d95174
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.aidl
@@ -0,0 +1,19 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android;
+
+parcelable NdefRecord;
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java
new file mode 100644
index 0000000..a0257fe
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NdefRecord.java
@@ -0,0 +1,293 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NdefRecord.java
+ * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
+ * Created         : 05-10-2009
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import android.location.Location;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+/**
+ * An NDEF record as specified by the <a href="http://www.nfc-forum.org/">NFC
+ * Forum</a>.
+ * 
+ * @see NdefMessage
+ * 
+ * @since AA01.04
+ * @hide
+ */
+public class NdefRecord implements Parcelable {
+
+	/**
+	 * Type Name Format - Empty record
+	 */
+	public static final short TNF_EMPTY = 0x0;
+
+	/**
+	 * Type Name Format - NFC Forum-defined type
+	 */
+	public static final short TNF_WELL_KNOWN_TYPE = 0x1;
+
+	/**
+	 * Type Name Format - RFC2045 MIME type
+	 */
+	public static final short TNF_MIME_MEDIA_TYPE = 0x2;
+
+	/**
+	 * Type Name Format - Absolute URI
+	 */
+	public static final short TNF_ABSOLUTE_URI = 0x3;
+
+	/**
+	 * Type Name Format - User-defined type
+	 */
+	public static final short TNF_EXTERNAL_TYPE = 0x4;
+
+	/**
+	 * Type Name Format - Unknown type
+	 */
+	public static final short TNF_UNKNOWN = 0x5;
+
+	/**
+	 * Type Name Format - Unchanged. This TNF is used for chunked records, so
+	 * that middle records inherits from the first record's type.
+	 */
+	public static final short TNF_UNCHANGED = 0x6;
+
+	/**
+	 * NFC Forum-defined Type - Smart Poster
+	 */
+	public static final byte[] TYPE_SMART_POSTER = { 0x53, 0x70 };
+
+	/**
+	 * NFC Forum-defined Type - Text
+	 */
+	public static final byte[] TYPE_TEXT = { 0x54 };
+
+	/**
+	 * NFC Forum-defined Type - URI
+	 */
+	public static final byte[] TYPE_URI = { 0x55 };
+
+	/**
+	 * NFC Forum-defined Global Type - Connection Handover Request
+	 */
+	public static final byte[] TYPE_HANDOVER_REQUEST = { 0x48, 0x72 };
+
+	/**
+	 * NFC Forum-defined Global Type - Connection Handover Select
+	 */
+	public static final byte[] TYPE_HANDOVER_SELECT = { 0x48, 0x73 };
+
+	/**
+	 * NFC Forum-defined Global Type - Connection Handover Carrier
+	 */
+	public static final byte[] TYPE_HANDOVER_CARRIER = { 0x48, 0x63 };
+
+	/**
+	 * NFC Forum-defined Local Type - Alternative Carrier
+	 */
+	public static final byte[] TYPE_ALTERNATIVE_CARRIER = { 0x61, 0x63 };
+
+	/* Flag values */
+	private static final int FLAG_MB = 0x80;
+	private static final int FLAG_ME = 0x40;
+	private static final int FLAG_CF = 0x20;
+	private static final int FLAG_SR = 0x10;
+	private static final int FLAG_IL = 0x08;
+
+	/**
+	 * Record Flags
+	 */
+	private short mFlags = 0;
+
+	/**
+	 * Record Type Name Format
+	 */
+	private short mTnf = 0;
+
+	/**
+	 * Record Type
+	 */
+	private byte[] mType = null;
+
+	/**
+	 * Record Identifier
+	 */
+	private byte[] mId = null;
+
+	/**
+	 * Record Payload
+	 */
+	private byte[] mPayload = null;
+
+	/**
+	 * Creates an NdefRecord given its Type Name Format, its type, its id and
+	 * its.
+	 * 
+	 * @param tnf
+	 *            Type Name Format
+	 * @param type
+	 *            record type
+	 * @param id
+	 *            record id (optional, can be null)
+	 * @param data
+	 *            record payload
+	 */
+	public NdefRecord(short tnf, byte[] type, byte[] id, byte[] data) {
+		
+		/* generate flag */
+		mFlags = FLAG_MB | FLAG_ME;
+		
+		/* Determine if it is a short record */
+		if(data.length < 0xFF)
+		{
+			mFlags |= FLAG_SR;
+		}
+		
+		/* Determine if an id is present */
+		if(id.length != 0)
+		{
+			mFlags |= FLAG_IL;
+		}
+		
+		mTnf = tnf;
+		mType = (byte[]) type.clone();
+		mId = (byte[]) id.clone();
+		mPayload = (byte[]) data.clone();
+	}
+
+	/**
+	 * Appends data to the record's payload.
+	 * 
+	 * @param data
+	 *            Data to be added to the record.
+	 */
+	public void appendPayload(byte[] data) {
+		byte[] newPayload = new byte[mPayload.length + data.length];
+
+		System.arraycopy(mPayload, 0, newPayload, 0, mPayload.length);
+		System.arraycopy(data, 0, newPayload, mPayload.length, data.length);
+
+		mPayload = newPayload;
+	}
+
+	/**
+	 * Returns record as a byte array.
+	 * 
+	 * @return record as a byte array.
+	 */
+	public byte[] toByteArray() {
+		return generate(mFlags, mTnf, mType, mId, mPayload);
+	}
+
+	private native byte[] generate(short flags, short tnf, byte[] type,
+			byte[] id, byte[] data);
+
+    /**
+     * (Parcelable) Describe the parcel
+     * {@hide}
+     */
+    public int describeContents() {
+        return 0;
+    }
+
+    /**
+     * (Parcelable) Convert current object to a Parcel
+     * {@hide}
+     */
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeInt(mTnf);
+        dest.writeInt(mType.length);
+        dest.writeByteArray(mType);
+        dest.writeInt(mId.length);
+        dest.writeByteArray(mId);
+        dest.writeInt(mPayload.length);
+        dest.writeByteArray(mPayload);
+    }
+
+    /**
+     * Creator class, needed when implementing from Parcelable
+     * {@hide}
+     */
+    public static final Parcelable.Creator<NdefRecord> CREATOR = new Parcelable.Creator<NdefRecord>() {
+        public NdefRecord createFromParcel(Parcel in) {
+            // TNF
+            short tnf = (short)in.readInt();
+            // Type
+            int typeLength = in.readInt();
+            byte[] type = new byte[typeLength];
+            in.readByteArray(type);
+            // ID
+            int idLength = in.readInt();
+            byte[] id = new byte[idLength];
+            in.readByteArray(id);
+            // Payload
+            int payloadLength = in.readInt();
+            byte[] payload = new byte[payloadLength];
+            in.readByteArray(payload);
+            
+            return new NdefRecord(tnf, type, id, payload);
+        }
+
+        public NdefRecord[] newArray(int size) {
+            return new NdefRecord[size];
+        }
+    };
+    
+    /**
+     * Returns record TNF
+     * 
+     * @return mTnf
+     */
+    public int getTnf(){
+    	return mTnf;
+    }
+    
+    /**
+     * Returns record TYPE
+     * 
+     * @return mType
+     */
+    public byte[] getType(){
+    	return mType;
+    }
+   
+    /**
+     * Returns record ID
+     * 
+     * @return mId
+     */
+    public byte[] getId(){
+    	return mId;
+    }
+    
+    /**
+     * Returns record Payload
+     * 
+     * @return mPayload
+     */
+    public byte[] getPayload(){
+    	return mPayload;
+    }
+    
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NdefTag.java b/core/java/com/trustedlogic/trustednfc/android/NdefTag.java
new file mode 100644
index 0000000..1d99241
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NdefTag.java
@@ -0,0 +1,126 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NDEFTag.java
+ * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
+ * Created         : 04-12-2009
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * NdefTag represents tags complying with the NFC Forum's NFC Data Exchange
+ * Format.
+ * 
+ * @since AA01.04
+ * @hide
+ */
+public class NdefTag extends NfcTag {
+
+    private static final String TAG = "NdefTag";
+
+
+    public NdefTag(NfcTag tag){
+		super(tag.mService,tag.mHandle);
+		this.isConnected = tag.isConnected; 
+		this.isClosed = tag.isClosed;
+		tag.isClosed = false;
+    }
+    
+    /**
+     * Internal constructor for the NfcNdefTag class.
+     * 
+     * @param service The entry point to the Nfc Service for NfcNdefTag class.
+     * @param handle The handle returned by the NFC service and used to identify
+     *            the tag in subsequent calls.
+     * @hide
+     */
+    NdefTag(INfcTag service, int handle) {
+        super(service, handle);
+    }
+
+    /**
+     * Read NDEF data from an NDEF tag.
+     * 
+     * @return the NDEF message read from the tag.
+     * @throws NfcException if the tag is not NDEF-formatted.
+     * @throws IOException if the target has been lost or the connection has
+     *             been closed.
+     * @see NdefMessage
+     */
+    public NdefMessage read() throws NfcException, IOException {
+        // Check state
+        checkState();
+        
+        //Check if the tag is Ndef compliant
+        if(isNdef != true){
+            isNdef = isNdef();
+            if(isNdef != true) {
+                throw new NfcException("Tag is not NDEF compliant");
+            }
+        }
+
+        // Perform transceive
+        try {
+            NdefMessage msg = mService.read(mHandle);
+            if (msg == null) {
+                throw new IOException("NDEF read failed");
+            }
+            return msg;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in read(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Write NDEF data to an NDEF-compliant tag.
+     * 
+     * @param msg NDEF message to be written to the tag.
+     * @throws NfcException if the tag is not NDEF formatted.
+     * @throws IOException if the target has been lost or the connection has
+     *             been closed.
+     * @see NdefMessage
+     */
+    public void write(NdefMessage msg) throws NfcException, IOException {
+        // Check state
+        checkState();
+        
+        //Check if the tag is Ndef compliant
+        if(isNdef != true){
+            isNdef = isNdef();
+            if(isNdef != true) {
+                throw new NfcException("Tag is not NDEF compliant");
+            }
+        }
+
+        // Perform transceive
+        try {
+            boolean isSuccess = mService.write(mHandle, msg);
+            if (!isSuccess) {
+                throw new IOException("NDEF write failed");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in write(): ", e);
+        }
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcException.java b/core/java/com/trustedlogic/trustednfc/android/NfcException.java
new file mode 100644
index 0000000..2497c15
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NfcException.java
@@ -0,0 +1,42 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NFCException.java
+ * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
+ * Created         : 26-08-2009
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+/**
+ * Generic exception thrown in case something unexpected happened during the
+ * NFCManager operations.
+ *
+ * @since AA01.04
+ * @hide
+ */
+public class NfcException extends Exception {
+   /**
+    * Constructs a new NfcException with the current stack trace and the
+    * specified detail message.
+    *
+    * @param s the detail message for this exception.
+    */
+   public NfcException(String s) {
+      super(s);
+   }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcManager.java b/core/java/com/trustedlogic/trustednfc/android/NfcManager.java
new file mode 100644
index 0000000..98ab5bf
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NfcManager.java
@@ -0,0 +1,656 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NfcManager.java
+ * Original-Author : Trusted Logic S.A. (Jeremie Corbier)
+ * Created         : 26-08-2009
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.media.MiniThumbFile;
+import android.os.Handler;
+import android.os.RemoteException;
+import android.util.Log;
+
+//import android.util.Log;
+
+/**
+ * This class provides the primary API for managing all aspects of NFC. Get an
+ * instance of this class by calling
+ * Context.getSystemService(Context.NFC_SERVICE).
+ * @hide
+ */
+public final class NfcManager {
+    /**
+     * Tag Reader Discovery mode
+     */
+    private static final int DISCOVERY_MODE_TAG_READER = 0;
+
+    /**
+     * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an
+     * NFC-IP1 communication. Implementations should not assume that the
+     * controller will end up behaving as an NFC-IP1 target or initiator and
+     * should handle both cases, depending on the type of the remote peer type.
+     */
+    private static final int DISCOVERY_MODE_NFCIP1 = 1;
+
+    /**
+     * Card Emulation mode Enables the manager to act as an NFC tag. Provided
+     * that a Secure Element (an UICC for instance) is connected to the NFC
+     * controller through its SWP interface, it can be exposed to the outside
+     * NFC world and be addressed by external readers the same way they would
+     * with a tag.
+     * <p>
+     * Which Secure Element is exposed is implementation-dependent.
+     * 
+     * @since AA01.04
+     */
+    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
+
+    /**
+     * Used as Parcelable extra field in
+     * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_TAG_DISCOVERED_ACTION}
+     * . It contains the NDEF message read from the NDEF tag discovered.
+     */
+    public static final String NDEF_MESSAGE_EXTRA = "com.trustedlogic.trustednfc.android.extra.NDEF_MESSAGE";
+
+    /**
+     * Broadcast Action: a NDEF tag has been discovered.
+     * <p>
+     * Always contains the extra field
+     * {@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_NOTIFY permission.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String NDEF_TAG_DISCOVERED_ACTION = "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED";
+
+    /**
+     * Used as byte array extra field in
+     * {@link com.trustedlogic.trustednfc.android.NfcManager#TRANSACTION_DETECTED_ACTION}
+     * . It contains the AID of the applet concerned by the transaction.
+     */
+    public static final String AID_EXTRA = "com.trustedlogic.trustednfc.android.extra.AID";
+
+    /**
+     * Broadcast Action: a transaction with a secure element has been detected.
+     * <p>
+     * Always contains the extra field
+     * {@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA}
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_NOTIFY permission
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String TRANSACTION_DETECTED_ACTION = "com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED";
+
+    /**
+     * LLCP link status: The LLCP link is activated.
+     * 
+     * @since AA02.01
+     */
+    public static final int LLCP_LINK_STATE_ACTIVATED = 0;
+
+    /**
+     * LLCP link status: The LLCP link is deactivated.
+     * 
+     * @since AA02.01
+     */
+    public static final int LLCP_LINK_STATE_DEACTIVATED = 1;
+
+    /**
+     * Used as int extra field in
+     * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_ACTION}
+     * . It contains the new state of the LLCP link.
+     */
+    public static final String LLCP_LINK_STATE_CHANGED_EXTRA = "com.trustedlogic.trustednfc.android.extra.LLCP_LINK_STATE";
+
+    /**
+     * Broadcast Action: the LLCP link state changed.
+     * <p>
+     * Always contains the extra field
+     * {@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_LLCP permission.
+     */
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String LLCP_LINK_STATE_CHANGED_ACTION = "com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED";
+
+    private static final String TAG = "NfcManager";
+
+    private Handler mHandler;
+
+    private INfcManager mService;
+
+    private INfcTag mNfcTagService;
+
+    private IP2pTarget mP2pTargetService;
+
+    private IP2pInitiator mP2pInitiatorService;
+
+    private ILlcpSocket mLlcpSocketService;
+
+    private ILlcpConnectionlessSocket mLlcpConnectionlessSocketService;
+
+    private ILlcpServiceSocket mLlcpServiceSocketService;
+
+    static NfcException convertErrorToNfcException(int errorCode) {
+        return convertErrorToNfcException(errorCode, null);
+    }
+
+    static NfcException convertErrorToNfcException(int errorCode, String message) {
+        if (message == null) {
+            message = "";
+        } else {
+            message = " (" + message + ")";
+        }
+
+        switch (errorCode) {
+            case ErrorCodes.ERROR_BUSY:
+                return new NfcException("Another operation is already pending" + message);
+            case ErrorCodes.ERROR_CANCELLED:
+                return new NfcException("Operation cancelled" + message);
+            case ErrorCodes.ERROR_TIMEOUT:
+                return new NfcException("Operation timed out" + message);
+            case ErrorCodes.ERROR_SOCKET_CREATION:
+                return new NfcException("Error during the creation of an Llcp socket:" + message);
+            case ErrorCodes.ERROR_SAP_USED:
+                return new NfcException("Error SAP already used:" + message);
+            case ErrorCodes.ERROR_SERVICE_NAME_USED:
+                return new NfcException("Error Service Name already used:" + message);
+            case ErrorCodes.ERROR_SOCKET_OPTIONS:
+                return new NfcException("Error Socket options:" + message);
+            case ErrorCodes.ERROR_INVALID_PARAM:
+                return new NfcException("Error Set Properties: invalid param" + message);
+            case ErrorCodes.ERROR_NFC_ON:
+                return new NfcException("Error Set Properties : NFC is ON" + message);
+            case ErrorCodes.ERROR_NOT_INITIALIZED:
+                return new NfcException("NFC is not running " + message);
+            case ErrorCodes.ERROR_SE_ALREADY_SELECTED:
+                return new NfcException("Secure Element already connected" + message);
+            case ErrorCodes.ERROR_NO_SE_CONNECTED:
+                return new NfcException("No Secure Element connected" + message);
+            case ErrorCodes.ERROR_SE_CONNECTED:
+                return new NfcException("A secure Element is already connected" + message);
+            default:
+                return new NfcException("Unkown error code " + errorCode + message);
+        }
+    }
+
+    /**
+     * @hide
+     */
+    public NfcManager(INfcManager service, Handler handler) {
+        mService = service;
+        mHandler = handler;
+        try {
+            mNfcTagService = mService.getNfcTagInterface();
+            mP2pInitiatorService = mService.getP2pInitiatorInterface();
+            mP2pTargetService = mService.getP2pTargetInterface();
+            mLlcpServiceSocketService = mService.getLlcpServiceInterface();
+            mLlcpConnectionlessSocketService = mService.getLlcpConnectionlessInterface();
+            mLlcpSocketService = mService.getLlcpInterface();
+        } catch (RemoteException e) {
+            mLlcpSocketService = null;
+            mNfcTagService = null;
+            mP2pInitiatorService = null;
+            mP2pTargetService = null;
+            mLlcpConnectionlessSocketService = null;
+            mLlcpServiceSocketService = null;
+        }
+    }
+
+    /**
+     * Return the status of the NFC feature
+     * 
+     * @return mIsNfcEnabled
+     * @since AA02.01
+     */
+    public boolean isEnabled() {
+        try {
+            return mService.isEnabled();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in isEnabled(): ", e);
+            return false;
+        }
+    }
+
+    /**
+     * Enable the NFC Feature
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_ADMIN permission
+     * 
+     * @throws NfcException if the enable failed
+     * @since AA02.01
+     */
+    public void enable() throws NfcException {
+        try {
+            boolean isSuccess = mService.enable();
+            if (isSuccess == false) {
+                throw new NfcException("NFC Service failed to enable");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in enable(): ", e);
+        }
+    }
+
+    /**
+     * Disable the NFC feature
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_ADMIN permission
+     * 
+     * @throws NfcException if the disable failed
+     * @since AA02.01
+     */
+    public void disable() throws NfcException {
+        try {
+            boolean isSuccess = mService.disable();
+            if (isSuccess == false) {
+                throw new NfcException("NFC Service failed to disable");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in disable(): ", e);
+        }
+    }
+
+    /**
+     * Get the list of the identifiers of the Secure Elements detected
+     * by the NFC controller.
+     * 
+     * @return list a list of Secure Element identifiers.
+     * @see #getSelectedSecureElement
+     * @see #selectSecureElement(int)
+     * @see #deselectSecureElement
+     * @since AA02.01
+     */
+    public int[] getSecureElementList() {
+        try {
+            return mService.getSecureElementList();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getSecureElementList(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Get the identifier of the currently selected secure element.
+     * 
+     * @return id identifier of the currently selected Secure Element. 0 if none.
+     * @see #getSecureElementList
+     * @see #selectSecureElement(int)
+     * @see #deselectSecureElement
+     * @since AA02.01
+     */
+    public int getSelectedSecureElement() {
+        try {
+            return mService.getSelectedSecureElement();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getSelectedSecureElement(): ", e);
+            return -1;
+        }
+    }
+
+    /**
+     * Select a specific Secure Element by its identifier.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_ADMIN permission
+     * 
+     * @throws NfcException if a or this secure element is already selected
+     * @see #getSecureElementList
+     * @see #getSelectedSecureElement
+     * @see #deselectSecureElement
+     * @since AA02.01
+     */
+    public void selectSecureElement(int seId) throws NfcException  {
+        try {
+           int status = mService.selectSecureElement(seId);
+           if(status != ErrorCodes.SUCCESS){
+               throw convertErrorToNfcException(status);
+           }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in selectSecureElement(): ", e);
+        }
+    }
+
+    /**
+     * Deselect the currently selected Secure Element
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_ADMIN permission
+     * 
+     * @throws NfcException if no secure Element is selected
+     * @see #getSecureElementList
+     * @see #getSelectedSecureElement
+     * @see #selectSecureElement(int)
+     * @since AA02.01
+     */
+    public void deselectSecureElement() throws NfcException {
+        try {
+            int status = mService.deselectSecureElement();
+            if(status != ErrorCodes.SUCCESS){
+                throw convertErrorToNfcException(status);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in deselectSecureElement(): ", e);
+        }
+    }
+
+    /**
+     * Open a connection with a remote NFC peer
+     * 
+     * This method does not return while no remote NFC peer enters the field.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_RAW permission
+     * 
+     * @return P2pDevice object to be used to communicate with the detected
+     *         peer.
+     * @throws IOException if the target has been lost or the connection has
+     *             been closed.
+     * @throws NfcException if an open is already started
+     * @see P2pDevice
+     * @see #getOpenTimeout
+     * @see #setOpenTimeout(int)
+     * @see #cancel
+     * @since AA02.01
+     */
+    public P2pDevice openP2pConnection() throws IOException, NfcException {
+        try {
+            int handle = mService.openP2pConnection();
+            // Handle potential errors
+            if (ErrorCodes.isError(handle)) {
+                if (handle == ErrorCodes.ERROR_IO) {
+                    throw new IOException();
+                } else {
+                    throw convertErrorToNfcException(handle);
+                }
+            }
+            // Build the public NfcTag object, depending on its type
+            if (mP2pTargetService.getMode(handle) == P2pDevice.MODE_P2P_TARGET) {
+                return new P2pTarget(mP2pTargetService, handle);
+            } else {
+                return new P2pInitiator(mP2pInitiatorService, handle);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in openTagConnection(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Open a connection with a tag
+     *
+     * This method does not return while no tag enters the field.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_RAW permission
+     * 
+     * @return tag object to be use to communicate with the detected NfcTag.
+     * @throws IOException if the target has been lost or the connection has
+     *             been closed.
+     * @throws NfcException if an open is already started
+     * @see NfcTag
+     * @see #getOpenTimeout
+     * @see #setOpenTimeout(int)
+     * @see #cancel
+     * @since AA02.01
+     */
+    public NfcTag openTagConnection() throws IOException, NfcException {
+        try {
+            int handle = mService.openTagConnection();
+            // Handle potential errors
+            if (ErrorCodes.isError(handle)) {
+                if (handle == ErrorCodes.ERROR_IO) {
+                    throw new IOException();
+                } else {
+                    throw convertErrorToNfcException(handle);
+                }
+            }
+            // Build the public NfcTag object
+            return new NfcTag(mNfcTagService, handle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in openTagConnection(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Set the timeout for open requests
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_RAW permission
+     * 
+     * @param timeout value of the timeout for open request
+     * @see #openP2pConnection
+     * @see #openTagConnection
+     * @see #getOpenTimeout
+     * @since AA02.01
+     */
+    public void setOpenTimeout(int timeout) {
+        try {
+            mService.setOpenTimeout(timeout);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in setOpenTimeout(): ", e);
+        }
+    }
+
+    /**
+     * Get the timeout value of open requests
+     * 
+     * @return mTimeout
+     * @see #setOpenTimeout(int)
+     * @since AA02.01
+     */
+    public int getOpenTimeout() {
+        try {
+            return mService.getOpenTimeout();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getOpenTimeout(): ", e);
+            return 0;
+        }
+    }
+
+    /**
+     * Cancel an openTagConnection or an openP2pConnection started
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_RAW permission
+     * 
+     * @see #openP2pConnection
+     * @see #openTagConnection
+     * @since AA02.01
+     */
+    public void cancel() {
+        try {
+            mService.cancel();
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in cancel(): ", e);
+        }
+    }
+
+    /**
+     * Creates a connectionless socket for a LLCP link and set its Service
+     * Access Point number (SAP)
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_LLCP permission
+     * 
+     * @param sap Service Access Point number related to the created
+     *            Connectionless socket.
+     * @return LlcpConnectionlessSocket object to be used in a LLCP
+     *         Connectionless communication.
+     * @throws IOException if the socket creation failed
+     * @throws NfcException if socket ressources are insufficicent
+     * @see LlcpConnectionlessSocket
+     * @since AA02.01
+     */
+    public LlcpConnectionlessSocket createLlcpConnectionlessSocket(int sap) throws IOException,
+            NfcException {
+
+        try {
+            int handle = mService.createLlcpConnectionlessSocket(sap);
+            // Handle potential errors
+            if (ErrorCodes.isError(handle)) {
+                if (handle == ErrorCodes.ERROR_IO) {
+                    throw new IOException();
+                } else {
+                    throw convertErrorToNfcException(handle);
+                }
+            }
+
+            // Build the public LlcpConnectionLess object
+            return new LlcpConnectionlessSocket(mLlcpConnectionlessSocketService, handle);
+
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in createLlcpConnectionlessSocket(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Creates a LlcpServiceSocket for a LLCP link, set its Service Access Point
+     * number (SAP).
+     * <p>
+     * During a LLCP communication, the LlcpServiceSocket will create LlcpSocket
+     * to communicate with incoming LLCP clients. For that, a server socket need
+     * to have some informations as a working buffer length in order to handle
+     * incoming data and some options to define the LLCP communication.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_LLCP permission
+     * 
+     * @param sap
+     * @param sn Service Name of the LlcpServiceSocket
+     * @param miu Maximum Information Unit (MIU) for a LlcpSocket created by the
+     *            LlcpServiceSocket
+     * @param rw Receive Window (RW) for a LlcpSocket created by the
+     *            LlcpServiceSocket
+     * @param linearBufferLength size of the memory space needed to handle
+     *            incoming data for every LlcpSocket created.
+     * @return LlcpServiceSocket object to be used as a LLCP Service in a
+     *         connection oriented communication.
+     * @throws IOException if the socket creation failed
+     * @throws NfcException if socket ressources are insufficicent
+     * @see LlcpServiceSocket
+     * @since AA02.01
+     */
+    public LlcpServiceSocket createLlcpServiceSocket(int sap, String sn, int miu, int rw,
+            int linearBufferLength) throws IOException, NfcException {
+        try {
+            int handle = mService.createLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
+            // Handle potential errors
+            if (ErrorCodes.isError(handle)) {
+                if (handle == ErrorCodes.ERROR_IO) {
+                    throw new IOException();
+                } else {
+                    throw convertErrorToNfcException(handle);
+                }
+            }
+
+            // Build the public LlcpServiceSocket object
+            return new LlcpServiceSocket(mLlcpServiceSocketService, mLlcpSocketService, handle);
+
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in createLlcpServiceSocket(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Creates a LlcpSocket for a LLCP link with a specific Service Access Point
+     * number (SAP)
+     * <p>
+     * A LlcpSocket need to have a linear buffer in order to handle incoming
+     * data. This linear buffer will be used to store incoming data as a stream.
+     * Data will be readable later.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_LLCP permission
+     * 
+     * @param sap Service Access Point number for the created socket
+     * @param miu Maximum Information Unit (MIU) of the communication socket
+     * @param rw Receive Window (RW) of the communication socket
+     * @param linearBufferLength size of the memory space needed to handle
+     *            incoming data with this socket
+     * @throws IOException if the socket creation failed
+     * @throws NfcException if socket ressources are insufficicent
+     * @see LlcpSocket
+     * @since AA02.01
+     */
+    public LlcpSocket createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
+            throws IOException, NfcException {
+        try {
+            int handle = mService.createLlcpSocket(sap, miu, rw, linearBufferLength);
+            // Handle potential errors
+            if (ErrorCodes.isError(handle)) {
+                if (handle == ErrorCodes.ERROR_IO) {
+                    throw new IOException();
+                } else {
+                    throw convertErrorToNfcException(handle);
+                }
+            }
+            // Build the public LlcpSocket object
+            return new LlcpSocket(mLlcpSocketService, handle);
+
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in createLlcpSocket(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Set different parameters like the NCIP General bytes, the LLCP link
+     * parameters and all tag discovery parameters.
+     * <p class="note">
+     * <strong>Note:</strong> Requires the NFC_ADMIN permission
+     * 
+     * @param param parameter to be updated with a new value
+     * @param value new value of the parameter
+     * @throws NfcException if incorrect parameters of NFC is ON
+     * @since AA02.01
+     */
+    public void setProperties(String param, String value) throws NfcException {
+        try {
+            int result = mService.setProperties(param, value);
+            // Handle potential errors
+            if (ErrorCodes.isError(result)) {
+                throw convertErrorToNfcException(result);
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in setProperties(): ", e);
+        }
+    }
+
+    /**
+     * Get the value of different parameters like the NCFIP General bytes, the
+     * LLCP link parameters and all tag discovery parameters.
+     * 
+     * @param param parameter to be updated
+     * @return String value of the requested parameter
+     * @throws RemoteException
+     * @since AA02.01
+     */
+    public String getProperties(String param) {
+        String value;
+        try {
+            value = mService.getProperties(param);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getProperties(): ", e);
+            return null;
+        }
+        return value;
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/NfcTag.java b/core/java/com/trustedlogic/trustednfc/android/NfcTag.java
new file mode 100644
index 0000000..798c7e4
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/NfcTag.java
@@ -0,0 +1,250 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NFCTag.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 26-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+/**
+ * This class represents tags with no known formatting. One can use the method
+ * {@link #isNdef()} to determine if the tag can store NDEF-formatted messages.
+ * <p>
+ * 
+ * <pre class="prettyprint">
+ * if (tag.isNdef()) {
+ *     NdefTag ndefTag = (NdefTag) tag;
+ *     NdefMessage msg = ndefTag.read();
+ * }
+ * </pre>
+ * 
+ * @since AA01.04
+ * @see NdefMessage
+ * @hide
+ */
+public class NfcTag {
+
+    private static final String TAG = "NfcTag";
+
+    /**
+     * The handle returned by the NFC service and used to identify the tag in
+     * every call of this class.
+     * 
+     * @hide
+     */
+    protected int mHandle;
+
+    /**
+     * The entry point for tag operations.
+     * 
+     * @hide
+     */
+    protected INfcTag mService;
+
+    /**
+     * Flag set when the object is closed and thus not usable any more.
+     * 
+     * @hide
+     */
+    protected boolean isClosed = false;
+
+    /**
+     * Flag set when the tag is connected.
+     * 
+     * @hide
+     */
+    protected boolean isConnected = false;
+    
+    /**
+     * Flag set when a check NDEF is performed.
+     * 
+     * @hide
+     */
+    protected boolean isNdef = false;
+
+    /**
+     * Check if tag is still opened.
+     * 
+     * @return data sent by the P2pInitiator.
+     * @throws NfcException if accessing a closed target.
+     * 
+     * @hide               
+     */
+    public void checkState() throws NfcException {
+        if (isClosed) {
+            throw new NfcException("Tag has been closed.");
+        }
+        if (!isConnected) {
+            throw new NfcException("Tag is not connected.");
+        }
+    }
+
+    /**
+     * Internal constructor for the NfcTag class.
+     * 
+     * @param service The entry point to the Nfc Service for NfcTag class.
+     * @param handle The handle returned by the NFC service and used to identify
+     *            the tag in subsequent calls.
+     * @hide
+     */
+    NfcTag(INfcTag service, int handle) {
+        this.mService = service;
+        this.mHandle = handle;
+    }
+
+    /**
+     * Connects to the tag. This shall be called prior to any other operation on
+     * the tag.
+     * 
+     * @throws IOException if the tag has been lost or the connection has been
+     *             closed.
+     * @throws nfcException if the tag is already in connected state.
+     */
+    public void connect() throws NfcException, IOException {
+        // Check state
+        if (isClosed) {
+            throw new NfcException("Tag has been closed.");
+        }
+        if (isConnected) {
+            throw new NfcException("Already connected");
+        }
+
+        // Perform connect
+        try {
+            int result = mService.connect(mHandle);
+            if (ErrorCodes.isError(result)) {
+                if (result == ErrorCodes.ERROR_IO) {
+                    throw new IOException("Failed to connect");
+                }
+                else {
+                    throw NfcManager.convertErrorToNfcException(result);
+                }
+            }
+            isConnected = true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in connect(): ", e);
+        }
+    }
+
+    /**
+     * Disconnects from the tag. This must be called so that other targets can
+     * be discovered. It restarts the NFC discovery loop.
+     * 
+     * @throws NfcException if the tag is already in disconnected state or not connected
+     */
+    public void close() throws NfcException {
+        // Check state
+        checkState();
+
+        try {
+            mService.close(mHandle);
+            isClosed = true;
+            isConnected = false;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in close(): ", e);
+        }
+    }
+
+    /**
+     * Exchanges raw data with the tag, whatever the tag type.
+     * 
+     * To exchange APDUs with a ISO14443-4-compliant tag, the data parameter
+     * must be filled with the C-APDU (CLA, INS, P1, P2 [, ...]). The returned
+     * data consists of the R-APDU ([...,] SW1, SW2).
+     * 
+     * @param data data to be sent to the tag
+     * @return data sent in response by the tag
+     * @throws IOException if the tag has been lost or the connection has been
+     *             closed.
+     * @throws NfcException in case of failure within the stack
+     */
+    public byte[] transceive(byte[] data) throws IOException, NfcException {
+        // Check state
+        checkState();
+
+        // Perform transceive
+        try {
+            byte[] response = mService.transceive(mHandle, data);
+            if (response == null) {
+                throw new IOException("Transceive failed");
+            }
+            return response;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in transceive(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Checks whether tag is NDEF-compliant or not.
+     * 
+     * @return true if the tag is NDEF-compliant, false otherwise
+     * @throws NfcException in case an error occurred when trying to determine
+     *             whether the tag is NDEF-compliant
+     */
+    public boolean isNdef() throws NfcException {
+        // Check state
+        checkState();
+
+        // Perform Check Ndef
+        try {
+            isNdef = mService.isNdef(mHandle);
+            return isNdef;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in isNdef(): ", e);
+            return false;
+        }
+    }
+
+    /**
+     * Returns target type. constants.
+     * 
+     * @return tag type.
+     */
+    public String getType() {
+        try {
+            return mService.getType(mHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getType(): ", e);
+            return null;
+        }
+    }
+    
+    /**
+     * Returns target UID.
+     * 
+     * @return tag UID.
+     */
+    public byte[] getUid() {
+        try {
+            return mService.getUid(mHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getType(): ", e);
+            return null;
+        }
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pDevice.java b/core/java/com/trustedlogic/trustednfc/android/P2pDevice.java
new file mode 100644
index 0000000..65800f2
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/P2pDevice.java
@@ -0,0 +1,89 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : P2PDevice.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ * Created         : 26-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+/**
+ * P2pDevice is the abstract base class for all supported P2P targets the
+ * NfcManager can handle.
+ * @hide
+ */
+public abstract class P2pDevice {
+
+    /**
+     * Peer-to-Peer Target.
+     */
+    public static final short MODE_P2P_TARGET = 0x00;
+
+    /**
+     * Peer-to-Peer Initiator.
+     */
+    public static final short MODE_P2P_INITIATOR = 0x01;
+
+    /**
+     * Invalid target type.
+     */
+    public static final short MODE_INVALID = 0xff;
+
+    /**
+     * Target handle, used by native calls.
+     * @hide
+     */
+    protected int mHandle;
+	
+    /**
+     * Flag set when the object is closed and thus not usable any more.
+     * @hide
+     */
+	protected boolean isClosed = false;
+
+    /**
+     * Prevent default constructor to be public.
+     * @hide
+     */
+	protected P2pDevice() {
+	}
+
+	/**
+     * Returns the remote NFC-IP1 General Bytes.
+     * 
+     * @return remote general bytes
+	 * @throws IOException 
+     */
+    public byte[] getGeneralBytes() throws IOException {
+        // Should not be called directly (use subclasses overridden method instead)
+        return null;
+    }
+
+    /**
+     * Returns target type. The value returned can be one of the TYPE_*
+     * constants.
+     * 
+     * @return target type.
+     */
+    public int getMode() {
+        // Should not be called directly (use subclasses overridden method instead)
+        return MODE_INVALID;
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java b/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java
new file mode 100644
index 0000000..0f28ae0
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/P2pInitiator.java
@@ -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.
+ */
+
+/**
+ * File            : P2PInitiator.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * P2pInitiator represents the initiator in an NFC-IP1 peer-to-peer
+ * communication.
+ * 
+ * @see P2pTarget
+ * @since AA02.01
+ * @hide
+ */
+public class P2pInitiator extends P2pDevice {
+
+    private static final String TAG = "P2pInitiator";
+
+	/**
+     * The entry point for P2P tag operations.
+     * @hide
+     */
+	private IP2pInitiator mService;
+	
+    /**
+     * Internal constructor for the P2pInitiator class.
+     * 
+     * @param handle The handle returned by the NFC service and used to identify
+     * 				 the tag in subsequent calls.
+     * 
+     * @hide
+     */
+    P2pInitiator(IP2pInitiator service, int handle) {
+        this.mService = service;
+        this.mHandle = handle;
+    }	
+
+    /**
+     * Receives data from a P2pInitiator.
+     * 
+     * @return data sent by the P2pInitiator.
+     * @throws IOException if the target has been lost or if the connection has
+     *             been closed.
+     */
+    public byte[] receive() throws IOException {
+        try {
+        	byte[] result = mService.receive(mHandle);
+        	if (result == null) {
+        		throw new IOException("Tag has been lost");
+        	}
+            return result;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in receive(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Sends data to a P2pInitiator.
+     * 
+     * @param data data to be sent to the P2pInitiator.
+     * @throws IOException if the target has been lost or if the connection has
+     *             been closed.
+     */
+    public void send(byte[] data) throws IOException {
+        try {
+        	boolean isSuccess = mService.send(mHandle, data);
+        	if (!isSuccess) {
+        		throw new IOException("Tag has been lost");
+        	}
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in send(): ", e);
+        }
+    }
+
+    @Override
+    public byte[] getGeneralBytes() {
+        try {
+            return mService.getGeneralBytes(mHandle);
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getGeneralBytes(): ", e);
+            return null;
+        }
+    }
+
+    @Override
+    public int getMode() {
+        return P2pDevice.MODE_P2P_INITIATOR;
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java b/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java
new file mode 100644
index 0000000..b5e00db
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/P2pTarget.java
@@ -0,0 +1,183 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : P2PTarget.java
+ * Original-Author : Trusted Logic S.A. (Daniel Tomas)
+ */
+
+package com.trustedlogic.trustednfc.android;
+
+import java.io.IOException;
+
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.os.RemoteException;
+import android.util.Log;
+
+/**
+ * P2pTarget represents the target in an NFC-IP1 peer-to-peer communication.
+ * 
+ * @see P2pInitiator
+ * @since AA02.01
+ * @hide
+ */
+public class P2pTarget extends P2pDevice {
+
+    private static final String TAG = "P2pTarget";
+
+	/**
+     * The entry point for P2P tag operations.
+     * @hide
+     */
+	private IP2pTarget mService;
+	
+    /**
+     * Flag set when the object is closed and thus not usable any more.
+     * @hide
+     */
+	private boolean isClosed = false;
+	
+    /**
+     * Flag set when the tag is connected.
+     * @hide
+     */
+	private boolean isConnected = false;
+	
+    /**
+     * Check if tag is still opened.
+     * 
+     * @return data sent by the P2pInitiator.
+     * @throws NfcException if accessing a closed target.
+     * 
+     * @hide          
+     */
+    public void checkState() throws NfcException {
+    	if(isClosed) {
+    		throw new NfcException("Tag has been closed.");
+    	}
+    }
+
+    /**
+     * Internal constructor for the P2pTarget class.
+     * 
+     * @param handle The handle returned by the NFC service and used to identify
+     * 				 the tag in subsequent calls.
+     * 
+     * @hide
+     */
+    P2pTarget(IP2pTarget service, int handle) {
+        this.mService = service;
+        this.mHandle = handle;
+    }	
+
+    /**
+     * Connects to the P2pTarget. This shall be called prior to any other
+     * operation on the P2pTarget.
+     * 
+     * @throws NfcException
+     */
+    public void connect() throws NfcException {
+    	// Check state
+    	checkState();
+    	if (isConnected) {
+    		throw new NfcException("Already connected");
+    	}
+    	
+    	// Perform connect
+        try {
+            int result = mService.connect(mHandle);
+            if (ErrorCodes.isError(result)) {
+                if (result == ErrorCodes.ERROR_IO) {
+                    throw new NfcException("Failed to connect");
+                }
+                else {
+                    throw NfcManager.convertErrorToNfcException(result);
+                }
+            }
+            isConnected = true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in connect(): ", e);
+        }
+    }
+
+    /**
+     * Disconnects from the P2p Target. This must be called so that other
+     * targets can be discovered. It restarts the NFC discovery loop.
+     * 
+     * @throws NFCException
+     */
+    public void disconnect() throws NfcException {
+        checkState();
+        try {
+            mService.disconnect(mHandle);
+            isConnected = true;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in disconnect(): ", e);
+        }
+    }
+
+    /**
+     * Exchanges raw data with the P2pTarget.
+     * 
+     * @param data data to be sent to the P2pTarget
+     * @return data sent in response by the P2pTarget
+     * @throws IOException if the target has been lost or the connection has
+     *             been closed.
+     * @throws NfcException in case of failure within the stack
+     */
+    public byte[] transceive(byte[] data) throws IOException, NfcException {
+    	// Check state
+    	checkState();
+
+    	// Perform transceive
+        try {
+            byte[] response = mService.transceive(mHandle, data);
+            if (response == null) {
+                throw new IOException("Transceive failed");
+            }
+            return response;
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in transceive(): ", e);
+            return null;
+        }
+    }
+
+    /**
+     * Get the General bytes of the connected P2P Target
+     * 
+     * @return general bytes of the connected P2P Target
+     * @throws IOException if the target in not in connected state
+     */
+    public byte[] getGeneralBytes() throws IOException {
+        try {
+            if(isConnected){
+                return mService.getGeneralBytes(mHandle);
+            }else{
+                throw new IOException("Target not in connected state");
+            }
+        } catch (RemoteException e) {
+            Log.e(TAG, "RemoteException in getGeneralBytes(): ", e);
+            return null;
+        }
+    }
+
+    @Override
+    public int getMode() {
+        return P2pDevice.MODE_P2P_TARGET;
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java b/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java
new file mode 100644
index 0000000..ca3b7e0
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/ErrorCodes.java
@@ -0,0 +1,91 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : ErrorCodes.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 26-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+/**
+ * This class defines all the error codes that can be returned by the service
+ * and producing an exception on the application level. These are needed since
+ * binders does not support exceptions.
+ * 
+ * @hide
+ */
+public class ErrorCodes {
+
+    public static boolean isError(int code) {
+        if (code < 0) {
+            return true;
+        } else {
+            return false;
+        }
+    }
+
+    public static final int SUCCESS = 0;
+    
+    public static final int ERROR_IO = -1;
+
+    public static final int ERROR_CANCELLED = -2;
+
+    public static final int ERROR_TIMEOUT = -3;
+
+    public static final int ERROR_BUSY = -4;
+
+    public static final int ERROR_CONNECT = -5;
+
+    public static final int ERROR_DISCONNECT = -5;
+
+    public static final int ERROR_READ = -6;
+
+    public static final int ERROR_WRITE = -7;
+
+    public static final int ERROR_INVALID_PARAM = -8;
+    
+    public static final int ERROR_INSUFFICIENT_RESOURCES = -9;
+    
+    public static final int ERROR_SOCKET_CREATION = -10;
+    
+    public static final int ERROR_SOCKET_NOT_CONNECTED = -11;
+    
+    public static final int ERROR_BUFFER_TO_SMALL = -12;
+
+    public static final int ERROR_SAP_USED = -13;
+    
+    public static final int ERROR_SERVICE_NAME_USED = -14;
+    
+    public static final int ERROR_SOCKET_OPTIONS = -15;
+    
+    public static final int ERROR_NFC_ON = -16;
+    
+    public static final int ERROR_NOT_INITIALIZED = -17;
+    
+    public static final int ERROR_SE_ALREADY_SELECTED = -18;
+    
+    public static final int ERROR_SE_CONNECTED = -19;
+    
+    public static final int ERROR_NO_SE_CONNECTED = -20;
+    
+    
+    
+    
+    
+    
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java
new file mode 100644
index 0000000..ccfbeb4
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpConnectionlessSocket.java
@@ -0,0 +1,68 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeLlcpConnectionLessSocket.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+import com.trustedlogic.trustednfc.android.LlcpPacket;
+
+/**
+ * LlcpConnectionlessSocket represents a LLCP Connectionless object to be used
+ * in a connectionless communication
+ * 
+ * @since AA02.01
+ * {@hide}
+ */
+
+public class NativeLlcpConnectionlessSocket {
+	
+	private int mHandle;
+	
+	private int mSap;
+	
+	private int mLinkMiu;
+	
+	public NativeLlcpConnectionlessSocket(){;
+	}
+	
+	public NativeLlcpConnectionlessSocket(int sap){
+		mSap = sap;
+	}
+	
+    public native boolean doSendTo(int sap, byte[] data);
+
+    public native LlcpPacket doReceiveFrom(int linkMiu);
+
+    public native boolean doClose();
+    
+    public int getLinkMiu(){
+    	return mLinkMiu;
+    }
+    
+    public int getSap(){
+    	return mSap;
+    }
+    
+    public int getHandle(){
+    	return mHandle;
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java
new file mode 100644
index 0000000..a01f135
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpServiceSocket.java
@@ -0,0 +1,82 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeLlcpServerSocket.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+/**
+ * LlcpServiceSocket represents a LLCP Service to be used in a
+ * Connection-oriented communication
+ * {@hide}
+ */
+
+public class NativeLlcpServiceSocket {
+
+	private int mHandle;
+	
+	private int mLocalMiu;
+	
+	private int mLocalRw;
+	
+	private int mLocalLinearBufferLength;
+	
+	private int mSap;
+	
+	private int mTimeout;
+	
+	private String mServiceName;
+	
+	public NativeLlcpServiceSocket(){
+		
+	}
+	
+	public NativeLlcpServiceSocket(String serviceName){
+		mServiceName = serviceName;
+	}
+	
+    public native NativeLlcpSocket doAccept(int timeout, int miu, int rw, int linearBufferLength);
+
+    public native boolean doClose();
+    
+    public int getHandle(){
+    	return mHandle;
+    }
+    
+    public void setAcceptTimeout(int timeout){
+    	mTimeout = timeout; 
+    }
+    
+    public int getAcceptTimeout(){
+    	return mTimeout;
+    }
+    
+    public int getRw(){
+    	return mLocalRw;
+    }
+    
+    public int getMiu(){
+    	return mLocalMiu;
+    }
+    
+    public int getLinearBufferLength(){
+    	return mLocalLinearBufferLength;
+    }
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java
new file mode 100644
index 0000000..077c5e0
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeLlcpSocket.java
@@ -0,0 +1,93 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeLlcpClientSocket.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+/**
+ * LlcpClientSocket represents a LLCP Connection-Oriented client to be used in a
+ * connection-oriented communication
+ * {@hide}
+ */
+
+public class NativeLlcpSocket {
+	
+	private int mHandle;
+	
+	private int mSap;
+	
+	private int mLocalMiu;
+	
+	private int mLocalRw;
+	
+    private int mTimeout;
+    
+    public NativeLlcpSocket(){
+    	
+    }
+    
+    public NativeLlcpSocket(int sap, int miu, int rw){
+    	mSap = sap;
+    	mLocalMiu = miu;
+    	mLocalRw = rw;
+    }
+
+    public native boolean doConnect(int nSap, int timeout);
+
+    public native boolean doConnectBy(String sn, int timeout);
+
+    public native boolean doClose();
+
+    public native boolean doSend(byte[] data);
+
+    public native int doReceive(byte[] recvBuff);
+    
+    public native int doGetRemoteSocketMiu();
+    
+    public native int doGetRemoteSocketRw();
+    
+    
+    
+    public void setConnectTimeout(int timeout){
+    	mTimeout = timeout;
+    }
+    
+    public int getConnectTimeout(){
+    	return mTimeout;
+    }
+    
+    public int getSap(){
+    	return mSap;
+    }
+    
+    public int getMiu(){
+    	return mLocalMiu;
+    }
+    
+    public int getRw(){
+    	return mLocalRw;
+    }
+    
+    public int getHandle(){
+    	return mHandle;
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java
new file mode 100644
index 0000000..d1e64a6
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNdefTag.java
@@ -0,0 +1,36 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeNdefTag.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+/**
+ * Native interface to the NDEF tag functions
+ *
+ * {@hide}
+ */
+public class NativeNdefTag {
+    private int mHandle;
+
+    public native byte[] doRead();
+
+    public native boolean doWrite(byte[] buf);
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java
new file mode 100644
index 0000000..2f5a0f09
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcManager.java
@@ -0,0 +1,325 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeNfcManager.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+import android.annotation.SdkConstant;
+import android.annotation.SdkConstant.SdkConstantType;
+import android.content.Context;
+import android.content.Intent;
+import android.os.Handler;
+import android.os.Message;
+import android.util.Log;
+
+import com.trustedlogic.trustednfc.android.NfcManager;
+import com.trustedlogic.trustednfc.android.NdefMessage;
+import com.trustedlogic.trustednfc.android.NfcTag;
+
+/**
+ * Native interface to the NFC Manager functions {@hide}
+ */
+public class NativeNfcManager {
+    
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA = "com.trustedlogic.trustednfc.android.extra.INTERNAL_LLCP_LINK_STATE";
+
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION = "com.trustedlogic.trustednfc.android.action.INTERNAL_LLCP_LINK_STATE_CHANGED";
+    
+    @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
+    public static final String INTERNAL_TARGET_DESELECTED_ACTION = "com.trustedlogic.trustednfc.android.action.INTERNAL_TARGET_DESELECTED";
+
+    /* Native structure */
+    private int mNative;
+
+    private Context mContext;
+
+    private Handler mNfcHandler;
+
+    private static final String TAG = "NativeNfcManager";
+
+    private static final int MSG_NDEF_TAG = 0;
+
+    private static final int MSG_CARD_EMULATION = 1;
+
+    private static final int MSG_LLCP_LINK_ACTIVATION = 2;
+
+    private static final int MSG_LLCP_LINK_DEACTIVATED = 3;
+
+    private static final int MSG_TARGET_DESELECTED = 4;
+
+    public NativeNfcManager(Context context) {
+        mNfcHandler = new NfcHandler();
+        mContext = context;
+    }
+
+    /**
+     * Initializes Native structure
+     */
+    public native boolean initializeNativeStructure();
+
+    /**
+     * Initializes NFC stack.
+     */
+    public native boolean initialize();
+
+    /**
+     * Deinitializes NFC stack.
+     */
+    public native boolean deinitialize();
+
+    /**
+     * Enable discory for the NdefMessage and Transaction notification
+     */
+    public native void enableDiscovery(int mode);
+
+    /**
+     * Disables an NFCManager mode of operation. Allows to disable tag reader,
+     * peer to peer initiator or target modes.
+     * 
+     * @param mode discovery mode to enable. Must be one of the provided
+     *            NFCManager.DISCOVERY_MODE_* constants.
+     */
+    public native void disableDiscoveryMode(int mode);
+
+    public native int[] doGetSecureElementList();
+
+    public native void doSelectSecureElement(int seID);
+
+    public native void doDeselectSecureElement(int seID);
+
+    public native NativeP2pDevice doOpenP2pConnection(int timeout);
+
+    public native NativeNfcTag doOpenTagConnection(int timeout);
+
+    public native int doGetLastError();
+
+    public native void doSetProperties(int param, int value);
+
+    public native void doCancel();
+
+    public native NativeLlcpConnectionlessSocket doCreateLlcpConnectionlessSocket(int nSap);
+
+    public native NativeLlcpServiceSocket doCreateLlcpServiceSocket(int nSap, String sn, int miu,
+            int rw, int linearBufferLength);
+
+    public native NativeLlcpSocket doCreateLlcpSocket(int sap, int miu, int rw,
+            int linearBufferLength);
+
+    public native boolean doCheckLlcp();
+
+    public native boolean doActivateLlcp();
+
+    private class NfcHandler extends Handler {
+        @Override
+        public void handleMessage(Message msg) {
+
+            try {
+                switch (msg.what) {
+                    case MSG_NDEF_TAG:
+                        Log.d(TAG, "Checking for NDEF tag message");
+                        NativeNfcTag tag = (NativeNfcTag) msg.obj;
+                        if (tag.doConnect()) {
+                            if (tag.checkNDEF()) {
+                                byte[] buff = tag.doRead();
+                                if (buff != null) {
+                                    NdefMessage msgNdef = new NdefMessage(buff);
+                                    if (msgNdef != null) {
+                                        /* Send broadcast ordered */
+                                        Intent NdefMessageIntent = new Intent();
+                                        NdefMessageIntent
+                                                .setAction(NfcManager.NDEF_TAG_DISCOVERED_ACTION);
+                                        NdefMessageIntent.putExtra(NfcManager.NDEF_MESSAGE_EXTRA,
+                                                msgNdef);
+                                        Log.d(TAG, "NDEF message found, broadcasting to applications");
+                                        mContext.sendOrderedBroadcast(NdefMessageIntent,
+                                                android.Manifest.permission.NFC_NOTIFY);
+                                        /* Disconnect tag */
+                                        tag.doAsyncDisconnect();
+                                    }
+                                } else {
+                                   Log.w(TAG, "Unable to read NDEF message (tag empty or not well formated)");
+                                    /* Disconnect tag */
+                                    tag.doAsyncDisconnect();
+                                }
+                            } else {
+                                Log.d(TAG, "Tag is *not* NDEF compliant");
+                                /* Disconnect tag */
+                                tag.doAsyncDisconnect();
+                            }
+                        } else {
+                            /* Disconnect tag */
+                            tag.doAsyncDisconnect();
+                        }
+                        break;
+                    case MSG_CARD_EMULATION:
+                        Log.d(TAG, "Card Emulation message");
+                        byte[] aid = (byte[]) msg.obj;
+                        /* Send broadcast ordered */
+                        Intent TransactionIntent = new Intent();
+                        TransactionIntent.setAction(NfcManager.TRANSACTION_DETECTED_ACTION);
+                        TransactionIntent.putExtra(NfcManager.AID_EXTRA, aid);
+                        Log.d(TAG, "Broadcasting Card Emulation event");
+                        mContext.sendOrderedBroadcast(TransactionIntent,
+                                android.Manifest.permission.NFC_NOTIFY);
+                        break;
+
+                    case MSG_LLCP_LINK_ACTIVATION:
+                        NativeP2pDevice device = (NativeP2pDevice) msg.obj;
+
+                        Log.d(TAG, "LLCP Activation message");
+
+                        if (device.getMode() == NativeP2pDevice.MODE_P2P_TARGET) {
+                            if (device.doConnect()) {
+                                /* Check Llcp compliancy */
+                                if (doCheckLlcp()) {
+                                    /* Activate Llcp Link */
+                                    if (doActivateLlcp()) {
+                                        Log.d(TAG, "Initiator Activate LLCP OK");
+                                        /* Broadcast Intent Link LLCP activated */
+                                        Intent LlcpLinkIntent = new Intent();
+                                        LlcpLinkIntent
+                                                .setAction(INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION);
+                                        LlcpLinkIntent.putExtra(
+                                                INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA,
+                                                NfcManager.LLCP_LINK_STATE_ACTIVATED);
+                                        Log.d(TAG, "Broadcasting internal LLCP activation");
+                                        mContext.sendBroadcast(LlcpLinkIntent);
+                                    }
+
+                                } else {
+                                    device.doDisconnect();
+                                }
+
+                            }
+
+                        } else if (device.getMode() == NativeP2pDevice.MODE_P2P_INITIATOR) {
+                            /* Check Llcp compliancy */
+                            if (doCheckLlcp()) {
+                                /* Activate Llcp Link */
+                                if (doActivateLlcp()) {
+                                    Log.d(TAG, "Target Activate LLCP OK");
+                                    /* Broadcast Intent Link LLCP activated */
+                                    Intent LlcpLinkIntent = new Intent();
+                                    LlcpLinkIntent
+                                            .setAction(INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION);
+                                    LlcpLinkIntent.putExtra(INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA,
+                                            NfcManager.LLCP_LINK_STATE_ACTIVATED);
+                                    Log.d(TAG, "Broadcasting internal LLCP activation");
+                                    mContext.sendBroadcast(LlcpLinkIntent);
+                                }
+                            }
+                        }
+                        break;
+
+                    case MSG_LLCP_LINK_DEACTIVATED:
+                        /* Broadcast Intent Link LLCP activated */
+                        Log.d(TAG, "LLCP Link Deactivated message");
+                        Intent LlcpLinkIntent = new Intent();
+                        LlcpLinkIntent.setAction(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION);
+                        LlcpLinkIntent.putExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA,
+                                NfcManager.LLCP_LINK_STATE_DEACTIVATED);
+                        Log.d(TAG, "Broadcasting LLCP deactivation");
+                        mContext.sendOrderedBroadcast(LlcpLinkIntent,
+                                android.Manifest.permission.NFC_LLCP);
+                        break;
+
+                    case MSG_TARGET_DESELECTED:
+                        /* Broadcast Intent Target Deselected */
+                        Log.d(TAG, "Target Deselected");
+                        Intent TargetDeselectedIntent = new Intent();
+                        TargetDeselectedIntent.setAction(INTERNAL_TARGET_DESELECTED_ACTION);
+                        Log.d(TAG, "Broadcasting Intent");
+                        mContext.sendOrderedBroadcast(TargetDeselectedIntent,
+                                android.Manifest.permission.NFC_LLCP);
+                        break;
+
+                    default:
+                        Log.e(TAG, "Unknown message received");
+                        break;
+                }
+            } catch (Exception e) {
+                // Log, don't crash!
+                Log.e(TAG, "Exception in NfcHandler.handleMessage:", e);
+            }
+        }
+    };
+
+    /**
+     * Notifies Ndef Message
+     */
+    private void notifyNdefMessageListeners(NativeNfcTag tag) {
+        Message msg = mNfcHandler.obtainMessage();
+
+        msg.what = MSG_NDEF_TAG;
+        msg.obj = tag;
+
+        mNfcHandler.sendMessage(msg);
+    }
+
+    /**
+     * Notifies transaction
+     */
+    private void notifyTargetDeselected() {
+        Message msg = mNfcHandler.obtainMessage();
+
+        msg.what = MSG_TARGET_DESELECTED;
+
+        mNfcHandler.sendMessage(msg);
+    }
+
+    /**
+     * Notifies transaction
+     */
+    private void notifyTransactionListeners(byte[] aid) {
+        Message msg = mNfcHandler.obtainMessage();
+
+        msg.what = MSG_CARD_EMULATION;
+        msg.obj = aid;
+
+        mNfcHandler.sendMessage(msg);
+    }
+
+    /**
+     * Notifies P2P Device detected, to activate LLCP link
+     */
+    private void notifyLlcpLinkActivation(NativeP2pDevice device) {
+        Message msg = mNfcHandler.obtainMessage();
+
+        msg.what = MSG_LLCP_LINK_ACTIVATION;
+        msg.obj = device;
+
+        mNfcHandler.sendMessage(msg);
+    }
+
+    /**
+     * Notifies P2P Device detected, to activate LLCP link
+     */
+    private void notifyLlcpLinkDeactivated() {
+        Message msg = mNfcHandler.obtainMessage();
+
+        msg.what = MSG_LLCP_LINK_DEACTIVATED;
+
+        mNfcHandler.sendMessage(msg);
+    }
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java
new file mode 100644
index 0000000..b92783d
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeNfcTag.java
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeNfcTag.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+/**
+ * Native interface to the NFC tag functions
+ * 
+ * {@hide}
+ */
+public class NativeNfcTag {
+	private int mHandle;
+
+	private String mType;
+	
+	private byte[] mUid;
+
+	public native boolean doConnect();
+
+	public native boolean doDisconnect();
+	
+	public native void doAsyncDisconnect();
+
+	public native byte[] doTransceive(byte[] data);
+
+	public native boolean checkNDEF();
+	
+    public native byte[] doRead();
+
+    public native boolean doWrite(byte[] buf);
+
+	public int getHandle() {
+		return mHandle;
+	}
+	
+	public String getType() {
+		return mType;
+	}
+	
+	public byte[] getUid() {
+		return mUid;
+	}
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java b/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java
new file mode 100644
index 0000000..75d25ba
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/internal/NativeP2pDevice.java
@@ -0,0 +1,75 @@
+/*
+ * 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.
+ */
+
+/**
+ * File            : NativeP2pDevice.java
+ * Original-Author : Trusted Logic S.A. (Sylvain Fonteneau)
+ * Created         : 18-02-2010
+ */
+
+package com.trustedlogic.trustednfc.android.internal;
+
+/**
+ * Native interface to the P2P Initiator functions
+ * 
+ * {@hide}
+ */
+public class NativeP2pDevice {
+	
+	/**
+	* Peer-to-Peer Target.
+	*/
+	public static final short MODE_P2P_TARGET          = 0x00;
+
+	/**
+	* Peer-to-Peer Initiator.
+	*/
+	public static final short MODE_P2P_INITIATOR       = 0x01;
+
+	/**
+	* Invalid target type.
+	*/
+	public static final short MODE_INVALID			   = 0xff;
+
+	private int mHandle;
+
+	private int mMode;
+
+	private byte[] mGeneralBytes;
+
+	public native byte[] doReceive();
+
+	public native boolean doSend(byte[] data);
+
+	public native boolean doConnect();
+
+	public native boolean doDisconnect();
+
+	public native byte[] doTransceive(byte[] data);
+	
+	public int getHandle() {
+		return mHandle;
+	}
+
+	public int getMode() {
+		return mMode;
+	}
+
+	public byte[] getGeneralBytes() {
+		return mGeneralBytes;
+	}
+
+}
diff --git a/core/java/com/trustedlogic/trustednfc/android/package.html b/core/java/com/trustedlogic/trustednfc/android/package.html
new file mode 100644
index 0000000..0c0b605
--- /dev/null
+++ b/core/java/com/trustedlogic/trustednfc/android/package.html
@@ -0,0 +1,473 @@
+<html>
+<body>
+
+<p>Provides classes that manage the NFC functionality.</p>
+
+<p>The NFC functionality is related to Near Field Communication.</p>
+
+<p>The NFC APIs let applications:</p>
+<ul>
+  <li>Scan for remote NFC targets (NFC Tag or NFC Peer)</li>
+  <li>Transfer raw data to and from remote NFC targets (NFC Tags or NFC Peer)</li>
+  <li>Read/Write NDEF data from/to remote NFC targets (NFC Tags)</li>
+  <li>Establish LLCP connection with a remote NFC target (NFC Peer with LLCP support)</li>
+  <li>Exchange data with a remote NFC target through LLCP services (NFC Peer with LLCP support)</li>
+  <li>Be notified of transactions on the local Secure Element by an external NFC reader</li>
+</ul>
+
+
+<h1>Setting Up NFC</h1>
+
+<p>
+Before an application can use the NFC feature, it needs to check if NFC is
+supported on the device by getting an instance of the
+{@link com.trustedlogic.trustednfc.android.NfcManager} class.
+</p>
+
+<pre>
+	NfcManager mNfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+	if (mNfcManager == null) {
+		// Device does not support NFC
+	}
+</pre>
+
+<p>
+An application can ensure that NFC is enabled.
+If not, an application with the needed permission can request that NFC be
+enabled.
+</p>
+
+<pre>
+	if (!mNfcManager.isEnabled) {
+		// NFC is currently disabled.
+		// Enable NFC.
+		mNfcManager.enable();
+	}
+</pre>
+
+<p>
+Before using the card emulation mode, an application can ensure that a secure
+element is selected ({@link com.trustedlogic.trustednfc.android.NfcManager#getSelectedSecureElement}).
+If not, an application with the needed permission can recover the list of
+available secure elements on the device
+({@link com.trustedlogic.trustednfc.android.NfcManager#getSecureElementList}) and select one
+({@link com.trustedlogic.trustednfc.android.NfcManager#selectSecureElement}).
+</p>
+
+<p>
+Before using the NFC feature, an application can configure the NFC device by
+calling {@link com.trustedlogic.trustednfc.android.NfcManager#setProperties}. This function allows:
+</p>
+<ul>
+  <li>Enabling/disabling the NFC device capabilities (RF types, baudrates,
+  NFCIP-1 mode and role...)</li>
+  <li>Settings the NFCIP-1 general bytes and the LLCP link parameters</li>
+</ul>
+<p>
+The setting properties can be customized according to the Device capabilities.
+The next table give the minimal set of properties supported by the Device.
+Depending on the implementation, the table may be completed.
+</p>
+<table>
+  <TR><TH> Property Name </TH><TH> Property Values </TH></TR>
+  <TR><TD> discovery.felica    </TD><TD> <b>true</b>|false </TD></TR>
+  <TR><TD> discovery.iso14443A </TD><TD> <b>true</b>|false </TD></TR>
+  <TR><TD> discovery.iso14443B </TD><TD> <b>true</b>|false </TD></TR>
+  <TR><TD> discovery.iso15693  </TD><TD> <b>true</b>|false </TD></TR>
+  <TR><TD> discovery.nfcip     </TD><TD> <b>true</b>|false </TD></TR>
+  <TR><TD> nfcip.baudrate     </TD><TD> 106|212|424 </TD></TR>
+  <TR><TD> nfcip.generalbytes </TD><TD>  </TD></TR>
+  <TR><TD> nfcip.mode         </TD><TD> active|passive|<b>all</b> </TD></TR>
+  <TR><TD> nfcip.role         </TD><TD> initiator|target|<b>both</b> </TD></TR>
+  <TR><TD> llcp.lto </TD><TD> <b>150</b> (0 to 255) </TD></TR>
+  <TR><TD> llcp.opt </TD><TD>   <b>0</b> (0 to 3) </TD></TR>
+  <TR><TD> llcp.miu </TD><TD> <b>128</b> (128 to 2176) </TD></TR>
+  <TR><TD> llcp.wks </TD><TD>   <b>1</b> (0 to 15) </TD></TR>
+</table> 
+<p>(default values in bold)</p>
+
+
+<h1>NFC Permissions</h1>
+
+<p>
+To change the NFC service settings such as enabling the NFC targets
+discovery or activating the secure element, an application must declare the
+NFC_ADMIN permission.
+</p>
+<p>
+To perform NFC raw communication with a remote NFC target in
+Reader/Write Mode or Peer-to-Peer Mode, an application must declare the NFC_RAW
+permission.
+</p>
+<p>
+To receive NDEF message or Secure Element intents, an application must declare
+the NFC_NOTIFY permission.
+</p>
+<p>
+To receive the LLCP link intent and perform an LLCP communication with a remote NFC target, an application must
+declare the NFC_LLCP permission.
+</p>
+
+
+<h1>NFC Usage</h1>
+
+<p>
+The following code samples illustrate the APIs usage regarding the NFC service
+use cases.
+</p>
+
+<h2>Reader/Writer Mode NDEF message notification</h2>
+
+<p>
+This code sample illustrates the NDEF message notification through an Intent declared in the manifest and a receiver implemented in the application.
+</p>
+<p>Main involved classes/methods:</p>
+
+<p>Manifest Example:</p>
+<pre>
+	&lt;receiver android:name=".NfcReaderDemoReceiver">
+            &lt;intent-filter>
+               &lt;action android:name= "com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED"/>
+            &lt;/intent-filter>
+        &lt;/receiver>
+</pre>
+
+<p>Receiver Example:</p>
+<ul>
+  <li>{@link com.trustedlogic.trustednfc.android.NdefMessage}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_TAG_DISCOVERED_ACTION}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#NDEF_MESSAGE_EXTRA}</li>
+</ul>
+<pre>
+public class NdefMessageReceiverSample extends BroadcastReceiver {
+	public void onReceive(Context context, Intent intent) {
+		if (intent.getAction().equals(NfcManager.NDEF_TAG_DISCOVERERD_ACTION)) {
+			NdefMessage msg = intent.getParcelableExtra(NfcManager.NDEF_MESSAGE_EXTRA);
+		
+		/* Manage the NdefMessage received */
+	}
+</pre>
+
+<h2>Reader/Writer Mode raw exchange</h2>
+
+<p>
+This code sample illustrates raw exchanges with a NFC target in Reader/Writer
+mode.
+</p>
+<p>Main involved classes/methods:</p>
+<ul>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcTag}</li>
+</ul>
+
+<pre>
+public class TagReaderSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runTagReader() {
+		NfcTag tag = null;
+		String type;
+		byte[] cmd = { 0x01, 0x02, 0x03 };
+		byte[] res;
+
+		while (true) {
+			try {
+				Log.i("NFC example", "Please wave in front of the tag");
+				// Open a connection on next available tag
+				try {
+					tag = manager.openTagConnection();
+				} catch (NfcException e) {
+					// TODO: Handle open failure
+				}
+
+				// Look for a mifare 4k
+				type = tag.getType();
+				if (type.equals("Mifare4K")) {
+					Log.i("NFC example", "Tag detected");
+					tag.connect();
+					// Ready to communicate, we can send transceive !
+					res = tag.transceive(cmd);
+				} else {
+					Log.i("NFC example", "Unknown tag");
+				}
+			} catch (IOException e) {
+				// TODO: Handle broken connection
+			} finally {
+				if (tag != null) {
+					tag.close();
+				}
+			}
+		}
+	}
+}
+</pre>
+
+<h2>Peer-to-Peer Mode raw exchange</h2>
+
+<p>
+This code sample illustrates raw exchanges with a NFC target in Peer-to-Peer
+mode.
+</p>
+<p>Main involved classes/methods:</p>
+<ul>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.P2pDevice}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.P2pInitiator}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.P2pTarget}</li>
+</ul>
+
+<pre>
+public class P2pSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runP2p() {
+		P2pDevice deviceP2p;
+		P2pInitiator initiator;
+		P2pTarget target;
+		byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		byte[] echo = new byte[data.length * 10];
+
+		try {
+			deviceP2p = manager.openP2pConnection();
+
+			if (deviceP2p.getMode() == P2pDevice.MODE_P2P_INITIATOR) {
+				target = new P2pTarget(deviceP2p);
+				// Connect to the detected P2P target
+				target.connect();
+				// send data to the target
+				target.transceive(data);
+				// disconnect the connected target
+				target.disconnect();
+			} else if (deviceP2p.getMode() == P2pDevice.MODE_P2P_TARGET) {
+				initiator = new P2pInitiator(deviceP2p);
+				//target in receive state 
+				echo = initiator.receive();	
+				// send back the data received
+				initiator.send(echo);
+			}
+		} catch (IOException e0) {
+
+		} catch (NfcException e1) {
+
+		}
+	}
+}
+</pre>
+
+<h2>Peer-to-Peer Mode LLCP exchange</h2>
+
+<p>
+This code sample illustrates how to get LLCP link state notification with the declaration of a Receiver in the manifest of the application  and the implementation 
+of the receiver in the application.
+</p>
+<p>Manifest Example:</p>
+<pre>
+	&lt;receiver android:name=".LlcpModeReceiverSample">
+            &lt;intent-filter>
+		&lt;action android:name= "com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED"/>
+            &lt;/intent-filter>
+        &lt;/receiver>
+</pre>
+
+<p>Receiver Example:</p>
+<ul>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_ACTION}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#LLCP_LINK_STATE_CHANGED_EXTRA}</li> 
+</ul> 
+<pre>
+public class LlcpModeReceiverSample extends BroadcastReceiver {
+	public void onReceive(Context context, Intent intent) {
+
+		if (intent.getAction().equals(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION)){
+			byte[] aid = intent.getByteArrayExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA);
+			/* Create an LLCP service or client and start an LLCP communication */
+		} 
+	}
+</pre>
+
+
+<p>
+This code samples illustrate LLCP exchanges with a NFC Peer.
+</p>
+<p>Main involved classes/methods:</p>
+<ul>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpSocket}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpConnectionlessSocket}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpServiceSocket}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.LlcpSocket}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.LlcpConnectionlessSocket}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.LlcpPacket}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.LlcpServiceSocket}</li>
+</ul>
+
+<pre>
+public class LlcpServerSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runLlcpClient() {
+		LlcpSocket sock;
+		byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		byte[] echo = new byte[data.length * 10];
+		int length = 0;
+
+		sock = manager.createLlcpSocket((short) 128, (byte) 2, 1024);
+		
+		// set a timeout in ms for connect request
+		sock.setConnectTimeout(10);
+		
+		try {
+			// Connect to remote service
+			// NOTE: could be sock.connect("com.trusted-logic.tnfc.testapp");
+			sock.connect((byte) 0x10);
+
+			// Send data
+			for (int i = 0; i < 10; i++) {
+				sock.send(data);
+			}
+
+			// Receive echo
+			while (length < 10 * data.length) {
+				length += sock.receive(echo);
+			}
+
+		} catch (IOException e) {
+			// TODO: Handle broken connection broken (link down, remote closure
+			// or connect rejected) or Timeout expired
+		}
+	}
+}
+</pre>
+
+<pre>
+public class LlcpClientSample {
+
+	/** The NFC manager to access NFC features */
+	private NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
+
+	private void runLlcpClient() {
+		LlcpSocket sock;
+		byte[] data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+		byte[] echo = new byte[data.length * 10];
+		int length = 0;
+
+		sock = manager.createLlcpSocket((short) 128, (byte) 2, 1024);
+		try {
+			// Connect to remote service
+			// NOTE: could be sock.connect("com.trusted-logic.tnfc.testapp");
+			sock.connect((byte) 0x10);
+
+			// Send data
+			for (int i = 0; i < 10; i++) {
+				sock.send(data);
+			}
+
+			// Receive echo
+			while (length < 10 * data.length) {
+				length += sock.receive(echo);
+			}
+
+		} catch (IOException e) {
+			// TODO: Handle broken connection broken (link down, remote closure
+			// or connect rejected)
+		}
+	}
+}
+</pre>
+
+<h2>Card Emulation Mode transaction notification</h2>
+
+<p>
+This code sample illustrates how to get the card emulation notification with the declaration of a Receiver in the manifest of the application  and the implementation 
+of the receiver in the application.
+</p>
+<p>Manifest Example:</p>
+<pre>
+	&lt;receiver android:name=".NfcReaderDemoReceiver">
+            &lt;intent-filter>
+		&lt;action android:name= "com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED"/>
+            &lt;/intent-filter>
+        &lt;/receiver>
+</pre>
+
+<p>Receiver Example:</p>
+<ul>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#TRANSACTION_DETECTED_ACTION}</li>
+  <li>{@link com.trustedlogic.trustednfc.android.NfcManager#AID_EXTRA}</li> 
+</ul> 
+<pre>
+public class CardEmulationReceiverSample extends BroadcastReceiver {
+	public void onReceive(Context context, Intent intent) {
+
+		if (intent.getAction().equals(NfcManager.TRANSACTION_DETECTED_ACTION)){
+			byte[] aid = intent.getByteArrayExtra(NfcManager.AID_EXTRA);
+			/* Manage the AID: */
+			/* For example start an activity related to this AID value or display a popup with the AID */
+		} 
+	}
+</pre>
+
+
+
+<h1>Multiple Applications rules</h1>
+
+<p>
+Several LLCP sockets can be created by a single application or by multiple
+applications by calling {@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpSocket}, 
+{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpConnectionlessSocket} or 
+{@link com.trustedlogic.trustednfc.android.NfcManager#createLlcpServiceSocket}, provided the local SAP
+numbers are differents.
+</p>
+
+<p>
+Only one application can open a raw connection by calling 
+{@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection} or
+{@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}.
+While this application has not closed or cancelled its connection, any other
+application that attempts to open another raw connection will raise an
+exception.
+During an open connnection, the card emulation mode is always enabled and 
+applications are able to receive card emulation intents.
+</p>
+
+<p>
+When an application opens a tag connection by calling 
+{@link com.trustedlogic.trustednfc.android.NfcManager#openTagConnection}, this operation is exclusive, no NDEF message intent are
+broadcast while the connection is not closed or canceled.
+</p>
+
+<p>
+When an application opens a peer-to-peer connection by calling
+{@link com.trustedlogic.trustednfc.android.NfcManager#openP2pConnection}, this operation is exclusive, no LLCP intent are broadcast and LLCP sockets are
+disabled while the connection is not closed or canceled. 
+</p>
+
+
+<h1>NFC Tag types</h1>
+
+<p>
+The {@link com.trustedlogic.trustednfc.android.NfcTag} type returned by
+{@link com.trustedlogic.trustednfc.android.NfcTag#getType} indicates the set of
+commands supported by the tag. These commands can be used in
+{@link com.trustedlogic.trustednfc.android.NfcTag#transceive}.
+</p>
+
+<TABLE BORDER="1">
+  <TR><TH> Tag Type </TH><TH> Returned string </TH></TR>
+  <TR><TD> Jewel/Topaz </TD><TD> Jewel </TD></TR>
+  <TR><TD> Mifare UltraLight </TD><TD> MifareUL </TD></TR>
+  <TR><TD> Mifare Standard 1K </TD><TD> Mifare1K </TD></TR>
+  <TR><TD> Mifare Standard 4K </TD><TD> Mifare4K </TD></TR>
+  <TR><TD> Mifare DESFIRE </TD><TD> MifareDESFIRE </TD></TR>
+  <TR><TD> Felica </TD><TD> Felica </TD></TR>
+  <TR><TD> ISO14443-4 A or B </TD><TD> Iso14443 </TD></TR>
+  <TR><TD> ISO15693 </TD><TD> Iso15693 </TD></TR>
+</TABLE> 
+
+</body>
+</html>
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index fffd185..64a2331 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -202,6 +202,14 @@
 	LOCAL_SHARED_LIBRARIES += libhwui
 endif
 
+ifeq ($(BOARD_HAVE_NFC),true)
+LOCAL_SHARED_LIBRARIES += \
+	libnfc_jni \
+	libnfc
+
+LOCAL_CFLAGS += -DHAVE_NFC
+endif
+
 ifeq ($(BOARD_HAVE_BLUETOOTH),true)
 LOCAL_C_INCLUDES += \
 	external/dbus \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index ff62e0d..a4a1a70 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -170,6 +170,18 @@
 extern int register_android_content_res_ObbScanner(JNIEnv* env);
 extern int register_android_content_res_Configuration(JNIEnv* env);
 
+#ifdef HAVE_NFC
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeNfcManager(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeNfcTag(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeNdefTag(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_NdefMessage(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_NdefRecord(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeP2pDevice(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeLlcpSocket(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeLlcpConnectionlessSocket(JNIEnv *env);
+extern int register_com_trustedlogic_trustednfc_android_internal_NativeLlcpServiceSocket(JNIEnv *env);
+#endif
+
 static AndroidRuntime* gCurRuntime = NULL;
 
 static void doThrow(JNIEnv* env, const char* exc, const char* msg = NULL)
@@ -1287,6 +1299,18 @@
 
     REG_JNI(register_android_content_res_ObbScanner),
     REG_JNI(register_android_content_res_Configuration),
+
+#ifdef HAVE_NFC
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeNfcManager),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeNfcTag),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeNdefTag),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_NdefMessage),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_NdefRecord),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeP2pDevice),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeLlcpSocket),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeLlcpConnectionlessSocket),
+    REG_JNI(register_com_trustedlogic_trustednfc_android_internal_NativeLlcpServiceSocket),
+#endif
 };
 
 /*
diff --git a/core/jni/android_view_GLES20Canvas.cpp b/core/jni/android_view_GLES20Canvas.cpp
index bbf3509..cb1556b1 100644
--- a/core/jni/android_view_GLES20Canvas.cpp
+++ b/core/jni/android_view_GLES20Canvas.cpp
@@ -30,6 +30,7 @@
 #include <SkTemplates.h>
 #include <SkXfermode.h>
 
+#include <DisplayListRenderer.h>
 #include <OpenGLDebugRenderer.h>
 #include <OpenGLRenderer.h>
 #include <SkiaShader.h>
@@ -378,6 +379,30 @@
     env->ReleaseStringChars(text, textArray);
 }
 
+// ----------------------------------------------------------------------------
+// Display lists
+// ----------------------------------------------------------------------------
+
+static OpenGLRenderer* android_view_GLES20Canvas_createDisplayListRenderer(
+        JNIEnv* env, jobject canvas) {
+    return new DisplayListRenderer;
+}
+
+static DisplayList* android_view_GLES20Canvas_createDisplayList(JNIEnv* env,
+        jobject canvas, DisplayListRenderer* renderer) {
+    return renderer->getDisplayList();
+}
+
+static void android_view_GLES20Canvas_destroyDisplayList(JNIEnv* env,
+        jobject canvas, DisplayList* displayList) {
+    delete displayList;
+}
+
+static void android_view_GLES20Canvas_drawDisplayList(JNIEnv* env,
+        jobject canvas, OpenGLRenderer* renderer, DisplayList* displayList) {
+    displayList->replay(*renderer);
+}
+
 #endif // USE_OPENGL_RENDERER
 
 // ----------------------------------------------------------------------------
@@ -455,6 +480,12 @@
 
     { "nGetClipBounds",     "(ILandroid/graphics/Rect;)Z",
             (void*) android_view_GLES20Canvas_getClipBounds },
+
+    { "nCreateDisplayListRenderer", "()I",     (void*) android_view_GLES20Canvas_createDisplayListRenderer },
+    { "nCreateDisplayList",  "(I)I",           (void*) android_view_GLES20Canvas_createDisplayList },
+    { "nDestroyDisplayList", "(I)V",           (void*) android_view_GLES20Canvas_destroyDisplayList },
+    { "nDrawDisplayList",    "(II)V",          (void*) android_view_GLES20Canvas_drawDisplayList },
+
 #endif
 };
 
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index d5065f6..3a1d76f 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -88,6 +88,10 @@
     <protected-broadcast android:name="android.hardware.action.USB_CAMERA_ATTACHED" />
     <protected-broadcast android:name="android.hardware.action.USB_CAMERA_DETACHED" />
 
+    <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.NDEF_TAG_DISCOVERED" />
+    <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.TRANSACTION_DETECTED" />
+    <protected-broadcast android:name="com.trustedlogic.trustednfc.android.action.LLCP_LINK_STATE_CHANGED" />
+
     <!-- ====================================== -->
     <!-- Permissions for things that cost money -->
     <!-- ====================================== -->
@@ -338,6 +342,30 @@
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth" />
 
+    <!-- Allows applications to access remote NFC devices
+         @hide -->
+    <permission android:name="com.trustedlogic.trustednfc.permission.NFC_RAW"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_nfcRaw"
+        android:label="@string/permlab_nfcRaw" />
+
+    <!-- Allows applications to be notified of remote NFC devices
+         @hide -->
+    <permission android:name="com.trustedlogic.trustednfc.permission.NFC_NOTIFY"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_nfcNotify"
+        android:label="@string/permlab_nfcNotify" />
+
+    <!-- Allows applications to be notified of remote NFC LLCP devices
+         @hide -->
+    <permission android:name="com.trustedlogic.trustednfc.permission.NFC_LLCP"
+        android:permissionGroup="android.permission-group.NETWORK"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_nfcLlcp"
+        android:label="@string/permlab_nfcLlcp" />
+
     <!-- Allows applications to call into AccountAuthenticators. Only
     the system can get this permission. -->
     <permission android:name="android.permission.ACCOUNT_MANAGER"
@@ -848,6 +876,14 @@
         android:description="@string/permdesc_bluetoothAdmin"
         android:label="@string/permlab_bluetoothAdmin" />
 
+    <!-- Allows applications to change NFC connectivity settings 
+         @hide -->
+    <permission android:name="com.trustedlogic.trustednfc.permission.NFC_ADMIN"
+        android:permissionGroup="android.permission-group.SYSTEM_TOOLS"
+        android:protectionLevel="dangerous"
+        android:description="@string/permdesc_nfcAdmin"
+        android:label="@string/permlab_nfcAdmin" />
+
     <!-- Allows an application to clear the caches of all installed
          applications on the device.  -->
     <permission android:name="android.permission.CLEAR_APP_CACHE"
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 153dd29..7a9b59a 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -1157,6 +1157,30 @@
       connections with paired devices.</string>
 
     <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_nfcAdmin">NFC administration</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_nfcAdmin">Allows an application to configure
+      the local NFC phone.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_nfcRaw">NFC full access to remote device</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_nfcRaw">Allows an application to access
+      remote NFC devices.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_nfcNotify">NFC notification from remote device</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_nfcNotify">Allows an application to be notified
+      of operations related to remote NFC devices.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permlab_nfcLlcp">NFC notification from remote LLCP device</string>
+    <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
+    <string name="permdesc_nfcLlcp">Allows an application to be notified
+      of LLCP operations related to remote NFC devices.</string>
+
+    <!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permlab_disableKeyguard">disable keylock</string>
     <!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
     <string name="permdesc_disableKeyguard">Allows an application to disable
@@ -1611,7 +1635,7 @@
 
     <!-- Do not translate.  WebView User Agent string -->
     <string name="web_user_agent" translatable="false">Mozilla/5.0 (Linux; U; <xliff:g id="x">Android %s</xliff:g>)
-        AppleWebKit/534.8 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.8</string>
+        AppleWebKit/534.9 (KHTML, like Gecko) Version/4.0 <xliff:g id="mobile">%s</xliff:g>Safari/534.9</string>
     <!-- Do not translate.  WebView User Agent targeted content -->
     <string name="web_user_agent_target_content" translatable="false">"Mobile "</string>
 
diff --git a/libs/hwui/DisplayListRenderer.cpp b/libs/hwui/DisplayListRenderer.cpp
index 16b6b56..ee90702 100644
--- a/libs/hwui/DisplayListRenderer.cpp
+++ b/libs/hwui/DisplayListRenderer.cpp
@@ -22,6 +22,229 @@
 namespace uirenderer {
 
 ///////////////////////////////////////////////////////////////////////////////
+// Display list
+///////////////////////////////////////////////////////////////////////////////
+
+DisplayList::DisplayList(const DisplayListRenderer& recorder) {
+    const SkWriter32& writer = recorder.writeStream();
+    init();
+
+    if (writer.size() == 0) {
+        return;
+    }
+
+    size_t size = writer.size();
+    void* buffer = sk_malloc_throw(size);
+    writer.flatten(buffer);
+    mReader.setMemory(buffer, size);
+
+    mRCPlayback.reset(&recorder.mRCRecorder);
+    mRCPlayback.setupBuffer(mReader);
+
+    mTFPlayback.reset(&recorder.mTFRecorder);
+    mTFPlayback.setupBuffer(mReader);
+
+    const SkTDArray<const SkFlatBitmap*>& bitmaps = recorder.getBitmaps();
+    mBitmapCount = bitmaps.count();
+    if (mBitmapCount > 0) {
+        mBitmaps = new SkBitmap[mBitmapCount];
+        for (const SkFlatBitmap** flatBitmapPtr = bitmaps.begin();
+                flatBitmapPtr != bitmaps.end(); flatBitmapPtr++) {
+            const SkFlatBitmap* flatBitmap = *flatBitmapPtr;
+            int index = flatBitmap->index() - 1;
+            flatBitmap->unflatten(&mBitmaps[index], &mRCPlayback);
+        }
+    }
+
+    const SkTDArray<const SkFlatMatrix*>& matrices = recorder.getMatrices();
+    mMatrixCount = matrices.count();
+    if (mMatrixCount > 0) {
+        mMatrices = new SkMatrix[mMatrixCount];
+        for (const SkFlatMatrix** matrixPtr = matrices.begin();
+                matrixPtr != matrices.end(); matrixPtr++) {
+            const SkFlatMatrix* flatMatrix = *matrixPtr;
+            flatMatrix->unflatten(&mMatrices[flatMatrix->index() - 1]);
+        }
+    }
+
+    const SkTDArray<const SkFlatPaint*>& paints = recorder.getPaints();
+    mPaintCount = paints.count();
+    if (mPaintCount > 0) {
+        mPaints = new SkPaint[mPaintCount];
+        for (const SkFlatPaint** flatPaintPtr = paints.begin();
+                flatPaintPtr != paints.end(); flatPaintPtr++) {
+            const SkFlatPaint* flatPaint = *flatPaintPtr;
+            int index = flatPaint->index() - 1;
+            flatPaint->unflatten(&mPaints[index], &mRCPlayback, &mTFPlayback);
+        }
+    }
+
+    mPathHeap = recorder.mPathHeap;
+    mPathHeap->safeRef();
+}
+
+DisplayList::~DisplayList() {
+    sk_free((void*) mReader.base());
+
+    Caches& caches = Caches::getInstance();
+    for (int i = 0; i < mBitmapCount; i++) {
+        caches.textureCache.remove(&mBitmaps[i]);
+    }
+
+    delete[] mBitmaps;
+    delete[] mMatrices;
+    delete[] mPaints;
+
+    mPathHeap->safeUnref();
+}
+
+void DisplayList::init() {
+    mBitmaps = NULL;
+    mMatrices = NULL;
+    mPaints = NULL;
+    mPathHeap = NULL;
+    mBitmapCount = mMatrixCount = mPaintCount = 0;
+}
+
+void DisplayList::replay(OpenGLRenderer& renderer) {
+    TextContainer text;
+    mReader.rewind();
+
+    int saveCount = renderer.getSaveCount() - 1;
+
+    while (!mReader.eof()) {
+        switch (mReader.readInt()) {
+            case AcquireContext: {
+                renderer.acquireContext();
+            }
+            break;
+            case ReleaseContext: {
+                renderer.releaseContext();
+            }
+            break;
+            case Save: {
+                renderer.save(getInt());
+            }
+            break;
+            case Restore: {
+                renderer.restore();
+            }
+            break;
+            case RestoreToCount: {
+                renderer.restoreToCount(saveCount + getInt());
+            }
+            break;
+            case SaveLayer: {
+                renderer.saveLayer(getFloat(), getFloat(), getFloat(), getFloat(),
+                        getPaint(), getInt());
+            }
+            break;
+            case Translate: {
+                renderer.translate(getFloat(), getFloat());
+            }
+            break;
+            case Rotate: {
+                renderer.rotate(getFloat());
+            }
+            break;
+            case Scale: {
+                renderer.scale(getFloat(), getFloat());
+            }
+            break;
+            case SetMatrix: {
+                renderer.setMatrix(getMatrix());
+            }
+            break;
+            case ConcatMatrix: {
+                renderer.concatMatrix(getMatrix());
+            }
+            break;
+            case ClipRect: {
+                renderer.clipRect(getFloat(), getFloat(), getFloat(), getFloat(),
+                        (SkRegion::Op) getInt());
+            }
+            break;
+            case DrawBitmap: {
+                renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawBitmapMatrix: {
+                renderer.drawBitmap(getBitmap(), getMatrix(), getPaint());
+            }
+            break;
+            case DrawBitmapRect: {
+                renderer.drawBitmap(getBitmap(), getFloat(), getFloat(), getFloat(), getFloat(),
+                        getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawPatch: {
+                int32_t* xDivs = NULL;
+                int32_t* yDivs = NULL;
+                uint32_t xDivsCount = 0;
+                uint32_t yDivsCount = 0;
+
+                SkBitmap* bitmap = getBitmap();
+
+                xDivs = getInts(xDivsCount);
+                yDivs = getInts(yDivsCount);
+
+                renderer.drawPatch(bitmap, xDivs, yDivs, xDivsCount, yDivsCount,
+                        getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawColor: {
+                renderer.drawColor(getInt(), (SkXfermode::Mode) getInt());
+            }
+            break;
+            case DrawRect: {
+                renderer.drawRect(getFloat(), getFloat(), getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case DrawPath: {
+                renderer.drawPath(getPath(), getPaint());
+            }
+            break;
+            case DrawLines: {
+                int count = 0;
+                float* points = getFloats(count);
+                renderer.drawLines(points, count, getPaint());
+            }
+            break;
+            case DrawText: {
+                getText(&text);
+                renderer.drawText(text.text(), text.length(), getInt(),
+                        getFloat(), getFloat(), getPaint());
+            }
+            break;
+            case ResetShader: {
+                renderer.resetShader();
+            }
+            break;
+            case SetupShader: {
+                // TODO: Implement
+            }
+            break;
+            case ResetColorFilter: {
+                renderer.resetColorFilter();
+            }
+            break;
+            case SetupColorFilter: {
+                // TODO: Implement
+            }
+            break;
+            case ResetShadow: {
+                renderer.resetShadow();
+            }
+            break;
+            case SetupShadow: {
+                renderer.setupShadow(getFloat(), getFloat(), getFloat(), getInt());
+            }
+            break;
+        }
+    }
+}
+
+///////////////////////////////////////////////////////////////////////////////
 // Base structure
 ///////////////////////////////////////////////////////////////////////////////
 
@@ -56,75 +279,89 @@
 // Operations
 ///////////////////////////////////////////////////////////////////////////////
 
+void DisplayListRenderer::setViewport(int width, int height) {
+    mOrthoMatrix.loadOrtho(0, width, height, 0, -1, 1);
+
+    mWidth = width;
+    mHeight = height;
+}
+
+void DisplayListRenderer::prepare() {
+    mSnapshot = new Snapshot(mFirstSnapshot,
+            SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+    mSaveCount = 1;
+    mSnapshot->setClip(0.0f, 0.0f, mWidth, mHeight);
+}
+
 void DisplayListRenderer::acquireContext() {
-    addOp(AcquireContext);
+    addOp(DisplayList::AcquireContext);
     OpenGLRenderer::acquireContext();
 }
 
 void DisplayListRenderer::releaseContext() {
-    addOp(ReleaseContext);
+    addOp(DisplayList::ReleaseContext);
     OpenGLRenderer::releaseContext();
 }
 
 int DisplayListRenderer::save(int flags) {
-    addOp(Save);
+    addOp(DisplayList::Save);
     addInt(flags);
     return OpenGLRenderer::save(flags);
 }
 
 void DisplayListRenderer::restore() {
-    addOp(Restore);
+    addOp(DisplayList::Restore);
     OpenGLRenderer::restore();
 }
 
 void DisplayListRenderer::restoreToCount(int saveCount) {
-    addOp(RestoreToCount);
+    addOp(DisplayList::RestoreToCount);
     addInt(saveCount);
     OpenGLRenderer::restoreToCount(saveCount);
 }
 
 int DisplayListRenderer::saveLayer(float left, float top, float right, float bottom,
         const SkPaint* p, int flags) {
-    addOp(SaveLayer);
+    addOp(DisplayList::SaveLayer);
     addBounds(left, top, right, bottom);
     addPaint(p);
     addInt(flags);
-    return OpenGLRenderer::saveLayer(left, top, right, bottom, p, flags);
+    return OpenGLRenderer::save(flags);
 }
 
 void DisplayListRenderer::translate(float dx, float dy) {
-    addOp(Translate);
+    addOp(DisplayList::Translate);
     addPoint(dx, dy);
     OpenGLRenderer::translate(dx, dy);
 }
 
 void DisplayListRenderer::rotate(float degrees) {
-    addOp(Rotate);
+    addOp(DisplayList::Rotate);
     addFloat(degrees);
     OpenGLRenderer::rotate(degrees);
 }
 
 void DisplayListRenderer::scale(float sx, float sy) {
-    addOp(Scale);
+    addOp(DisplayList::Scale);
     addPoint(sx, sy);
     OpenGLRenderer::scale(sx, sy);
 }
 
 void DisplayListRenderer::setMatrix(SkMatrix* matrix) {
-    addOp(SetMatrix);
+    addOp(DisplayList::SetMatrix);
     addMatrix(matrix);
     OpenGLRenderer::setMatrix(matrix);
 }
 
 void DisplayListRenderer::concatMatrix(SkMatrix* matrix) {
-    addOp(ConcatMatrix);
+    addOp(DisplayList::ConcatMatrix);
     addMatrix(matrix);
     OpenGLRenderer::concatMatrix(matrix);
 }
 
 bool DisplayListRenderer::clipRect(float left, float top, float right, float bottom,
         SkRegion::Op op) {
-    addOp(ClipRect);
+    addOp(DisplayList::ClipRect);
     addBounds(left, top, right, bottom);
     addInt(op);
     return OpenGLRenderer::clipRect(left, top, right, bottom, op);
@@ -132,88 +369,77 @@
 
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float left, float top,
         const SkPaint* paint) {
-    addOp(DrawBitmap);
+    addOp(DisplayList::DrawBitmap);
     addBitmap(bitmap);
     addPoint(left, top);
     addPaint(paint);
-    OpenGLRenderer::drawBitmap(bitmap, left, top, paint);
 }
 
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, const SkMatrix* matrix,
         const SkPaint* paint) {
-    addOp(DrawBitmapMatrix);
+    addOp(DisplayList::DrawBitmapMatrix);
     addBitmap(bitmap);
     addMatrix(matrix);
     addPaint(paint);
-    OpenGLRenderer::drawBitmap(bitmap, matrix, paint);
 }
 
 void DisplayListRenderer::drawBitmap(SkBitmap* bitmap, float srcLeft, float srcTop,
         float srcRight, float srcBottom, float dstLeft, float dstTop,
         float dstRight, float dstBottom, const SkPaint* paint) {
-    addOp(DrawBitmapRect);
+    addOp(DisplayList::DrawBitmapRect);
     addBitmap(bitmap);
     addBounds(srcLeft, srcTop, srcRight, srcBottom);
     addBounds(dstLeft, dstTop, dstRight, dstBottom);
     addPaint(paint);
-    OpenGLRenderer::drawBitmap(bitmap, srcLeft, srcTop, srcRight, srcBottom,
-            dstLeft, dstTop, dstRight, dstBottom, paint);
 }
 
 void DisplayListRenderer::drawPatch(SkBitmap* bitmap, const int32_t* xDivs, const int32_t* yDivs,
         uint32_t width, uint32_t height, float left, float top, float right, float bottom,
         const SkPaint* paint) {
-    addOp(DrawPatch);
+    addOp(DisplayList::DrawPatch);
     addBitmap(bitmap);
     addInts(xDivs, width);
     addInts(yDivs, height);
     addBounds(left, top, right, bottom);
     addPaint(paint);
-    OpenGLRenderer::drawPatch(bitmap, xDivs, yDivs, width, height,
-            left, top, right, bottom, paint);
 }
 
 void DisplayListRenderer::drawColor(int color, SkXfermode::Mode mode) {
-    addOp(DrawColor);
+    addOp(DisplayList::DrawColor);
     addInt(color);
     addInt(mode);
-    OpenGLRenderer::drawColor(color, mode);
 }
 
 void DisplayListRenderer::drawRect(float left, float top, float right, float bottom,
         const SkPaint* paint) {
-    addOp(DrawRect);
+    addOp(DisplayList::DrawRect);
     addBounds(left, top, right, bottom);
     addPaint(paint);
-    OpenGLRenderer::drawRect(left, top, right, bottom, paint);
 }
 
 void DisplayListRenderer::drawPath(SkPath* path, SkPaint* paint) {
-    addOp(DrawPath);
+    addOp(DisplayList::DrawPath);
     addPath(path);
     addPaint(paint);
-    OpenGLRenderer::drawPath(path, paint);
 }
 
 void DisplayListRenderer::drawLines(float* points, int count, const SkPaint* paint) {
-    addOp(DrawLines);
+    addOp(DisplayList::DrawLines);
     addFloats(points, count);
     addPaint(paint);
-    OpenGLRenderer::drawLines(points, count, paint);
 }
 
 void DisplayListRenderer::drawText(const char* text, int bytesCount, int count,
         float x, float y, SkPaint* paint) {
-    addOp(DrawText);
+    addOp(DisplayList::DrawText);
     addText(text, bytesCount);
     addInt(count);
     addPoint(x, y);
     addPaint(paint);
-    OpenGLRenderer::drawText(text, bytesCount, count, x, y, paint);
 }
 
 void DisplayListRenderer::resetShader() {
-    addOp(ResetShader);
+    addOp(DisplayList::ResetShader);
     OpenGLRenderer::resetShader();
 }
 
@@ -223,7 +449,7 @@
 }
 
 void DisplayListRenderer::resetColorFilter() {
-    addOp(ResetColorFilter);
+    addOp(DisplayList::ResetColorFilter);
     OpenGLRenderer::resetColorFilter();
 }
 
@@ -233,12 +459,12 @@
 }
 
 void DisplayListRenderer::resetShadow() {
-    addOp(ResetShadow);
+    addOp(DisplayList::ResetShadow);
     OpenGLRenderer::resetShadow();
 }
 
 void DisplayListRenderer::setupShadow(float radius, float dx, float dy, int color) {
-    addOp(SetupShadow);
+    addOp(DisplayList::SetupShadow);
     addFloat(radius);
     addPoint(dx, dy);
     addInt(color);
diff --git a/libs/hwui/DisplayListRenderer.h b/libs/hwui/DisplayListRenderer.h
index 7a20b59..735f0e7 100644
--- a/libs/hwui/DisplayListRenderer.h
+++ b/libs/hwui/DisplayListRenderer.h
@@ -81,7 +81,7 @@
 
     int count() const { return mPaths.count(); }
 
-    const SkPath& operator[](int index) const {
+    SkPath& operator[](int index) const {
         return *mPaths[index];
     }
 
@@ -103,16 +103,18 @@
 };
 
 ///////////////////////////////////////////////////////////////////////////////
-// Renderer
+// Display list
 ///////////////////////////////////////////////////////////////////////////////
 
+class DisplayListRenderer;
+
 /**
- * Records drawing commands in a display list for latter playback.
+ * Replays recorded drawing commands.
  */
-class DisplayListRenderer: public OpenGLRenderer {
+class DisplayList {
 public:
-    DisplayListRenderer();
-    ~DisplayListRenderer();
+    DisplayList(const DisplayListRenderer& recorder);
+    ~DisplayList();
 
     enum Op {
         AcquireContext,
@@ -121,7 +123,6 @@
         Restore,
         RestoreToCount,
         SaveLayer,
-        SaveLayerAlpha,
         Translate,
         Rotate,
         Scale,
@@ -145,6 +146,109 @@
         SetupShadow
     };
 
+    void replay(OpenGLRenderer& renderer);
+
+private:
+    void init();
+
+    class TextContainer {
+    public:
+        size_t length() const {
+            return mByteLength;
+        }
+
+        const char* text() const {
+            return (const char*) mText;
+        }
+
+        size_t mByteLength;
+        const char* mText;
+    };
+
+    SkBitmap* getBitmap() {
+        int index = getInt();
+        return &mBitmaps[index - 1];
+    }
+
+    inline int getIndex() {
+        return mReader.readInt();
+    }
+
+    inline int getInt() {
+        return mReader.readInt();
+    }
+
+    SkMatrix* getMatrix() {
+        int index = getInt();
+        if (index == 0) {
+            return NULL;
+        }
+        return &mMatrices[index - 1];
+    }
+
+    SkPath* getPath() {
+        return &(*mPathHeap)[getInt() - 1];
+    }
+
+    SkPaint* getPaint() {
+        int index = getInt();
+        if (index == 0) {
+            return NULL;
+        }
+        return &mPaints[index - 1];
+    }
+
+    inline float getFloat() {
+        return mReader.readScalar();
+    }
+
+    int32_t* getInts(uint32_t& count) {
+        count = getInt();
+        return (int32_t*) mReader.skip(count * sizeof(int32_t));
+    }
+
+    float* getFloats(int& count) {
+        count = getInt();
+        return (float*) mReader.skip(count * sizeof(float));
+    }
+
+    void getText(TextContainer* text) {
+        size_t length = text->mByteLength = getInt();
+        text->mText = (const char*) mReader.skip(length);
+    }
+
+    PathHeap* mPathHeap;
+
+    SkBitmap* mBitmaps;
+    int mBitmapCount;
+
+    SkMatrix* mMatrices;
+    int mMatrixCount;
+
+    SkPaint* mPaints;
+    int mPaintCount;
+
+    mutable SkFlattenableReadBuffer mReader;
+
+    SkRefCntPlayback mRCPlayback;
+    SkTypefacePlayback mTFPlayback;
+};
+
+///////////////////////////////////////////////////////////////////////////////
+// Renderer
+///////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Records drawing commands in a display list for latter playback.
+ */
+class DisplayListRenderer: public OpenGLRenderer {
+public:
+    DisplayListRenderer();
+    ~DisplayListRenderer();
+
+    void setViewport(int width, int height);
+    void prepare();
+
     void acquireContext();
     void releaseContext();
 
@@ -189,8 +293,28 @@
 
     void reset();
 
+    DisplayList* getDisplayList() const {
+        return new DisplayList(*this);
+    }
+
+    const SkWriter32& writeStream() const {
+        return mWriter;
+    }
+
+    const SkTDArray<const SkFlatBitmap*>& getBitmaps() const {
+        return mBitmaps;
+    }
+
+    const SkTDArray<const SkFlatMatrix*>& getMatrices() const {
+        return mMatrices;
+    }
+
+    const SkTDArray<const SkFlatPaint*>& getPaints() const {
+        return mPaints;
+    }
+
 private:
-    inline void addOp(Op drawOp) {
+    inline void addOp(DisplayList::Op drawOp) {
         mWriter.writeInt(drawOp);
     }
 
@@ -199,6 +323,7 @@
     }
 
     void addInts(const int32_t* values, uint32_t count) {
+        mWriter.writeInt(count);
         for (uint32_t i = 0; i < count; i++) {
             mWriter.writeInt(values[i]);
         }
@@ -209,6 +334,7 @@
     }
 
     void addFloats(const float* values, int count) {
+        mWriter.writeInt(count);
         for (int i = 0; i < count; i++) {
             mWriter.writeScalar(values[i]);
         }
@@ -273,6 +399,8 @@
     SkRefCntRecorder mRCRecorder;
     SkRefCntRecorder mTFRecorder;
 
+    friend class DisplayList;
+
 }; // class DisplayListRenderer
 
 }; // namespace uirenderer
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index d505d80..1974cf0 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -54,6 +54,8 @@
 // Renderer
 ///////////////////////////////////////////////////////////////////////////////
 
+class DisplayListRenderer;
+
 /**
  * OpenGL renderer used to draw accelerated 2D graphics. The API is a
  * simplified version of Skia's Canvas API.
@@ -63,7 +65,7 @@
     OpenGLRenderer();
     virtual ~OpenGLRenderer();
 
-    void setViewport(int width, int height);
+    virtual void setViewport(int width, int height);
 
     virtual void prepare();
     virtual void finish();
@@ -428,6 +430,8 @@
     // Misc
     GLint mMaxTextureSize;
 
+    friend class DisplayListRenderer;
+
 }; // class OpenGLRenderer
 
 }; // namespace uirenderer
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index 7db6710..717f63c 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -19,6 +19,7 @@
 import com.android.server.am.ActivityManagerService;
 import com.android.internal.os.BinderInternal;
 import com.android.internal.os.SamplingProfilerIntegration;
+import com.trustedlogic.trustednfc.android.server.NfcService;
 
 import dalvik.system.VMRuntime;
 import dalvik.system.Zygote;
@@ -44,6 +45,7 @@
 import android.server.BluetoothService;
 import android.server.search.SearchManagerService;
 import android.util.EventLog;
+import android.util.Log;
 import android.util.Slog;
 
 import java.io.File;
@@ -413,6 +415,20 @@
             } catch (Throwable e) {
                 Slog.e(TAG, "Failure starting Recognition Service", e);
             }
+            
+            try {
+                Slog.i(TAG, "Nfc Service");
+                NfcService nfc;
+                try {
+                    nfc = new NfcService(context);
+                } catch (UnsatisfiedLinkError e) { // gross hack to detect NFC
+                    nfc = null;
+                    Slog.w(TAG, "No NFC support");
+                }
+                ServiceManager.addService(Context.NFC_SERVICE, nfc);
+            } catch (Throwable e) {
+                Slog.e(TAG, "Failure starting NFC Service", e);
+            }
 
             try {
                 Slog.i(TAG, "DiskStats Service");
diff --git a/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java b/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java
new file mode 100644
index 0000000..431b798
--- /dev/null
+++ b/services/java/com/trustedlogic/trustednfc/android/server/NfcService.java
@@ -0,0 +1,2111 @@
+/*
+ * 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 com.trustedlogic.trustednfc.android.server;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.ListIterator;
+import java.util.Set;
+
+import com.trustedlogic.trustednfc.android.ILlcpConnectionlessSocket;
+import com.trustedlogic.trustednfc.android.ILlcpServiceSocket;
+import com.trustedlogic.trustednfc.android.INfcManager;
+import com.trustedlogic.trustednfc.android.ILlcpSocket;
+import com.trustedlogic.trustednfc.android.INfcTag;
+import com.trustedlogic.trustednfc.android.IP2pInitiator;
+import com.trustedlogic.trustednfc.android.IP2pTarget;
+import com.trustedlogic.trustednfc.android.LlcpPacket;
+import com.trustedlogic.trustednfc.android.NdefMessage;
+import com.trustedlogic.trustednfc.android.NfcException;
+import com.trustedlogic.trustednfc.android.NfcManager;
+import com.trustedlogic.trustednfc.android.internal.NativeLlcpConnectionlessSocket;
+import com.trustedlogic.trustednfc.android.internal.NativeLlcpServiceSocket;
+import com.trustedlogic.trustednfc.android.internal.NativeLlcpSocket;
+import com.trustedlogic.trustednfc.android.internal.NativeNfcManager;
+import com.trustedlogic.trustednfc.android.internal.NativeNfcTag;
+import com.trustedlogic.trustednfc.android.internal.NativeP2pDevice;
+import com.trustedlogic.trustednfc.android.internal.ErrorCodes;
+
+import android.os.Handler;
+import android.os.Looper;
+import android.os.Message;
+import android.os.Process;
+import android.os.RemoteException;
+import android.provider.Settings;
+import android.provider.Settings.SettingNotFoundException;
+import android.util.Log;
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+
+public class NfcService extends INfcManager.Stub implements Runnable {
+
+    /**
+     * NFC Service tag
+     */
+    private static final String TAG = "NfcService";
+
+    /**
+     * NFC features disabled state
+     */
+    private static final short NFC_STATE_DISABLED = 0x00;
+
+    /**
+     * NFC features enabled state
+     */
+    private static final short NFC_STATE_ENABLED = 0x01;
+
+    /**
+     * NFC Discovery for Reader mode
+     */
+    private static final int DISCOVERY_MODE_READER = 0;
+
+    /**
+     * NFC Discovery for Card Emulation Mode
+     */
+    private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
+
+    /**
+     * LLCP Service Socket type
+     */
+    private static final int LLCP_SERVICE_SOCKET_TYPE = 0;
+
+    /**
+     * LLCP Socket type
+     */
+    private static final int LLCP_SOCKET_TYPE = 1;
+
+    /**
+     * LLCP Connectionless socket type
+     */
+    private static final int LLCP_CONNECTIONLESS_SOCKET_TYPE = 2;
+
+    /**
+     * Maximun number of sockets managed
+     */
+    private static final int LLCP_SOCKET_NB_MAX = 5;
+
+    /**
+     * Default value for the Maximum Information Unit parameter
+     */
+    private static final int LLCP_LTO_DEFAULT_VALUE = 150;
+
+    /**
+     * Default value for the Maximum Information Unit parameter
+     */
+    private static final int LLCP_LTO_MAX_VALUE = 255;
+
+    /**
+     * Maximun value for the Receive Window
+     */
+    private static final int LLCP_RW_MAX_VALUE = 15;
+
+    /**
+     * Default value for the Maximum Information Unit parameter
+     */
+    private static final int LLCP_MIU_DEFAULT_VALUE = 128;
+
+    /**
+     * Default value for the Maximum Information Unit parameter
+     */
+    private static final int LLCP_MIU_MAX_VALUE = 2176;
+
+    /**
+     * Default value for the Well Known Service List parameter
+     */
+    private static final int LLCP_WKS_DEFAULT_VALUE = 1;
+
+    /**
+     * Max value for the Well Known Service List parameter
+     */
+    private static final int LLCP_WKS_MAX_VALUE = 15;
+
+    /**
+     * Default value for the Option parameter
+     */
+    private static final int LLCP_OPT_DEFAULT_VALUE = 0;
+
+    /**
+     * Max value for the Option parameter
+     */
+    private static final int LLCP_OPT_MAX_VALUE = 3;
+
+    /**
+     * LLCP Properties
+     */
+    private static final int PROPERTY_LLCP_LTO = 0;
+
+    private static final int PROPERTY_LLCP_MIU = 1;
+
+    private static final int PROPERTY_LLCP_WKS = 2;
+
+    private static final int PROPERTY_LLCP_OPT = 3;
+
+    private static final String PROPERTY_LLCP_LTO_VALUE = "llcp.lto";
+
+    private static final String PROPERTY_LLCP_MIU_VALUE = "llcp.miu";
+
+    private static final String PROPERTY_LLCP_WKS_VALUE = "llcp.wks";
+
+    private static final String PROPERTY_LLCP_OPT_VALUE = "llcp.opt";
+
+    /**
+     * NFC Reader Properties
+     */
+    private static final int PROPERTY_NFC_DISCOVERY_A = 4;
+
+    private static final int PROPERTY_NFC_DISCOVERY_B = 5;
+
+    private static final int PROPERTY_NFC_DISCOVERY_F = 6;
+
+    private static final int PROPERTY_NFC_DISCOVERY_15693 = 7;
+
+    private static final int PROPERTY_NFC_DISCOVERY_NFCIP = 8;
+
+    private static final String PROPERTY_NFC_DISCOVERY_A_VALUE = "discovery.iso14443A";
+
+    private static final String PROPERTY_NFC_DISCOVERY_B_VALUE = "discovery.iso14443B";
+
+    private static final String PROPERTY_NFC_DISCOVERY_F_VALUE = "discovery.felica";
+
+    private static final String PROPERTY_NFC_DISCOVERY_15693_VALUE = "discovery.iso15693";
+
+    private static final String PROPERTY_NFC_DISCOVERY_NFCIP_VALUE = "discovery.nfcip";
+
+    private Context mContext;
+
+    private HashMap<Integer, Object> mObjectMap = new HashMap<Integer, Object>();
+
+    private HashMap<Integer, Object> mSocketMap = new HashMap<Integer, Object>();
+
+    private LinkedList<RegisteredSocket> mRegisteredSocketList = new LinkedList<RegisteredSocket>();
+
+    private int mLlcpLinkState = NfcManager.LLCP_LINK_STATE_DEACTIVATED;
+
+    private int mGeneratedSocketHandle = 0;
+
+    private int mNbSocketCreated = 0;
+
+    private boolean mIsNfcEnabled = false;
+
+    private NfcHandler mNfcHandler;
+
+    private int mSelectedSeId = 0;
+
+    private int mTimeout = 0;
+
+    private int mNfcState;
+
+    private int mNfcSecureElementState;
+
+    private boolean mOpenPending = false;
+
+    private NativeNfcManager mManager;
+
+    private ILlcpSocket mLlcpSocket = new ILlcpSocket.Stub() {
+
+        public int close(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                    isSuccess = socket.doClose();
+                    if (isSuccess) {
+                        /* Remove the socket closed from the hmap */
+                        RemoveSocket(nativeHandle);
+                        /* Update mNbSocketCreated */
+                        mNbSocketCreated--;
+                        return ErrorCodes.SUCCESS;
+                    } else {
+                        return ErrorCodes.ERROR_IO;
+                    }
+                } else {
+                    /* Remove the socket closed from the hmap */
+                    RemoveSocket(nativeHandle);
+
+                    /* Remove registered socket from the list */
+                    RemoveRegisteredSocket(nativeHandle);
+
+                    /* Update mNbSocketCreated */
+                    mNbSocketCreated--;
+
+                    return ErrorCodes.SUCCESS;
+                }
+            } else {
+                return ErrorCodes.ERROR_IO;
+            }
+        }
+
+        public int connect(int nativeHandle, int sap) throws RemoteException {
+            NativeLlcpSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                isSuccess = socket.doConnect(sap, socket.getConnectTimeout());
+                if (isSuccess) {
+                    return ErrorCodes.SUCCESS;
+                } else {
+                    return ErrorCodes.ERROR_IO;
+                }
+            } else {
+                return ErrorCodes.ERROR_IO;
+            }
+
+        }
+
+        public int connectByName(int nativeHandle, String sn) throws RemoteException {
+            NativeLlcpSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                isSuccess = socket.doConnectBy(sn, socket.getConnectTimeout());
+                if (isSuccess) {
+                    return ErrorCodes.SUCCESS;
+                } else {
+                    return ErrorCodes.ERROR_IO;
+                }
+            } else {
+                return ErrorCodes.ERROR_IO;
+            }
+
+        }
+
+        public int getConnectTimeout(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                return socket.getConnectTimeout();
+            } else {
+                return 0;
+            }
+        }
+
+        public int getLocalSap(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                return socket.getSap();
+            } else {
+                return 0;
+            }
+        }
+
+        public int getLocalSocketMiu(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                return socket.getMiu();
+            } else {
+                return 0;
+            }
+        }
+
+        public int getLocalSocketRw(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                return socket.getRw();
+            } else {
+                return 0;
+            }
+        }
+
+        public int getRemoteSocketMiu(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                if (socket.doGetRemoteSocketMiu() != 0) {
+                    return socket.doGetRemoteSocketMiu();
+                } else {
+                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
+                }
+            } else {
+                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
+            }
+        }
+
+        public int getRemoteSocketRw(int nativeHandle) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                if (socket.doGetRemoteSocketRw() != 0) {
+                    return socket.doGetRemoteSocketRw();
+                } else {
+                    return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
+                }
+            } else {
+                return ErrorCodes.ERROR_SOCKET_NOT_CONNECTED;
+            }
+        }
+
+        public int receive(int nativeHandle, byte[] receiveBuffer) throws RemoteException {
+            NativeLlcpSocket socket = null;
+            int receiveLength = 0;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                receiveLength = socket.doReceive(receiveBuffer);
+                if (receiveLength != 0) {
+                    return receiveLength;
+                } else {
+                    return ErrorCodes.ERROR_IO;
+                }
+            } else {
+                return ErrorCodes.ERROR_IO;
+            }
+        }
+
+        public int send(int nativeHandle, byte[] data) throws RemoteException {
+            NativeLlcpSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                isSuccess = socket.doSend(data);
+                if (isSuccess) {
+                    return ErrorCodes.SUCCESS;
+                } else {
+                    return ErrorCodes.ERROR_IO;
+                }
+            } else {
+                return ErrorCodes.ERROR_IO;
+            }
+        }
+
+        public void setConnectTimeout(int nativeHandle, int timeout) throws RemoteException {
+            NativeLlcpSocket socket = null;
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                socket.setConnectTimeout(timeout);
+            }
+        }
+
+    };
+
+    private ILlcpServiceSocket mLlcpServerSocketService = new ILlcpServiceSocket.Stub() {
+
+        public int accept(int nativeHandle) throws RemoteException {
+            NativeLlcpServiceSocket socket = null;
+            NativeLlcpSocket clientSocket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
+                /* find the socket in the hmap */
+                socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
+                if (socket != null) {
+                    clientSocket = socket.doAccept(socket.getAcceptTimeout(), socket.getMiu(),
+                            socket.getRw(), socket.getLinearBufferLength());
+                    if (clientSocket != null) {
+                        /* Add the socket into the socket map */
+                        mSocketMap.put(clientSocket.getHandle(), clientSocket);
+                        mNbSocketCreated++;
+                        return clientSocket.getHandle();
+                    } else {
+                        return ErrorCodes.ERROR_IO;
+                    }
+                } else {
+                    return ErrorCodes.ERROR_IO;
+                }
+            } else {
+                return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+            }
+
+        }
+
+        public void close(int nativeHandle) throws RemoteException {
+            NativeLlcpServiceSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                    isSuccess = socket.doClose();
+                    if (isSuccess) {
+                        /* Remove the socket closed from the hmap */
+                        RemoveSocket(nativeHandle);
+                        /* Update mNbSocketCreated */
+                        mNbSocketCreated--;
+                    }
+                } else {
+                    /* Remove the socket closed from the hmap */
+                    RemoveSocket(nativeHandle);
+
+                    /* Remove registered socket from the list */
+                    RemoveRegisteredSocket(nativeHandle);
+
+                    /* Update mNbSocketCreated */
+                    mNbSocketCreated--;
+                }
+            }
+        }
+
+        public int getAcceptTimeout(int nativeHandle) throws RemoteException {
+            NativeLlcpServiceSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                return socket.getAcceptTimeout();
+            } else {
+                return 0;
+            }
+        }
+
+        public void setAcceptTimeout(int nativeHandle, int timeout) throws RemoteException {
+            NativeLlcpServiceSocket socket = null;
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpServiceSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                socket.setAcceptTimeout(timeout);
+            }
+        }
+    };
+
+    private ILlcpConnectionlessSocket mLlcpConnectionlessSocketService = new ILlcpConnectionlessSocket.Stub() {
+
+        public void close(int nativeHandle) throws RemoteException {
+            NativeLlcpConnectionlessSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                    isSuccess = socket.doClose();
+                    if (isSuccess) {
+                        /* Remove the socket closed from the hmap */
+                        RemoveSocket(nativeHandle);
+                        /* Update mNbSocketCreated */
+                        mNbSocketCreated--;
+                    }
+                } else {
+                    /* Remove the socket closed from the hmap */
+                    RemoveSocket(nativeHandle);
+
+                    /* Remove registered socket from the list */
+                    RemoveRegisteredSocket(nativeHandle);
+
+                    /* Update mNbSocketCreated */
+                    mNbSocketCreated--;
+                }
+            }
+        }
+
+        public int getSap(int nativeHandle) throws RemoteException {
+            NativeLlcpConnectionlessSocket socket = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                return socket.getSap();
+            } else {
+                return 0;
+            }
+        }
+
+        public LlcpPacket receiveFrom(int nativeHandle) throws RemoteException {
+            NativeLlcpConnectionlessSocket socket = null;
+            LlcpPacket packet;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                packet = socket.doReceiveFrom(socket.getLinkMiu());
+                if (packet != null) {
+                    return packet;
+                }
+                return null;
+            } else {
+                return null;
+            }
+        }
+
+        public int sendTo(int nativeHandle, LlcpPacket packet) throws RemoteException {
+            NativeLlcpConnectionlessSocket socket = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the socket in the hmap */
+            socket = (NativeLlcpConnectionlessSocket) findSocket(nativeHandle);
+            if (socket != null) {
+                isSuccess = socket.doSendTo(packet.getRemoteSap(), packet.getDataBuffer());
+                if (isSuccess) {
+                    return ErrorCodes.SUCCESS;
+                } else {
+                    return ErrorCodes.ERROR_IO;
+                }
+            } else {
+                return ErrorCodes.ERROR_IO;
+            }
+        }
+    };
+
+    private INfcTag mNfcTagService = new INfcTag.Stub() {
+
+        public int close(int nativeHandle) throws RemoteException {
+            NativeNfcTag tag = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                if (tag.doDisconnect()) {
+                    /* Remove the device from the hmap */
+                    RemoveObject(nativeHandle);
+                    /* Restart polling loop for notification */
+                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
+                    mOpenPending = false;
+                    return ErrorCodes.SUCCESS;
+                }
+
+            }
+            /* Restart polling loop for notification */
+            mManager.enableDiscovery(DISCOVERY_MODE_READER);
+            mOpenPending = false;
+            return ErrorCodes.ERROR_DISCONNECT;
+        }
+
+        public int connect(int nativeHandle) throws RemoteException {
+            NativeNfcTag tag = null;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                if (tag.doConnect())
+                    return ErrorCodes.SUCCESS;
+            }
+            /* Restart polling loop for notification */
+            mManager.enableDiscovery(DISCOVERY_MODE_READER);
+            mOpenPending = false;
+            return ErrorCodes.ERROR_CONNECT;
+        }
+
+        public String getType(int nativeHandle) throws RemoteException {
+            NativeNfcTag tag = null;
+            String type;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                type = tag.getType();
+                return type;
+            }
+            return null;
+        }
+
+        public byte[] getUid(int nativeHandle) throws RemoteException {
+            NativeNfcTag tag = null;
+            byte[] uid;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                uid = tag.getUid();
+                return uid;
+            }
+            return null;
+        }
+
+        public boolean isNdef(int nativeHandle) throws RemoteException {
+            NativeNfcTag tag = null;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return isSuccess;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                isSuccess = tag.checkNDEF();
+            }
+            return isSuccess;
+        }
+
+        public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException {
+            NativeNfcTag tag = null;
+            byte[] response;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                response = tag.doTransceive(data);
+                return response;
+            }
+            return null;
+        }
+
+        public NdefMessage read(int nativeHandle) throws RemoteException {
+            NativeNfcTag tag;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                byte[] buf = tag.doRead();
+                if (buf == null)
+                    return null;
+
+                /* Create an NdefMessage */
+                try {
+                    return new NdefMessage(buf);
+                } catch (NfcException e) {
+                    return null;
+                }
+            }
+            return null;
+        }
+
+        public boolean write(int nativeHandle, NdefMessage msg) throws RemoteException {
+            NativeNfcTag tag;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return isSuccess;
+            }
+
+            /* find the tag in the hmap */
+            tag = (NativeNfcTag) findObject(nativeHandle);
+            if (tag != null) {
+                isSuccess = tag.doWrite(msg.toByteArray());
+            }
+            return isSuccess;
+
+        }
+
+    };
+
+    private IP2pInitiator mP2pInitiatorService = new IP2pInitiator.Stub() {
+
+        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                byte[] buff = device.getGeneralBytes();
+                if (buff == null)
+                    return null;
+                return buff;
+            }
+            return null;
+        }
+
+        public int getMode(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                return device.getMode();
+            }
+            return ErrorCodes.ERROR_INVALID_PARAM;
+        }
+
+        public byte[] receive(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                byte[] buff = device.doReceive();
+                if (buff == null)
+                    return null;
+                return buff;
+            }
+            /* Restart polling loop for notification */
+            mManager.enableDiscovery(DISCOVERY_MODE_READER);
+            mOpenPending = false;
+            return null;
+        }
+
+        public boolean send(int nativeHandle, byte[] data) throws RemoteException {
+            NativeP2pDevice device;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return isSuccess;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                isSuccess = device.doSend(data);
+            }
+            return isSuccess;
+        }
+    };
+
+    private IP2pTarget mP2pTargetService = new IP2pTarget.Stub() {
+
+        public int connect(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                if (device.doConnect()) {
+                    return ErrorCodes.SUCCESS;
+                }
+            }
+            return ErrorCodes.ERROR_CONNECT;
+        }
+
+        public boolean disconnect(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+            boolean isSuccess = false;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return isSuccess;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                if (isSuccess = device.doDisconnect()) {
+                    mOpenPending = false;
+                    /* remove the device from the hmap */
+                    RemoveObject(nativeHandle);
+                    /* Restart polling loop for notification */
+                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
+                }
+            }
+            return isSuccess;
+
+        }
+
+        public byte[] getGeneralBytes(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                byte[] buff = device.getGeneralBytes();
+                if (buff == null)
+                    return null;
+                return buff;
+            }
+            return null;
+        }
+
+        public int getMode(int nativeHandle) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return ErrorCodes.ERROR_NOT_INITIALIZED;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                return device.getMode();
+            }
+            return ErrorCodes.ERROR_INVALID_PARAM;
+        }
+
+        public byte[] transceive(int nativeHandle, byte[] data) throws RemoteException {
+            NativeP2pDevice device;
+
+            // Check if NFC is enabled
+            if (!mIsNfcEnabled) {
+                return null;
+            }
+
+            /* find the device in the hmap */
+            device = (NativeP2pDevice) findObject(nativeHandle);
+            if (device != null) {
+                byte[] buff = device.doTransceive(data);
+                if (buff == null)
+                    return null;
+                return buff;
+            }
+            return null;
+        }
+    };
+
+    private class NfcHandler extends Handler {
+
+        @Override
+        public void handleMessage(Message msg) {
+            try {
+
+            } catch (Exception e) {
+                // Log, don't crash!
+                Log.e(TAG, "Exception in NfcHandler.handleMessage:", e);
+            }
+        }
+
+    };
+
+    public NfcService(Context context) {
+        super();
+        mContext = context;
+        mManager = new NativeNfcManager(mContext);
+
+        mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter(
+                NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION));
+
+        mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter(
+                NfcManager.LLCP_LINK_STATE_CHANGED_ACTION));
+        
+        mContext.registerReceiver(mNfcServiceReceiver, new IntentFilter(
+                NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION));
+
+        Thread thread = new Thread(null, this, "NfcService");
+        thread.start();
+
+        mManager.initializeNativeStructure();
+
+            int nfcState = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.NFC_ON, 0);
+
+            if (nfcState == NFC_STATE_ENABLED) {
+                if (this._enable()) {
+                }
+            }
+
+    }
+
+    public void run() {
+        Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
+        Looper.prepare();
+        mNfcHandler = new NfcHandler();
+        Looper.loop();
+    }
+
+    public void cancel() throws RemoteException {
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW,
+                "NFC_RAW permission required to cancel NFC opening");
+        if (mOpenPending) {
+            mOpenPending = false;
+            mManager.doCancel();
+            /* Restart polling loop for notification */
+            mManager.enableDiscovery(DISCOVERY_MODE_READER);
+        }
+    }
+
+    public int createLlcpConnectionlessSocket(int sap) throws RemoteException {
+
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_LLCP,
+                "NFC_LLCP permission required for LLCP operations with NFC service");
+
+        /* Check SAP is not already used */
+
+        /* Check nb socket created */
+        if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
+            /* Store the socket handle */
+            int sockeHandle = mGeneratedSocketHandle;
+
+            if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                NativeLlcpConnectionlessSocket socket;
+
+                socket = mManager.doCreateLlcpConnectionlessSocket(sap);
+                if (socket != null) {
+                    /* Update the number of socket created */
+                    mNbSocketCreated++;
+
+                    /* Add the socket into the socket map */
+                    mSocketMap.put(sockeHandle, socket);
+
+                    return sockeHandle;
+                } else {
+                    /*
+                     * socket creation error - update the socket handle
+                     * generation
+                     */
+                    mGeneratedSocketHandle -= 1;
+
+                    /* Get Error Status */
+                    int errorStatus = mManager.doGetLastError();
+
+                    switch (errorStatus) {
+                        case ErrorCodes.ERROR_BUFFER_TO_SMALL:
+                            return ErrorCodes.ERROR_BUFFER_TO_SMALL;
+                        case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
+                            return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+                        default:
+                            return ErrorCodes.ERROR_SOCKET_CREATION;
+                    }
+                }
+            } else {
+                /* Check SAP is not already used */
+                if (!CheckSocketSap(sap)) {
+                    return ErrorCodes.ERROR_SAP_USED;
+                }
+
+                NativeLlcpConnectionlessSocket socket = new NativeLlcpConnectionlessSocket(sap);
+
+                /* Add the socket into the socket map */
+                mSocketMap.put(sockeHandle, socket);
+
+                /* Update the number of socket created */
+                mNbSocketCreated++;
+
+                /* Create new registered socket */
+                RegisteredSocket registeredSocket = new RegisteredSocket(
+                        LLCP_CONNECTIONLESS_SOCKET_TYPE, sockeHandle, sap);
+
+                /* Put this socket into a list of registered socket */
+                mRegisteredSocketList.add(registeredSocket);
+            }
+
+            /* update socket handle generation */
+            mGeneratedSocketHandle++;
+
+            return sockeHandle;
+
+        } else {
+            /* No socket available */
+            return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+        }
+
+    }
+
+    public int createLlcpServiceSocket(int sap, String sn, int miu, int rw, int linearBufferLength)
+            throws RemoteException {
+
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_LLCP,
+                "NFC_LLCP permission required for LLCP operations with NFC service");
+
+        if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
+            int sockeHandle = mGeneratedSocketHandle;
+
+            if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                NativeLlcpServiceSocket socket;
+
+                socket = mManager.doCreateLlcpServiceSocket(sap, sn, miu, rw, linearBufferLength);
+                if (socket != null) {
+                    /* Update the number of socket created */
+                    mNbSocketCreated++;
+                    /* Add the socket into the socket map */
+                    mSocketMap.put(sockeHandle, socket);
+                } else {
+                    /* socket creation error - update the socket handle counter */
+                    mGeneratedSocketHandle -= 1;
+
+                    /* Get Error Status */
+                    int errorStatus = mManager.doGetLastError();
+
+                    switch (errorStatus) {
+                        case ErrorCodes.ERROR_BUFFER_TO_SMALL:
+                            return ErrorCodes.ERROR_BUFFER_TO_SMALL;
+                        case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
+                            return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+                        default:
+                            return ErrorCodes.ERROR_SOCKET_CREATION;
+                    }
+                }
+            } else {
+
+                /* Check SAP is not already used */
+                if (!CheckSocketSap(sap)) {
+                    return ErrorCodes.ERROR_SAP_USED;
+                }
+
+                /* Service Name */
+                if (!CheckSocketServiceName(sn)) {
+                    return ErrorCodes.ERROR_SERVICE_NAME_USED;
+                }
+
+                /* Check socket options */
+                if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
+                    return ErrorCodes.ERROR_SOCKET_OPTIONS;
+                }
+
+                NativeLlcpServiceSocket socket = new NativeLlcpServiceSocket(sn);
+
+                /* Add the socket into the socket map */
+                mSocketMap.put(sockeHandle, socket);
+
+                /* Update the number of socket created */
+                mNbSocketCreated++;
+
+                /* Create new registered socket */
+                RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SERVICE_SOCKET_TYPE,
+                        sockeHandle, sap, sn, miu, rw, linearBufferLength);
+
+                /* Put this socket into a list of registered socket */
+                mRegisteredSocketList.add(registeredSocket);
+            }
+
+            /* update socket handle generation */
+            mGeneratedSocketHandle += 1;
+
+            Log.d(TAG, "Llcp Service Socket Handle =" + sockeHandle);
+            return sockeHandle;
+        } else {
+            /* No socket available */
+            return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+        }
+    }
+
+    public int createLlcpSocket(int sap, int miu, int rw, int linearBufferLength)
+            throws RemoteException {
+
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_LLCP,
+                "NFC_LLCP permission required for LLCP operations with NFC service");
+
+        if (mNbSocketCreated < LLCP_SOCKET_NB_MAX) {
+
+            int sockeHandle = mGeneratedSocketHandle;
+
+            if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                NativeLlcpSocket socket;
+
+                socket = mManager.doCreateLlcpSocket(sap, miu, rw, linearBufferLength);
+
+                if (socket != null) {
+                    /* Update the number of socket created */
+                    mNbSocketCreated++;
+                    /* Add the socket into the socket map */
+                    mSocketMap.put(sockeHandle, socket);
+                } else {
+                    /*
+                     * socket creation error - update the socket handle
+                     * generation
+                     */
+                    mGeneratedSocketHandle -= 1;
+
+                    /* Get Error Status */
+                    int errorStatus = mManager.doGetLastError();
+
+                    switch (errorStatus) {
+                        case ErrorCodes.ERROR_BUFFER_TO_SMALL:
+                            return ErrorCodes.ERROR_BUFFER_TO_SMALL;
+                        case ErrorCodes.ERROR_INSUFFICIENT_RESOURCES:
+                            return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+                        default:
+                            return ErrorCodes.ERROR_SOCKET_CREATION;
+                    }
+                }
+            } else {
+
+                /* Check SAP is not already used */
+                if (!CheckSocketSap(sap)) {
+                    return ErrorCodes.ERROR_SAP_USED;
+                }
+
+                /* Check Socket options */
+                if (!CheckSocketOptions(miu, rw, linearBufferLength)) {
+                    return ErrorCodes.ERROR_SOCKET_OPTIONS;
+                }
+
+                NativeLlcpSocket socket = new NativeLlcpSocket(sap, miu, rw);
+
+                /* Add the socket into the socket map */
+                mSocketMap.put(sockeHandle, socket);
+
+                /* Update the number of socket created */
+                mNbSocketCreated++;
+                /* Create new registered socket */
+                RegisteredSocket registeredSocket = new RegisteredSocket(LLCP_SOCKET_TYPE,
+                        sockeHandle, sap, miu, rw, linearBufferLength);
+
+                /* Put this socket into a list of registered socket */
+                mRegisteredSocketList.add(registeredSocket);
+            }
+
+            /* update socket handle generation */
+            mGeneratedSocketHandle++;
+
+            return sockeHandle;
+        } else {
+            /* No socket available */
+            return ErrorCodes.ERROR_INSUFFICIENT_RESOURCES;
+        }
+    }
+
+    public int deselectSecureElement() throws RemoteException {
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+
+        if (mSelectedSeId == 0) {
+            return ErrorCodes.ERROR_NO_SE_CONNECTED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN,
+                "NFC_ADMIN permission required to deselect NFC Secure Element");
+
+            mManager.doDeselectSecureElement(mSelectedSeId);
+        mNfcSecureElementState = 0;
+            mSelectedSeId = 0;
+        
+        /* Store that a secure element is deselected */
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.NFC_SECURE_ELEMENT_ON, 0);
+
+        /* Reset Secure Element ID */
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.NFC_SECURE_ELEMENT_ID, 0);
+        
+
+        return ErrorCodes.SUCCESS; 
+    }
+
+    public boolean disable() throws RemoteException {
+        boolean isSuccess = false;
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN,
+                "NFC_ADMIN permission required to disable NFC service");
+        if (isEnabled()) {
+            isSuccess = mManager.deinitialize();
+            if (isSuccess) {
+                mIsNfcEnabled = false;
+            }
+        }
+
+        updateNfcOnSetting();
+
+        return isSuccess;
+    }
+
+    public boolean enable() throws RemoteException {
+        boolean isSuccess = false;
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN,
+                "NFC_ADMIN permission required to enable NFC service");
+        if (!isEnabled()) {
+            reset();
+            isSuccess = _enable();
+        }
+        return isSuccess;
+    }
+
+    private boolean _enable() {
+        boolean isSuccess = mManager.initialize();
+        if (isSuccess) {
+            /* Check persistent properties */
+            checkProperties();
+
+            /* Check Secure Element setting */
+            mNfcSecureElementState = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_SECURE_ELEMENT_ON, 0);
+
+            if (mNfcSecureElementState == 1) {
+
+                int secureElementId = Settings.System.getInt(mContext.getContentResolver(),
+                        Settings.System.NFC_SECURE_ELEMENT_ID, 0);
+                int[] Se_list = mManager.doGetSecureElementList();
+                if (Se_list != null) {
+                    for (int i = 0; i < Se_list.length; i++) {
+                        if (Se_list[i] == secureElementId) {
+                            mManager.doSelectSecureElement(Se_list[i]);
+                            mSelectedSeId = Se_list[i];
+                            break;
+                        }
+                    }
+                }
+            }
+
+            /* Start polling loop */
+            mManager.enableDiscovery(DISCOVERY_MODE_READER);
+
+            mIsNfcEnabled = true;
+        } else {
+            mIsNfcEnabled = false;
+        }
+
+        updateNfcOnSetting();
+
+        return isSuccess;
+    }
+
+    private void updateNfcOnSetting() {
+        int state;
+
+        if (mIsNfcEnabled) {
+            state = NFC_STATE_ENABLED;
+        } else {
+            state = NFC_STATE_DISABLED;
+        }
+
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_ON, state);
+    }
+
+    private void checkProperties() {
+        int value;
+
+        /* LLCP LTO */
+        value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_LTO,
+                LLCP_LTO_DEFAULT_VALUE);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_LTO, value);
+        mManager.doSetProperties(PROPERTY_LLCP_LTO, value);
+
+        /* LLCP MIU */
+        value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_MIU,
+                LLCP_MIU_DEFAULT_VALUE);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_MIU, value);
+        mManager.doSetProperties(PROPERTY_LLCP_MIU, value);
+
+        /* LLCP WKS */
+        value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_WKS,
+                LLCP_WKS_DEFAULT_VALUE);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_WKS, value);
+        mManager.doSetProperties(PROPERTY_LLCP_WKS, value);
+
+        /* LLCP OPT */
+        value = Settings.System.getInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_OPT,
+                LLCP_OPT_DEFAULT_VALUE);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_OPT, value);
+        mManager.doSetProperties(PROPERTY_LLCP_OPT, value);
+
+        /* NFC READER A */
+        value = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.NFC_DISCOVERY_A, 1);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_A,
+                value);
+        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, value);
+
+        /* NFC READER B */
+        value = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.NFC_DISCOVERY_B, 1);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_B,
+                value);
+        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, value);
+
+        /* NFC READER F */
+        value = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.NFC_DISCOVERY_F, 1);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_F,
+                value);
+        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, value);
+
+        /* NFC READER 15693 */
+        value = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.NFC_DISCOVERY_15693, 1);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_15693,
+                value);
+        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, value);
+
+        /* NFC NFCIP */
+        value = Settings.System.getInt(mContext.getContentResolver(),
+                Settings.System.NFC_DISCOVERY_NFCIP, 1);
+        Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_NFCIP,
+                value);
+        mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, value);
+    }
+
+    public ILlcpConnectionlessSocket getLlcpConnectionlessInterface() throws RemoteException {
+        return mLlcpConnectionlessSocketService;
+    }
+
+    public ILlcpSocket getLlcpInterface() throws RemoteException {
+        return mLlcpSocket;
+    }
+
+    public ILlcpServiceSocket getLlcpServiceInterface() throws RemoteException {
+        return mLlcpServerSocketService;
+    }
+
+    public INfcTag getNfcTagInterface() throws RemoteException {
+        return mNfcTagService;
+    }
+
+    public int getOpenTimeout() throws RemoteException {
+        return mTimeout;
+    }
+
+    public IP2pInitiator getP2pInitiatorInterface() throws RemoteException {
+        return mP2pInitiatorService;
+    }
+
+    public IP2pTarget getP2pTargetInterface() throws RemoteException {
+        return mP2pTargetService;
+    }
+
+    public String getProperties(String param) throws RemoteException {
+        int value;
+
+        if (param == null) {
+            return "Wrong parameter";
+        }
+
+        if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_LLCP_LTO, 0);
+        } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_LLCP_MIU, 0);
+        } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_LLCP_WKS, 0);
+        } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_LLCP_OPT, 0);
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_A, 0);
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_B, 0);
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_F, 0);
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_NFCIP, 0);
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
+            value = Settings.System.getInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_15693, 0);
+        } else {
+            return "Unknown property";
+        }
+
+        if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)
+                || param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)
+                || param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)
+                || param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)
+                || param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
+            if (value == 0) {
+                return "false";
+            } else if (value == 1) {
+                return "true";
+            } else {
+                return "Unknown Value";
+            }
+        }else{
+            return "" + value;
+        }
+
+    }
+
+    public int[] getSecureElementList() throws RemoteException {
+        int[] list = null;
+        if (mIsNfcEnabled == true) {
+            list = mManager.doGetSecureElementList();
+        }
+        return list;
+    }
+
+    public int getSelectedSecureElement() throws RemoteException {
+        return mSelectedSeId;
+    }
+
+    public boolean isEnabled() throws RemoteException {
+        return mIsNfcEnabled;
+    }
+
+    public int openP2pConnection() throws RemoteException {
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW,
+                "NFC_RAW permission required to open NFC P2P connection");
+        if (!mOpenPending) {
+            NativeP2pDevice device;
+            mOpenPending = true;
+            device = mManager.doOpenP2pConnection(mTimeout);
+            if (device != null) {
+                /* add device to the Hmap */
+                mObjectMap.put(device.getHandle(), device);
+                return device.getHandle();
+            } else {
+                mOpenPending = false;
+                /* Restart polling loop for notification */
+                mManager.enableDiscovery(DISCOVERY_MODE_READER);
+                return ErrorCodes.ERROR_IO;
+            }
+        } else {
+            return ErrorCodes.ERROR_BUSY;
+        }
+
+    }
+
+    public int openTagConnection() throws RemoteException {
+        NativeNfcTag tag;
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW,
+                "NFC_RAW permission required to open NFC Tag connection");
+        if (!mOpenPending) {
+            mOpenPending = true;
+            tag = mManager.doOpenTagConnection(mTimeout);
+            if (tag != null) {
+                mObjectMap.put(tag.getHandle(), tag);
+                return tag.getHandle();
+            } else {
+                mOpenPending = false;
+                /* Restart polling loop for notification */
+                mManager.enableDiscovery(DISCOVERY_MODE_READER);
+                return ErrorCodes.ERROR_IO;
+            }
+        } else {
+            return ErrorCodes.ERROR_BUSY;
+        }
+    }
+
+    public int selectSecureElement(int seId) throws RemoteException {
+        // Check if NFC is enabled
+        if (!mIsNfcEnabled) {
+            return ErrorCodes.ERROR_NOT_INITIALIZED;
+        }
+        
+        if (mSelectedSeId == seId) {
+            return ErrorCodes.ERROR_SE_ALREADY_SELECTED;
+        }
+
+        if (mSelectedSeId != 0) {
+            return ErrorCodes.ERROR_SE_CONNECTED;
+        }
+
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN,
+                "NFC_ADMIN permission required to select NFC Secure Element");
+
+            mSelectedSeId = seId;
+            mManager.doSelectSecureElement(mSelectedSeId);
+
+        /* Store that a secure element is selected */
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.NFC_SECURE_ELEMENT_ON, 1);
+
+        /* Store the ID of the Secure Element Selected */
+        Settings.System.putInt(mContext.getContentResolver(),
+                Settings.System.NFC_SECURE_ELEMENT_ID, mSelectedSeId);
+        
+        mNfcSecureElementState = 1;
+
+        return ErrorCodes.SUCCESS;
+
+    }
+
+    public void setOpenTimeout(int timeout) throws RemoteException {
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_RAW,
+                "NFC_RAW permission required to set NFC connection timeout");
+        mTimeout = timeout;
+    }
+
+    public int setProperties(String param, String value) throws RemoteException {
+        mContext.enforceCallingPermission(android.Manifest.permission.NFC_ADMIN,
+                "NFC_ADMIN permission required to set NFC Properties");
+
+        if (isEnabled()) {
+            return ErrorCodes.ERROR_NFC_ON;
+        }
+
+        int val;
+
+        /* Check params validity */
+        if (param == null || value == null) {
+            return ErrorCodes.ERROR_INVALID_PARAM;
+        }
+
+        if (param.equals(PROPERTY_LLCP_LTO_VALUE)) {
+            val = Integer.parseInt(value);
+
+            /* Check params */
+            if (val > LLCP_LTO_MAX_VALUE)
+                return ErrorCodes.ERROR_INVALID_PARAM;
+
+            /* Store value */
+            Settings.System
+                    .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_LTO, val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_LLCP_LTO, val);
+
+        } else if (param.equals(PROPERTY_LLCP_MIU_VALUE)) {
+            val = Integer.parseInt(value);
+
+            /* Check params */
+            if ((val < LLCP_MIU_DEFAULT_VALUE) || (val > LLCP_MIU_MAX_VALUE))
+                return ErrorCodes.ERROR_INVALID_PARAM;
+
+            /* Store value */
+            Settings.System
+                    .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_MIU, val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_LLCP_MIU, val);
+
+        } else if (param.equals(PROPERTY_LLCP_WKS_VALUE)) {
+            val = Integer.parseInt(value);
+
+            /* Check params */
+            if (val > LLCP_WKS_MAX_VALUE)
+                return ErrorCodes.ERROR_INVALID_PARAM;
+
+            /* Store value */
+            Settings.System
+                    .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_WKS, val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_LLCP_WKS, val);
+
+        } else if (param.equals(PROPERTY_LLCP_OPT_VALUE)) {
+            val = Integer.parseInt(value);
+
+            /* Check params */
+            if (val > LLCP_OPT_MAX_VALUE)
+                return ErrorCodes.ERROR_INVALID_PARAM;
+
+            /* Store value */
+            Settings.System
+                    .putInt(mContext.getContentResolver(), Settings.System.NFC_LLCP_OPT, val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_LLCP_OPT, val);
+
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_A_VALUE)) {
+
+            /* Check params */
+            if (value.equals("true")) {
+                val = 1;
+            } else if (value.equals("false")) {
+                val = 0;
+            } else {
+                return ErrorCodes.ERROR_INVALID_PARAM;
+            }
+            /* Store value */
+            Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_A,
+                    val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_A, val);
+
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_B_VALUE)) {
+
+            /* Check params */
+            if (value.equals("true")) {
+                val = 1;
+            } else if (value.equals("false")) {
+                val = 0;
+            } else {
+                return ErrorCodes.ERROR_INVALID_PARAM;
+            }
+
+            /* Store value */
+            Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_B,
+                    val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_B, val);
+
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_F_VALUE)) {
+
+            /* Check params */
+            if (value.equals("true")) {
+                val = 1;
+            } else if (value.equals("false")) {
+                val = 0;
+            } else {
+                return ErrorCodes.ERROR_INVALID_PARAM;
+            }
+
+            /* Store value */
+            Settings.System.putInt(mContext.getContentResolver(), Settings.System.NFC_DISCOVERY_F,
+                    val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_F, val);
+
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_15693_VALUE)) {
+
+            /* Check params */
+            if (value.equals("true")) {
+                val = 1;
+            } else if (value.equals("false")) {
+                val = 0;
+            } else {
+                return ErrorCodes.ERROR_INVALID_PARAM;
+            }
+
+            /* Store value */
+            Settings.System.putInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_15693, val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_15693, val);
+
+        } else if (param.equals(PROPERTY_NFC_DISCOVERY_NFCIP_VALUE)) {
+
+            /* Check params */
+            if (value.equals("true")) {
+                val = 1;
+            } else if (value.equals("false")) {
+                val = 0;
+            } else {
+                return ErrorCodes.ERROR_INVALID_PARAM;
+            }
+
+            /* Store value */
+            Settings.System.putInt(mContext.getContentResolver(),
+                    Settings.System.NFC_DISCOVERY_NFCIP, val);
+
+            /* Update JNI */
+            mManager.doSetProperties(PROPERTY_NFC_DISCOVERY_NFCIP, val);
+        } else {
+            return ErrorCodes.ERROR_INVALID_PARAM;
+        }
+
+        return ErrorCodes.SUCCESS;
+    }
+
+    // Reset all internals
+    private void reset() {
+
+        // Clear tables
+        mObjectMap.clear();
+        mSocketMap.clear();
+        mRegisteredSocketList.clear();
+
+        // Reset variables
+        mLlcpLinkState = NfcManager.LLCP_LINK_STATE_DEACTIVATED;
+        mNbSocketCreated = 0;
+        mIsNfcEnabled = false;
+        mSelectedSeId = 0;
+        mTimeout = 0;
+        mNfcState = NFC_STATE_DISABLED;
+        mOpenPending = false;
+    }
+
+    private Object findObject(int key) {
+        Object device = null;
+
+        device = mObjectMap.get(key);
+
+        return device;
+    }
+
+    private void RemoveObject(int key) {
+        mObjectMap.remove(key);
+    }
+
+    private Object findSocket(int key) {
+        Object socket = null;
+
+        socket = mSocketMap.get(key);
+
+        return socket;
+    }
+
+    private void RemoveSocket(int key) {
+        mSocketMap.remove(key);
+    }
+
+    private boolean CheckSocketSap(int sap) {
+        /* List of sockets registered */
+        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
+
+        while (it.hasNext()) {
+            RegisteredSocket registeredSocket = it.next();
+
+            if (sap == registeredSocket.mSap) {
+                /* SAP already used */
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private boolean CheckSocketOptions(int miu, int rw, int linearBufferlength) {
+
+        if (rw > LLCP_RW_MAX_VALUE || miu < LLCP_MIU_DEFAULT_VALUE || linearBufferlength < miu) {
+            return false;
+        }
+        return true;
+    }
+
+    private boolean CheckSocketServiceName(String sn) {
+
+        /* List of sockets registered */
+        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
+
+        while (it.hasNext()) {
+            RegisteredSocket registeredSocket = it.next();
+
+            if (sn.equals(registeredSocket.mServiceName)) {
+                /* Service Name already used */
+                return false;
+            }
+        }
+        return true;
+    }
+
+    private void RemoveRegisteredSocket(int nativeHandle) {
+        /* check if sockets are registered */
+        ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
+
+        while (it.hasNext()) {
+            RegisteredSocket registeredSocket = it.next();
+            if (registeredSocket.mHandle == nativeHandle) {
+                /* remove the registered socket from the list */
+                it.remove();
+                Log.d(TAG, "socket removed");
+            }
+        }
+    }
+
+    /*
+     * RegisteredSocket class to store the creation request of socket until the
+     * LLCP link in not activated
+     */
+    private class RegisteredSocket {
+        private int mType;
+
+        private int mHandle;
+
+        private int mSap;
+
+        private int mMiu;
+
+        private int mRw;
+
+        private String mServiceName;
+
+        private int mlinearBufferLength;
+
+        RegisteredSocket(int type, int handle, int sap, String sn, int miu, int rw,
+                int linearBufferLength) {
+            mType = type;
+            mHandle = handle;
+            mSap = sap;
+            mServiceName = sn;
+            mRw = rw;
+            mMiu = miu;
+            mlinearBufferLength = linearBufferLength;
+        }
+
+        RegisteredSocket(int type, int handle, int sap, int miu, int rw, int linearBufferLength) {
+            mType = type;
+            mHandle = handle;
+            mSap = sap;
+            mRw = rw;
+            mMiu = miu;
+            mlinearBufferLength = linearBufferLength;
+        }
+
+        RegisteredSocket(int type, int handle, int sap) {
+            mType = type;
+            mHandle = handle;
+            mSap = sap;
+        }
+    }
+
+    private BroadcastReceiver mNfcServiceReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.d(TAG, "Internal NFC Intent received");
+
+            /* LLCP Link deactivation */
+            if (intent.getAction().equals(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION)) {
+                mLlcpLinkState = intent.getIntExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA,
+                        NfcManager.LLCP_LINK_STATE_DEACTIVATED);
+
+                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_DEACTIVATED) {
+                    /* restart polling loop */
+                    mManager.enableDiscovery(DISCOVERY_MODE_READER);
+                }
+
+            }
+            /* LLCP Link activation */
+            else if (intent.getAction().equals(
+                    NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_ACTION)) {
+
+                mLlcpLinkState = intent.getIntExtra(
+                        NativeNfcManager.INTERNAL_LLCP_LINK_STATE_CHANGED_EXTRA,
+                        NfcManager.LLCP_LINK_STATE_DEACTIVATED);
+
+                if (mLlcpLinkState == NfcManager.LLCP_LINK_STATE_ACTIVATED) {
+                    /* check if sockets are registered */
+                    ListIterator<RegisteredSocket> it = mRegisteredSocketList.listIterator();
+
+                    Log.d(TAG, "Nb socket resgistered = " + mRegisteredSocketList.size());
+
+                    while (it.hasNext()) {
+                        RegisteredSocket registeredSocket = it.next();
+
+                        switch (registeredSocket.mType) {
+                            case LLCP_SERVICE_SOCKET_TYPE:
+                                Log.d(TAG, "Registered Llcp Service Socket");
+                                NativeLlcpServiceSocket serviceSocket;
+
+                                serviceSocket = mManager.doCreateLlcpServiceSocket(
+                                        registeredSocket.mSap, registeredSocket.mServiceName,
+                                        registeredSocket.mMiu, registeredSocket.mRw,
+                                        registeredSocket.mlinearBufferLength);
+
+                                if (serviceSocket != null) {
+                                    /* Add the socket into the socket map */
+                                    mSocketMap.put(registeredSocket.mHandle, serviceSocket);
+                                } else {
+                                    /*
+                                     * socket creation error - update the socket
+                                     * handle counter
+                                     */
+                                    mGeneratedSocketHandle -= 1;
+                                }
+                                break;
+
+                            case LLCP_SOCKET_TYPE:
+                                Log.d(TAG, "Registered Llcp Socket");
+                                NativeLlcpSocket clientSocket;
+                                clientSocket = mManager.doCreateLlcpSocket(registeredSocket.mSap,
+                                        registeredSocket.mMiu, registeredSocket.mRw,
+                                        registeredSocket.mlinearBufferLength);
+                                if (clientSocket != null) {
+                                    /* Add the socket into the socket map */
+                                    mSocketMap.put(registeredSocket.mHandle, clientSocket);
+                                } else {
+                                    /*
+                                     * socket creation error - update the socket
+                                     * handle counter
+                                     */
+                                    mGeneratedSocketHandle -= 1;
+                                }
+                                break;
+
+                            case LLCP_CONNECTIONLESS_SOCKET_TYPE:
+                                Log.d(TAG, "Registered Llcp Connectionless Socket");
+                                NativeLlcpConnectionlessSocket connectionlessSocket;
+                                connectionlessSocket = mManager
+                                        .doCreateLlcpConnectionlessSocket(registeredSocket.mSap);
+                                if (connectionlessSocket != null) {
+                                    /* Add the socket into the socket map */
+                                    mSocketMap.put(registeredSocket.mHandle, connectionlessSocket);
+                                } else {
+                                    /*
+                                     * socket creation error - update the socket
+                                     * handle counter
+                                     */
+                                    mGeneratedSocketHandle -= 1;
+                                }
+                                break;
+
+                        }
+                    }
+
+                    /* Remove all registered socket from the list */
+                    mRegisteredSocketList.clear();
+
+                    /* Broadcast Intent Link LLCP activated */
+                    Intent LlcpLinkIntent = new Intent();
+                    LlcpLinkIntent.setAction(NfcManager.LLCP_LINK_STATE_CHANGED_ACTION);
+
+                    LlcpLinkIntent.putExtra(NfcManager.LLCP_LINK_STATE_CHANGED_EXTRA,
+                            NfcManager.LLCP_LINK_STATE_ACTIVATED);
+
+                    Log.d(TAG, "Broadcasting LLCP activation");
+                    mContext.sendOrderedBroadcast(LlcpLinkIntent,
+                            android.Manifest.permission.NFC_LLCP);
+                }
+            }            
+            /* Target Deactivated */
+            else if (intent.getAction().equals(
+                    NativeNfcManager.INTERNAL_TARGET_DESELECTED_ACTION)) {
+                if(mOpenPending != false){
+                    mOpenPending = false;
+                }
+                /* Restart polling loop for notification */
+                mManager.enableDiscovery(DISCOVERY_MODE_READER);
+                
+            }
+        }
+    };
+}
diff --git a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
index 0204782..dea549a 100644
--- a/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
+++ b/tests/DumpRenderTree/src/com/android/dumprendertree/FileFilter.java
@@ -98,8 +98,6 @@
         ignoreResultList.add("fast/encoding/hanarei-blog32-fc2-com.html"); // fails in Java HTTP stack, see http://b/issue?id=3046986
         ignoreResultList.add("fast/encoding/mailto-always-utf-8.html"); // Requires waitForPolicyDelegate(), see http://b/issue?id=3043468
         ignoreResultList.add("fast/encoding/percent-escaping.html"); // fails in Java HTTP stack, see http://b/issue?id=3046984
-        ignoreResultList.add("fast/events/touch/basic-multi-touch-events.html"); // Requires multi-touch
-        ignoreResultList.add("fast/events/touch/touch-target.html"); // Requires multi-touch
         ignoreResultList.add("http/tests/appcache/empty-manifest.html"); // flaky
         ignoreResultList.add("http/tests/appcache/fallback.html"); // http://b/issue?id=2713004
         ignoreResultList.add("http/tests/appcache/foreign-iframe-main.html"); // flaky - skips states
@@ -114,11 +112,13 @@
         ignoreResultList.add("storage/transaction-error-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
         ignoreResultList.add("storage/transaction-success-callback-isolated-world.html"); // Requires layoutTestController.evaluateScriptInIsolatedWorld()
 
-        // Expected failures due to unsupported features.
+        // Expected failures due to unsupported features or tests unsuitable for Android.
         ignoreResultList.add("fast/encoding/char-decoding-mac.html"); // Mac-specific encodings (also marked Won't Fix in Chromium, bug 7388)
         ignoreResultList.add("fast/encoding/char-encoding-mac.html"); // Mac-specific encodings (also marked Won't Fix in Chromium, bug 7388)
         ignoreResultList.add("fast/encoding/idn-security.html"); // Mac-specific IDN checks (also marked Won't Fix in Chromium, bug 21814)
+        ignoreResultList.add("fast/events/touch/basic-multi-touch-events.html"); // Requires multi-touch gestures not supported by Android system
         ignoreResultList.add("fast/events/touch/touch-coords-in-zoom-and-scroll.html"); // Requires eventSender.zoomPageIn(),zoomPageOut()
+        ignoreResultList.add("fast/events/touch/touch-target.html"); // Requires multi-touch gestures not supported by Android system
         ignoreResultList.add("fast/workers"); // workers not supported
         ignoreResultList.add("http/tests/eventsource/workers"); // workers not supported
         ignoreResultList.add("http/tests/workers"); // workers not supported
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java
index 8ac0436..68bcf11 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/EventSenderImpl.java
@@ -142,9 +142,9 @@
     private Handler mEventSenderHandler = new Handler() {
         @Override
         public void handleMessage(Message msg) {
-            TouchPoint touchPoint;
             Bundle bundle;
-            KeyEvent event;
+            MotionEvent event;
+            long ts;
 
             switch (msg.what) {
                 case MSG_ENABLE_DOM_UI_EVENT_LOGGING:
@@ -177,45 +177,25 @@
                 /** MOUSE */
 
                 case MSG_MOUSE_DOWN:
-                    /** TODO: Implement */
+                    ts = SystemClock.uptimeMillis();
+                    event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_DOWN, mMouseX, mMouseY, 0);
+                    mWebView.onTouchEvent(event);
                     break;
 
                 case MSG_MOUSE_UP:
-                    /** TODO: Implement */
+                    ts = SystemClock.uptimeMillis();
+                    event = MotionEvent.obtain(ts, ts, MotionEvent.ACTION_UP, mMouseX, mMouseY, 0);
+                    mWebView.onTouchEvent(event);
                     break;
 
                 case MSG_MOUSE_CLICK:
-                    /** TODO: Implement */
+                    mouseDown();
+                    mouseUp();
                     break;
 
                 case MSG_MOUSE_MOVE_TO:
-                    int x = msg.arg1;
-                    int y = msg.arg2;
-
-                    event = null;
-                    if (x > mMouseX) {
-                        event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_RIGHT);
-                    } else if (x < mMouseX) {
-                        event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_LEFT);
-                    }
-                    if (event != null) {
-                        mWebView.onKeyDown(event.getKeyCode(), event);
-                        mWebView.onKeyUp(event.getKeyCode(), event);
-                    }
-
-                    event = null;
-                    if (y > mMouseY) {
-                        event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_DOWN);
-                    } else if (y < mMouseY) {
-                        event = new KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_DPAD_UP);
-                    }
-                    if (event != null) {
-                        mWebView.onKeyDown(event.getKeyCode(), event);
-                        mWebView.onKeyUp(event.getKeyCode(), event);
-                    }
-
-                    mMouseX = x;
-                    mMouseY = y;
+                    mMouseX = msg.arg1;
+                    mMouseY = msg.arg2;
                     break;
 
                 /** TOUCH */
@@ -597,4 +577,4 @@
 
         return KeyEvent.KEYCODE_UNKNOWN;
     }
-}
\ No newline at end of file
+}
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java
index 17e19d0..f42dc86 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/ManagerService.java
@@ -267,7 +267,7 @@
             bytes = FsUtils.readDataFromUrl(FileFilter.getUrl(relativePath));
         }
 
-        mLastExpectedResultPathFetched = relativePath;
+        mLastExpectedResultPathFetched = bytes == null ? null : relativePath;
         return bytes;
     }
 
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
index 25c5ad5..8d01a53 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/Summarizer.java
@@ -539,7 +539,11 @@
         String textSource = result.getExpectedTextResultPath();
         String imageSource = result.getExpectedImageResultPath();
 
-        if (textSource != null) {
+        if (textSource == null) {
+            // Show if a text result is missing. We may want to revisit this decision when we add
+            // support for image results.
+            html.append("<span class=\"source\">Expected textual result missing</span>");
+        } else {
             html.append("<span class=\"source\">Expected textual result from: ");
             html.append("<a href=\"" + ForwarderManager.getHostSchemePort(false) + "LayoutTests/" +
                     textSource + "\"");
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
index f835b6a..3d2b98b 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/TextResult.java
@@ -87,20 +87,26 @@
 
     @Override
     public ResultCode getResultCode() {
-        if (mResultCode != null) {
-            return mResultCode;
-        }
-
-        if (mExpectedResult == null) {
-            mResultCode = AbstractResult.ResultCode.NO_EXPECTED_RESULT;
-        } else if (!mExpectedResult.equals(mActualResult)) {
-            mResultCode = AbstractResult.ResultCode.RESULTS_DIFFER;
-        } else {
-            mResultCode = AbstractResult.ResultCode.RESULTS_MATCH;
+        if (mResultCode == null) {
+            mResultCode = resultsMatch() ? AbstractResult.ResultCode.RESULTS_MATCH
+                    : AbstractResult.ResultCode.RESULTS_DIFFER;
         }
         return mResultCode;
     }
 
+    private boolean resultsMatch() {
+        assert mExpectedResult != null;
+        assert mActualResult != null;
+        // Trim leading and trailing empty lines, as other WebKit platforms do.
+        String leadingEmptyLines = "^\\n+";
+        String trailingEmptyLines = "\\n+$";
+        String trimmedExpectedResult = mExpectedResult.replaceFirst(leadingEmptyLines, "")
+                .replaceFirst(trailingEmptyLines, "");
+        String trimmedActualResult = mActualResult.replaceFirst(leadingEmptyLines, "")
+                .replaceFirst(trailingEmptyLines, "");
+        return trimmedExpectedResult.equals(trimmedActualResult);
+    }
+
     @Override
     public boolean didCrash() {
         return false;
@@ -125,7 +131,7 @@
     public String getActualTextResult() {
         String additionalTextResultString = getAdditionalTextOutputString();
         if (additionalTextResultString != null) {
-            return additionalTextResultString+ mActualResult;
+            return additionalTextResultString + mActualResult;
         }
 
         return mActualResult;
@@ -159,11 +165,16 @@
 
     @Override
     public void setExpectedTextResult(String expectedResult) {
-        mExpectedResult = expectedResult;
+        // For text results, we use an empty string for the expected result when none is
+        // present, as other WebKit platforms do.
+        mExpectedResult = expectedResult == null ? "" : expectedResult;
     }
 
     @Override
     public String getDiffAsHtml() {
+        assert mExpectedResult != null;
+        assert mActualResult != null;
+
         StringBuilder html = new StringBuilder();
         html.append("<table class=\"visual_diff\">");
         html.append("    <tr class=\"headers\">");
@@ -172,11 +183,7 @@
         html.append("        <td colspan=\"2\">Actual result:</td>");
         html.append("    </tr>");
 
-        if (mExpectedResult == null || mActualResult == null) {
-            appendNullsHtml(html);
-        } else {
-            appendDiffHtml(html);
-        }
+        appendDiffHtml(html);
 
         html.append("    <tr class=\"footers\">");
         html.append("        <td colspan=\"2\"></td>");
@@ -201,36 +208,15 @@
 
         VisualDiffUtils.generateExpectedResultLines(diffs, expectedLineNums, expectedLines);
         VisualDiffUtils.generateActualResultLines(diffs, actualLineNums, actualLines);
+        // TODO: We should use a map for each line number and lines pair.
+        assert expectedLines.size() == expectedLineNums.size();
+        assert actualLines.size() == actualLineNums.size();
+        assert expectedLines.size() == actualLines.size();
 
         html.append(VisualDiffUtils.getHtml(expectedLineNums, expectedLines,
                 actualLineNums, actualLines));
     }
 
-    private void appendNullsHtml(StringBuilder html) {
-        /** TODO: Create a separate row for each line of not null result */
-        html.append("    <tr class=\"results\">");
-        html.append("    <td class=\"line_count\">");
-        html.append("    </td>");
-        html.append("    <td class=\"line\">");
-        if (mExpectedResult == null) {
-            html.append("Expected result was NULL");
-        } else {
-            html.append(mExpectedResult.replace("\n", "<br />"));
-        }
-        html.append("        </td>");
-        html.append("        <td class=\"space\"></td>");
-        html.append("    <td class=\"line_count\">");
-        html.append("    </td>");
-        html.append("    <td class=\"line\">");
-        if (mActualResult == null) {
-            html.append("Actual result was NULL");
-        } else {
-            html.append(mActualResult.replace("\n", "<br />"));
-        }
-        html.append("        </td>");
-        html.append("    </tr>");
-    }
-
     @Override
     public TestType getType() {
         return TestType.TEXT;
diff --git a/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java b/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
index 26bf75c..d7f7313 100644
--- a/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
+++ b/tests/DumpRenderTree2/src/com/android/dumprendertree2/VisualDiffUtils.java
@@ -68,35 +68,38 @@
 
         String line = "";
         int i = 1;
-        for (diff_match_patch.Diff diff : diffs) {
+        diff_match_patch.Diff diff;
+        int size = diffs.size();
+        boolean isLastDiff;
+        for (int j = 0; j < size; j++) {
+            diff = diffs.get(j);
+            isLastDiff = j == size - 1;
             switch (diff.operation) {
                 case DELETE:
-                    line = processDiff(diff, lineNums, lines, line, i, delSpan);
+                    line = processDiff(diff, lineNums, lines, line, i, delSpan, isLastDiff);
                     if (line.equals("")) {
                         i++;
                     }
                     break;
 
                 case INSERT:
-                    if (diff.text.endsWith("\n")) {
-                        lineNums.add(DONT_PRINT_LINE_NUMBER);
-                        lines.add("");
+                    // If the line is currently empty and this insertion is the entire line, the
+                    // expected line is absent, so it has no line number.
+                    if (diff.text.endsWith("\n") || isLastDiff) {
+                        lineNums.add(line.equals("") ? DONT_PRINT_LINE_NUMBER : i++);
+                        lines.add(line);
+                        line = "";
                     }
                     break;
 
                 case EQUAL:
-                    line = processDiff(diff, lineNums, lines, line, i, eqlSpan);
+                    line = processDiff(diff, lineNums, lines, line, i, eqlSpan, isLastDiff);
                     if (line.equals("")) {
                         i++;
                     }
                     break;
             }
         }
-
-        if (!line.isEmpty()) {
-            lines.add(line);
-            lineNums.add(i);
-        }
     }
 
     public static void generateActualResultLines(LinkedList<diff_match_patch.Diff> diffs,
@@ -106,35 +109,38 @@
 
         String line = "";
         int i = 1;
-        for (diff_match_patch.Diff diff : diffs) {
+        diff_match_patch.Diff diff;
+        int size = diffs.size();
+        boolean isLastDiff;
+        for (int j = 0; j < size; j++) {
+            diff = diffs.get(j);
+            isLastDiff = j == size - 1;
             switch (diff.operation) {
                 case INSERT:
-                    line = processDiff(diff, lineNums, lines, line, i, insSpan);
+                    line = processDiff(diff, lineNums, lines, line, i, insSpan, isLastDiff);
                     if (line.equals("")) {
                         i++;
                     }
                     break;
 
                 case DELETE:
-                    if (diff.text.endsWith("\n")) {
-                        lineNums.add(DONT_PRINT_LINE_NUMBER);
-                        lines.add("");
+                    // If the line is currently empty and deletion is the entire line, the
+                    // actual line is absent, so it has no line number.
+                    if (diff.text.endsWith("\n") || isLastDiff) {
+                        lineNums.add(line.equals("") ? DONT_PRINT_LINE_NUMBER : i++);
+                        lines.add(line);
+                        line = "";
                     }
                     break;
 
                 case EQUAL:
-                    line = processDiff(diff, lineNums, lines, line, i, eqlSpan);
+                    line = processDiff(diff, lineNums, lines, line, i, eqlSpan, isLastDiff);
                     if (line.equals("")) {
                         i++;
                     }
                     break;
             }
         }
-
-        if (!line.isEmpty()) {
-            lines.add(line);
-            lineNums.add(i);
-        }
     }
 
     /**
@@ -147,15 +153,16 @@
      * @param line
      * @param i
      * @param begSpan
+     * @param forceOutputLine Force the current line to be output
      * @return
      */
     public static String processDiff(diff_match_patch.Diff diff, LinkedList<Integer> lineNums,
-            LinkedList<String> lines, String line, int i, String begSpan) {
+            LinkedList<String> lines, String line, int i, String begSpan, boolean forceOutputLine) {
         String endSpan = "</span>";
         String br = "&nbsp;";
 
-        if (diff.text.endsWith("\n")) {
-            lineNums.add(i++);
+        if (diff.text.endsWith("\n") || forceOutputLine) {
+            lineNums.add(i);
             /** TODO: Think of better way to replace stuff */
             line += begSpan + diff.text.replace("  ", "&nbsp;&nbsp;")
                     + endSpan + br;
@@ -204,4 +211,4 @@
         }
         return html.toString();
     }
-}
\ No newline at end of file
+}