Merge "split Surface in two classes: SurfaceControl and Surface"
diff --git a/core/java/android/app/UiAutomationConnection.java b/core/java/android/app/UiAutomationConnection.java
index 9b5857f..06ef472 100644
--- a/core/java/android/app/UiAutomationConnection.java
+++ b/core/java/android/app/UiAutomationConnection.java
@@ -27,7 +27,7 @@
 import android.os.ServiceManager;
 import android.view.IWindowManager;
 import android.view.InputEvent;
-import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.accessibility.AccessibilityEvent;
 import android.view.accessibility.IAccessibilityManager;
 
@@ -135,7 +135,7 @@
         }
         final long identity = Binder.clearCallingIdentity();
         try {
-            return Surface.screenshot(width, height);
+            return SurfaceControl.screenshot(width, height);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
diff --git a/core/java/android/view/Choreographer.java b/core/java/android/view/Choreographer.java
index b661748..f28e4b5 100644
--- a/core/java/android/view/Choreographer.java
+++ b/core/java/android/view/Choreographer.java
@@ -693,7 +693,7 @@
             // At this time Surface Flinger won't send us vsyncs for secondary displays
             // but that could change in the future so let's log a message to help us remember
             // that we need to fix this.
-            if (builtInDisplayId != Surface.BUILT_IN_DISPLAY_ID_MAIN) {
+            if (builtInDisplayId != SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                 Log.d(TAG, "Received vsync from secondary display, but we don't support "
                         + "this case yet.  Choreographer needs a way to explicitly request "
                         + "vsync for a specific display to ensure it doesn't lose track "
diff --git a/core/java/android/view/DisplayEventReceiver.java b/core/java/android/view/DisplayEventReceiver.java
index a919ffc..4dade20 100644
--- a/core/java/android/view/DisplayEventReceiver.java
+++ b/core/java/android/view/DisplayEventReceiver.java
@@ -102,7 +102,7 @@
      * @param timestampNanos The timestamp of the pulse, in the {@link System#nanoTime()}
      * timebase.
      * @param builtInDisplayId The surface flinger built-in display id such as
-     * {@link Surface#BUILT_IN_DISPLAY_ID_MAIN}.
+     * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_MAIN}.
      * @param frame The frame number.  Increases by one for each vertical sync interval.
      */
     public void onVsync(long timestampNanos, int builtInDisplayId, int frame) {
@@ -114,7 +114,7 @@
      * @param timestampNanos The timestamp of the event, in the {@link System#nanoTime()}
      * timebase.
      * @param builtInDisplayId The surface flinger built-in display id such as
-     * {@link Surface#BUILT_IN_DISPLAY_ID_HDMI}.
+     * {@link SurfaceControl#BUILT_IN_DISPLAY_ID_HDMI}.
      * @param connected True if the display is connected, false if it disconnected.
      */
     public void onHotplug(long timestampNanos, int builtInDisplayId, boolean connected) {
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index 48b7180..5e96dad 100644
--- a/core/java/android/view/Surface.java
+++ b/core/java/android/view/Surface.java
@@ -16,20 +16,15 @@
 
 package android.view;
 
-import dalvik.system.CloseGuard;
-
 import android.content.res.CompatibilityInfo.Translator;
-import android.graphics.Bitmap;
 import android.graphics.Canvas;
 import android.graphics.Matrix;
 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.SystemProperties;
+import android.os.Parcelable;
 import android.util.Log;
+import dalvik.system.CloseGuard;
 
 /**
  * Handle onto a raw buffer that is being managed by the screen compositor.
@@ -37,9 +32,6 @@
 public class Surface implements Parcelable {
     private static final String TAG = "Surface";
 
-    private static final boolean HEADLESS = "1".equals(
-        SystemProperties.get("ro.config.headless", "0"));
-
     public static final Parcelable.Creator<Surface> CREATOR =
             new Parcelable.Creator<Surface>() {
         public Surface createFromParcel(Parcel source) {
@@ -78,130 +70,6 @@
      */
     public static final int ROTATION_270 = 3;
 
-    /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
-     * these are different from the logical display ids used elsewhere in the framework */
-
-    /**
-     * Built-in physical display id: Main display.
-     * Use only with {@link #getBuiltInDisplay()}.
-     * @hide
-     */
-    public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
-
-    /**
-     * 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;
-
-    /**
-     * 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;
-
-    /**
-     * 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;
-
-    // 0x1000 is reserved for an independent DRM protected flag in framework
-
-    /**
-     * Surface creation flag: Creates a normal surface.
-     * This is the default.
-     * @hide
-     */
-    public static final int FX_SURFACE_NORMAL   = 0x00000000;
-
-    /**
-     * 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;
-
-    /**
-     * 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;
-
-    /**
-     * @hide
-     */
-    public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
-
-    /**
-     * 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) */
-    
-    /**
-     * 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;
@@ -211,8 +79,8 @@
     // 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 mNativeSurface; // Surface*
-    private int mNativeSurfaceControl; // SurfaceControl*
+    int mNativeObject; // package scope only for SurfaceControl access
+
     private int mGenerationId; // incremented each time mNativeSurface changes
     private final Canvas mCanvas = new CompatibleCanvas();
     private int mCanvasSaveCount; // Canvas save count at time of lockCanvas()
@@ -225,112 +93,12 @@
     // non compatibility mode.
     private Matrix mCompatibleMatrix;
 
-    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 boolean nativeIsConsumerRunningBehind();
-
-    private native Canvas nativeLockCanvas(Rect dirty);
-    private native void nativeUnlockCanvasAndPost(Canvas canvas);
-
-    private static native Bitmap nativeScreenshot(IBinder displayToken,
-            int width, int height, int minLayer, int maxLayer, boolean allLayers);
-
-    private static native void nativeOpenTransaction();
-    private static native void nativeCloseTransaction();
-    private static native void nativeSetAnimationTransaction();
-
-    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);
-
-    private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
-    private static native IBinder nativeCreateDisplay(String name, boolean secure);
-    private static native void nativeSetDisplaySurface(
-            IBinder displayToken, Surface surface);
-    private static native void nativeSetDisplayLayerStack(
-            IBinder displayToken, int layerStack);
-    private static native void nativeSetDisplayProjection(
-            IBinder displayToken, int orientation, Rect layerStackRect, Rect displayRect);
-    private static native boolean nativeGetDisplayInfo(
-            IBinder displayToken, PhysicalDisplayInfo outInfo);
-    private static native void nativeBlankDisplay(IBinder displayToken);
-    private static native void nativeUnblankDisplay(IBinder displayToken);
-
-    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().
      * @hide
      */
     public Surface() {
-        checkHeadless();
-
-        mCloseGuard.open("release");
-    }
-
-    /**
-     * 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");
     }
 
@@ -349,11 +117,9 @@
             throw new IllegalArgumentException("surfaceTexture must not be null");
         }
 
-        checkHeadless();
-
         mName = surfaceTexture.toString();
         try {
-            nativeCreateFromSurfaceTexture(surfaceTexture);
+            mNativeObject = nativeCreateFromSurfaceTexture(surfaceTexture);
         } catch (OutOfResourcesException ex) {
             // We can't throw OutOfResourcesException because it would be an API change.
             throw new RuntimeException(ex);
@@ -362,13 +128,20 @@
         mCloseGuard.open("release");
     }
 
+    private Surface(int nativeObject) {
+        mNativeObject = nativeObject;
+        mCloseGuard.open("release");
+    }
+
     @Override
     protected void finalize() throws Throwable {
         try {
             if (mCloseGuard != null) {
                 mCloseGuard.warnIfOpen();
             }
-            nativeRelease();
+            if (mNativeObject != 0) {
+                nativeRelease(mNativeObject);
+            }
         } finally {
             super.finalize();
         }
@@ -380,7 +153,10 @@
      * This will make the surface invalid.
      */
     public void release() {
-        nativeRelease();
+        if (mNativeObject != 0) {
+            nativeRelease(mNativeObject);
+            mNativeObject = 0;
+        }
         mCloseGuard.close();
     }
 
@@ -391,7 +167,10 @@
      * @hide
      */
     public void destroy() {
-        nativeDestroy();
+        if (mNativeObject != 0) {
+            nativeDestroy(mNativeObject);
+            mNativeObject = 0;
+        }
         mCloseGuard.close();
     }
 
@@ -402,7 +181,8 @@
      * Otherwise returns false.
      */
     public boolean isValid() {
-        return nativeIsValid();
+        if (mNativeObject == 0) return false;
+        return nativeIsValid(mNativeObject);
     }
 
     /**
@@ -423,7 +203,8 @@
      * @hide
      */
     public boolean isConsumerRunningBehind() {
-        return nativeIsConsumerRunningBehind();
+        checkNotReleased();
+        return nativeIsConsumerRunningBehind(mNativeObject);
     }
 
     /**
@@ -441,9 +222,10 @@
      * entire surface should be redrawn.
      * @return A canvas for drawing into the surface.
      */
-    public Canvas lockCanvas(Rect dirty)
+    public Canvas lockCanvas(Rect inOutDirty)
             throws OutOfResourcesException, IllegalArgumentException {
-        return nativeLockCanvas(dirty);
+        checkNotReleased();
+        return nativeLockCanvas(mNativeObject, inOutDirty);
     }
 
     /**
@@ -453,7 +235,8 @@
      * @param canvas The canvas previously obtained from {@link #lockCanvas}.
      */
     public void unlockCanvasAndPost(Canvas canvas) {
-        nativeUnlockCanvasAndPost(canvas);
+        checkNotReleased();
+        nativeUnlockCanvasAndPost(mNativeObject, canvas);
     }
 
     /** 
@@ -476,190 +259,6 @@
         }
     }
 
-    /**
-     * 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();
-    }
-
-    /** flag the transaction as an animation @hide */
-    public static void setAnimationTransaction() {
-        nativeSetAnimationTransaction();
-    }
-
-    /** @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, boolean secure) {
-        if (name == null) {
-            throw new IllegalArgumentException("name must not be null");
-        }
-        return nativeCreateDisplay(name, secure);
-    }
-
-    /** @hide */
-    public static void setDisplaySurface(IBinder displayToken, Surface surface) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        nativeSetDisplaySurface(displayToken, surface);
-    }
-
-    /** @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 setDisplayProjection(IBinder displayToken,
-            int orientation, Rect layerStackRect, Rect displayRect) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        if (layerStackRect == null) {
-            throw new IllegalArgumentException("layerStackRect must not be null");
-        }
-        if (displayRect == null) {
-            throw new IllegalArgumentException("displayRect must not be null");
-        }
-        nativeSetDisplayProjection(displayToken, orientation, layerStackRect, displayRect);
-    }
-
-    /** @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);
-    }
-
-    /** @hide */
-    public static void blankDisplay(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        nativeBlankDisplay(displayToken);
-    }
-
-    /** @hide */
-    public static void unblankDisplay(IBinder displayToken) {
-        if (displayToken == null) {
-            throw new IllegalArgumentException("displayToken must not be null");
-        }
-        nativeUnblankDisplay(displayToken);
-    }
 
     /**
      * Copy another surface to this one.  This surface now holds a reference
@@ -670,13 +269,15 @@
      * in to it.
      * @hide
      */
-    public void copyFrom(Surface other) {
+    public void copyFrom(SurfaceControl other) {
         if (other == null) {
             throw new IllegalArgumentException("other must not be null");
         }
-        if (other != this) {
-            nativeCopyFrom(other);
+        if (other.mNativeObject == 0) {
+            throw new NullPointerException(
+                    "SurfaceControl native object is null. Are you using a released SurfaceControl?");
         }
+        mNativeObject = nativeCopyFrom(mNativeObject, other.mNativeObject);
     }
 
     /**
@@ -692,7 +293,13 @@
             throw new IllegalArgumentException("other must not be null");
         }
         if (other != this) {
-            nativeTransferFrom(other);
+            if (mNativeObject != 0) {
+                // release our reference to our native object
+                nativeRelease(mNativeObject);
+            }
+            // transfer the reference from other to us
+            mNativeObject = other.mNativeObject;
+            other.mNativeObject = 0;
         }
     }
 
@@ -705,9 +312,8 @@
         if (source == null) {
             throw new IllegalArgumentException("source must not be null");
         }
-
         mName = source.readString();
-        nativeReadFromParcel(source);
+        mNativeObject = nativeReadFromParcel(mNativeObject, source);
     }
 
     @Override
@@ -715,9 +321,8 @@
         if (dest == null) {
             throw new IllegalArgumentException("dest must not be null");
         }
-
         dest.writeString(mName);
-        nativeWriteToParcel(dest);
+        nativeWriteToParcel(mNativeObject, dest);
         if ((flags & Parcelable.PARCELABLE_WRITE_RETURN_VALUE) != 0) {
             release();
         }
@@ -728,85 +333,18 @@
         return "Surface(name=" + mName + ")";
     }
 
-    private static void checkHeadless() {
-        if (HEADLESS) {
-            throw new UnsupportedOperationException("Device is headless");
-        }
-    }
-
     /**
      * 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 known to surface flinger.
-     * @hide
-     */
-    public static final class PhysicalDisplayInfo {
-        public int width;
-        public int height;
-        public float refreshRate;
-        public float density;
-        public float xDpi;
-        public float yDpi;
-        public boolean secure;
-
-        public PhysicalDisplayInfo() {
-        }
-
-        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
-            copyFrom(other);
-        }
-
-        @Override
-        public boolean equals(Object o) {
-            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
-        }
-
-        public boolean equals(PhysicalDisplayInfo other) {
-            return other != null
-                    && width == other.width
-                    && height == other.height
-                    && refreshRate == other.refreshRate
-                    && density == other.density
-                    && xDpi == other.xDpi
-                    && yDpi == other.yDpi
-                    && secure == other.secure;
-        }
-
-        @Override
-        public int hashCode() {
-            return 0; // don't care
-        }
-
-        public void copyFrom(PhysicalDisplayInfo other) {
-            width = other.width;
-            height = other.height;
-            refreshRate = other.refreshRate;
-            density = other.density;
-            xDpi = other.xDpi;
-            yDpi = other.yDpi;
-            secure = other.secure;
-        }
-
-        // For debugging purposes
-        @Override
-        public String toString() {
-            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
-                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
-                    + "}";
-        }
-    }
-
-    /**
      * Returns a human readable representation of a rotation.
      *
      * @param rotation The rotation.
@@ -893,4 +431,25 @@
             mOrigMatrix.set(m);
         }
     }
+
+    private void checkNotReleased() {
+        if (mNativeObject == 0) throw new NullPointerException(
+                "mNativeObject is null. Have you called release() already?");
+    }
+
+    private native int nativeCreateFromSurfaceTexture(SurfaceTexture surfaceTexture)
+            throws OutOfResourcesException;
+
+    private native void nativeRelease(int nativeObject);
+    private native void nativeDestroy(int nativeObject);
+    private native boolean nativeIsValid(int nativeObject);
+
+    private native boolean nativeIsConsumerRunningBehind(int nativeObject);
+
+    private native Canvas nativeLockCanvas(int nativeObject, Rect dirty);
+    private native void nativeUnlockCanvasAndPost(int nativeObject, Canvas canvas);
+    
+    private native int nativeCopyFrom(int nativeObject, int surfaceControlNativeObject);
+    private native int nativeReadFromParcel(int nativeObject, Parcel source);
+    private native void nativeWriteToParcel(int nativeObject, Parcel dest);
 }
diff --git a/core/java/android/view/SurfaceControl.java b/core/java/android/view/SurfaceControl.java
new file mode 100644
index 0000000..dd288b9
--- /dev/null
+++ b/core/java/android/view/SurfaceControl.java
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.view;
+
+import dalvik.system.CloseGuard;
+import android.graphics.Bitmap;
+import android.graphics.Rect;
+import android.graphics.Region;
+import android.os.IBinder;
+import android.os.SystemProperties;
+import android.util.Log;
+
+/**
+ * SurfaceControl
+ *  @hide
+ */
+public class SurfaceControl {
+    private static final String TAG = "SurfaceControl";
+    private final CloseGuard mCloseGuard = CloseGuard.get();
+    private String mName;
+    int mNativeObject; // package visibility only for Surface.java access
+
+    private static final boolean HEADLESS = "1".equals(
+        SystemProperties.get("ro.config.headless", "0"));
+
+    /**
+     * 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);
+        }
+    }
+
+    /* flags used in constructor (keep in sync with ISurfaceComposerClient.h) */
+
+    /**
+     * Surface creation flag: Surface is created hidden
+     */
+    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. 
+     *
+     */
+    public static final int SECURE = 0x00000080;
+
+    /**
+     * 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.
+     *
+     */
+    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.
+     *
+     */
+    public static final int OPAQUE = 0x00000400;
+
+    /**
+     * 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.
+     *
+     */
+    public static final int PROTECTED_APP = 0x00000800;
+
+    // 0x1000 is reserved for an independent DRM protected flag in framework
+
+    /**
+     * Surface creation flag: Creates a normal surface.
+     * This is the default.
+     *
+     */
+    public static final int FX_SURFACE_NORMAL   = 0x00000000;
+
+    /**
+     * 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.
+     *
+     * @deprecated
+     */
+    @Deprecated
+    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.
+     *
+     */
+    public static final int FX_SURFACE_DIM = 0x00020000;
+
+    /**
+     *
+     */
+    public static final int FX_SURFACE_SCREENSHOT = 0x00030000;
+
+    /**
+     * Mask used for FX values above.
+     *
+     */
+    public static final int FX_SURFACE_MASK = 0x000F0000;
+
+    /* flags used with setFlags() (keep in sync with ISurfaceComposer.h) */
+
+    /**
+     * Surface flag: Hide the surface.
+     * Equivalent to calling hide().
+     */
+    public static final int SURFACE_HIDDEN = 0x01;
+
+
+    /* built-in physical display ids (keep in sync with ISurfaceComposer.h)
+     * these are different from the logical display ids used elsewhere in the framework */
+
+    /**
+     * Built-in physical display id: Main display.
+     * Use only with {@link SurfaceControl#getBuiltInDisplay()}.
+     */
+    public static final int BUILT_IN_DISPLAY_ID_MAIN = 0;
+
+    /**
+     * Built-in physical display id: Attached HDMI display.
+     * Use only with {@link SurfaceControl#getBuiltInDisplay()}.
+     */
+    public static final int BUILT_IN_DISPLAY_ID_HDMI = 1;
+
+
+
+    /**
+     * 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.
+     */
+    public SurfaceControl(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 & SurfaceControl.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;
+        mNativeObject = nativeCreate(session, name, w, h, format, flags);
+        if (mNativeObject == 0) {
+            throw new OutOfResourcesException(
+                    "Couldn't allocate SurfaceControl native object");
+        }
+        
+        mCloseGuard.open("release");
+    }
+    
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            if (mCloseGuard != null) {
+                mCloseGuard.warnIfOpen();
+            }
+            if (mNativeObject != 0) {
+                nativeRelease(mNativeObject);
+            }
+        } finally {
+            super.finalize();
+        }
+    }
+
+    @Override
+    public String toString() {
+        return "Surface(name=" + mName + ")";
+    }
+
+    /**
+     * 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() {
+        if (mNativeObject != 0) {
+            nativeRelease(mNativeObject);
+            mNativeObject = 0;
+        }
+        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.
+     */
+    public void destroy() {
+        if (mNativeObject != 0) {
+            nativeDestroy(mNativeObject);
+            mNativeObject = 0;
+        }
+        mCloseGuard.close();
+    }
+
+    private void checkNotReleased() {
+        if (mNativeObject == 0) throw new NullPointerException(
+                "mNativeObject is null. Have you called release() already?");
+    }
+    
+    /*
+     * set surface parameters.
+     * needs to be inside open/closeTransaction block
+     */
+
+    /** start a transaction */
+    public static void openTransaction() {
+        nativeOpenTransaction();
+    }
+
+    /** end a transaction */
+    public static void closeTransaction() {
+        nativeCloseTransaction();
+    }
+
+    /** flag the transaction as an animation */
+    public static void setAnimationTransaction() {
+        nativeSetAnimationTransaction();
+    }
+
+    public void setLayer(int zorder) {
+        checkNotReleased();
+        nativeSetLayer(mNativeObject, zorder);
+    }
+
+    public void setPosition(int x, int y) {
+        checkNotReleased();
+        nativeSetPosition(mNativeObject, (float)x, (float)y);
+    }
+
+    public void setPosition(float x, float y) {
+        checkNotReleased();
+        nativeSetPosition(mNativeObject, x, y);
+    }
+
+    public void setSize(int w, int h) {
+        checkNotReleased();
+        nativeSetSize(mNativeObject, w, h);
+    }
+
+    public void hide() {
+        checkNotReleased();
+        nativeSetFlags(mNativeObject, SURFACE_HIDDEN, SURFACE_HIDDEN);
+    }
+
+    public void show() {
+        checkNotReleased();
+        nativeSetFlags(mNativeObject, 0, SURFACE_HIDDEN);
+    }
+
+    public void setTransparentRegionHint(Region region) {
+        checkNotReleased();
+        nativeSetTransparentRegionHint(mNativeObject, region);
+    }
+
+    public void setAlpha(float alpha) {
+        checkNotReleased();
+        nativeSetAlpha(mNativeObject, alpha);
+    }
+
+    public void setMatrix(float dsdx, float dtdx, float dsdy, float dtdy) {
+        checkNotReleased();
+        nativeSetMatrix(mNativeObject, dsdx, dtdx, dsdy, dtdy);
+    }
+
+    public void setFlags(int flags, int mask) {
+        checkNotReleased();
+        nativeSetFlags(mNativeObject, flags, mask);
+    }
+
+    public void setWindowCrop(Rect crop) {
+        checkNotReleased();
+        if (crop != null) {
+            nativeSetWindowCrop(mNativeObject, 
+                crop.left, crop.top, crop.right, crop.bottom);
+        } else {
+            nativeSetWindowCrop(mNativeObject, 0, 0, 0, 0);
+        }
+    }
+
+    public void setLayerStack(int layerStack) {
+        checkNotReleased();
+        nativeSetLayerStack(mNativeObject, layerStack);
+    }
+
+    /*
+     * set display parameters.
+     * needs to be inside open/closeTransaction block
+     */
+
+    /**
+     * Describes the properties of a physical display known to surface flinger.
+     */
+    public static final class PhysicalDisplayInfo {
+        public int width;
+        public int height;
+        public float refreshRate;
+        public float density;
+        public float xDpi;
+        public float yDpi;
+        public boolean secure;
+    
+        public PhysicalDisplayInfo() {
+        }
+    
+        public PhysicalDisplayInfo(PhysicalDisplayInfo other) {
+            copyFrom(other);
+        }
+    
+        @Override
+        public boolean equals(Object o) {
+            return o instanceof PhysicalDisplayInfo && equals((PhysicalDisplayInfo)o);
+        }
+    
+        public boolean equals(PhysicalDisplayInfo other) {
+            return other != null
+                    && width == other.width
+                    && height == other.height
+                    && refreshRate == other.refreshRate
+                    && density == other.density
+                    && xDpi == other.xDpi
+                    && yDpi == other.yDpi
+                    && secure == other.secure;
+        }
+    
+        @Override
+        public int hashCode() {
+            return 0; // don't care
+        }
+    
+        public void copyFrom(PhysicalDisplayInfo other) {
+            width = other.width;
+            height = other.height;
+            refreshRate = other.refreshRate;
+            density = other.density;
+            xDpi = other.xDpi;
+            yDpi = other.yDpi;
+            secure = other.secure;
+        }
+    
+        // For debugging purposes
+        @Override
+        public String toString() {
+            return "PhysicalDisplayInfo{" + width + " x " + height + ", " + refreshRate + " fps, "
+                    + "density " + density + ", " + xDpi + " x " + yDpi + " dpi, secure " + secure
+                    + "}";
+        }
+    }
+
+    public static void unblankDisplay(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeUnblankDisplay(displayToken);
+    }
+
+    public static void blankDisplay(IBinder displayToken) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeBlankDisplay(displayToken);
+    }
+
+    public static boolean getDisplayInfo(IBinder displayToken, SurfaceControl.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);
+    }
+
+    public static void setDisplayProjection(IBinder displayToken,
+            int orientation, Rect layerStackRect, Rect displayRect) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (layerStackRect == null) {
+            throw new IllegalArgumentException("layerStackRect must not be null");
+        }
+        if (displayRect == null) {
+            throw new IllegalArgumentException("displayRect must not be null");
+        }
+        nativeSetDisplayProjection(displayToken, orientation,
+                layerStackRect.left, layerStackRect.top, layerStackRect.right, layerStackRect.bottom, 
+                displayRect.left, displayRect.top, displayRect.right, displayRect.bottom);
+    }
+
+    public static void setDisplayLayerStack(IBinder displayToken, int layerStack) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        nativeSetDisplayLayerStack(displayToken, layerStack);
+    }
+
+    public static void setDisplaySurface(IBinder displayToken, Surface surface) {
+        if (displayToken == null) {
+            throw new IllegalArgumentException("displayToken must not be null");
+        }
+        if (surface == null) {
+            throw new IllegalArgumentException("surface must not be null");
+        }
+        if (surface.mNativeObject == 0) 
+            throw new NullPointerException("Surface native object is null. Are you using a released surface?");
+            
+        nativeSetDisplaySurface(displayToken, surface.mNativeObject);
+    }
+
+    public static IBinder createDisplay(String name, boolean secure) {
+        if (name == null) {
+            throw new IllegalArgumentException("name must not be null");
+        }
+        return nativeCreateDisplay(name, secure);
+    }
+
+    public static IBinder getBuiltInDisplay(int builtInDisplayId) {
+        return nativeGetBuiltInDisplay(builtInDisplayId);
+    }
+
+    
+    /**
+     * 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.
+     *
+     */
+    public static Bitmap screenshot(int width, int height, int minLayer, int maxLayer) {
+        // TODO: should take the display as a parameter
+        IBinder displayToken = SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
+        return nativeScreenshot(displayToken, width, height, minLayer, maxLayer, false);
+    }
+
+    /**
+     * Like {@link SurfaceControl#screenshot(int, int, int, int)} but includes all
+     * Surfaces in the screenshot.
+     *
+     */
+    public static Bitmap screenshot(int width, int height) {
+        // TODO: should take the display as a parameter
+        IBinder displayToken = SurfaceControl.getBuiltInDisplay(SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN);
+        return nativeScreenshot(displayToken, width, height, 0, 0, true);
+    }
+    
+    private static void checkHeadless() {
+        if (HEADLESS) {
+            throw new UnsupportedOperationException("Device is headless");
+        }
+    }
+    
+    
+
+    private native int nativeCreate(SurfaceSession session, String name,
+            int w, int h, int format, int flags)
+            throws OutOfResourcesException;
+    private native void nativeRelease(int nativeObject);
+    private native void nativeDestroy(int nativeObject);
+    
+    private static native Bitmap nativeScreenshot(IBinder displayToken,
+            int width, int height, int minLayer, int maxLayer, boolean allLayers);
+    
+    private static native void nativeOpenTransaction();
+    private static native void nativeCloseTransaction();
+    private static native void nativeSetAnimationTransaction();
+
+    private native void nativeSetLayer(int nativeObject, int zorder);
+    private native void nativeSetPosition(int nativeObject, float x, float y);
+    private native void nativeSetSize(int nativeObject, int w, int h);
+    private native void nativeSetTransparentRegionHint(int nativeObject, Region region);
+    private native void nativeSetAlpha(int nativeObject, float alpha);
+    private native void nativeSetMatrix(int nativeObject, float dsdx, float dtdx, float dsdy, float dtdy);
+    private native void nativeSetFlags(int nativeObject, int flags, int mask);
+    private native void nativeSetWindowCrop(int nativeObject, int l, int t, int r, int b);
+    private native void nativeSetLayerStack(int nativeObject, int layerStack);
+
+    private static native IBinder nativeGetBuiltInDisplay(int physicalDisplayId);
+    private static native IBinder nativeCreateDisplay(String name, boolean secure);
+    private static native void nativeSetDisplaySurface(
+            IBinder displayToken, int nativeSurfaceObject);
+    private static native void nativeSetDisplayLayerStack(
+            IBinder displayToken, int layerStack);
+    private static native void nativeSetDisplayProjection(
+            IBinder displayToken, int orientation,
+            int l, int t, int r, int b, 
+            int L, int T, int R, int B);
+    private static native boolean nativeGetDisplayInfo(
+            IBinder displayToken, SurfaceControl.PhysicalDisplayInfo outInfo);
+    private static native void nativeBlankDisplay(IBinder displayToken);
+    private static native void nativeUnblankDisplay(IBinder displayToken);
+}
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 5337329..c6b7631 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -42,6 +42,7 @@
 	android_emoji_EmojiFactory.cpp \
 	android_view_DisplayEventReceiver.cpp \
 	android_view_Surface.cpp \
+	android_view_SurfaceControl.cpp \
 	android_view_SurfaceSession.cpp \
 	android_view_TextureView.cpp \
 	android_view_InputChannel.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index aa59b43..86d3cb6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -47,8 +47,6 @@
 
 using namespace android;
 
-extern void register_BindTest();
-
 extern int register_android_os_Binder(JNIEnv* env);
 extern int register_android_os_Process(JNIEnv* env);
 extern int register_android_graphics_Bitmap(JNIEnv*);
@@ -121,6 +119,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_SurfaceControl(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);
@@ -1113,6 +1112,7 @@
     REG_JNI(register_android_view_GLES20Canvas),
     REG_JNI(register_android_view_HardwareRenderer),
     REG_JNI(register_android_view_Surface),
+    REG_JNI(register_android_view_SurfaceControl),
     REG_JNI(register_android_view_SurfaceSession),
     REG_JNI(register_android_view_TextureView),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 0e0893b..7c65662 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -23,6 +23,7 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 #include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <android_runtime/android_view_Surface.h>
 
 #include <cutils/properties.h>
 #include <utils/Vector.h>
@@ -36,7 +37,6 @@
 
 struct fields_t {
     jfieldID    context;
-    jfieldID    surface;
     jfieldID    facing;
     jfieldID    orientation;
     jfieldID    canDisableShutterSound;
@@ -537,10 +537,8 @@
     sp<Camera> camera = get_native_camera(env, thiz, NULL);
     if (camera == 0) return;
 
-    sp<Surface> surface = NULL;
-    if (jSurface != NULL) {
-        surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
-    }
+    sp<Surface> surface = android_view_Surface_getSurface(env, jSurface);
+
     if (camera->setPreviewDisplay(surface) != NO_ERROR) {
         jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
     }
@@ -965,7 +963,6 @@
 {
     field fields_to_find[] = {
         { "android/hardware/Camera", "mNativeContext",   "I", &fields.context },
-        { "android/view/Surface",    ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface },
         { "android/hardware/Camera$CameraInfo", "facing",   "I", &fields.facing },
         { "android/hardware/Camera$CameraInfo", "orientation",   "I", &fields.orientation },
         { "android/hardware/Camera$CameraInfo", "canDisableShutterSound",   "Z",
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 40b505c..6f71868 100644
--- a/core/jni/android_view_Surface.cpp
+++ b/core/jni/android_view_Surface.cpp
@@ -18,41 +18,30 @@
 
 #include <stdio.h>
 
+#include "jni.h"
+#include "JNIHelp.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>
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_Surface.h>
+#include <android_runtime/android_graphics_SurfaceTexture.h>
 
-#include <gui/ISurfaceComposer.h>
 #include <gui/Surface.h>
-#include <gui/SurfaceComposerClient.h>
 #include <gui/GLConsumer.h>
 
-#include <ui/DisplayInfo.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
-#include <EGL/egl.h>
-
 #include <SkCanvas.h>
 #include <SkBitmap.h>
 #include <SkRegion.h>
-#include <SkPixelRef.h>
 
-#include "jni.h"
-#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 <utils/Log.h>
 
 #include <ScopedUtfChars.h>
 
-
 // ----------------------------------------------------------------------------
 
 namespace android {
@@ -62,8 +51,7 @@
 
 static struct {
     jclass clazz;
-    jfieldID mNativeSurface;
-    jfieldID mNativeSurfaceControl;
+    jfieldID mNativeObject;
     jfieldID mGenerationId;
     jfieldID mCanvas;
     jfieldID mCanvasSaveCount;
@@ -82,166 +70,19 @@
     jfieldID mSurfaceFormat;
 } gCanvasClassInfo;
 
-static struct {
-    jfieldID width;
-    jfieldID height;
-    jfieldID refreshRate;
-    jfieldID density;
-    jfieldID xDpi;
-    jfieldID yDpi;
-    jfieldID secure;
-} gPhysicalDisplayInfoClassInfo;
-
-
-class ScreenshotPixelRef : public SkPixelRef {
-public:
-    ScreenshotPixelRef(SkColorTable* ctable) {
-        fCTable = ctable;
-        SkSafeRef(ctable);
-        setImmutable();
-    }
-
-    virtual ~ScreenshotPixelRef() {
-        SkSafeUnref(fCTable);
-    }
-
-    status_t update(const sp<IBinder>& display, int width, int height,
-            int minLayer, int maxLayer, bool allLayers) {
-        status_t res = (width > 0 && height > 0)
-                ? (allLayers
-                        ? mScreenshot.update(display, width, height)
-                        : mScreenshot.update(display, width, height, minLayer, maxLayer))
-                : mScreenshot.update(display);
-        if (res != NO_ERROR) {
-            return res;
-        }
-
-        return NO_ERROR;
-    }
-
-    uint32_t getWidth() const {
-        return mScreenshot.getWidth();
-    }
-
-    uint32_t getHeight() const {
-        return mScreenshot.getHeight();
-    }
-
-    uint32_t getStride() const {
-        return mScreenshot.getStride();
-    }
-
-    uint32_t getFormat() const {
-        return mScreenshot.getFormat();
-    }
-
-protected:
-    // overrides from SkPixelRef
-    virtual void* onLockPixels(SkColorTable** ct) {
-        *ct = fCTable;
-        return (void*)mScreenshot.getPixels();
-    }
-
-    virtual void onUnlockPixels() {
-    }
-
-private:
-    ScreenshotClient mScreenshot;
-    SkColorTable*    fCTable;
-
-    typedef SkPixelRef INHERITED;
-};
-
-
 // ----------------------------------------------------------------------------
 
-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<ANativeWindow> android_view_Surface_getNativeWindow(JNIEnv* env, jobject surfaceObj) {
+    return android_view_Surface_getSurface(env, surfaceObj);
+}
+
 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 sp<IGraphicBufferProducer> getISurfaceTexture(JNIEnv* env, jobject surfaceObj) {
-    if (surfaceObj) {
-        sp<Surface> surface(getSurface(env, surfaceObj));
-        if (surface != NULL) {
-            return surface->getSurfaceTexture();
-        }
-    }
-    return NULL;
+    return reinterpret_cast<Surface *>(
+            env->GetIntField(surfaceObj, gSurfaceClassInfo.mNativeObject));
 }
 
 jobject android_view_Surface_createFromISurfaceTexture(JNIEnv* env,
@@ -255,7 +96,7 @@
         return NULL;
     }
 
-    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor);
+    jobject surfaceObj = env->NewObject(gSurfaceClassInfo.clazz, gSurfaceClassInfo.ctor, surface.get());
     if (surfaceObj == NULL) {
         if (env->ExceptionCheck()) {
             ALOGE("Could not create instance of Surface from IGraphicBufferProducer.");
@@ -264,82 +105,55 @@
         }
         return NULL;
     }
-
-    setSurface(env, surfaceObj, surface);
+    surface->incStrong(surfaceObj);
     return surfaceObj;
 }
 
-
 // ----------------------------------------------------------------------------
 
-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,
+static jint nativeCreateFromSurfaceTexture(JNIEnv* env, jobject surfaceObj,
         jobject surfaceTextureObj) {
     sp<GLConsumer> st(SurfaceTexture_getSurfaceTexture(env, surfaceTextureObj));
     if (st == NULL) {
         jniThrowException(env, "java/lang/IllegalArgumentException",
                 "SurfaceTexture has already been released");
-        return;
+        return 0;
     }
 
     sp<IGraphicBufferProducer> bq = st->getBufferQueue();
-
     sp<Surface> surface(new Surface(bq));
     if (surface == NULL) {
         jniThrowException(env, OutOfResourcesException, NULL);
-        return;
+        return 0;
     }
 
-    setSurface(env, surfaceObj, surface);
+    surface->incStrong(surfaceObj);
+    return int(surface.get());
 }
 
-static void nativeRelease(JNIEnv* env, jobject surfaceObj) {
-    setSurfaceControl(env, surfaceObj, NULL);
-    setSurface(env, surfaceObj, NULL);
+static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
+    sur->decStrong(surfaceObj);
 }
 
-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 void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
+    sur->decStrong(surfaceObj);
 }
 
-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 jboolean nativeIsValid(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
+    return Surface::isValid(sur) ? JNI_TRUE : JNI_FALSE;
 }
 
-static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) {
-    sp<Surface> surface(getSurface(env, surfaceObj));
-    if (!Surface::isValid(surface)) {
+static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
+    if (!Surface::isValid(sur)) {
         doThrowIAE(env);
         return JNI_FALSE;
     }
-
     int value = 0;
-    ANativeWindow* anw = static_cast<ANativeWindow*>(surface.get());
+    ANativeWindow* anw = static_cast<ANativeWindow*>(sur.get());
     anw->query(anw, NATIVE_WINDOW_CONSUMER_RUNNING_BEHIND, &value);
     return value;
 }
@@ -359,8 +173,9 @@
     }
 }
 
-static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jobject dirtyRectObj) {
-    sp<Surface> surface(getSurface(env, surfaceObj));
+static jobject nativeLockCanvas(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject dirtyRectObj) {
+    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
+
     if (!Surface::isValid(surface)) {
         doThrowIAE(env);
         return NULL;
@@ -440,14 +255,14 @@
     return canvasObj;
 }
 
-static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jobject canvasObj) {
+static void nativeUnlockCanvasAndPost(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject canvasObj) {
     jobject ownCanvasObj = env->GetObjectField(surfaceObj, gSurfaceClassInfo.mCanvas);
     if (!env->IsSameObject(ownCanvasObj, canvasObj)) {
         doThrowIAE(env);
         return;
     }
 
-    sp<Surface> surface(getSurface(env, surfaceObj));
+    sp<Surface> surface(reinterpret_cast<Surface *>(nativeObject));
     if (!Surface::isValid(surface)) {
         return;
     }
@@ -467,393 +282,81 @@
     }
 }
 
-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(displayToken, width, height,
-            minLayer, maxLayer, allLayers) != NO_ERROR) {
-        delete pixels;
-        return NULL;
-    }
-
-    uint32_t w = pixels->getWidth();
-    uint32_t h = pixels->getHeight();
-    uint32_t s = pixels->getStride();
-    uint32_t f = pixels->getFormat();
-    ssize_t bpr = s * android::bytesPerPixel(f);
-
-    SkBitmap* bitmap = new SkBitmap();
-    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
-    if (f == PIXEL_FORMAT_RGBX_8888) {
-        bitmap->setIsOpaque(true);
-    }
-
-    if (w > 0 && h > 0) {
-        bitmap->setPixelRef(pixels)->unref();
-        bitmap->lockPixels();
-    } else {
-        // be safe with an empty bitmap.
-        delete pixels;
-        bitmap->setPixels(NULL);
-    }
-
-    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
-}
-
-static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
-    SurfaceComposerClient::openGlobalTransaction();
-}
-
-static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
-    SurfaceComposerClient::closeGlobalTransaction();
-}
-
-static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
-    SurfaceComposerClient::setAnimationTransaction();
-}
-
-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) {
-        doThrowIAE(env);
-    }
-}
-
-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) {
-        doThrowIAE(env);
-    }
-}
-
-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) {
-        doThrowIAE(env);
-    }
-}
-
-static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint flags, jint mask) {
-    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
-    if (surface == NULL) return;
-
-    status_t err = surface->setFlags(flags, mask);
-    if (err < 0 && err != NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jobject regionObj) {
-    sp<SurfaceControl> surface(getSurfaceControl(env, surfaceObj));
-    if (surface == NULL) return;
-
-    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 (region->isComplex()) {
-        SkRegion::Iterator it(*region);
-        while (!it.done()) {
-            const SkIRect& r(it.rect());
-            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
-            it.next();
-        }
-    }
-
-    status_t err = surface->setTransparentRegionHint(reg);
-    if (err < 0 && err != NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-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) {
-        doThrowIAE(env);
-    }
-}
-
-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) {
-        doThrowIAE(env);
-    }
-}
-
-static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jobject cropObj) {
-    const sp<SurfaceControl>& surface(getSurfaceControl(env, surfaceObj));
-    if (surface == NULL) return;
-
-    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 {
-        crop.left = crop.top = crop.right = crop.bottom = 0;
-    }
-
-    status_t err = surface->setCrop(crop);
-    if (err < 0 && err != NO_INIT) {
-        doThrowIAE(env);
-    }
-}
-
-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) {
-        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,
-        jboolean secure) {
-    ScopedUtfChars name(env, nameObj);
-    sp<IBinder> token(SurfaceComposerClient::createDisplay(
-            String8(name.c_str()), bool(secure)));
-    return javaObjectForIBinder(env, token);
-}
-
-static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
-        jobject tokenObj, jobject surfaceObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return;
-
-    sp<IGraphicBufferProducer> bufferProducer(getISurfaceTexture(env, surfaceObj));
-    SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
-}
-
-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 nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
-        jobject tokenObj, jint orientation, jobject layerStackRectObj, jobject displayRectObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return;
-
-    Rect layerStackRect;
-    layerStackRect.left = env->GetIntField(layerStackRectObj, gRectClassInfo.left);
-    layerStackRect.top = env->GetIntField(layerStackRectObj, gRectClassInfo.top);
-    layerStackRect.right = env->GetIntField(layerStackRectObj, gRectClassInfo.right);
-    layerStackRect.bottom = env->GetIntField(layerStackRectObj, gRectClassInfo.bottom);
-
-    Rect displayRect;
-    displayRect.left = env->GetIntField(displayRectObj, gRectClassInfo.left);
-    displayRect.top = env->GetIntField(displayRectObj, gRectClassInfo.top);
-    displayRect.right = env->GetIntField(displayRectObj, gRectClassInfo.right);
-    displayRect.bottom = env->GetIntField(displayRectObj, gRectClassInfo.bottom);
-
-    SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
-}
-
-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);
-    env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
-    return JNI_TRUE;
-}
-
-static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return;
-
-    ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
-    SurfaceComposerClient::blankDisplay(token);
-}
-
-static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
-    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
-    if (token == NULL) return;
-
-    ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
-    SurfaceComposerClient::unblankDisplay(token);
-}
-
 // ----------------------------------------------------------------------------
 
-static void nativeCopyFrom(JNIEnv* env, jobject surfaceObj, jobject otherObj) {
+static jint nativeCopyFrom(JNIEnv* env, jobject surfaceObj,
+        jint nativeObject, jint surfaceControlNativeObj) {
     /*
      * 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.
      */
 
-    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, surfaceObj, other);
+    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(surfaceControlNativeObj));
+    sp<Surface> other(ctrl->getSurface());
+    if (other != NULL) {
+        other->incStrong(surfaceObj);
     }
+
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeObject));
+    if (sur != NULL) {
+        sur->decStrong(surfaceObj);
+    }
+
+    return int(other.get());
 }
 
-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 jint nativeReadFromParcel(JNIEnv* env, jobject surfaceObj,
+        jint nativeObject, jobject parcelObj) {
+    Parcel* parcel = parcelForJavaObject(env, parcelObj);
+    if (parcel == NULL) {
+        doThrowNPE(env);
+        return 0;
+    }
+    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
+    if (self != NULL) {
+        self->decStrong(surfaceObj);
+    }
+    sp<Surface> sur(Surface::readFromParcel(*parcel));
+    if (sur != NULL) {
+        sur->incStrong(surfaceObj);
+    }
+    return int(sur.get());
 }
 
-static void nativeReadFromParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
+static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj,
+        jint nativeObject, jobject parcelObj) {
     Parcel* parcel = parcelForJavaObject(env, parcelObj);
     if (parcel == NULL) {
         doThrowNPE(env);
         return;
     }
-
-    sp<Surface> surface(Surface::readFromParcel(*parcel));
-    setSurfaceControl(env, surfaceObj, NULL);
-    setSurface(env, surfaceObj, surface);
-}
-
-static void nativeWriteToParcel(JNIEnv* env, jobject surfaceObj, jobject parcelObj) {
-    Parcel* parcel = parcelForJavaObject(env, parcelObj);
-    if (parcel == NULL) {
-        doThrowNPE(env);
-        return;
-    }
-
-    // The Java instance may have a SurfaceControl (in the case of the
-    // WindowManager or a system app). In that case, we defer to the
-    // SurfaceControl to send its ISurface. Otherwise, if the Surface is
-    // 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.
-    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
-    if (control != NULL) {
-        SurfaceControl::writeSurfaceToParcel(control, parcel);
-    } else {
-        sp<Surface> surface(android_view_Surface_getSurface(env, surfaceObj));
-        if (surface != NULL) {
-            Surface::writeToParcel(surface, parcel);
-        } else {
-            SurfaceControl::writeSurfaceToParcel(NULL, parcel);
-        }
-    }
+    sp<Surface> self(reinterpret_cast<Surface *>(nativeObject));
+    Surface::writeToParcel(self, parcel);
 }
 
 // ----------------------------------------------------------------------------
 
 static JNINativeMethod gSurfaceMethods[] = {
-    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)V",
-            (void*)nativeCreate },
-    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)V",
+    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)I",
             (void*)nativeCreateFromSurfaceTexture },
-    {"nativeRelease", "()V",
+    {"nativeRelease", "(I)V",
             (void*)nativeRelease },
-    {"nativeDestroy", "()V",
+    {"nativeDestroy", "(I)V",
             (void*)nativeDestroy },
-    {"nativeIsValid", "()Z",
+    {"nativeIsValid", "(I)Z",
             (void*)nativeIsValid },
-    {"nativeIsConsumerRunningBehind", "()Z",
+    {"nativeIsConsumerRunningBehind", "(I)Z",
             (void*)nativeIsConsumerRunningBehind },
-    {"nativeLockCanvas", "(Landroid/graphics/Rect;)Landroid/graphics/Canvas;",
+    {"nativeLockCanvas", "(ILandroid/graphics/Rect;)Landroid/graphics/Canvas;",
             (void*)nativeLockCanvas },
-    {"nativeUnlockCanvasAndPost", "(Landroid/graphics/Canvas;)V",
+    {"nativeUnlockCanvasAndPost", "(ILandroid/graphics/Canvas;)V",
             (void*)nativeUnlockCanvasAndPost },
-    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
-            (void*)nativeScreenshot },
-    {"nativeOpenTransaction", "()V",
-            (void*)nativeOpenTransaction },
-    {"nativeCloseTransaction", "()V",
-            (void*)nativeCloseTransaction },
-    {"nativeSetAnimationTransaction", "()V",
-            (void*)nativeSetAnimationTransaction },
-    {"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;Z)Landroid/os/IBinder;",
-            (void*)nativeCreateDisplay },
-    {"nativeSetDisplaySurface", "(Landroid/os/IBinder;Landroid/view/Surface;)V",
-            (void*)nativeSetDisplaySurface },
-    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
-            (void*)nativeSetDisplayLayerStack },
-    {"nativeSetDisplayProjection", "(Landroid/os/IBinder;ILandroid/graphics/Rect;Landroid/graphics/Rect;)V",
-            (void*)nativeSetDisplayProjection },
-    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/Surface$PhysicalDisplayInfo;)Z",
-            (void*)nativeGetDisplayInfo },
-    {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
-            (void*)nativeBlankDisplay },
-    {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
-            (void*)nativeUnblankDisplay },
-    {"nativeCopyFrom", "(Landroid/view/Surface;)V",
+    {"nativeCopyFrom", "(II)I",
             (void*)nativeCopyFrom },
-    {"nativeTransferFrom", "(Landroid/view/Surface;)V",
-            (void*)nativeTransferFrom },
-    {"nativeReadFromParcel", "(Landroid/os/Parcel;)V",
+    {"nativeReadFromParcel", "(ILandroid/os/Parcel;)I",
             (void*)nativeReadFromParcel },
-    {"nativeWriteToParcel", "(Landroid/os/Parcel;)V",
+    {"nativeWriteToParcel", "(ILandroid/os/Parcel;)V",
             (void*)nativeWriteToParcel },
 };
 
@@ -864,17 +367,15 @@
 
     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.mNativeObject =
+            env->GetFieldID(gSurfaceClassInfo.clazz, "mNativeObject", "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");
-    gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "()V");
+    gSurfaceClassInfo.ctor = env->GetMethodID(gSurfaceClassInfo.clazz, "<init>", "(I)V");
 
     clazz = env->FindClass("android/graphics/Canvas");
     gCanvasClassInfo.mNativeCanvas = env->GetFieldID(clazz, "mNativeCanvas", "I");
@@ -886,14 +387,6 @@
     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");
-    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
     return err;
 }
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
new file mode 100644
index 0000000..7398895
--- /dev/null
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2013 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 "SurfaceControl"
+
+#include <stdio.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+#include "android/graphics/GraphicsJNI.h"
+#include "android/graphics/Region.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_SurfaceSession.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <ui/DisplayInfo.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <utils/Log.h>
+
+#include <ScopedUtfChars.h>
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static const char* const OutOfResourcesException =
+    "android/view/Surface$OutOfResourcesException";
+
+static struct {
+    jfieldID width;
+    jfieldID height;
+    jfieldID refreshRate;
+    jfieldID density;
+    jfieldID xDpi;
+    jfieldID yDpi;
+    jfieldID secure;
+} gPhysicalDisplayInfoClassInfo;
+
+
+class ScreenshotPixelRef : public SkPixelRef {
+public:
+    ScreenshotPixelRef(SkColorTable* ctable) {
+        fCTable = ctable;
+        SkSafeRef(ctable);
+        setImmutable();
+    }
+
+    virtual ~ScreenshotPixelRef() {
+        SkSafeUnref(fCTable);
+    }
+
+    status_t update(const sp<IBinder>& display, int width, int height,
+            int minLayer, int maxLayer, bool allLayers) {
+        status_t res = (width > 0 && height > 0)
+                ? (allLayers
+                        ? mScreenshot.update(display, width, height)
+                        : mScreenshot.update(display, width, height, minLayer, maxLayer))
+                : mScreenshot.update(display);
+        if (res != NO_ERROR) {
+            return res;
+        }
+
+        return NO_ERROR;
+    }
+
+    uint32_t getWidth() const {
+        return mScreenshot.getWidth();
+    }
+
+    uint32_t getHeight() const {
+        return mScreenshot.getHeight();
+    }
+
+    uint32_t getStride() const {
+        return mScreenshot.getStride();
+    }
+
+    uint32_t getFormat() const {
+        return mScreenshot.getFormat();
+    }
+
+protected:
+    // overrides from SkPixelRef
+    virtual void* onLockPixels(SkColorTable** ct) {
+        *ct = fCTable;
+        return (void*)mScreenshot.getPixels();
+    }
+
+    virtual void onUnlockPixels() {
+    }
+
+private:
+    ScreenshotClient mScreenshot;
+    SkColorTable*    fCTable;
+
+    typedef SkPixelRef INHERITED;
+};
+
+
+// ----------------------------------------------------------------------------
+
+static jint 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 0;
+    }
+    surface->incStrong(surfaceObj);
+    return int(surface.get());
+}
+
+static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
+    ctrl->decStrong(surfaceObj);
+}
+
+static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
+    ctrl->clear();
+    ctrl->decStrong(surfaceObj);
+}
+
+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 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(displayToken, width, height,
+            minLayer, maxLayer, allLayers) != NO_ERROR) {
+        delete pixels;
+        return NULL;
+    }
+
+    uint32_t w = pixels->getWidth();
+    uint32_t h = pixels->getHeight();
+    uint32_t s = pixels->getStride();
+    uint32_t f = pixels->getFormat();
+    ssize_t bpr = s * android::bytesPerPixel(f);
+
+    SkBitmap* bitmap = new SkBitmap();
+    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
+    if (f == PIXEL_FORMAT_RGBX_8888) {
+        bitmap->setIsOpaque(true);
+    }
+
+    if (w > 0 && h > 0) {
+        bitmap->setPixelRef(pixels)->unref();
+        bitmap->lockPixels();
+    } else {
+        // be safe with an empty bitmap.
+        delete pixels;
+        bitmap->setPixels(NULL);
+    }
+
+    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
+}
+
+static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::openGlobalTransaction();
+}
+
+static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::closeGlobalTransaction();
+}
+
+static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::setAnimationTransaction();
+}
+
+static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint zorder) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setLayer(zorder);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat x, jfloat y) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setPosition(x, y);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint w, jint h) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setSize(w, h);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint flags, jint mask) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setFlags(flags, mask);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject regionObj) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    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 (region->isComplex()) {
+        SkRegion::Iterator it(*region);
+        while (!it.done()) {
+            const SkIRect& r(it.rect());
+            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
+            it.next();
+        }
+    }
+
+    status_t err = ctrl->setTransparentRegionHint(reg);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat alpha) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setAlpha(alpha);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, jint nativeObject,
+        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jint nativeObject,
+        jint l, jint t, jint r, jint b) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    Rect crop(l, t, r, b);
+    status_t err = ctrl->setCrop(crop);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint layerStack) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setLayerStack(layerStack);
+    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,
+        jboolean secure) {
+    ScopedUtfChars name(env, nameObj);
+    sp<IBinder> token(SurfaceComposerClient::createDisplay(
+            String8(name.c_str()), bool(secure)));
+    return javaObjectForIBinder(env, token);
+}
+
+static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint nativeSurfaceObject) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
+    sp<IGraphicBufferProducer> bufferProducer(sur->getSurfaceTexture());
+    SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
+}
+
+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 nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint orientation,
+        jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom,
+        jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+    Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom);
+    Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom);
+    SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
+}
+
+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);
+    env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
+    return JNI_TRUE;
+}
+
+static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
+    SurfaceComposerClient::blankDisplay(token);
+}
+
+static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
+    SurfaceComposerClient::unblankDisplay(token);
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod sSurfaceControlMethods[] = {
+    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)I",
+            (void*)nativeCreate },
+    {"nativeRelease", "(I)V",
+            (void*)nativeRelease },
+    {"nativeDestroy", "(I)V",
+            (void*)nativeDestroy },
+    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
+            (void*)nativeScreenshot },
+    {"nativeOpenTransaction", "()V",
+            (void*)nativeOpenTransaction },
+    {"nativeCloseTransaction", "()V",
+            (void*)nativeCloseTransaction },
+    {"nativeSetAnimationTransaction", "()V",
+            (void*)nativeSetAnimationTransaction },
+    {"nativeSetLayer", "(II)V",
+            (void*)nativeSetLayer },
+    {"nativeSetPosition", "(IFF)V",
+            (void*)nativeSetPosition },
+    {"nativeSetSize", "(III)V",
+            (void*)nativeSetSize },
+    {"nativeSetTransparentRegionHint", "(ILandroid/graphics/Region;)V",
+            (void*)nativeSetTransparentRegionHint },
+    {"nativeSetAlpha", "(IF)V",
+            (void*)nativeSetAlpha },
+    {"nativeSetMatrix", "(IFFFF)V",
+            (void*)nativeSetMatrix },
+    {"nativeSetFlags", "(III)V",
+            (void*)nativeSetFlags },
+    {"nativeSetWindowCrop", "(IIIII)V",
+            (void*)nativeSetWindowCrop },
+    {"nativeSetLayerStack", "(II)V",
+            (void*)nativeSetLayerStack },
+    {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
+            (void*)nativeGetBuiltInDisplay },
+    {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
+            (void*)nativeCreateDisplay },
+    {"nativeSetDisplaySurface", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplaySurface },
+    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayLayerStack },
+    {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
+            (void*)nativeSetDisplayProjection },
+    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z",
+            (void*)nativeGetDisplayInfo },
+    {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
+            (void*)nativeBlankDisplay },
+    {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
+            (void*)nativeUnblankDisplay },
+};
+
+int register_android_view_SurfaceControl(JNIEnv* env)
+{
+    int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl",
+            sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
+
+    jclass clazz = env->FindClass("android/view/SurfaceControl$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");
+    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
+    return err;
+}
+
+};
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index b6e6ceb..ac10cd4 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -34,6 +34,7 @@
 #include "android_runtime/AndroidRuntime.h"
 
 #include <system/audio.h>
+#include <android_runtime/android_view_Surface.h>
 
 // ----------------------------------------------------------------------------
 
@@ -47,8 +48,6 @@
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
-    /* actually in android.view.Surface XXX */
-    jfieldID    surface_native;
 
     jmethodID   post_event;
 };
@@ -109,8 +108,7 @@
 static sp<Surface> get_surface(JNIEnv* env, jobject clazz)
 {
     ALOGV("get_surface");
-    Surface* const p = (Surface*)env->GetIntField(clazz, fields.surface_native);
-    return sp<Surface>(p);
+    return android_view_Surface_getSurface(env, clazz);
 }
 
 // Returns true if it throws an exception.
@@ -409,11 +407,6 @@
         return;
     }
 
-    fields.surface_native = env->GetFieldID(surface, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    if (fields.surface_native == NULL) {
-        return;
-    }
-
     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
     if (fields.post_event == NULL) {
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 41c28c0..c1ad516 100644
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -34,6 +34,8 @@
 
 #include "VideoEditorMain.h"
 
+#include <android_runtime/android_view_Surface.h>
+
 extern "C" {
 #include <M4OSA_Clock.h>
 #include <M4OSA_CharStar.h>
@@ -628,19 +630,8 @@
                                                 (NULL == surface),
                                                 "surface is null");
 
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, surface);
 
-    jfieldID surface_native =
-            pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
-
-    Surface* const p = (Surface*)pEnv->GetIntField(surface, surface_native);
-    sp<Surface> previewSurface = sp<Surface>(p);
     // Validate the mSurface's mNativeSurface field
     videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
                                                 (NULL == previewSurface.get()),
@@ -709,19 +700,9 @@
     videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
                                                 (NULL == mSurface),
                                                 "mSurface is null");
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
 
-    jfieldID surface_native =
-            pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
 
-    Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native);
-    sp<Surface> previewSurface = sp<Surface>(p);
     // Validate the mSurface's mNativeSurface field
     videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
                                                 (NULL == previewSurface.get()),
@@ -1038,20 +1019,8 @@
     videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
                                                 (NULL == mSurface),
                                                 "mSurface is null");
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
 
-    jfieldID surface_native =
-            pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
-
-    Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native);
-    sp<Surface> previewSurface = sp<Surface>(p);
-
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
 
     const char *pString = pEnv->GetStringUTFChars(filePath, NULL);
     if (pString == M4OSA_NULL) {
@@ -2144,21 +2113,8 @@
                                                 (NULL == mSurface),
                                                 "mSurface is null");
 
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
-    //jfieldID surface_native = pEnv->GetFieldID(surfaceClass, "mSurface", "I");
-    jfieldID surface_native
-        = pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
 
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
-
-    Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native);
-
-    sp<Surface> previewSurface = sp<Surface>(p);
     // Validate the mSurface's mNativeSurface field
     videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
                                                 (NULL == previewSurface.get()),
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index ddfaad5..b498368 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -50,6 +50,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -455,7 +456,7 @@
         }
 
         // Take the screenshot
-        mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
+        mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
         if (mScreenBitmap == null) {
             notifyScreenshotError(mContext, mNotificationManager);
             finisher.run();
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
index a3ab3c1..4161147 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 
@@ -122,7 +123,7 @@
     public final void setLayerStackInTransactionLocked(int layerStack) {
         if (mCurrentLayerStack != layerStack) {
             mCurrentLayerStack = layerStack;
-            Surface.setDisplayLayerStack(mDisplayToken, layerStack);
+            SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack);
         }
     }
 
@@ -155,7 +156,7 @@
             }
             mCurrentDisplayRect.set(displayRect);
 
-            Surface.setDisplayProjection(mDisplayToken,
+            SurfaceControl.setDisplayProjection(mDisplayToken,
                     orientation, layerStackRect, displayRect);
         }
     }
@@ -166,7 +167,7 @@
     public final void setSurfaceInTransactionLocked(Surface surface) {
         if (mCurrentSurface != surface) {
             mCurrentSurface = surface;
-            Surface.setDisplaySurface(mDisplayToken, surface);
+            SurfaceControl.setDisplaySurface(mDisplayToken, surface);
         }
     }
 
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index ee2d617..475f27b 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -25,7 +25,8 @@
 import android.view.Display;
 import android.view.DisplayEventReceiver;
 import android.view.Surface;
-import android.view.Surface.PhysicalDisplayInfo;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.PhysicalDisplayInfo;
 
 import java.io.PrintWriter;
 
@@ -39,15 +40,15 @@
     private static final String TAG = "LocalDisplayAdapter";
 
     private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
-            Surface.BUILT_IN_DISPLAY_ID_MAIN,
-            Surface.BUILT_IN_DISPLAY_ID_HDMI,
+            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
+            SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
     };
 
     private final SparseArray<LocalDisplayDevice> mDevices =
             new SparseArray<LocalDisplayDevice>();
     private HotplugDisplayEventReceiver mHotplugReceiver;
 
-    private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
+    private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
 
     // Called with SyncRoot lock held.
     public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -67,8 +68,8 @@
     }
 
     private void tryConnectDisplayLocked(int builtInDisplayId) {
-        IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId);
-        if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) {
+        IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
+        if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
             LocalDisplayDevice device = mDevices.get(builtInDisplayId);
             if (device == null) {
                 // Display was added.
@@ -97,20 +98,20 @@
 
     private final class LocalDisplayDevice extends DisplayDevice {
         private final int mBuiltInDisplayId;
-        private final PhysicalDisplayInfo mPhys;
+        private final SurfaceControl.PhysicalDisplayInfo mPhys;
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
         private boolean mBlanked;
 
         public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
-                PhysicalDisplayInfo phys) {
+                SurfaceControl.PhysicalDisplayInfo phys) {
             super(LocalDisplayAdapter.this, displayToken);
             mBuiltInDisplayId = builtInDisplayId;
-            mPhys = new PhysicalDisplayInfo(phys);
+            mPhys = new SurfaceControl.PhysicalDisplayInfo(phys);
         }
 
-        public boolean updatePhysicalDisplayInfoLocked(PhysicalDisplayInfo phys) {
+        public boolean updatePhysicalDisplayInfoLocked(SurfaceControl.PhysicalDisplayInfo phys) {
             if (!mPhys.equals(phys)) {
                 mPhys.copyFrom(phys);
                 mHavePendingChanges = true;
@@ -142,7 +143,7 @@
                             | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
                 }
 
-                if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) {
+                if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                     mInfo.name = getContext().getResources().getString(
                             com.android.internal.R.string.display_manager_built_in_display_name);
                     mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
@@ -172,13 +173,13 @@
         @Override
         public void blankLocked() {
             mBlanked = true;
-            Surface.blankDisplay(getDisplayTokenLocked());
+            SurfaceControl.blankDisplay(getDisplayTokenLocked());
         }
 
         @Override
         public void unblankLocked() {
             mBlanked = false;
-            Surface.unblankDisplay(getDisplayTokenLocked());
+            SurfaceControl.unblankDisplay(getDisplayTokenLocked());
         }
 
         @Override
diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java
index 36e9f74..a18352c 100644
--- a/services/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -30,6 +30,7 @@
 import android.view.Display;
 import android.view.Gravity;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -284,7 +285,7 @@
         @Override
         public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
             synchronized (getSyncRoot()) {
-                IBinder displayToken = Surface.createDisplay(mName, false);
+                IBinder displayToken = SurfaceControl.createDisplay(mName, false);
                 mDevice = new OverlayDisplayDevice(displayToken, mName,
                         mWidth, mHeight, refreshRate, mDensityDpi, surfaceTexture);
 
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index c8a44d2..b655b3a 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -41,6 +41,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -332,7 +333,7 @@
 
         String name = display.getFriendlyDisplayName();
         String address = display.getDeviceAddress();
-        IBinder displayToken = Surface.createDisplay(name, secure);
+        IBinder displayToken = SurfaceControl.createDisplay(name, secure);
         mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
                 refreshRate, deviceFlags, address, surface);
         sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 8e19e11..2828e5e 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -34,6 +34,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
 import java.io.PrintWriter;
@@ -80,7 +81,8 @@
     private int mDisplayWidth;      // real width, not rotated
     private int mDisplayHeight;     // real height, not rotated
     private SurfaceSession mSurfaceSession;
-    private Surface mSurface;
+    private SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
     private NaturalSurfaceLayout mSurfaceLayout;
     private EGLDisplay mEglDisplay;
     private EGLConfig mEglConfig;
@@ -370,7 +372,7 @@
 
     private boolean captureScreenshotTextureAndSetViewport() {
         // TODO: Use a SurfaceTexture to avoid the extra texture upload.
-        Bitmap bitmap = Surface.screenshot(mDisplayWidth, mDisplayHeight,
+        Bitmap bitmap = SurfaceControl.screenshot(mDisplayWidth, mDisplayHeight,
                 0, ELECTRON_BEAM_LAYER - 1);
         if (bitmap == null) {
             Slog.e(TAG, "Could not take a screenshot!");
@@ -525,32 +527,33 @@
             mSurfaceSession = new SurfaceSession();
         }
 
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
-            if (mSurface == null) {
+            if (mSurfaceControl == null) {
                 try {
                     int flags;
                     if (mMode == MODE_FADE) {
-                        flags = Surface.FX_SURFACE_DIM | Surface.HIDDEN;
+                        flags = SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN;
                     } else {
-                        flags = Surface.OPAQUE | Surface.HIDDEN;
+                        flags = SurfaceControl.OPAQUE | SurfaceControl.HIDDEN;
                     }
-                    mSurface = new Surface(mSurfaceSession,
+                    mSurfaceControl = new SurfaceControl(mSurfaceSession,
                             "ElectronBeam", mDisplayWidth, mDisplayHeight,
                             PixelFormat.OPAQUE, flags);
-                } catch (Surface.OutOfResourcesException ex) {
+                } catch (SurfaceControl.OutOfResourcesException ex) {
                     Slog.e(TAG, "Unable to create surface.", ex);
                     return false;
                 }
             }
 
-            mSurface.setLayerStack(mDisplayLayerStack);
-            mSurface.setSize(mDisplayWidth, mDisplayHeight);
-
-            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurface);
+            mSurfaceControl.setLayerStack(mDisplayLayerStack);
+            mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
+            mSurface.copyFrom(mSurfaceControl);
+            
+            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl);
             mSurfaceLayout.onDisplayTransaction();
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
         }
         return true;
     }
@@ -560,6 +563,7 @@
             int[] eglSurfaceAttribList = new int[] {
                     EGL14.EGL_NONE
             };
+            // turn our SurfaceControl into a Surface
             mEglSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface,
                     eglSurfaceAttribList, 0);
             if (mEglSurface == null) {
@@ -580,16 +584,17 @@
     }
 
     private void destroySurface() {
-        if (mSurface != null) {
+        if (mSurfaceControl != null) {
             mSurfaceLayout.dispose();
             mSurfaceLayout = null;
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
-                mSurface.destroy();
+                mSurfaceControl.destroy();
+                mSurface.release();
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
             }
-            mSurface = null;
+            mSurfaceControl = null;
             mSurfaceVisible = false;
             mSurfaceAlpha = 0f;
         }
@@ -597,13 +602,13 @@
 
     private boolean showSurface(float alpha) {
         if (!mSurfaceVisible || mSurfaceAlpha != alpha) {
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
-                mSurface.setLayer(ELECTRON_BEAM_LAYER);
-                mSurface.setAlpha(alpha);
-                mSurface.show();
+                mSurfaceControl.setLayer(ELECTRON_BEAM_LAYER);
+                mSurfaceControl.setAlpha(alpha);
+                mSurfaceControl.show();
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
             }
             mSurfaceVisible = true;
             mSurfaceAlpha = alpha;
@@ -708,9 +713,9 @@
      */
     private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
         private final DisplayManagerService mDisplayManager;
-        private Surface mSurface;
+        private SurfaceControl mSurface;
 
-        public NaturalSurfaceLayout(DisplayManagerService displayManager, Surface surface) {
+        public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surface) {
             mDisplayManager = displayManager;
             mSurface = surface;
             mDisplayManager.registerDisplayTransactionListener(this);
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index ad68307..297324b 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -6,6 +6,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
@@ -38,7 +39,7 @@
     boolean allDrawn;
 
     // Special surface for thumbnail animation.
-    Surface thumbnail;
+    SurfaceControl thumbnail;
     int thumbnailTransactionSeq;
     int thumbnailX;
     int thumbnailY;
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 5b77b20..a197840 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -23,6 +23,7 @@
 import android.graphics.Rect;
 import android.util.Slog;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
 /**
@@ -33,7 +34,7 @@
         final int left;
         final int top;
         final int layer;
-        final Surface surface;
+        final SurfaceControl surface;
 
         BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b, int layerStack)
                 throws Surface.OutOfResourcesException {
@@ -42,13 +43,17 @@
             this.layer = layer;
             int w = r-l;
             int h = b-t;
-            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
-                        + l + ", " + t + ")",
-                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
-            } else {
-                surface = new Surface(session, "BlackSurface",
-                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+            try {
+                if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+                    surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
+                            + l + ", " + t + ")",
+                            w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+                } else {
+                    surface = new SurfaceControl(session, "BlackSurface",
+                            w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+                }
+            } catch (SurfaceControl.OutOfResourcesException e) {
+                throw new Surface.OutOfResourcesException(e.getMessage());
             }
             surface.setAlpha(1);
             surface.setLayerStack(layerStack);
diff --git a/services/java/com/android/server/wm/DimLayer.java b/services/java/com/android/server/wm/DimLayer.java
index 88efe2e..9bd36ba 100644
--- a/services/java/com/android/server/wm/DimLayer.java
+++ b/services/java/com/android/server/wm/DimLayer.java
@@ -7,6 +7,7 @@
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 
@@ -18,7 +19,7 @@
     final DisplayContent mDisplayContent;
 
     /** Actual surface that dims */
-    Surface mDimSurface;
+    SurfaceControl mDimSurface;
 
     /** Last value passed to mDimSurface.setAlpha() */
     float mAlpha = 0;
@@ -47,17 +48,17 @@
     DimLayer(WindowManagerService service, int displayId) {
         if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
         mDisplayContent = service.getDisplayContentLocked(displayId);
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                 mDimSurface = new WindowStateAnimator.SurfaceTrace(service.mFxSession,
                     "DimSurface",
                     16, 16, PixelFormat.OPAQUE,
-                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+                    SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
             } else {
-                mDimSurface = new Surface(service.mFxSession, TAG,
+                mDimSurface = new SurfaceControl(service.mFxSession, TAG,
                     16, 16, PixelFormat.OPAQUE,
-                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+                    SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
             }
             if (WindowManagerService.SHOW_TRANSACTIONS ||
                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(TAG,
@@ -66,7 +67,7 @@
         } catch (Exception e) {
             Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
         }
     }
 
diff --git a/services/java/com/android/server/wm/DisplayMagnifier.java b/services/java/com/android/server/wm/DisplayMagnifier.java
index 61093ad..55c6fa6 100644
--- a/services/java/com/android/server/wm/DisplayMagnifier.java
+++ b/services/java/com/android/server/wm/DisplayMagnifier.java
@@ -43,6 +43,7 @@
 import android.view.MagnificationSpec;
 import android.view.Surface;
 import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.animation.DecelerateInterpolator;
@@ -481,7 +482,8 @@
             private final Paint mPaint = new Paint();
 
             private final ValueAnimator mShowHideFrameAnimator;
-            private final Surface mSurface;
+            private final SurfaceControl mSurfaceControl;
+            private final Surface mSurface = new Surface();
 
             private boolean mShown;
             private int mAlpha;
@@ -489,20 +491,21 @@
             private boolean mInvalidated;
 
             public ViewportWindow(Context context) {
-                Surface surface = null;
+                SurfaceControl surface = null;
                 try {
                     mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
-                    surface = new Surface(mWindowManagerService.mFxSession, SURFACE_TITLE,
-                            mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-                } catch (OutOfResourcesException oore) {
+                    surface = new SurfaceControl(mWindowManagerService.mFxSession, SURFACE_TITLE,
+                            mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+                } catch (SurfaceControl.OutOfResourcesException oore) {
                     /* ignore */
                 }
-                mSurface = surface;
-                mSurface.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack());
-                mSurface.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
+                mSurfaceControl = surface;
+                mSurfaceControl.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack());
+                mSurfaceControl.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
                         WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY)
                         * WindowManagerService.TYPE_LAYER_MULTIPLIER);
-                mSurface.setPosition(0, 0);
+                mSurfaceControl.setPosition(0, 0);
+                mSurface.copyFrom(mSurfaceControl);
 
                 TypedValue typedValue = new TypedValue();
                 context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
@@ -591,7 +594,7 @@
             public void updateSize() {
                 synchronized (mWindowManagerService.mWindowMap) {
                     mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
-                    mSurface.setSize(mTempPoint.x, mTempPoint.y);
+                    mSurfaceControl.setSize(mTempPoint.x, mTempPoint.y);
                     invalidate(mDirtyRect);
                 }
             }
@@ -641,16 +644,17 @@
                     canvas.drawPath(path, mPaint);
 
                     mSurface.unlockCanvasAndPost(canvas);
-
+                    
                     if (mAlpha > 0) {
-                        mSurface.show();
+                        mSurfaceControl.show();
                     } else {
-                        mSurface.hide();
+                        mSurfaceControl.hide();
                     }
                 }
             }
 
             public void releaseSurface() {
+                mSurfaceControl.release();
                 mSurface.release();
             }
         }
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 72fc180..63f306f 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -34,6 +34,7 @@
 import android.view.DragEvent;
 import android.view.InputChannel;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.View;
 import android.view.WindowManager;
 
@@ -45,7 +46,7 @@
 class DragState {
     final WindowManagerService mService;
     IBinder mToken;
-    Surface mSurface;
+    SurfaceControl mSurface;
     int mFlags;
     IBinder mLocalWin;
     ClipData mData;
@@ -64,7 +65,7 @@
 
     private final Region mTmpRegion = new Region();
 
-    DragState(WindowManagerService service, IBinder token, Surface surface,
+    DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
             int flags, IBinder localWin) {
         mService = service;
         mToken = token;
@@ -293,14 +294,14 @@
         // Move the surface to the given touch
         if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                 WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw");
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             mSurface.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DRAG "
                     + mSurface + ": pos=(" +
                     (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                     WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
         }
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 71a61c6..05397ac 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -27,6 +27,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -43,7 +44,7 @@
 
     final Context mContext;
     final Display mDisplay;
-    Surface mSurface;
+    SurfaceControl mSurface;
     BlackFrame mCustomBlackFrame;
     BlackFrame mExitingBlackFrame;
     BlackFrame mEnteringBlackFrame;
@@ -213,7 +214,7 @@
         if (!inTransaction) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
         }
 
         try {
@@ -221,22 +222,17 @@
                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                     mSurface = new SurfaceTrace(session, "FreezeSurface",
                             mWidth, mHeight,
-                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+                            PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_SCREENSHOT | SurfaceControl.HIDDEN);
                 } else {
-                    mSurface = new Surface(session, "FreezeSurface",
+                    mSurface = new SurfaceControl(session, "FreezeSurface",
                             mWidth, mHeight,
-                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
-                }
-                if (!mSurface.isValid()) {
-                    // Screenshot failed, punt.
-                    mSurface = null;
-                    return;
+                            PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_SCREENSHOT | SurfaceControl.HIDDEN);
                 }
                 mSurface.setLayerStack(mDisplay.getLayerStack());
                 mSurface.setLayer(FREEZE_LAYER + 1);
                 mSurface.setAlpha(0);
                 mSurface.show();
-            } catch (Surface.OutOfResourcesException e) {
+            } catch (SurfaceControl.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate freeze surface", e);
             }
 
@@ -247,7 +243,7 @@
             setRotationInTransaction(originalRotation);
         } finally {
             if (!inTransaction) {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation");
             }
@@ -496,7 +492,7 @@
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
 
             // Compute the transformation matrix that must be applied
             // the the black frame to make it stay in the initial position
@@ -516,7 +512,7 @@
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                         WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
@@ -527,7 +523,7 @@
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 // Compute the transformation matrix that must be applied
                 // the the black frame to make it stay in the initial position
@@ -546,7 +542,7 @@
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                         WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
@@ -557,7 +553,7 @@
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
 
             try {
                 Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
@@ -568,7 +564,7 @@
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                         WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 3b4c1ab..7a0fa16 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -40,6 +40,7 @@
 import android.view.IWindowSession;
 import android.view.InputChannel;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 
@@ -313,10 +314,10 @@
             mService.mDragState.mThumbOffsetY = thumbCenterY;
 
             // Make the surface visible at the proper location
-            final Surface surface = mService.mDragState.mSurface;
+            final SurfaceControl surface = mService.mDragState.mSurface;
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                     WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 surface.setPosition(touchX - thumbCenterX,
                         touchY - thumbCenterY);
@@ -325,7 +326,7 @@
                 surface.setLayerStack(display.getLayerStack());
                 surface.show();
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                         WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag");
             }
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 90bbd08..31628e3 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -24,29 +24,32 @@
 import android.graphics.Region;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
 class StrictModeFlash {
     private static final String TAG = "StrictModeFlash";
 
-    Surface mSurface;
-    int mLastDW;
-    int mLastDH;
-    boolean mDrawNeeded;
-    final int mThickness = 20;
+    private final SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
+    private int mLastDW;
+    private int mLastDH;
+    private boolean mDrawNeeded;
+    private final int mThickness = 20;
 
     public StrictModeFlash(Display display, SurfaceSession session) {
+        SurfaceControl ctrl = null;
         try {
-            mSurface = new Surface(session, "StrictModeFlash",
-                1, 1, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-        } catch (Surface.OutOfResourcesException e) {
-            return;
+            ctrl = new SurfaceControl(session, "StrictModeFlash",
+                1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            ctrl.setLayerStack(display.getLayerStack());
+            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
+            ctrl.setPosition(0, 0);
+            ctrl.show();
+            mSurface.copyFrom(ctrl);
+        } catch (SurfaceControl.OutOfResourcesException e) {
         }
-
-        mSurface.setLayerStack(display.getLayerStack());
-        mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
-        mSurface.setPosition(0, 0);
-        mSurface.show();
+        mSurfaceControl = ctrl;
         mDrawNeeded = true;
     }
 
@@ -88,14 +91,14 @@
     // Note: caller responsible for being inside
     // Surface.openTransaction() / closeTransaction()
     public void setVisibility(boolean on) {
-        if (mSurface == null) {
+        if (mSurfaceControl == null) {
             return;
         }
         drawIfNeeded();
         if (on) {
-            mSurface.show();
+            mSurfaceControl.show();
         } else {
-            mSurface.hide();
+            mSurfaceControl.hide();
         }
     }
 
@@ -105,7 +108,7 @@
         }
         mLastDW = dw;
         mLastDH = dh;
-        mSurface.setSize(dw, dh);
+        mSurfaceControl.setSize(dw, dh);
         mDrawNeeded = true;
     }
 
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index ac152c9..fedd314 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -28,6 +28,7 @@
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.Surface.OutOfResourcesException;
 
@@ -35,21 +36,20 @@
  * Displays a watermark on top of the window manager's windows.
  */
 class Watermark {
-    final Display mDisplay;
-    final String[] mTokens;
-    final String mText;
-    final Paint mTextPaint;
-    final int mTextWidth;
-    final int mTextHeight;
-    final int mTextAscent;
-    final int mTextDescent;
-    final int mDeltaX;
-    final int mDeltaY;
+    private final Display mDisplay;
+    private final String[] mTokens;
+    private final String mText;
+    private final Paint mTextPaint;
+    private final int mTextWidth;
+    private final int mTextHeight;
+    private final int mDeltaX;
+    private final int mDeltaY;
 
-    Surface mSurface;
-    int mLastDW;
-    int mLastDH;
-    boolean mDrawNeeded;
+    private final SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
+    private int mLastDW;
+    private int mLastDH;
+    private boolean mDrawNeeded;
 
     Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) {
         if (false) {
@@ -90,8 +90,6 @@
 
         FontMetricsInt fm = mTextPaint.getFontMetricsInt();
         mTextWidth = (int)mTextPaint.measureText(mText);
-        mTextAscent = fm.ascent;
-        mTextDescent = fm.descent;
         mTextHeight = fm.descent - fm.ascent;
 
         mDeltaX = WindowManagerService.getPropertyInt(tokens, 2,
@@ -112,22 +110,25 @@
         mTextPaint.setColor(color);
         mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
 
+        SurfaceControl ctrl = null;
         try {
-            mSurface = new Surface(session, "WatermarkSurface",
-                    1, 1, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-            mSurface.setLayerStack(mDisplay.getLayerStack());
-            mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
-            mSurface.setPosition(0, 0);
-            mSurface.show();
-        } catch (OutOfResourcesException e) {
+            ctrl = new SurfaceControl(session, "WatermarkSurface",
+                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            ctrl.setLayerStack(mDisplay.getLayerStack());
+            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
+            ctrl.setPosition(0, 0);
+            ctrl.show();
+            mSurface.copyFrom(ctrl);
+        } catch (SurfaceControl.OutOfResourcesException e) {
         }
+        mSurfaceControl = ctrl;
     }
 
     void positionSurface(int dw, int dh) {
         if (mLastDW != dw || mLastDH != dh) {
             mLastDW = dw;
             mLastDH = dh;
-            mSurface.setSize(dw, dh);
+            mSurfaceControl.setSize(dw, dh);
             mDrawNeeded = true;
         }
     }
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 92ad485..2381cde 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -22,6 +22,7 @@
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 
@@ -528,8 +529,8 @@
 
         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                 TAG, ">>> OPEN TRANSACTION animateLocked");
-        Surface.openTransaction();
-        Surface.setAnimationTransaction();
+        SurfaceControl.openTransaction();
+        SurfaceControl.setAnimationTransaction();
         try {
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
@@ -621,7 +622,7 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                     TAG, "<<< CLOSE TRANSACTION animateLocked");
         }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 7d2574d..fbfa6a1 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -132,6 +132,7 @@
 import android.view.MagnificationSpec;
 import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewTreeObserver;
@@ -781,11 +782,11 @@
         // Add ourself to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
 
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             createWatermarkInTransaction();
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
         }
     }
 
@@ -2473,7 +2474,7 @@
         }
     }
 
-    static void logSurface(Surface s, String title, String msg, RuntimeException where) {
+    static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
         String str = "  SURFACE " + s + ": " + msg + " / " + title;
         if (where != null) {
             Slog.i(TAG, str, where);
@@ -2770,7 +2771,7 @@
                     if (!win.mHasSurface) {
                         surfaceChanged = true;
                     }
-                    Surface surface = winAnimator.createSurfaceLocked();
+                    SurfaceControl surface = winAnimator.createSurfaceLocked();
                     if (surface != null) {
                         outSurface.copyFrom(surface);
                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
@@ -5102,7 +5103,7 @@
 
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     ">>> OPEN TRANSACTION showStrictModeViolation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 // TODO(multi-display): support multiple displays
                 if (mStrictModeFlash == null) {
@@ -5111,7 +5112,7 @@
                 }
                 mStrictModeFlash.setVisibility(on);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                         "<<< CLOSE TRANSACTION showStrictModeViolation");
             }
@@ -5266,7 +5267,7 @@
                             + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
                 }
             }
-            rawss = Surface.screenshot(dw, dh, 0, maxLayer);
+            rawss = SurfaceControl.screenshot(dw, dh, 0, maxLayer);
         }
 
         if (rawss == null) {
@@ -5476,7 +5477,7 @@
             if (SHOW_TRANSACTIONS) {
                 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
             }
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
         }
         try {
             // NOTE: We disable the rotation in the emulator because
@@ -5494,7 +5495,7 @@
             mDisplayManagerService.performTraversalInTransactionFromWindowManager();
         } finally {
             if (!inTransaction) {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) {
                     Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
                 }
@@ -6316,8 +6317,8 @@
                         // TODO(multi-display): support other displays
                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
                         final Display display = displayContent.getDisplay();
-                        Surface surface = new Surface(session, "drag surface",
-                                width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
+                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
                         surface.setLayerStack(display.getLayerStack());
                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
                                 + surface + ": CREATE");
@@ -6334,7 +6335,7 @@
                     } else {
                         Slog.w(TAG, "Drag already in progress");
                     }
-                } catch (Surface.OutOfResourcesException e) {
+                } catch (SurfaceControl.OutOfResourcesException e) {
                     Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
                     if (mDragState != null) {
                         mDragState.reset();
@@ -7927,10 +7928,10 @@
                     // TODO(multi-display): support other displays
                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
                     final Display display = displayContent.getDisplay();
-                    Surface surface = new Surface(mFxSession,
+                    SurfaceControl surface = new SurfaceControl(mFxSession,
                             "thumbnail anim",
                             dirty.width(), dirty.height(),
-                            PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
                     surface.setLayerStack(display.getLayerStack());
                     appAnimator.thumbnail = surface;
                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surface + ": CREATE");
@@ -7951,10 +7952,14 @@
                     mAppTransition.getStartingPoint(p);
                     appAnimator.thumbnailX = p.x;
                     appAnimator.thumbnailY = p.y;
-                } catch (Surface.OutOfResourcesException e) {
+                } catch (SurfaceControl.OutOfResourcesException e) {
                     Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
                             + " h=" + dirty.height(), e);
                     appAnimator.clearThumbnail();
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.e(TAG, "Can't allocate Canvas surface w=" + dirty.width()
+                            + " h=" + dirty.height(), e);
+                    appAnimator.clearThumbnail();
                 }
             }
 
@@ -8214,7 +8219,7 @@
 
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
 
             if (mWatermark != null) {
@@ -8489,7 +8494,7 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
         }
@@ -8902,7 +8907,7 @@
 
     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
                                            boolean secure) {
-        final Surface surface = winAnimator.mSurface;
+        final SurfaceControl surface = winAnimator.mSurface;
         boolean leakedSurface = false;
         boolean killedApps = false;
 
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index a4c6a9e..82e59a8 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
 import android.view.DisplayInfo;
 import android.view.MagnificationSpec;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
@@ -87,8 +88,8 @@
     int mAnimLayer;
     int mLastLayer;
 
-    Surface mSurface;
-    Surface mPendingDestroySurface;
+    SurfaceControl mSurface;
+    SurfaceControl mPendingDestroySurface;
 
     /**
      * Set when we have changed the size of the surface, to know that
@@ -477,7 +478,7 @@
         return true;
     }
 
-    static class SurfaceTrace extends Surface {
+    static class SurfaceTrace extends SurfaceControl {
         private final static String SURFACE_TAG = "SurfaceTrace";
         final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
 
@@ -623,7 +624,7 @@
         }
     }
 
-    Surface createSurfaceLocked() {
+    SurfaceControl createSurfaceLocked() {
         if (mSurface == null) {
             if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
                     "createSurface " + this + ": mDrawState=DRAW_PENDING");
@@ -641,11 +642,11 @@
 
             mService.makeWindowFreezingScreenIfNeededLocked(mWin);
 
-            int flags = Surface.HIDDEN;
+            int flags = SurfaceControl.HIDDEN;
             final WindowManager.LayoutParams attrs = mWin.mAttrs;
 
             if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
-                flags |= Surface.SECURE;
+                flags |= SurfaceControl.SECURE;
             }
             if (WindowState.DEBUG_VISIBILITY) Slog.v(
                 TAG, "Creating surface in session "
@@ -681,7 +682,7 @@
                         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
                 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
                 if (!PixelFormat.formatHasAlpha(attrs.format)) {
-                    flags |= Surface.OPAQUE;
+                    flags |= SurfaceControl.OPAQUE;
                 }
                 if (DEBUG_SURFACE_TRACE) {
                     mSurface = new SurfaceTrace(
@@ -689,7 +690,7 @@
                             attrs.getTitle().toString(),
                             w, h, format, flags);
                 } else {
-                    mSurface = new Surface(
+                    mSurface = new SurfaceControl(
                         mSession.mSurfaceSession,
                         attrs.getTitle().toString(),
                         w, h, format, flags);
@@ -703,7 +704,7 @@
                         + attrs.format + " flags=0x"
                         + Integer.toHexString(flags)
                         + " / " + this);
-            } catch (Surface.OutOfResourcesException e) {
+            } catch (SurfaceControl.OutOfResourcesException e) {
                 mWin.mHasSurface = false;
                 Slog.w(TAG, "OutOfResourcesException creating surface");
                 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
@@ -727,7 +728,7 @@
                         + mWin.mCompatFrame.width() + "x" + mWin.mCompatFrame.height()
                         + "), layer=" + mAnimLayer + " HIDE", null);
             }
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 try {
                     mSurfaceX = mWin.mFrame.left + mWin.mXOffset;
@@ -744,7 +745,7 @@
                 }
                 mLastHidden = true;
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                         "<<< CLOSE TRANSACTION createSurfaceLocked");
             }
@@ -1324,13 +1325,13 @@
         }
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
             ">>> OPEN TRANSACTION setTransparentRegion");
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
                     "transparentRegionHint=" + region, null);
             mSurface.setTransparentRegionHint(region);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     "<<< CLOSE TRANSACTION setTransparentRegion");
         }
@@ -1351,7 +1352,7 @@
             }
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     ">>> OPEN TRANSACTION setWallpaperOffset");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
                         "POS " + left + ", " + top, null);
@@ -1361,7 +1362,7 @@
                 Slog.w(TAG, "Error positioning surface of " + mWin
                         + " pos=(" + left + "," + top + ")", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                         "<<< CLOSE TRANSACTION setWallpaperOffset");
             }