Add plumbing for new surface flinger display API.

Cleaned up the implementation of Surface and SurfaceSession
to use more consistent naming and structure.

Added JNI for all of the new surface flinger display API calls.

Enforced the requirement that all Surfaces created by
the window manager be named.

Updated the display manager service to use the new methods.

Change-Id: I2a658f1bfd0437e1c6f9d22df8d4ffcce7284ca2
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 84b3d64..cf1767d7 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,6 +16,8 @@
 
 package android.view;
 
+import dalvik.system.CloseGuard;
+
 import android.content.res.CompatibilityInfo.Translator;
 import android.graphics.Bitmap;
 import android.graphics.Canvas;
@@ -23,9 +25,9 @@
 import android.graphics.Rect;
 import android.graphics.Region;
 import android.graphics.SurfaceTexture;
+import android.os.IBinder;
 import android.os.Parcelable;
 import android.os.Parcel;
-import android.os.Process;
 import android.os.SystemProperties;
 import android.util.Log;
 
@@ -33,206 +35,187 @@
  * Handle onto a raw buffer that is being managed by the screen compositor.
  */
 public class Surface implements Parcelable {
-    private static final String LOG_TAG = "Surface";
-    private static final boolean DEBUG_RELEASE = false;
-    
-    /* orientations for setOrientation() */
-    public static final int ROTATION_0       = 0;
-    public static final int ROTATION_90      = 1;
-    public static final int ROTATION_180     = 2;
-    public static final int ROTATION_270     = 3;
+    private static final String TAG = "Surface";
 
-    private static final boolean headless = "1".equals(
+    private static final boolean HEADLESS = "1".equals(
         SystemProperties.get("ro.config.headless", "0"));
 
-    private static void checkHeadless() {
-        if(headless) {
-            throw new UnsupportedOperationException("Device is headless");
+    public static final Parcelable.Creator<Surface> CREATOR =
+            new Parcelable.Creator<Surface>() {
+        public Surface createFromParcel(Parcel source) {
+            try {
+                Surface s = new Surface();
+                s.readFromParcel(source);
+                return s;
+            } catch (Exception e) {
+                Log.e(TAG, "Exception creating surface from parcel", e);
+                return null;
+            }
         }
-    }
+
+        public Surface[] newArray(int size) {
+            return new Surface[size];
+        }
+    };
 
     /**
-     * Create Surface from a {@link SurfaceTexture}.
-     *
-     * Images drawn to the Surface will be made available to the {@link
-     * SurfaceTexture}, which can attach them an OpenGL ES texture via {@link
-     * SurfaceTexture#updateTexImage}.
-     *
-     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
-     * Surface.
+     * Rotation constant: 0 degree rotation (natural orientation)
      */
-    public Surface(SurfaceTexture surfaceTexture) {
-        checkHeadless();
-
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
-        initFromSurfaceTexture(surfaceTexture);
-    }
+    public static final int ROTATION_0 = 0;
 
     /**
-     * Does this object hold a valid surface?  Returns true if it holds
-     * a physical surface, so lockCanvas() will succeed.  Otherwise
-     * returns false.
+     * Rotation constant: 90 degree rotation.
      */
-    public native   boolean isValid();
-
-    /** Release the local reference to the server-side surface.  
-     * Always call release() when you're done with a Surface. This will
-     * make the surface invalid.
-     */
-    public native void release();
-
-    /** draw into a surface */
-    public Canvas lockCanvas(Rect dirty) throws OutOfResourcesException, IllegalArgumentException {
-        /*
-         * the dirty rectangle may be expanded to the surface's size, if for
-         * instance it has been resized or if the bits were lost, since the last
-         * call.
-         */
-        return lockCanvasNative(dirty);
-    }
-
-    /** unlock the surface and asks a page flip */
-    public native   void unlockCanvasAndPost(Canvas canvas);
-
-    /** 
-     * unlock the surface. the screen won't be updated until
-     * post() or postAll() is called
-     */
-    public native   void unlockCanvas(Canvas canvas);
-
-    @Override
-    public String toString() {
-        return "Surface(name=" + mName + ", identity=" + getIdentity() + ")";
-    }
-
-    public int describeContents() {
-        return 0;
-    }
-
-    public native   void readFromParcel(Parcel source);
-    public native   void writeToParcel(Parcel dest, int flags);
+    public static final int ROTATION_90 = 1;
 
     /**
-     * Exception thrown when a surface couldn't be created or resized
+     * Rotation constant: 180 degree rotation.
      */
-    public static class OutOfResourcesException extends Exception {
-        public OutOfResourcesException() {
-        }
-        public OutOfResourcesException(String name) {
-            super(name);
-        }
-    }
-    
-    /*
-     * -----------------------------------------------------------------------
-     * No user serviceable parts beyond this point
-     * -----------------------------------------------------------------------
+    public static final int ROTATION_180 = 2;
+
+    /**
+     * Rotation constant: 270 degree rotation.
      */
+    public static final int ROTATION_270 = 3;
 
-    /* flags used in constructor (keep in sync with ISurfaceComposer.h) */
+    /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
+     * these are different from the logical display ids used elsewhere in the framework */
 
-    /** Surface is created hidden @hide */
-    public static final int HIDDEN              = 0x00000004;
+    /**
+     * Built-in physical display id: Main display.
+     * Use only with {@link #getBuiltInDisplay()}.
+     * @hide
+     */
+    public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
 
-    /** The surface contains secure content, special measures will
-     * be taken to disallow the surface's content to be copied from
-     * another process. In particular, screenshots and VNC servers will
+    /**
+     * Built-in physical display id: Attached HDMI display.
+     * Use only with {@link #getBuiltInDisplay()}.
+     * @hide
+     */
+    public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
+
+    /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
+
+    /**
+     * Surface creation flag: Surface is created hidden
+     * @hide */
+    public static final int HIDDEN = 0x00000004;
+
+    /**
+     * Surface creation flag: The surface contains secure content, special
+     * measures will be taken to disallow the surface's content to be copied
+     * from another process. In particular, screenshots and VNC servers will
      * be disabled, but other measures can take place, for instance the
      * surface might not be hardware accelerated. 
-     * @hide*/
-    public static final int SECURE              = 0x00000080;
-    
-    /** Creates a surface where color components are interpreted as 
-     *  "non pre-multiplied" by their alpha channel. Of course this flag is
-     *  meaningless for surfaces without an alpha channel. By default
-     *  surfaces are pre-multiplied, which means that each color component is
-     *  already multiplied by its alpha value. In this case the blending
-     *  equation used is:
-     *  
-     *    DEST = SRC + DEST * (1-SRC_ALPHA)
-     *    
-     *  By contrast, non pre-multiplied surfaces use the following equation:
-     *  
-     *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
-     *    
-     *  pre-multiplied surfaces must always be used if transparent pixels are
-     *  composited on top of each-other into the surface. A pre-multiplied
-     *  surface can never lower the value of the alpha component of a given
-     *  pixel.
-     *  
-     *  In some rare situations, a non pre-multiplied surface is preferable.
-     *  
-     *  @hide
+     * @hide
      */
-    public static final int NON_PREMULTIPLIED   = 0x00000100;
-    
+    public static final int SECURE = 0x00000080;
+
     /**
-     * Indicates that the surface must be considered opaque, even if its
-     * pixel format is set to translucent. This can be useful if an
+     * Surface creation flag: Creates a surface where color components are interpreted
+     * as "non pre-multiplied" by their alpha channel. Of course this flag is
+     * meaningless for surfaces without an alpha channel. By default
+     * surfaces are pre-multiplied, which means that each color component is
+     * already multiplied by its alpha value. In this case the blending
+     * equation used is:
+     *
+     *    DEST = SRC + DEST * (1-SRC_ALPHA)
+     *
+     * By contrast, non pre-multiplied surfaces use the following equation:
+     *
+     *    DEST = SRC * SRC_ALPHA * DEST * (1-SRC_ALPHA)
+     *
+     * pre-multiplied surfaces must always be used if transparent pixels are
+     * composited on top of each-other into the surface. A pre-multiplied
+     * surface can never lower the value of the alpha component of a given
+     * pixel.
+     *
+     * In some rare situations, a non pre-multiplied surface is preferable.
+     * @hide
+     */
+    public static final int NON_PREMULTIPLIED = 0x00000100;
+
+    /**
+     * Surface creation flag: Indicates that the surface must be considered opaque,
+     * even if its pixel format is set to translucent. This can be useful if an
      * application needs full RGBA 8888 support for instance but will
      * still draw every pixel opaque.
-     * 
      * @hide
      */
-    public static final int OPAQUE              = 0x00000400;
-    
+    public static final int OPAQUE = 0x00000400;
+
     /**
-     * Application requires a hardware-protected path to an
+     * Surface creation flag: Application requires a hardware-protected path to an
      * external display sink. If a hardware-protected path is not available,
      * then this surface will not be displayed on the external sink.
-     *
      * @hide
      */
-    public static final int PROTECTED_APP       = 0x00000800;
+    public static final int PROTECTED_APP = 0x00000800;
 
     // 0x1000 is reserved for an independent DRM protected flag in framework
 
-    /** Creates a normal surface. This is the default. @hide */
+    /**
+     * Surface creation flag: Creates a normal surface.
+     * This is the default.
+     * @hide
+     */
     public static final int FX_SURFACE_NORMAL   = 0x00000000;
-    
-    /** Creates a Blur surface. Everything behind this surface is blurred
-     * by some amount. The quality and refresh speed of the blur effect
-     * is not settable or guaranteed.
-     * It is an error to lock a Blur surface, since it doesn't have
-     * a backing store.
+
+    /**
+     * Surface creation flag: Creates a Blur surface.
+     * Everything behind this surface is blurred by some amount.
+     * The quality and refresh speed of the blur effect is not settable or guaranteed.
+     * It is an error to lock a Blur surface, since it doesn't have a backing store.
      * @hide
      * @deprecated
      */
     @Deprecated
-    public static final int FX_SURFACE_BLUR     = 0x00010000;
-    
-    /** Creates a Dim surface. Everything behind this surface is dimmed
-     * by the amount specified in {@link #setAlpha}.
-     * It is an error to lock a Dim surface, since it doesn't have
-     * a backing store.
+    public static final int FX_SURFACE_BLUR = 0x00010000;
+
+    /**
+     * Surface creation flag: Creates a Dim surface.
+     * Everything behind this surface is dimmed by the amount specified
+     * in {@link #setAlpha}.  It is an error to lock a Dim surface, since it
+     * doesn't have a backing store.
      * @hide
      */
-    public static final int FX_SURFACE_DIM     = 0x00020000;
+    public static final int FX_SURFACE_DIM = 0x00020000;
 
-    /** @hide */
-    public static final int FX_SURFACE_SCREENSHOT   = 0x00030000;
+    /**
+     * @hide
+     */
+    public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
 
-    /** Mask used for FX values above @hide */
-    public static final int FX_SURFACE_MASK     = 0x000F0000;
+    /**
+     * Mask used for FX values above.
+     * @hide
+     */
+    public static final int FX_SURFACE_MASK = 0x000F0000;
 
     /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
     
-    /** Hide the surface. Equivalent to calling hide(). @hide */
-    public static final int SURFACE_HIDDEN    = 0x01;
+    /**
+     * Surface flag: Hide the surface.
+     * Equivalent to calling hide().
+     * @hide
+     */
+    public static final int SURFACE_HIDDEN = 0x01;
 
+
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private String mName;
+
+    // Note: These fields are accessed by native code.
     // The mSurfaceControl will only be present for Surfaces used by the window
     // server or system processes. When this class is parceled we defer to the
     // mSurfaceControl to do the parceling. Otherwise we parcel the
     // mNativeSurface.
-    private int mSurfaceControl;
-    private int mSaveCount;
-    private Canvas mCanvas;
-    private int mNativeSurface;
-    private int mSurfaceGenerationId;
-    private String mName;
+    private int mNativeSurface; // Surface*
+    private int mNativeSurfaceControl; // SurfaceControl*
+    private int mGenerationId; // incremented each time mNativeSurface changes
+    private final Canvas mCanvas = new CompatibleCanvas();
+    private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
 
     // The Translator for density compatibility mode.  This is used for scaling
     // the canvas to perform the appropriate density transformation.
@@ -242,53 +225,436 @@
     // non compatibility mode.
     private Matrix mCompatibleMatrix;
 
-    private Exception mCreationStack;
+    private native void nativeCreate(SurfaceSession session, String name,
+            int w, int h, int format, int flags)
+            throws OutOfResourcesException;
+    private native void nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
+            throws OutOfResourcesException;
+    private native void nativeRelease();
+    private native void nativeDestroy();
 
+    private native boolean nativeIsValid();
+    private native int nativeGetIdentity();
+    private native boolean nativeIsConsumerRunningBehind();
 
-    /*
-     * We use a class initializer to allow the native code to cache some
-     * field offsets.
-     */
-    native private static void nativeClassInit();
-    static { nativeClassInit(); }
+    private native Canvas nativeLockCanvas(Rect dirty);
+    private native void nativeUnlockCanvasAndPost(Canvas canvas);
 
-    /** create a surface with a name @hide */
-    public Surface(SurfaceSession s,
-            int pid, String name, int layerStack, int w, int h, int format, int flags)
-        throws OutOfResourcesException {
-        // FIXME: remove pid and layerstack arguments
-        checkHeadless();
+    private static native Bitmap nativeScreenshot(IBinder displayToken,
+            int width, int height, int minLayer, int maxLayer, boolean allLayers);
 
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
+    private static native void nativeOpenTransaction();
+    private static native void nativeCloseTransaction();
 
-        if (name == null) {
-            name = "<pid " + Process.myPid() + ">";
-        }
+    private native void nativeSetLayer(int zorder);
+    private native void nativeSetPosition(float x, float y);
+    private native void nativeSetSize(int w, int h);
+    private native void nativeSetTransparentRegionHint(Region region);
+    private native void nativeSetAlpha(float alpha);
+    private native void nativeSetMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
+    private native void nativeSetFlags(int flags, int mask);
+    private native void nativeSetWindowCrop(Rect crop);
+    private native void nativeSetLayerStack(int layerStack);
 
-        mCanvas = new CompatibleCanvas();
-        init(s, name, w, h, format, flags);
-        setLayerStack(layerStack);
-        mName = name;
-    }
+    private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
+    private static native IBinder nativeCreateDisplay(String name);
+    private static native void nativeSetDisplaySurface(
+            IBinder displayToken, SurfaceTexture surfaceTexture);
+    private static native void nativeSetDisplayLayerStack(
+            IBinder displayToken, int layerStack);
+    private static native void nativeSetDisplayOrientation(
+            IBinder displayToken, int orientation);
+    private static native void nativeSetDisplayViewport(
+            IBinder displayToken, Rect viewport);
+    private static native void nativeSetDisplayFrame(
+            IBinder displayToken, Rect frame);
+    private static native boolean nativeGetDisplayInfo(
+            IBinder displayToken, PhysicalDisplayInfo outInfo);
+
+    private native void nativeCopyFrom(Surface other);
+    private native void nativeTransferFrom(Surface other);
+    private native void nativeReadFromParcel(Parcel source);
+    private native void nativeWriteToParcel(Parcel dest);
+
 
     /**
-     * Create an empty surface, which will later be filled in by
-     * readFromParcel().
+     * Create an empty surface, which will later be filled in by readFromParcel().
      * @hide
      */
     public Surface() {
         checkHeadless();
 
-        if (DEBUG_RELEASE) {
-            mCreationStack = new Exception();
-        }
-        mCanvas = new CompatibleCanvas();
+        mCloseGuard.open("release");
     }
 
-    private Surface(Parcel source) throws OutOfResourcesException {
-        init(source);
+    /**
+     * Create a surface with a name.
+     *
+     * The surface creation flags specify what kind of surface to create and
+     * certain options such as whether the surface can be assumed to be opaque
+     * and whether it should be initially hidden.  Surfaces should always be
+     * created with the {@link #HIDDEN} flag set to ensure that they are not
+     * made visible prematurely before all of the surface's properties have been
+     * configured.
+     *
+     * Good practice is to first create the surface with the {@link #HIDDEN} flag
+     * specified, open a transaction, set the surface layer, layer stack, alpha,
+     * and position, call {@link #show} if appropriate, and close the transaction.
+     *
+     * @param session The surface session, must not be null.
+     * @param name The surface name, must not be null.
+     * @param w The surface initial width.
+     * @param h The surface initial height.
+     * @param flags The surface creation flags.  Should always include {@link #HIDDEN}
+     * in the creation flags.
+     * @hide
+     */
+    public Surface(SurfaceSession session,
+            String name, int w, int h, int format, int flags)
+            throws OutOfResourcesException {
+        if (session == null) {
+            throw new IllegalArgumentException("session must not be null");
+        }
+        if (name == null) {
+            throw new IllegalArgumentException("name must not be null");
+        }
+
+        if ((flags & HIDDEN) == 0) {
+            Log.w(TAG, "Surfaces should always be created with the HIDDEN flag set "
+                    + "to ensure that they are not made visible prematurely before "
+                    + "all of the surface's properties have been configured.  "
+                    + "Set the other properties and make the surface visible within "
+                    + "a transaction.  New surface name: " + name,
+                    new Throwable());
+        }
+
+        checkHeadless();
+
+        mName = name;
+        nativeCreate(session, name, w, h, format, flags);
+
+        mCloseGuard.open("release");
+    }
+
+    /**
+     * Create Surface from a {@link SurfaceTexture}.
+     *
+     * Images drawn to the Surface will be made available to the {@link
+     * SurfaceTexture}, which can attach them to an OpenGL ES texture via {@link
+     * SurfaceTexture#updateTexImage}.
+     *
+     * @param surfaceTexture The {@link SurfaceTexture} that is updated by this
+     * Surface.
+     */
+    public Surface(SurfaceTexture surfaceTexture) {
+        if (surfaceTexture == null) {
+            throw new IllegalArgumentException("surfaceTexture must not be null");
+        }
+
+        checkHeadless();
+
+        mName = surfaceTexture.toString();
+        try {
+            nativeCreateFromSurfaceTexture(surfaceTexture);
+        } catch (OutOfResourcesException ex) {
+            // We can't throw OutOfResourcesException because it would be an API change.
+            throw new RuntimeException(ex);
+        }
+
+        mCloseGuard.open("release");
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            nativeRelease();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    /**
+     * Release the local reference to the server-side surface.
+     * Always call release() when you're done with a Surface.
+     * This will make the surface invalid.
+     */
+    public void release() {
+        nativeRelease();
+        mCloseGuard.close();
+    }
+
+    /**
+     * Free all server-side state associated with this surface and
+     * release this object's reference.  This method can only be
+     * called from the process that created the service.
+     * @hide
+     */
+    public void destroy() {
+        nativeDestroy();
+        mCloseGuard.close();
+    }
+
+    /**
+     * Returns true if this object holds a valid surface.
+     *
+     * @return True if it holds a physical surface, so lockCanvas() will succeed.
+     * Otherwise returns false.
+     */
+    public boolean isValid() {
+        return nativeIsValid();
+    }
+
+    /**
+     * Gets the generation number of this surface, incremented each time
+     * the native surface contained within this object changes.
+     *
+     * @return The current generation number.
+     * @hide
+     */
+    public int getGenerationId() {
+        return mGenerationId;
+    }
+
+    /**
+     * Returns true if the consumer of this Surface is running behind the producer.
+     *
+     * @return True if the consumer is more than one buffer ahead of the producer.
+     * @hide
+     */
+    public boolean isConsumerRunningBehind() {
+        return nativeIsConsumerRunningBehind();
+    }
+
+    /**
+     * Gets a {@link Canvas} for drawing into this surface.
+     *
+     * After drawing into the provided {@link Canvas}, the caller should
+     * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
+     *
+     * @param dirty A rectangle that represents the dirty region that the caller wants
+     * to redraw.  This function may choose to expand the dirty rectangle if for example
+     * the surface has been resized or if the previous contents of the surface were
+     * not available.  The caller should redraw the entire dirty region as represented
+     * by the contents of the dirty rect upon return from this function.
+     * The caller may also pass <code>null</code> instead, in the case where the
+     * entire surface should be redrawn.
+     * @return A canvas for drawing into the surface.
+     */
+    public Canvas lockCanvas(Rect dirty)
+            throws OutOfResourcesException, IllegalArgumentException {
+        return nativeLockCanvas(dirty);
+    }
+
+    /**
+     * Posts the new contents of the {@link Canvas} to the surface and
+     * releases the {@link Canvas}.
+     *
+     * @param canvas The canvas previously obtained from {@link #lockCanvas}.
+     */
+    public void unlockCanvasAndPost(Canvas canvas) {
+        nativeUnlockCanvasAndPost(canvas);
+    }
+
+    /** 
+     * @deprecated This API has been removed and is not supported.  Do not use.
+     */
+    @Deprecated
+    public void unlockCanvas(Canvas canvas) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Sets the translator used to scale canvas's width/height in compatibility
+     * mode.
+     */
+    void setCompatibilityTranslator(Translator translator) {
+        if (translator != null) {
+            float appScale = translator.applicationScale;
+            mCompatibleMatrix = new Matrix();
+            mCompatibleMatrix.setScale(appScale, appScale);
+        }
+    }
+
+    /**
+     * Like {@link #screenshot(int, int, int, int)} but includes all
+     * Surfaces in the screenshot.
+     *
+     * @hide
+     */
+    public static Bitmap screenshot(int width, int height) {
+        // TODO: should take the display as a parameter
+        IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
+        return nativeScreenshot(displayToken, width, height, 0, 0, true);
+    }
+
+    /**
+     * Copy the current screen contents into a bitmap and return it.
+     *
+     * @param width The desired width of the returned bitmap; the raw
+     * screen will be scaled down to this size.
+     * @param height The desired height of the returned bitmap; the raw
+     * screen will be scaled down to this size.
+     * @param minLayer The lowest (bottom-most Z order) surface layer to
+     * include in the screenshot.
+     * @param maxLayer The highest (top-most Z order) surface layer to
+     * include in the screenshot.
+     * @return Returns a Bitmap containing the screen contents, or null
+     * if an error occurs.
+     *
+     * @hide
+     */
+    public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
+        // TODO: should take the display as a parameter
+        IBinder displayToken = getBuiltInDisplay(BUILT_IN_DISPLAY_ID_MAIN);
+        return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
+    }
+
+    /*
+     * set surface parameters.
+     * needs to be inside open/closeTransaction block
+     */
+
+    /** start a transaction @hide */
+    public static void openTransaction() {
+        nativeOpenTransaction();
+    }
+
+    /** end a transaction @hide */
+    public static void closeTransaction() {
+        nativeCloseTransaction();
+    }
+
+    /** @hide */
+    public void setLayer(int zorder) {
+        nativeSetLayer(zorder);
+    }
+
+    /** @hide */
+    public void setPosition(int x, int y) {
+        nativeSetPosition((float)x, (float)y);
+    }
+
+    /** @hide */
+    public void setPosition(float x, float y) {
+        nativeSetPosition(x, y);
+    }
+
+    /** @hide */
+    public void setSize(int w, int h) {
+        nativeSetSize(w, h);
+    }
+
+    /** @hide */
+    public void hide() {
+        nativeSetFlags(SURFACE_HIDDEN, SURFACE_HIDDEN);
+    }
+
+    /** @hide */
+    public void show() {
+        nativeSetFlags(0, SURFACE_HIDDEN);
+    }
+
+    /** @hide */
+    public void setTransparentRegionHint(Region region) {
+        nativeSetTransparentRegionHint(region);
+    }
+
+    /** @hide */
+    public void setAlpha(float alpha) {
+        nativeSetAlpha(alpha);
+    }
+
+    /** @hide */
+    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+        nativeSetMatrix(dsdx, dtdx, dsdy, dtdy);
+    }
+
+    /** @hide */
+    public void setFlags(int flags, int mask) {
+        nativeSetFlags(flags, mask);
+    }
+
+    /** @hide */
+    public void setWindowCrop(Rect crop) {
+        nativeSetWindowCrop(crop);
+    }
+
+    /** @hide */
+    public void setLayerStack(int layerStack) {
+        nativeSetLayerStack(layerStack);
+    }
+
+    /** @hide */
+    public static IBinder getBuiltInDisplay(int builtInDisplayId) {
+        return nativeGetBuiltInDisplay(builtInDisplayId);
+    }
+
+    /** @hide */
+    public static IBinder createDisplay(String name) {
+        if (name == null) {
+            throw new IllegalArgumentException("name must not be null");
+        }
+        return nativeCreateDisplay(name);
+    }
+
+    /** @hide */
+    public static void setDisplaySurface(IBinder displayToken, SurfaceTexture surfaceTexture) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplaySurface(displayToken, surfaceTexture);
+    }
+
+    /** @hide */
+    public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplayLayerStack(displayToken, layerStack);
+    }
+
+    /** @hide */
+    public static void setDisplayOrientation(IBinder displayToken, int orientation) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplayOrientation(displayToken, orientation);
+    }
+
+    /** @hide */
+    public static void setDisplayViewport(IBinder displayToken, Rect viewport) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (viewport == null) {
+            throw new IllegalArgumentException("viewport must not be null");
+        }
+        nativeSetDisplayViewport(displayToken, viewport);
+    }
+
+    /** @hide */
+    public static void setDisplayFrame(IBinder displayToken, Rect frame) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (frame == null) {
+            throw new IllegalArgumentException("frame must not be null");
+        }
+        nativeSetDisplayFrame(displayToken, frame);
+    }
+
+    /** @hide */
+    public static boolean getDisplayInfo(IBinder displayToken, PhysicalDisplayInfo outInfo) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (outInfo == null) {
+            throw new IllegalArgumentException("outInfo must not be null");
+        }
+        return nativeGetDisplayInfo(displayToken, outInfo);
     }
 
     /**
@@ -300,35 +666,99 @@
      * in to it.
      * @hide
      */
-    public native void copyFrom(Surface o);
+    public void copyFrom(Surface other) {
+        if (other == null) {
+            throw new IllegalArgumentException("other must not be null");
+        }
+        if (other != this) {
+            nativeCopyFrom(other);
+        }
+    }
 
     /**
-     * Transfer the native state from 'o' to this surface, releasing it
-     * from 'o'.  This is for use in the client side for drawing into a
+     * Transfer the native state from 'other' to this surface, releasing it
+     * from 'other'.  This is for use in the client side for drawing into a
      * surface; not guaranteed to work on the window manager side.
      * This is for use by the client to move the underlying surface from
      * one Surface object to another, in particular in SurfaceFlinger.
      * @hide.
      */
-    public native void transferFrom(Surface o);
-
-    /** @hide */
-    public int getGenerationId() {
-        return mSurfaceGenerationId;
+    public void transferFrom(Surface other) {
+        if (other == null) {
+            throw new IllegalArgumentException("other must not be null");
+        }
+        if (other != this) {
+            nativeTransferFrom(other);
+        }
     }
 
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public void readFromParcel(Parcel source) {
+        if (source == null) {
+            throw new IllegalArgumentException("source must not be null");
+        }
+
+        mName = source.readString();
+        nativeReadFromParcel(source);
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        if (dest == null) {
+            throw new IllegalArgumentException("dest must not be null");
+        }
+
+        dest.writeString(mName);
+        nativeWriteToParcel(dest);
+        if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
+            release();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")";
+    }
+
+    private static void checkHeadless() {
+        if (HEADLESS) {
+            throw new UnsupportedOperationException("Device is headless");
+        }
+    }
 
     /**
-     * Whether the consumer of this Surface is running behind the producer;
-     * that is, isConsumerRunningBehind() returns true if the consumer is more
-     * than one buffer ahead of the producer.
+     * Exception thrown when a surface couldn't be created or resized.
+     */
+    public static class OutOfResourcesException extends Exception {
+        public OutOfResourcesException() {
+        }
+
+        public OutOfResourcesException(String name) {
+            super(name);
+        }
+    }
+
+    /**
+     * Describes the properties of a physical display.
      * @hide
      */
-    public native boolean isConsumerRunningBehind();
+    public static final class PhysicalDisplayInfo {
+        // TODO: redesign this
+        public int width;
+        public int height;
+        public float refreshRate;
+        public float density;
+        public float xDpi;
+        public float yDpi;
+    }
 
     /**
-     * A Canvas class that can handle the compatibility mode. This does two
-     * things differently.
+     * A Canvas class that can handle the compatibility mode.
+     * This does two things differently.
      * <ul>
      * <li>Returns the width and height of the target metrics, rather than
      * native. For example, the canvas returns 320x480 even if an app is running
@@ -341,7 +771,7 @@
      * that this model does not work, but we hope this works for many apps.
      * </ul>
      */
-    private class CompatibleCanvas extends Canvas {
+    private final class CompatibleCanvas extends Canvas {
         // A temp matrix to remember what an application obtained via {@link getMatrix}
         private Matrix mOrigMatrix = null;
 
@@ -385,137 +815,4 @@
             mOrigMatrix.set(m);
         }
     }
-
-    /**
-     * Sets the translator used to scale canvas's width/height in compatibility
-     * mode.
-     */
-    void setCompatibilityTranslator(Translator translator) {
-        if (translator != null) {
-            float appScale = translator.applicationScale;
-            mCompatibleMatrix = new Matrix();
-            mCompatibleMatrix.setScale(appScale, appScale);
-        }
-    }
-    
-    /** Free all server-side state associated with this surface and
-     * release this object's reference. @hide */
-    public native void destroy();
-
-    private native Canvas lockCanvasNative(Rect dirty) throws OutOfResourcesException;
-
-    /**
-     * set the orientation of the given display.
-     * @param display
-     * @param orientation
-     * @hide
-     */
-    public static native void setOrientation(int display, int orientation);
-
-    /**
-     * Like {@link #screenshot(int, int, int, int)} but includes all
-     * Surfaces in the screenshot.
-     *
-     * @hide
-     */
-    public static native Bitmap screenshot(int width, int height);
-    
-    /**
-     * Copy the current screen contents into a bitmap and return it.
-     *
-     * @param width The desired width of the returned bitmap; the raw
-     * screen will be scaled down to this size.
-     * @param height The desired height of the returned bitmap; the raw
-     * screen will be scaled down to this size.
-     * @param minLayer The lowest (bottom-most Z order) surface layer to
-     * include in the screenshot.
-     * @param maxLayer The highest (top-most Z order) surface layer to
-     * include in the screenshot.
-     * @return Returns a Bitmap containing the screen contents.
-     *
-     * @hide
-     */
-    public static native Bitmap screenshot(int width, int height, int minLayer, int maxLayer);
-
-    
-    /*
-     * set surface parameters.
-     * needs to be inside open/closeTransaction block
-     */
-    
-    /** start a transaction @hide */
-    public static native   void openTransaction();
-    /** end a transaction @hide */
-    public static native   void closeTransaction();
-    /** @hide */
-    public native   void setLayer(int zorder);
-    /** @hide */
-    public void setPosition(int x, int y) { setPosition((float)x, (float)y); }
-    /** @hide */
-    public native   void setPosition(float x, float y);
-    /** @hide */
-    public native   void setSize(int w, int h);
-    /** @hide */
-    public native   void hide();
-    /** @hide */
-    public native   void show();
-    /** @hide */
-    public native   void setTransparentRegionHint(Region region);
-    /** @hide */
-    public native   void setAlpha(float alpha);
-    /** @hide */
-    public native   void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy);
-    /** @hide */
-    public native   void setFlags(int flags, int mask);
-    /** @hide */
-    public native   void setWindowCrop(Rect crop);
-    /** @hide */
-    public native   void setLayerStack(int layerStack);
-
-
-   
-    public static final Parcelable.Creator<Surface> CREATOR
-            = new Parcelable.Creator<Surface>()
-    {
-        public Surface createFromParcel(Parcel source) {
-            try {
-                return new Surface(source);
-            } catch (Exception e) {
-                Log.e(LOG_TAG, "Exception creating surface from parcel", e);
-            }
-            return null;
-        }
-
-        public Surface[] newArray(int size) {
-            return new Surface[size];
-        }
-    };
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            super.finalize();
-        } finally {
-            if (mNativeSurface != 0 || mSurfaceControl != 0) {
-                if (DEBUG_RELEASE) {
-                    Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 
-                            + mNativeSurface + ", " + mSurfaceControl + ")", mCreationStack);
-                } else {
-                    Log.w(LOG_TAG, "Surface.finalize() has work. You should have called release() (" 
-                            + mNativeSurface + ", " + mSurfaceControl + ")");
-                }
-            }
-            release();            
-        }
-    }
-    
-    private native void init(SurfaceSession s, String name,
-            int w, int h, int format, int flags)
-            throws OutOfResourcesException;
-
-    private native void init(Parcel source) throws OutOfResourcesException;
-
-    private native void initFromSurfaceTexture(SurfaceTexture surfaceTexture);
-
-    private native int getIdentity();
 }
diff --git a/core/java/android/view/SurfaceSession.java b/core/java/android/view/SurfaceSession.java
index 2491abe..0dfd94a 100644
--- a/core/java/android/view/SurfaceSession.java
+++ b/core/java/android/view/SurfaceSession.java
@@ -16,30 +16,32 @@
 
 package android.view;
 
-
 /**
  * An instance of this class represents a connection to the surface
- * flinger, in which you can create one or more Surface instances that will
+ * flinger, from which you can create one or more Surface instances that will
  * be composited to the screen.
  * {@hide}
  */
-public class SurfaceSession {
-    private int mClient;
+public final class SurfaceSession {
+    // Note: This field is accessed by native code.
+    private int mNativeClient; // SurfaceComposerClient*
 
-    private native void nativeInit();
-    private native void nativeDestroy();
-    private native void nativeKill();
+    private static native int nativeCreate();
+    private static native void nativeDestroy(int ptr);
+    private static native void nativeKill(int ptr);
 
     /** Create a new connection with the surface flinger. */
     public SurfaceSession() {
-        nativeInit();
+        mNativeClient = nativeCreate();
     }
 
     /* no user serviceable parts here ... */
     @Override
     protected void finalize() throws Throwable {
         try {
-            nativeDestroy();
+            if (mNativeClient != 0) {
+                nativeDestroy(mNativeClient);
+            }
         } finally {
             super.finalize();
         }
@@ -48,10 +50,10 @@
     /**
      * Forcibly detach native resources associated with this object.
      * Unlike destroy(), after this call any surfaces that were created
-     * from the session will no longer work. The session itself is destroyed.
+     * from the session will no longer work.
      */
     public void kill() {
-        nativeKill();
+        nativeKill(mNativeClient);
     }
 }
 
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index f950d3d..9d45479 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -46,6 +46,7 @@
 	android_emoji_EmojiFactory.cpp \
 	android_view_DisplayEventReceiver.cpp \
 	android_view_Surface.cpp \
+	android_view_SurfaceSession.cpp \
 	android_view_TextureView.cpp \
 	android_view_InputChannel.cpp \
 	android_view_InputDevice.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index 0c88297..55563a8 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -121,6 +121,7 @@
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
 extern int register_android_view_HardwareRenderer(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
+extern int register_android_view_SurfaceSession(JNIEnv* env);
 extern int register_android_view_TextureView(JNIEnv* env);
 extern int register_android_database_CursorWindow(JNIEnv* env);
 extern int register_android_database_SQLiteConnection(JNIEnv* env);
@@ -1094,6 +1095,7 @@
     REG_JNI(register_android_view_GLES20Canvas),
     REG_JNI(register_android_view_HardwareRenderer),
     REG_JNI(register_android_view_Surface),
+    REG_JNI(register_android_view_SurfaceSession),
     REG_JNI(register_android_view_TextureView),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
     REG_JNI(register_com_google_android_gles_jni_GLImpl),
diff --git a/core/jni/android_app_NativeActivity.cpp b/core/jni/android_app_NativeActivity.cpp
index 074afa3..21162f4 100644
--- a/core/jni/android_app_NativeActivity.cpp
+++ b/core/jni/android_app_NativeActivity.cpp
@@ -436,7 +436,7 @@
     
     void setSurface(jobject _surface) {
         if (_surface != NULL) {
-            nativeWindow = android_Surface_getNativeWindow(env, _surface);
+            nativeWindow = android_view_Surface_getNativeWindow(env, _surface);
         } else {
             nativeWindow = NULL;
         }
diff --git a/core/jni/android_opengl_EGL14.cpp b/core/jni/android_opengl_EGL14.cpp
index c271aeb..b1664c6 100644
--- a/core/jni/android_opengl_EGL14.cpp
+++ b/core/jni/android_opengl_EGL14.cpp
@@ -549,7 +549,7 @@
         goto exit;
     }
 
-    window = android::android_Surface_getNativeWindow(_env, win);
+    window = android::android_view_Surface_getNativeWindow(_env, win);
 
     if (window == NULL)
         goto not_valid_surface;
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index c302b23..4d5e680 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -18,8 +18,10 @@
 
 #include <stdio.h>
 
+#include "android_os_Parcel.h"
 #include "android_util_Binder.h"
 #include "android/graphics/GraphicsJNI.h"
+#include "android/graphics/Region.h"
 
 #include <binder/IMemory.h>
 
@@ -28,6 +30,7 @@
 #include <gui/SurfaceComposerClient.h>
 #include <gui/SurfaceTexture.h>
 
+#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
@@ -42,439 +45,50 @@
 #include "JNIHelp.h"
 #include <android_runtime/AndroidRuntime.h>
 #include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_view_SurfaceSession.h>
 #include <android_runtime/android_graphics_SurfaceTexture.h>
 #include <utils/misc.h>
 
+#include <ScopedUtfChars.h>
+
 
 // ----------------------------------------------------------------------------
 
 namespace android {
 
-enum {
-    // should match Parcelable.java
-    PARCELABLE_WRITE_RETURN_VALUE = 0x0001
-};
-
-// ----------------------------------------------------------------------------
-
 static const char* const OutOfResourcesException =
     "android/view/Surface$OutOfResourcesException";
 
-const char* const kSurfaceSessionClassPathName = "android/view/SurfaceSession";
-const char* const kSurfaceClassPathName = "android/view/Surface";
+static struct {
+    jclass clazz;
+    jfieldID mNativeSurface;
+    jfieldID mNativeSurfaceControl;
+    jfieldID mGenerationId;
+    jfieldID mCanvas;
+    jfieldID mCanvasSaveCount;
+} gSurfaceClassInfo;
 
-struct sso_t {
-    jfieldID client;
-};
-static sso_t sso;
+static struct {
+    jfieldID left;
+    jfieldID top;
+    jfieldID right;
+    jfieldID bottom;
+} gRectClassInfo;
 
-struct so_t {
-    jfieldID surfaceControl;
-    jfieldID surfaceGenerationId;
-    jfieldID surface;
-    jfieldID saveCount;
-    jfieldID canvas;
-};
-static so_t so;
+static struct {
+    jfieldID mNativeCanvas;
+    jfieldID mSurfaceFormat;
+} gCanvasClassInfo;
 
-struct ro_t {
-    jfieldID l;
-    jfieldID t;
-    jfieldID r;
-    jfieldID b;
-};
-static ro_t ro;
+static struct {
+    jfieldID width;
+    jfieldID height;
+    jfieldID refreshRate;
+    jfieldID density;
+    jfieldID xDpi;
+    jfieldID yDpi;
+} gPhysicalDisplayInfoClassInfo;
 
-struct po_t {
-    jfieldID x;
-    jfieldID y;
-};
-static po_t po;
-
-struct co_t {
-    jfieldID surfaceFormat;
-};
-static co_t co;
-
-struct no_t {
-    jfieldID native_canvas;
-    jfieldID native_region;
-    jfieldID native_parcel;
-};
-static no_t no;
-
-
-// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-
-static void SurfaceSession_nativeInit(JNIEnv* env, jobject clazz)
-{
-    sp<SurfaceComposerClient> client = new SurfaceComposerClient;
-    client->incStrong(clazz);
-    env->SetIntField(clazz, sso.client, (int)client.get());
-}
-
-static void SurfaceSession_nativeDestroy(JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient* client =
-            (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
-    if (client != 0) {
-        client->decStrong(clazz);
-        env->SetIntField(clazz, sso.client, 0);
-    }
-}
-
-static void SurfaceSession_nativeKill(JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient* client =
-            (SurfaceComposerClient*)env->GetIntField(clazz, sso.client);
-    if (client != 0) {
-        client->dispose();
-        client->decStrong(clazz);
-        env->SetIntField(clazz, sso.client, 0);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject clazz)
-{
-    SurfaceControl* const p =
-        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
-    return sp<SurfaceControl>(p);
-}
-
-static void setSurfaceControl(JNIEnv* env, jobject clazz,
-        const sp<SurfaceControl>& surface)
-{
-    SurfaceControl* const p =
-        (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
-    if (surface.get()) {
-        surface->incStrong(clazz);
-    }
-    if (p) {
-        p->decStrong(clazz);
-    }
-    env->SetIntField(clazz, so.surfaceControl, (int)surface.get());
-}
-
-static sp<Surface> getSurface(JNIEnv* env, jobject clazz)
-{
-    sp<Surface> result(Surface_getSurface(env, clazz));
-    if (result == 0) {
-        /*
-         * if this method is called from the WindowManager's process, it means
-         * the client is is not remote, and therefore is allowed to have
-         * a Surface (data), so we create it here.
-         * If we don't have a SurfaceControl, it means we're in a different
-         * process.
-         */
-
-        SurfaceControl* const control =
-            (SurfaceControl*)env->GetIntField(clazz, so.surfaceControl);
-        if (control) {
-            result = control->getSurface();
-            if (result != 0) {
-                result->incStrong(clazz);
-                env->SetIntField(clazz, so.surface, (int)result.get());
-            }
-        }
-    }
-    return result;
-}
-
-sp<ANativeWindow> android_Surface_getNativeWindow(
-        JNIEnv* env, jobject clazz) {
-    return getSurface(env, clazz);
-}
-
-bool android_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
-    jclass surfaceClass = env->FindClass(kSurfaceClassPathName);
-    return env->IsInstanceOf(obj, surfaceClass);
-}
-
-sp<Surface> Surface_getSurface(JNIEnv* env, jobject clazz) {
-    sp<Surface> surface((Surface*)env->GetIntField(clazz, so.surface));
-    return surface;
-}
-
-void setSurface(JNIEnv* env, jobject clazz, const sp<Surface>& surface)
-{
-    Surface* const p = (Surface*)env->GetIntField(clazz, so.surface);
-    if (surface.get()) {
-        surface->incStrong(clazz);
-    }
-    if (p) {
-        p->decStrong(clazz);
-    }
-    env->SetIntField(clazz, so.surface, (int)surface.get());
-    // This test is conservative and it would be better to compare the ISurfaces
-    if (p && p != surface.get()) {
-        jint generationId = env->GetIntField(clazz, so.surfaceGenerationId);
-        generationId++;
-        env->SetIntField(clazz, so.surfaceGenerationId, generationId);
-    }
-}
-
-// ----------------------------------------------------------------------------
-
-static void Surface_init(
-        JNIEnv* env, jobject clazz,
-        jobject session,
-        jstring jname, jint w, jint h, jint format, jint flags)
-{
-    if (session == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    SurfaceComposerClient* client =
-            (SurfaceComposerClient*)env->GetIntField(session, sso.client);
-
-    const jchar* str = env->GetStringCritical(jname, 0);
-    const String8 name(str, env->GetStringLength(jname));
-    env->ReleaseStringCritical(jname, str);
-    sp<SurfaceControl> surface = client->createSurface(name, w, h, format, flags);
-
-    if (surface == 0) {
-        jniThrowException(env, OutOfResourcesException, NULL);
-        return;
-    }
-    setSurfaceControl(env, clazz, surface);
-}
-
-static void Surface_initFromSurfaceTexture(
-        JNIEnv* env, jobject clazz, jobject jst)
-{
-    sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, jst));
-
-    if (st == NULL) {
-        jniThrowException(env, "java/lang/IllegalArgumentException",
-                "SurfaceTexture has already been released");
-        return;
-    }
-    sp<ISurfaceTexture> bq = st->getBufferQueue();
-
-    sp<Surface> surface(new Surface(bq));
-    if (surface == NULL) {
-        jniThrowException(env, OutOfResourcesException, NULL);
-        return;
-    }
-    setSurfaceControl(env, clazz, NULL);
-    setSurface(env, clazz, surface);
-}
-
-static void Surface_initParcel(JNIEnv* env, jobject clazz, jobject argParcel)
-{
-    Parcel* parcel = (Parcel*)env->GetIntField(argParcel, no.native_parcel);
-    if (parcel == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    sp<Surface> sur(Surface::readFromParcel(*parcel));
-    setSurface(env, clazz, sur);
-}
-
-static jint Surface_getIdentity(JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
-    if (control != 0) return (jint) control->getIdentity();
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (surface != 0) return (jint) surface->getIdentity();
-    return -1;
-}
-
-static void Surface_destroy(JNIEnv* env, jobject clazz, uintptr_t *ostack)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (SurfaceControl::isValid(surface)) {
-        surface->clear();
-    }
-    setSurfaceControl(env, clazz, 0);
-    setSurface(env, clazz, 0);
-}
-
-static void Surface_release(JNIEnv* env, jobject clazz, uintptr_t *ostack)
-{
-    setSurfaceControl(env, clazz, 0);
-    setSurface(env, clazz, 0);
-}
-
-static jboolean Surface_isValid(JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surfaceControl(getSurfaceControl(env, clazz));
-    if (surfaceControl != 0) {
-        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
-    }
-    const sp<Surface>& surface(getSurface(env, clazz));
-    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
-}
-
-static jboolean Surface_isConsumerRunningBehind(JNIEnv* env, jobject clazz)
-{
-    int value = 0;
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (!Surface::isValid(surface)) {
-        doThrowIAE(env);
-        return 0;
-    }
-    ANativeWindow* anw = static_cast<ANativeWindow *>(surface.get());
-    anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
-    return (jboolean)value;
-}
-
-static inline SkBitmap::Config convertPixelFormat(PixelFormat format)
-{
-    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
-        we can map to SkBitmap::kARGB_8888_Config, and optionally call
-        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
-    */
-    switch (format) {
-    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
-    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
-    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
-    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
-    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
-    default:                        return SkBitmap::kNo_Config;
-    }
-}
-
-static jobject Surface_lockCanvas(JNIEnv* env, jobject clazz, jobject dirtyRect)
-{
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (!Surface::isValid(surface)) {
-        doThrowIAE(env);
-        return 0;
-    }
-
-    // get dirty region
-    Region dirtyRegion;
-    if (dirtyRect) {
-        Rect dirty;
-        dirty.left  = env->GetIntField(dirtyRect, ro.l);
-        dirty.top   = env->GetIntField(dirtyRect, ro.t);
-        dirty.right = env->GetIntField(dirtyRect, ro.r);
-        dirty.bottom= env->GetIntField(dirtyRect, ro.b);
-        if (!dirty.isEmpty()) {
-            dirtyRegion.set(dirty);
-        }
-    } else {
-        dirtyRegion.set(Rect(0x3FFF,0x3FFF));
-    }
-
-    Surface::SurfaceInfo info;
-    status_t err = surface->lock(&info, &dirtyRegion);
-    if (err < 0) {
-        const char* const exception = (err == NO_MEMORY) ?
-            OutOfResourcesException :
-            "java/lang/IllegalArgumentException";
-        jniThrowException(env, exception, NULL);
-        return 0;
-    }
-
-    // Associate a SkCanvas object to this surface
-    jobject canvas = env->GetObjectField(clazz, so.canvas);
-    env->SetIntField(canvas, co.surfaceFormat, info.format);
-
-    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
-    SkBitmap bitmap;
-    ssize_t bpr = info.s * bytesPerPixel(info.format);
-    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
-    if (info.format == PIXEL_FORMAT_RGBX_8888) {
-        bitmap.setIsOpaque(true);
-    }
-    if (info.w > 0 && info.h > 0) {
-        bitmap.setPixels(info.bits);
-    } else {
-        // be safe with an empty bitmap.
-        bitmap.setPixels(NULL);
-    }
-    nativeCanvas->setBitmapDevice(bitmap);
-
-    SkRegion clipReg;
-    if (dirtyRegion.isRect()) { // very common case
-        const Rect b(dirtyRegion.getBounds());
-        clipReg.setRect(b.left, b.top, b.right, b.bottom);
-    } else {
-        size_t count;
-        Rect const* r = dirtyRegion.getArray(&count);
-        while (count) {
-            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
-            r++, count--;
-        }
-    }
-
-    nativeCanvas->clipRegion(clipReg);
-
-    int saveCount = nativeCanvas->save();
-    env->SetIntField(clazz, so.saveCount, saveCount);
-
-    if (dirtyRect) {
-        const Rect& bounds(dirtyRegion.getBounds());
-        env->SetIntField(dirtyRect, ro.l, bounds.left);
-        env->SetIntField(dirtyRect, ro.t, bounds.top);
-        env->SetIntField(dirtyRect, ro.r, bounds.right);
-        env->SetIntField(dirtyRect, ro.b, bounds.bottom);
-    }
-
-    return canvas;
-}
-
-static void Surface_unlockCanvasAndPost(
-        JNIEnv* env, jobject clazz, jobject argCanvas)
-{
-    jobject canvas = env->GetObjectField(clazz, so.canvas);
-    if (env->IsSameObject(canvas, argCanvas) == JNI_FALSE) {
-        doThrowIAE(env);
-        return;
-    }
-
-    const sp<Surface>& surface(getSurface(env, clazz));
-    if (!Surface::isValid(surface))
-        return;
-
-    // detach the canvas from the surface
-    SkCanvas* nativeCanvas = (SkCanvas*)env->GetIntField(canvas, no.native_canvas);
-    int saveCount = env->GetIntField(clazz, so.saveCount);
-    nativeCanvas->restoreToCount(saveCount);
-    nativeCanvas->setBitmapDevice(SkBitmap());
-    env->SetIntField(clazz, so.saveCount, 0);
-
-    // unlock surface
-    status_t err = surface->unlockAndPost();
-    if (err < 0) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_unlockCanvas(
-        JNIEnv* env, jobject clazz, jobject argCanvas)
-{
-    // XXX: this API has been removed
-    doThrowIAE(env);
-}
-
-static void Surface_openTransaction(
-        JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient::openGlobalTransaction();
-}
-
-static void Surface_closeTransaction(
-        JNIEnv* env, jobject clazz)
-{
-    SurfaceComposerClient::closeGlobalTransaction();
-}
-
-static void Surface_setOrientation(
-        JNIEnv* env, jobject clazz, jint, jint orientation)
-{
-    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(
-            ISurfaceComposer::eDisplayIdMain);
-    SurfaceComposerClient::setDisplayOrientation(display, orientation);
-}
 
 class ScreenshotPixelRef : public SkPixelRef {
 public:
@@ -483,6 +97,7 @@
         SkSafeRef(ctable);
         setImmutable();
     }
+
     virtual ~ScreenshotPixelRef() {
         SkSafeUnref(fCTable);
     }
@@ -534,17 +149,311 @@
     typedef SkPixelRef INHERITED;
 };
 
-static jobject doScreenshot(JNIEnv* env, jobject clazz,
-        jint width, jint height,
-        jint minLayer, jint maxLayer, bool allLayers)
-{
-    sp<IBinder> display = SurfaceComposerClient::getBuiltInDisplay(
-            ISurfaceComposer::eDisplayIdMain);
+
+// ----------------------------------------------------------------------------
+
+static sp<SurfaceControl> getSurfaceControl(JNIEnv* env, jobject surfaceObj) {
+    return reinterpret_cast<SurfaceControl*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
+}
+
+static void setSurfaceControl(JNIEnv* env, jobject surfaceObj,
+        const sp<SurfaceControl>& surface) {
+    SurfaceControl* const p = reinterpret_cast<SurfaceControl*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
+    if (surface.get()) {
+        surface->incStrong(surfaceObj);
+    }
+    if (p) {
+        p->decStrong(surfaceObj);
+    }
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl,
+            reinterpret_cast<jint>(surface.get()));
+}
+
+static sp<Surface> getSurface(JNIEnv* env, jobject surfaceObj) {
+    sp<Surface> result(android_view_Surface_getSurface(env, surfaceObj));
+    if (result == NULL) {
+        /*
+         * if this method is called from the WindowManager's process, it means
+         * the client is is not remote, and therefore is allowed to have
+         * a Surface (data), so we create it here.
+         * If we don't have a SurfaceControl, it means we're in a different
+         * process.
+         */
+
+        SurfaceControl* const control = reinterpret_cast<SurfaceControl*>(
+                env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurfaceControl));
+        if (control) {
+            result = control->getSurface();
+            if (result != NULL) {
+                result->incStrong(surfaceObj);
+                env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface,
+                        reinterpret_cast<jint>(result.get()));
+            }
+        }
+    }
+    return result;
+}
+
+sp<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
+    return getSurface(env, surfaceObj);
+}
+
+bool android_view_Surface_isInstanceOf(JNIEnv* env, jobject obj) {
+    return env->IsInstanceOf(obj, gSurfaceClassInfo.clazz);
+}
+
+sp<Surface> android_view_Surface_getSurface(JNIEnv* env, jobject surfaceObj) {
+    return reinterpret_cast<Surface*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface));
+}
+
+static void setSurface(JNIEnv* env, jobject surfaceObj, const sp<Surface>& surface) {
+    Surface* const p = reinterpret_cast<Surface*>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface));
+    if (surface.get()) {
+        surface->incStrong(surfaceObj);
+    }
+    if (p) {
+        p->decStrong(surfaceObj);
+    }
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mNativeSurface,
+            reinterpret_cast<jint>(surface.get()));
+
+    // This test is conservative and it would be better to compare the ISurfaces
+    if (p && p != surface.get()) {
+        jint generationId = env->GetIntField(surfaceObj,
+                gSurfaceClassInfo.mGenerationId);
+        generationId++;
+        env->SetIntField(surfaceObj,
+                gSurfaceClassInfo.mGenerationId, generationId);
+    }
+}
+
+// ----------------------------------------------------------------------------
+
+static void nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj,
+        jstring nameStr, jint w, jint h, jint format, jint flags) {
+    ScopedUtfChars name(env, nameStr);
+    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
+
+    sp<SurfaceControl> surface = client->createSurface(
+            String8(name.c_str()), w, h, format, flags);
+    if (surface == NULL) {
+        jniThrowException(env, OutOfResourcesException, NULL);
+        return;
+    }
+
+    setSurfaceControl(env, surfaceObj, surface);
+}
+
+static void nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj,
+        jobject surfaceTextureObj) {
+    sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
+    if (st == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "SurfaceTexture has already been released");
+        return;
+    }
+
+    sp<ISurfaceTexture> bq = st->getBufferQueue();
+
+    sp<Surface> surface(new Surface(bq));
+    if (surface == NULL) {
+        jniThrowException(env, OutOfResourcesException, NULL);
+        return;
+    }
+
+    setSurface(env, surfaceObj, surface);
+}
+
+static void nativeRelease(JNIEnv* env, jobject surfaceObj) {
+    setSurfaceControl(env, surfaceObj, NULL);
+    setSurface(env, surfaceObj, NULL);
+}
+
+static void nativeDestroy(JNIEnv* env, jobject surfaceObj) {
+    sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj));
+    if (SurfaceControl::isValid(surfaceControl)) {
+        surfaceControl->clear();
+    }
+    setSurfaceControl(env, surfaceObj, NULL);
+    setSurface(env, surfaceObj, NULL);
+}
+
+static jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj) {
+    sp<SurfaceControl> surfaceControl(getSurfaceControl(env, surfaceObj));
+    if (surfaceControl != NULL) {
+        return SurfaceControl::isValid(surfaceControl) ? JNI_TRUE : JNI_FALSE;
+    }
+
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    return Surface::isValid(surface) ? JNI_TRUE : JNI_FALSE;
+}
+
+static jint nativeGetIdentity(JNIEnv* env, jobject surfaceObj) {
+    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
+    if (control != NULL) {
+        return jint(control->getIdentity());
+    }
+
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (surface != NULL) {
+        return jint(surface->getIdentity());
+    }
+
+    return -1;
+}
+
+static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) {
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (!Surface::isValid(surface)) {
+        doThrowIAE(env);
+        return JNI_FALSE;
+    }
+
+    int value = 0;
+    ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
+    anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
+    return value;
+}
+
+static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
+    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
+        we can map to SkBitmap::kARGB_8888_Config, and optionally call
+        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
+    */
+    switch (format) {
+    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
+    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
+    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
+    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
+    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
+    default:                        return SkBitmap::kNo_Config;
+    }
+}
+
+static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (!Surface::isValid(surface)) {
+        doThrowIAE(env);
+        return NULL;
+    }
+
+    // get dirty region
+    Region dirtyRegion;
+    if (dirtyRectObj) {
+        Rect dirty;
+        dirty.left = env->GetIntField(dirtyRectObj, gRectClassInfo.left);
+        dirty.top = env->GetIntField(dirtyRectObj, gRectClassInfo.top);
+        dirty.right = env->GetIntField(dirtyRectObj, gRectClassInfo.right);
+        dirty.bottom = env->GetIntField(dirtyRectObj, gRectClassInfo.bottom);
+        if (!dirty.isEmpty()) {
+            dirtyRegion.set(dirty);
+        }
+    } else {
+        dirtyRegion.set(Rect(0x3FFF, 0x3FFF));
+    }
+
+    Surface::SurfaceInfo info;
+    status_t err = surface->lock(&info, &dirtyRegion);
+    if (err < 0) {
+        const char* const exception = (err == NO_MEMORY) ?
+                OutOfResourcesException :
+                "java/lang/IllegalArgumentException";
+        jniThrowException(env, exception, NULL);
+        return NULL;
+    }
+
+    // Associate a SkCanvas object to this surface
+    jobject canvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
+    env->SetIntField(canvasObj, gCanvasClassInfo.mSurfaceFormat, info.format);
+
+    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
+            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+    SkBitmap bitmap;
+    ssize_t bpr = info.s * bytesPerPixel(info.format);
+    bitmap.setConfig(convertPixelFormat(info.format), info.w, info.h, bpr);
+    if (info.format == PIXEL_FORMAT_RGBX_8888) {
+        bitmap.setIsOpaque(true);
+    }
+    if (info.w > 0 && info.h > 0) {
+        bitmap.setPixels(info.bits);
+    } else {
+        // be safe with an empty bitmap.
+        bitmap.setPixels(NULL);
+    }
+    nativeCanvas->setBitmapDevice(bitmap);
+
+    SkRegion clipReg;
+    if (dirtyRegion.isRect()) { // very common case
+        const Rect b(dirtyRegion.getBounds());
+        clipReg.setRect(b.left, b.top, b.right, b.bottom);
+    } else {
+        size_t count;
+        Rect const* r = dirtyRegion.getArray(&count);
+        while (count) {
+            clipReg.op(r->left, r->top, r->right, r->bottom, SkRegion::kUnion_Op);
+            r++, count--;
+        }
+    }
+
+    nativeCanvas->clipRegion(clipReg);
+
+    int saveCount = nativeCanvas->save();
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, saveCount);
+
+    if (dirtyRectObj) {
+        const Rect& bounds(dirtyRegion.getBounds());
+        env->SetIntField(dirtyRectObj, gRectClassInfo.left, bounds.left);
+        env->SetIntField(dirtyRectObj, gRectClassInfo.top, bounds.top);
+        env->SetIntField(dirtyRectObj, gRectClassInfo.right, bounds.right);
+        env->SetIntField(dirtyRectObj, gRectClassInfo.bottom, bounds.bottom);
+    }
+
+    return canvasObj;
+}
+
+static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) {
+    jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
+    if (!env->IsSameObject(ownCanvasObj, canvasObj)) {
+        doThrowIAE(env);
+        return;
+    }
+
+    sp<Surface> surface(getSurface(env, surfaceObj));
+    if (!Surface::isValid(surface)) {
+        return;
+    }
+
+    // detach the canvas from the surface
+    SkCanvas* nativeCanvas = reinterpret_cast<SkCanvas*>(
+            env->GetIntField(canvasObj, gCanvasClassInfo.mNativeCanvas));
+    int saveCount = env->GetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount);
+    nativeCanvas->restoreToCount(saveCount);
+    nativeCanvas->setBitmapDevice(SkBitmap());
+    env->SetIntField(surfaceObj, gSurfaceClassInfo.mCanvasSaveCount, 0);
+
+    // unlock surface
+    status_t err = surface->unlockAndPost();
+    if (err < 0) {
+        doThrowIAE(env);
+    }
+}
+
+static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
+        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
+    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
+    if (displayToken == NULL) {
+        return NULL;
+    }
+
     ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
-    if (pixels->update(display, width, height,
+    if (pixels->update(displayToken, width, height,
             minLayer, maxLayer, allLayers) != NO_ERROR) {
         delete pixels;
-        return 0;
+        return NULL;
     }
 
     uint32_t w = pixels->getWidth();
@@ -571,94 +480,68 @@
     return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
 }
 
-static jobject Surface_screenshotAll(JNIEnv* env, jobject clazz, jint width, jint height)
-{
-    return doScreenshot(env, clazz, width, height, 0, 0, true);
+static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::openGlobalTransaction();
 }
 
-static jobject Surface_screenshot(JNIEnv* env, jobject clazz, jint width, jint height,
-        jint minLayer, jint maxLayer)
-{
-    return doScreenshot(env, clazz, width, height, minLayer, maxLayer, false);
+static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::closeGlobalTransaction();
 }
 
-static void Surface_setLayer(
-        JNIEnv* env, jobject clazz, jint zorder)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint zorder) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setLayer(zorder);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setPosition(
-        JNIEnv* env, jobject clazz, jfloat x, jfloat y)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jfloat x, jfloat y) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setPosition(x, y);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setSize(
-        JNIEnv* env, jobject clazz, jint w, jint h)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint w, jint h) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setSize(w, h);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_hide(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->hide();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
+static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
 
-static void Surface_show(
-        JNIEnv* env, jobject clazz)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    status_t err = surface->show();
-    if (err<0 && err!=NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-static void Surface_setFlags(
-        JNIEnv* env, jobject clazz, jint flags, jint mask)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
     status_t err = surface->setFlags(flags, mask);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setTransparentRegion(
-        JNIEnv* env, jobject clazz, jobject argRegion)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
-    SkRegion* nativeRegion = (SkRegion*)env->GetIntField(argRegion, no.native_region);
+static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
 
-    const SkIRect& b(nativeRegion->getBounds());
+    SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
+    if (!region) {
+        doThrowIAE(env);
+        return;
+    }
+
+    const SkIRect& b(region->getBounds());
     Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
-    if (nativeRegion->isComplex()) {
-        SkRegion::Iterator it(*nativeRegion);
+    if (region->isComplex()) {
+        SkRegion::Iterator it(*region);
         while (!it.done()) {
             const SkIRect& r(it.rect());
             reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
@@ -667,132 +550,197 @@
     }
 
     status_t err = surface->setTransparentRegionHint(reg);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setAlpha(
-        JNIEnv* env, jobject clazz, jfloat alpha)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jfloat alpha) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setAlpha(alpha);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setMatrix(
-        JNIEnv* env, jobject clazz,
-        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, clazz));
-    if (surface == 0) return;
+static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj,
+        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setMatrix(dsdx, dtdx, dsdy, dtdy);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setWindowCrop(JNIEnv* env, jobject thiz, jobject crop)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz));
-    if (surface == 0) return;
+static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) {
+    const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
 
-    Rect nativeCrop;
-    if (crop) {
-        nativeCrop.left  = env->GetIntField(crop, ro.l);
-        nativeCrop.top   = env->GetIntField(crop, ro.t);
-        nativeCrop.right = env->GetIntField(crop, ro.r);
-        nativeCrop.bottom= env->GetIntField(crop, ro.b);
+    Rect crop;
+    if (cropObj) {
+        crop.left = env->GetIntField(cropObj, gRectClassInfo.left);
+        crop.top = env->GetIntField(cropObj, gRectClassInfo.top);
+        crop.right = env->GetIntField(cropObj, gRectClassInfo.right);
+        crop.bottom = env->GetIntField(cropObj, gRectClassInfo.bottom);
     } else {
-        nativeCrop.left = nativeCrop.top = nativeCrop.right =
-                nativeCrop.bottom = 0;
+        crop.left = crop.top = crop.right = crop.bottom = 0;
     }
 
-    status_t err = surface->setCrop(nativeCrop);
-    if (err<0 && err!=NO_INIT) {
+    status_t err = surface->setCrop(crop);
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
-static void Surface_setLayerStack(JNIEnv* env, jobject thiz, jint layerStack)
-{
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, thiz));
-    if (surface == 0) return;
+static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint layerStack) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    if (surface == NULL) return;
+
     status_t err = surface->setLayerStack(layerStack);
-    if (err<0 && err!=NO_INIT) {
+    if (err < 0 && err != NO_INIT) {
         doThrowIAE(env);
     }
 }
 
+static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
+    sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
+    return javaObjectForIBinder(env, token);
+}
+
+static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj) {
+    ScopedUtfChars name(env, nameObj);
+    // TODO: pass the name to SF.
+    sp<IBinder> token(SurfaceComposerClient::createDisplay());
+    return javaObjectForIBinder(env, token);
+}
+
+static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject surfaceTextureObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    if (!surfaceTextureObj) {
+        SurfaceComposerClient::setDisplaySurface(token, NULL);
+        return;
+    }
+
+    sp<SurfaceTexture> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
+    if (st == NULL) {
+        jniThrowException(env, "java/lang/IllegalArgumentException",
+                "SurfaceTexture has already been released");
+        return;
+    }
+
+    sp<ISurfaceTexture> bq = st->getBufferQueue();
+    SurfaceComposerClient::setDisplaySurface(token, bq);
+}
+
+static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint layerStack) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
+}
+
+static void nativeSetDisplayOrientation(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint orientation) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    SurfaceComposerClient::setDisplayOrientation(token, orientation);
+}
+
+static void nativeSetDisplayViewport(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject rectObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    Rect rect;
+    rect.left = env->GetIntField(rectObj, gRectClassInfo.left);
+    rect.top = env->GetIntField(rectObj, gRectClassInfo.top);
+    rect.right = env->GetIntField(rectObj, gRectClassInfo.right);
+    rect.bottom = env->GetIntField(rectObj, gRectClassInfo.bottom);
+    SurfaceComposerClient::setDisplayViewport(token, rect);
+}
+
+static void nativeSetDisplayFrame(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject rectObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    Rect rect;
+    rect.left = env->GetIntField(rectObj, gRectClassInfo.left);
+    rect.top = env->GetIntField(rectObj, gRectClassInfo.top);
+    rect.right = env->GetIntField(rectObj, gRectClassInfo.right);
+    rect.bottom = env->GetIntField(rectObj, gRectClassInfo.bottom);
+    SurfaceComposerClient::setDisplayFrame(token, rect);
+}
+
+static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject infoObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return JNI_FALSE;
+
+    DisplayInfo info;
+    if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
+        return JNI_FALSE;
+    }
+
+    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
+    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
+    return JNI_TRUE;
+}
+
 // ----------------------------------------------------------------------------
 
-static void Surface_copyFrom(
-        JNIEnv* env, jobject clazz, jobject other)
-{
-    if (clazz == other)
-        return;
-
-    if (other == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
+static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
     /*
      * This is used by the WindowManagerService just after constructing
      * a Surface and is necessary for returning the Surface reference to
      * the caller. At this point, we should only have a SurfaceControl.
      */
 
-    const sp<SurfaceControl>& surface = getSurfaceControl(env, clazz);
-    const sp<SurfaceControl>& rhs = getSurfaceControl(env, other);
-    if (!SurfaceControl::isSameSurface(surface, rhs)) {
+    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
+    sp<SurfaceControl> other(getSurfaceControl(env, otherObj));
+    if (!SurfaceControl::isSameSurface(surface, other)) {
         // we reassign the surface only if it's a different one
         // otherwise we would loose our client-side state.
-        setSurfaceControl(env, clazz, rhs);
+        setSurfaceControl(env, surfaceObj, other);
     }
 }
 
-static void Surface_transferFrom(
-        JNIEnv* env, jobject clazz, jobject other)
-{
-    if (clazz == other)
-        return;
-
-    if (other == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    sp<SurfaceControl> control(getSurfaceControl(env, other));
-    sp<Surface> surface(Surface_getSurface(env, other));
-    setSurfaceControl(env, clazz, control);
-    setSurface(env, clazz, surface);
-    setSurfaceControl(env, other, 0);
-    setSurface(env, other, 0);
+static void nativeTransferFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
+    sp<SurfaceControl> control(getSurfaceControl(env, otherObj));
+    sp<Surface> surface(android_view_Surface_getSurface(env, otherObj));
+    setSurfaceControl(env, surfaceObj, control);
+    setSurface(env, surfaceObj, surface);
+    setSurfaceControl(env, otherObj, NULL);
+    setSurface(env, otherObj, NULL);
 }
 
-static void Surface_readFromParcel(
-        JNIEnv* env, jobject clazz, jobject argParcel)
-{
-    Parcel* parcel = (Parcel*)env->GetIntField( argParcel, no.native_parcel);
+static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
     if (parcel == NULL) {
         doThrowNPE(env);
         return;
     }
 
-    sp<Surface> sur(Surface::readFromParcel(*parcel));
-    setSurface(env, clazz, sur);
+    sp<Surface> surface(Surface::readFromParcel(*parcel));
+    setSurfaceControl(env, surfaceObj, NULL);
+    setSurface(env, surfaceObj, surface);
 }
 
-static void Surface_writeToParcel(
-        JNIEnv* env, jobject clazz, jobject argParcel, jint flags)
-{
-    Parcel* parcel = (Parcel*)env->GetIntField(
-            argParcel, no.native_parcel);
-
+static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
     if (parcel == NULL) {
         doThrowNPE(env);
         return;
@@ -804,110 +752,125 @@
     // available we let it parcel itself. Finally, if the Surface is also
     // NULL we fall back to using the SurfaceControl path which sends an
     // empty surface; this matches legacy behavior.
-    const sp<SurfaceControl>& control(getSurfaceControl(env, clazz));
+    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
     if (control != NULL) {
         SurfaceControl::writeSurfaceToParcel(control, parcel);
     } else {
-        sp<Surface> surface(Surface_getSurface(env, clazz));
+        sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj));
         if (surface != NULL) {
             Surface::writeToParcel(surface, parcel);
         } else {
             SurfaceControl::writeSurfaceToParcel(NULL, parcel);
         }
     }
-    if (flags & PARCELABLE_WRITE_RETURN_VALUE) {
-        setSurfaceControl(env, clazz, NULL);
-        setSurface(env, clazz, NULL);
-    }
 }
 
 // ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-// ----------------------------------------------------------------------------
-
-static void nativeClassInit(JNIEnv* env, jclass clazz);
-
-static JNINativeMethod gSurfaceSessionMethods[] = {
-    {"nativeInit",     "()V",  (void*)SurfaceSession_nativeInit },
-    {"nativeDestroy",  "()V",  (void*)SurfaceSession_nativeDestroy },
-    {"nativeKill",     "()V",  (void*)SurfaceSession_nativeKill },
-};
 
 static JNINativeMethod gSurfaceMethods[] = {
-    {"nativeClassInit",     "()V",  (void*)nativeClassInit },
-    {"init",                "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V",  (void*)Surface_init },
-    {"init",                "(Landroid/os/Parcel;)V",  (void*)Surface_initParcel },
-    {"initFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V", (void*)Surface_initFromSurfaceTexture },
-    {"getIdentity",         "()I",  (void*)Surface_getIdentity },
-    {"destroy",             "()V",  (void*)Surface_destroy },
-    {"release",             "()V",  (void*)Surface_release },
-    {"copyFrom",            "(Landroid/view/Surface;)V",  (void*)Surface_copyFrom },
-    {"transferFrom",        "(Landroid/view/Surface;)V",  (void*)Surface_transferFrom },
-    {"isValid",             "()Z",  (void*)Surface_isValid },
-    {"lockCanvasNative",    "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",  (void*)Surface_lockCanvas },
-    {"unlockCanvasAndPost", "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvasAndPost },
-    {"unlockCanvas",        "(Landroid/graphics/Canvas;)V", (void*)Surface_unlockCanvas },
-    {"openTransaction",     "()V",  (void*)Surface_openTransaction },
-    {"closeTransaction",    "()V",  (void*)Surface_closeTransaction },
-    {"setOrientation",      "(II)V", (void*)Surface_setOrientation },
-    {"screenshot",          "(II)Landroid/graphics/Bitmap;", (void*)Surface_screenshotAll },
-    {"screenshot",          "(IIII)Landroid/graphics/Bitmap;", (void*)Surface_screenshot },
-    {"setLayer",            "(I)V", (void*)Surface_setLayer },
-    {"setPosition",         "(FF)V",(void*)Surface_setPosition },
-    {"setSize",             "(II)V",(void*)Surface_setSize },
-    {"hide",                "()V",  (void*)Surface_hide },
-    {"show",                "()V",  (void*)Surface_show },
-    {"setFlags",            "(II)V",(void*)Surface_setFlags },
-    {"setTransparentRegionHint","(Landroid/graphics/Region;)V", (void*)Surface_setTransparentRegion },
-    {"setAlpha",            "(F)V", (void*)Surface_setAlpha },
-    {"setMatrix",           "(FFFF)V",  (void*)Surface_setMatrix },
-    {"readFromParcel",      "(Landroid/os/Parcel;)V", (void*)Surface_readFromParcel },
-    {"writeToParcel",       "(Landroid/os/Parcel;I)V", (void*)Surface_writeToParcel },
-    {"isConsumerRunningBehind", "()Z", (void*)Surface_isConsumerRunningBehind },
-    {"setWindowCrop",       "(Landroid/graphics/Rect;)V", (void*)Surface_setWindowCrop },
-    {"setLayerStack",        "(I)V", (void*)Surface_setLayerStack },
+    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V",
+            (void*)nativeCreate },
+    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V",
+            (void*)nativeCreateFromSurfaceTexture },
+    {"nativeRelease", "()V",
+            (void*)nativeRelease },
+    {"nativeDestroy", "()V",
+            (void*)nativeDestroy },
+    {"nativeIsValid", "()Z",
+            (void*)nativeIsValid },
+    {"nativeGetIdentity", "()I",
+            (void*)nativeGetIdentity },
+    {"nativeIsConsumerRunningBehind", "()Z",
+            (void*)nativeIsConsumerRunningBehind },
+    {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",
+            (void*)nativeLockCanvas },
+    {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V",
+            (void*)nativeUnlockCanvasAndPost },
+    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
+            (void*)nativeScreenshot },
+    {"nativeOpenTransaction", "()V",
+            (void*)nativeOpenTransaction },
+    {"nativeCloseTransaction", "()V",
+            (void*)nativeCloseTransaction },
+    {"nativeSetLayer", "(I)V",
+            (void*)nativeSetLayer },
+    {"nativeSetPosition", "(FF)V",
+            (void*)nativeSetPosition },
+    {"nativeSetSize", "(II)V",
+            (void*)nativeSetSize },
+    {"nativeSetTransparentRegionHint", "(Landroid/graphics/Region;)V",
+            (void*)nativeSetTransparentRegionHint },
+    {"nativeSetAlpha", "(F)V",
+            (void*)nativeSetAlpha },
+    {"nativeSetMatrix", "(FFFF)V",
+            (void*)nativeSetMatrix },
+    {"nativeSetFlags", "(II)V",
+            (void*)nativeSetFlags },
+    {"nativeSetWindowCrop", "(Landroid/graphics/Rect;)V",
+            (void*)nativeSetWindowCrop },
+    {"nativeSetLayerStack", "(I)V",
+            (void*)nativeSetLayerStack },
+    {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
+            (void*)nativeGetBuiltInDisplay },
+    {"nativeCreateDisplay", "(Ljava/lang/String;)Landroid/os/IBinder;",
+            (void*)nativeCreateDisplay },
+    {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/graphics/SurfaceTexture;)V",
+            (void*)nativeSetDisplaySurface },
+    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayLayerStack },
+    {"nativeSetDisplayOrientation", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayOrientation },
+    {"nativeSetDisplayViewport", "(Landroid/os/IBinder;Landroid/graphics/Rect;)V",
+            (void*)nativeSetDisplayViewport },
+    {"nativeSetDisplayFrame", "(Landroid/os/IBinder;Landroid/graphics/Rect;)V",
+            (void*)nativeSetDisplayFrame },
+    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z",
+            (void*)nativeGetDisplayInfo },
+    {"nativeCopyFrom", "(Landroid/view/Surface;)V",
+            (void*)nativeCopyFrom },
+    {"nativeTransferFrom", "(Landroid/view/Surface;)V",
+            (void*)nativeTransferFrom },
+    {"nativeReadFromParcel", "(Landroid/os/Parcel;)V",
+            (void*)nativeReadFromParcel },
+    {"nativeWriteToParcel", "(Landroid/os/Parcel;)V",
+            (void*)nativeWriteToParcel },
 };
 
-void nativeClassInit(JNIEnv* env, jclass clazz)
-{
-    so.surface = env->GetFieldID(clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    so.surfaceGenerationId = env->GetFieldID(clazz, "mSurfaceGenerationId", "I");
-    so.surfaceControl = env->GetFieldID(clazz, "mSurfaceControl", "I");
-    so.saveCount = env->GetFieldID(clazz, "mSaveCount", "I");
-    so.canvas    = env->GetFieldID(clazz, "mCanvas", "Landroid/graphics/Canvas;");
-
-    jclass surfaceSession = env->FindClass("android/view/SurfaceSession");
-    sso.client = env->GetFieldID(surfaceSession, "mClient", "I");
-
-    jclass canvas = env->FindClass("android/graphics/Canvas");
-    no.native_canvas = env->GetFieldID(canvas, "mNativeCanvas", "I");
-    co.surfaceFormat = env->GetFieldID(canvas, "mSurfaceFormat", "I");
-
-    jclass region = env->FindClass("android/graphics/Region");
-    no.native_region = env->GetFieldID(region, "mNativeRegion", "I");
-
-    jclass parcel = env->FindClass("android/os/Parcel");
-    no.native_parcel = env->GetFieldID(parcel, "mNativePtr", "I");
-
-    jclass rect = env->FindClass("android/graphics/Rect");
-    ro.l = env->GetFieldID(rect, "left", "I");
-    ro.t = env->GetFieldID(rect, "top", "I");
-    ro.r = env->GetFieldID(rect, "right", "I");
-    ro.b = env->GetFieldID(rect, "bottom", "I");
-
-    jclass point = env->FindClass("android/graphics/Point");
-    po.x = env->GetFieldID(point, "x", "I");
-    po.y = env->GetFieldID(point, "y", "I");
-}
-
 int register_android_view_Surface(JNIEnv* env)
 {
-    int err;
-    err = AndroidRuntime::registerNativeMethods(env, kSurfaceSessionClassPathName,
-            gSurfaceSessionMethods, NELEM(gSurfaceSessionMethods));
-
-    err |= AndroidRuntime::registerNativeMethods(env, kSurfaceClassPathName,
+    int err = AndroidRuntime::registerNativeMethods(env, "android/view/Surface",
             gSurfaceMethods, NELEM(gSurfaceMethods));
+
+    jclass clazz = env->FindClass("android/view/Surface");
+    gSurfaceClassInfo.clazz = jclass(env->NewGlobalRef(clazz));
+    gSurfaceClassInfo.mNativeSurface =
+            env->GetFieldID(gSurfaceClassInfo.clazz, ANDROID_VIEW_SURFACE_JNI_ID, "I");
+    gSurfaceClassInfo.mNativeSurfaceControl =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeSurfaceControl", "I");
+    gSurfaceClassInfo.mGenerationId =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mGenerationId", "I");
+    gSurfaceClassInfo.mCanvas =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvas", "Landroid/graphics/Canvas;");
+    gSurfaceClassInfo.mCanvasSaveCount =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mCanvasSaveCount", "I");
+
+    clazz = env->FindClass("android/graphics/Canvas");
+    gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
+    gCanvasClassInfo.mSurfaceFormat = env->GetFieldID(clazz, "mSurfaceFormat", "I");
+
+    clazz = env->FindClass("android/graphics/Rect");
+    gRectClassInfo.left = env->GetFieldID(clazz, "left", "I");
+    gRectClassInfo.top = env->GetFieldID(clazz, "top", "I");
+    gRectClassInfo.right = env->GetFieldID(clazz, "right", "I");
+    gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I");
+
+    clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo");
+    gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
+    gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
+    gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
+    gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
+    gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
+    gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
     return err;
 }
 
diff --git a/core/jni/android_view_SurfaceSession.cpp b/core/jni/android_view_SurfaceSession.cpp
new file mode 100644
index 0000000..1494bc5
--- /dev/null
+++ b/core/jni/android_view_SurfaceSession.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2012 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.
+ */
+
+#define LOG_TAG "SurfaceSession"
+
+#include "JNIHelp.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_SurfaceSession.h>
+#include <utils/Log.h>
+#include <utils/RefBase.h>
+
+#include <gui/SurfaceComposerClient.h>
+
+namespace android {
+
+static struct {
+    jfieldID mNativeClient;
+} gSurfaceSessionClassInfo;
+
+
+sp<SurfaceComposerClient> android_view_SurfaceSession_getClient(
+        JNIEnv* env, jobject surfaceSessionObj) {
+    return reinterpret_cast<SurfaceComposerClient*>(
+            env->GetIntField(surfaceSessionObj, gSurfaceSessionClassInfo.mNativeClient));
+}
+
+
+static jint nativeCreate(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient* client = new SurfaceComposerClient();
+    client->incStrong(clazz);
+    return reinterpret_cast<jint>(client);
+}
+
+static void nativeDestroy(JNIEnv* env, jclass clazz, jint ptr) {
+    SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
+    client->decStrong(clazz);
+}
+
+static void nativeKill(JNIEnv* env, jclass clazz, jint ptr) {
+    SurfaceComposerClient* client = reinterpret_cast<SurfaceComposerClient*>(ptr);
+    client->dispose();
+}
+
+
+static JNINativeMethod gMethods[] = {
+    /* name, signature, funcPtr */
+    { "nativeCreate", "()I",
+            (void*)nativeCreate },
+    { "nativeDestroy", "(I)V",
+            (void*)nativeDestroy },
+    { "nativeKill", "(I)V",
+            (void*)nativeKill }
+};
+
+int register_android_view_SurfaceSession(JNIEnv* env) {
+    int res = jniRegisterNativeMethods(env, "android/view/SurfaceSession",
+            gMethods, NELEM(gMethods));
+    LOG_ALWAYS_FATAL_IF(res < 0, "Unable to register native methods.");
+
+    jclass clazz = env->FindClass("android/view/SurfaceSession");
+    gSurfaceSessionClassInfo.mNativeClient = env->GetFieldID(clazz, "mNativeClient", "I");
+    return 0;
+}
+
+} // namespace android
diff --git a/core/jni/com_google_android_gles_jni_EGLImpl.cpp b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
index 9c6c7de..f8904bd 100644
--- a/core/jni/com_google_android_gles_jni_EGLImpl.cpp
+++ b/core/jni/com_google_android_gles_jni_EGLImpl.cpp
@@ -326,7 +326,7 @@
         return 0;
     }
 
-    window = android_Surface_getNativeWindow(_env, native_window);
+    window = android_view_Surface_getNativeWindow(_env, native_window);
     if (window == NULL)
         goto not_valid_surface;