split Surface in two classes: SurfaceControl and Surface

SurfaceControl is the window manager side; it can
control the attributes of a surface but cannot push buffers
to it. Surface on the other hand is the application (producer)
side and is used to push buffers to the surface.

Change-Id: Ib6754c968924e87e8dd02a2073c7a447f729f4dd
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 d705024..f47865e 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 94324f8..74fd391 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);
@@ -1112,6 +1111,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;
+}
+
+};