Merge "fix argument mismatches in Paint JNI"
diff --git a/api/current.txt b/api/current.txt
index 2615e0b..536a2c8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -16597,9 +16597,15 @@
   public class StatFs {
     ctor public StatFs(java.lang.String);
     method public int getAvailableBlocks();
+    method public long getAvailableBlocksLong();
+    method public long getAvailableBytes();
     method public int getBlockCount();
+    method public long getBlockCountLong();
     method public int getBlockSize();
+    method public long getBlockSizeLong();
     method public int getFreeBlocks();
+    method public long getFreeBlocksLong();
+    method public long getFreeBytes();
     method public void restat(java.lang.String);
   }
 
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/net/CaptivePortalTracker.java b/core/java/android/net/CaptivePortalTracker.java
index 354a8c4..21995c0 100644
--- a/core/java/android/net/CaptivePortalTracker.java
+++ b/core/java/android/net/CaptivePortalTracker.java
@@ -25,14 +25,15 @@
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
+import android.database.ContentObserver;
 import android.net.ConnectivityManager;
 import android.net.IConnectivityManager;
+import android.os.Handler;
 import android.os.UserHandle;
 import android.os.Message;
 import android.os.RemoteException;
 import android.provider.Settings;
 import android.telephony.TelephonyManager;
-import android.util.Log;
 
 import com.android.internal.util.State;
 import com.android.internal.util.StateMachine;
@@ -81,15 +82,21 @@
     private State mActiveNetworkState = new ActiveNetworkState();
     private State mDelayedCaptiveCheckState = new DelayedCaptiveCheckState();
 
+    private static final String SETUP_WIZARD_PACKAGE = "com.google.android.setupwizard";
+    private boolean mDeviceProvisioned = false;
+    private ProvisioningObserver mProvisioningObserver;
+
     private CaptivePortalTracker(Context context, IConnectivityManager cs) {
         super(TAG);
 
         mContext = context;
         mConnService = cs;
         mTelephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);
+        mProvisioningObserver = new ProvisioningObserver();
 
         IntentFilter filter = new IntentFilter();
         filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+        filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE);
         mContext.registerReceiver(mReceiver, filter);
 
         mServer = Settings.Global.getString(mContext.getContentResolver(),
@@ -106,11 +113,31 @@
         setInitialState(mNoActiveNetworkState);
     }
 
+    private class ProvisioningObserver extends ContentObserver {
+        ProvisioningObserver() {
+            super(new Handler());
+            mContext.getContentResolver().registerContentObserver(Settings.Global.getUriFor(
+                    Settings.Global.DEVICE_PROVISIONED), false, this);
+            onChange(false); // load initial value
+        }
+
+        @Override
+        public void onChange(boolean selfChange) {
+            mDeviceProvisioned = Settings.Global.getInt(mContext.getContentResolver(),
+                    Settings.Global.DEVICE_PROVISIONED, 0) != 0;
+        }
+    }
+
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
             String action = intent.getAction();
-            if (action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
+            // Normally, we respond to CONNECTIVITY_ACTION, allowing time for the change in
+            // connectivity to stabilize, but if the device is not yet provisioned, respond
+            // immediately to speed up transit through the setup wizard.
+            if ((mDeviceProvisioned && action.equals(ConnectivityManager.CONNECTIVITY_ACTION))
+                    || (!mDeviceProvisioned
+                            && action.equals(ConnectivityManager.CONNECTIVITY_ACTION_IMMEDIATE))) {
                 NetworkInfo info = intent.getParcelableExtra(
                         ConnectivityManager.EXTRA_NETWORK_INFO);
                 sendMessage(obtainMessage(CMD_CONNECTIVITY_CHANGE, info));
@@ -222,8 +249,12 @@
         @Override
         public void enter() {
             if (DBG) log(getName() + "\n");
-            sendMessageDelayed(obtainMessage(CMD_DELAYED_CAPTIVE_CHECK,
-                        ++mDelayedCheckToken, 0), DELAYED_CHECK_INTERVAL_MS);
+            Message message = obtainMessage(CMD_DELAYED_CAPTIVE_CHECK, ++mDelayedCheckToken, 0);
+            if (mDeviceProvisioned) {
+                sendMessageDelayed(message, DELAYED_CHECK_INTERVAL_MS);
+            } else {
+                sendMessage(message);
+            }
         }
 
         @Override
@@ -233,13 +264,26 @@
                 case CMD_DELAYED_CAPTIVE_CHECK:
                     if (message.arg1 == mDelayedCheckToken) {
                         InetAddress server = lookupHost(mServer);
-                        if (server != null) {
-                            if (isCaptivePortal(server)) {
-                                if (DBG) log("Captive network " + mNetworkInfo);
+                        boolean captive = server != null && isCaptivePortal(server);
+                        if (captive) {
+                            if (DBG) log("Captive network " + mNetworkInfo);
+                        } else {
+                            if (DBG) log("Not captive network " + mNetworkInfo);
+                        }
+                        if (mDeviceProvisioned) {
+                            if (captive) {
+                                // Setup Wizard will assist the user in connecting to a captive
+                                // portal, so make the notification visible unless during setup
                                 setNotificationVisible(true);
                             }
+                        } else {
+                            Intent intent = new Intent(
+                                    ConnectivityManager.ACTION_CAPTIVE_PORTAL_TEST_COMPLETED);
+                            intent.putExtra(ConnectivityManager.EXTRA_IS_CAPTIVE_PORTAL, captive);
+                            intent.setPackage(SETUP_WIZARD_PACKAGE);
+                            mContext.sendBroadcast(intent);
                         }
-                        if (DBG) log("Not captive network " + mNetworkInfo);
+
                         transitionTo(mActiveNetworkState);
                     }
                     break;
diff --git a/core/java/android/net/ConnectivityManager.java b/core/java/android/net/ConnectivityManager.java
index a8a68d0..000c56c 100644
--- a/core/java/android/net/ConnectivityManager.java
+++ b/core/java/android/net/ConnectivityManager.java
@@ -228,6 +228,21 @@
     public static final String EXTRA_ERRORED_TETHER = "erroredArray";
 
     /**
+     * Broadcast Action: The captive portal tracker has finished its test.
+     * Sent only while running Setup Wizard, in lieu of showing a user
+     * notification.
+     * @hide
+     */
+    public static final String ACTION_CAPTIVE_PORTAL_TEST_COMPLETED =
+            "android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED";
+    /**
+     * The lookup key for a boolean that indicates whether a captive portal was detected.
+     * Retrieve it with {@link android.content.Intent#getBooleanExtra(String,boolean)}.
+     * @hide
+     */
+    public static final String EXTRA_IS_CAPTIVE_PORTAL = "captivePortal";
+
+    /**
      * The absence of APN..
      * @hide
      */
diff --git a/core/java/android/os/StatFs.java b/core/java/android/os/StatFs.java
index ca7fdba..60ec0d7 100644
--- a/core/java/android/os/StatFs.java
+++ b/core/java/android/os/StatFs.java
@@ -65,6 +65,14 @@
     }
 
     /**
+     * The size, in bytes, of a block on the file system. This corresponds to
+     * the Unix {@code statfs.f_bsize} field.
+     */
+    public long getBlockSizeLong() {
+        return mStat.f_bsize;
+    }
+
+    /**
      * The total number of blocks on the file system. This corresponds to the
      * Unix {@code statfs.f_blocks} field.
      */
@@ -73,6 +81,14 @@
     }
 
     /**
+     * The size, in bytes, of a block on the file system. This corresponds to
+     * the Unix {@code statfs.f_bsize} field.
+     */
+    public long getBlockCountLong() {
+        return mStat.f_blocks;
+    }
+
+    /**
      * The total number of blocks that are free on the file system, including
      * reserved blocks (that are not available to normal applications). This
      * corresponds to the Unix {@code statfs.f_bfree} field. Most applications
@@ -83,10 +99,44 @@
     }
 
     /**
+     * The total number of blocks that are free on the file system, including
+     * reserved blocks (that are not available to normal applications). This
+     * corresponds to the Unix {@code statfs.f_bfree} field. Most applications
+     * will want to use {@link #getAvailableBlocks()} instead.
+     */
+    public long getFreeBlocksLong() {
+        return mStat.f_bfree;
+    }
+
+    /**
+     * The number of bytes that are free on the file system, including
+     * reserved blocks (that are not available to normal applications).
+     */
+    public long getFreeBytes() {
+        return mStat.f_bfree * mStat.f_bsize;
+    }
+
+    /**
      * The number of blocks that are free on the file system and available to
      * applications. This corresponds to the Unix {@code statfs.f_bavail} field.
      */
     public int getAvailableBlocks() {
         return (int) mStat.f_bavail;
     }
+
+    /**
+     * The number of blocks that are free on the file system and available to
+     * applications. This corresponds to the Unix {@code statfs.f_bavail} field.
+     */
+    public long getAvailableBlocksLong() {
+        return mStat.f_bavail;
+    }
+
+    /**
+     * The number of bytes that are free on the file system and available to
+     * applications.
+     */
+    public long getAvailableBytes() {
+        return mStat.f_bavail * mStat.f_bsize;
+    }
 }
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 25954b9..8715349 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -2671,13 +2671,6 @@
             MOVED_TO_GLOBAL.add(Settings.Global.TETHER_DUN_APN);
             MOVED_TO_GLOBAL.add(Settings.Global.TETHER_DUN_REQUIRED);
             MOVED_TO_GLOBAL.add(Settings.Global.TETHER_SUPPORTED);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_HELP_URI);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_MAX_NTP_CACHE_AGE_SEC);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_NOTIFICATION_TYPE);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_POLLING_SEC);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_RESET_DAY);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_THRESHOLD_BYTES);
-            MOVED_TO_GLOBAL.add(Settings.Global.THROTTLE_VALUE_KBITSPS);
             MOVED_TO_GLOBAL.add(Settings.Global.USB_MASS_STORAGE_ENABLED);
             MOVED_TO_GLOBAL.add(Settings.Global.USE_GOOGLE_MAIL);
             MOVED_TO_GLOBAL.add(Settings.Global.WEB_AUTOFILL_QUERY_URL);
@@ -4706,50 +4699,6 @@
        public static final String TETHER_DUN_APN = "tether_dun_apn";
 
        /**
-        * The bandwidth throttle polling freqency in seconds
-        * @hide
-        */
-       public static final String THROTTLE_POLLING_SEC = "throttle_polling_sec";
-
-       /**
-        * The bandwidth throttle threshold (long)
-        * @hide
-        */
-       public static final String THROTTLE_THRESHOLD_BYTES = "throttle_threshold_bytes";
-
-       /**
-        * The bandwidth throttle value (kbps)
-        * @hide
-        */
-       public static final String THROTTLE_VALUE_KBITSPS = "throttle_value_kbitsps";
-
-       /**
-        * The bandwidth throttle reset calendar day (1-28)
-        * @hide
-        */
-       public static final String THROTTLE_RESET_DAY = "throttle_reset_day";
-
-       /**
-        * The throttling notifications we should send
-        * @hide
-        */
-       public static final String THROTTLE_NOTIFICATION_TYPE = "throttle_notification_type";
-
-       /**
-        * Help URI for data throttling policy
-        * @hide
-        */
-       public static final String THROTTLE_HELP_URI = "throttle_help_uri";
-
-       /**
-        * The length of time in Sec that we allow our notion of NTP time
-        * to be cached before we refresh it
-        * @hide
-        */
-       public static final String THROTTLE_MAX_NTP_CACHE_AGE_SEC =
-               "throttle_max_ntp_cache_age_sec";
-
-       /**
         * USB Mass Storage Enabled
         */
        public static final String USB_MASS_STORAGE_ENABLED = "usb_mass_storage_enabled";
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/GLES20Canvas.java b/core/java/android/view/GLES20Canvas.java
index 1810205..40f2261 100644
--- a/core/java/android/view/GLES20Canvas.java
+++ b/core/java/android/view/GLES20Canvas.java
@@ -901,9 +901,9 @@
         final int count = (meshWidth + 1) * (meshHeight + 1);
         checkRange(verts.length, vertOffset, count * 2);
 
-        // TODO: Colors are ignored for now
-        colors = null;
-        colorOffset = 0;
+        if (colors != null) {
+            checkRange(colors.length, colorOffset, count);
+        }
 
         int modifiers = paint != null ? setupModifiers(bitmap, paint) : MODIFIER_NONE;
         try {
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index a9ad97f..885327c 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -97,9 +97,6 @@
     void startAppFreezingScreen(IBinder token, int configChanges);
     void stopAppFreezingScreen(IBinder token, boolean force);
     void removeAppToken(IBinder token);
-    void moveAppToken(int index, IBinder token);
-    void moveAppTokensToTop(in List<IBinder> tokens);
-    void moveAppTokensToBottom(in List<IBinder> tokens);
 
     // Re-evaluate the current orientation from the caller's state.
     // If there is a change, the new Configuration is returned and the
diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java
index a972b75..63f0e1f 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,113 +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 int nativeGetIdentity();
-    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");
     }
 
@@ -350,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);
@@ -363,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();
         }
@@ -381,7 +153,10 @@
      * This will make the surface invalid.
      */
     public void release() {
-        nativeRelease();
+        if (mNativeObject != 0) {
+            nativeRelease(mNativeObject);
+            mNativeObject = 0;
+        }
         mCloseGuard.close();
     }
 
@@ -392,7 +167,10 @@
      * @hide
      */
     public void destroy() {
-        nativeDestroy();
+        if (mNativeObject != 0) {
+            nativeDestroy(mNativeObject);
+            mNativeObject = 0;
+        }
         mCloseGuard.close();
     }
 
@@ -403,7 +181,8 @@
      * Otherwise returns false.
      */
     public boolean isValid() {
-        return nativeIsValid();
+        if (mNativeObject == 0) return false;
+        return nativeIsValid(mNativeObject);
     }
 
     /**
@@ -424,7 +203,8 @@
      * @hide
      */
     public boolean isConsumerRunningBehind() {
-        return nativeIsConsumerRunningBehind();
+        checkNotReleased();
+        return nativeIsConsumerRunningBehind(mNativeObject);
     }
 
     /**
@@ -433,7 +213,7 @@
      * After drawing into the provided {@link Canvas}, the caller should
      * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface.
      *
-     * @param dirty A rectangle that represents the dirty region that the caller wants
+     * @param inOutDirty A rectangle that represents the dirty region that the caller wants
      * to redraw.  This function may choose to expand the dirty rectangle if for example
      * the surface has been resized or if the previous contents of the surface were
      * not available.  The caller should redraw the entire dirty region as represented
@@ -442,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);
     }
 
     /**
@@ -454,7 +235,8 @@
      * @param canvas The canvas previously obtained from {@link #lockCanvas}.
      */
     public void unlockCanvasAndPost(Canvas canvas) {
-        nativeUnlockCanvasAndPost(canvas);
+        checkNotReleased();
+        nativeUnlockCanvasAndPost(mNativeObject, canvas);
     }
 
     /** 
@@ -477,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
@@ -671,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);
     }
 
     /**
@@ -693,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;
         }
     }
 
@@ -706,9 +312,8 @@
         if (source == null) {
             throw new IllegalArgumentException("source must not be null");
         }
-
         mName = source.readString();
-        nativeReadFromParcel(source);
+        mNativeObject = nativeReadFromParcel(mNativeObject, source);
     }
 
     @Override
@@ -716,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();
         }
@@ -726,13 +330,7 @@
 
     @Override
     public String toString() {
-        return "Surface(name=" + mName + ", identity=" + nativeGetIdentity() + ")";
-    }
-
-    private static void checkHeadless() {
-        if (HEADLESS) {
-            throw new UnsupportedOperationException("Device is headless");
-        }
+        return "Surface(name=" + mName + ")";
     }
 
     /**
@@ -741,73 +339,12 @@
     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.
@@ -894,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/java/android/widget/TextView.java b/core/java/android/widget/TextView.java
index cad7ae3..a1ced6e 100644
--- a/core/java/android/widget/TextView.java
+++ b/core/java/android/widget/TextView.java
@@ -607,6 +607,8 @@
         int typefaceIndex = -1;
         int styleIndex = -1;
         boolean allCaps = false;
+        int shadowcolor = 0;
+        float dx = 0, dy = 0, r = 0;
 
         final Resources.Theme theme = context.getTheme();
 
@@ -667,6 +669,22 @@
                 case com.android.internal.R.styleable.TextAppearance_textAllCaps:
                     allCaps = appearance.getBoolean(attr, false);
                     break;
+
+                case com.android.internal.R.styleable.TextAppearance_shadowColor:
+                    shadowcolor = a.getInt(attr, 0);
+                    break;
+
+                case com.android.internal.R.styleable.TextAppearance_shadowDx:
+                    dx = a.getFloat(attr, 0);
+                    break;
+
+                case com.android.internal.R.styleable.TextAppearance_shadowDy:
+                    dy = a.getFloat(attr, 0);
+                    break;
+
+                case com.android.internal.R.styleable.TextAppearance_shadowRadius:
+                    r = a.getFloat(attr, 0);
+                    break;
                 }
             }
 
@@ -690,8 +708,6 @@
         int maxlength = -1;
         CharSequence text = "";
         CharSequence hint = null;
-        int shadowcolor = 0;
-        float dx = 0, dy = 0, r = 0;
         boolean password = false;
         int inputType = EditorInfo.TYPE_NULL;
 
@@ -2331,6 +2347,19 @@
 
         setTypefaceFromAttrs(familyName, typefaceIndex, styleIndex);
 
+        final int shadowcolor = appearance.getInt(
+                com.android.internal.R.styleable.TextAppearance_shadowColor, 0);
+        if (shadowcolor != 0) {
+            final float dx = appearance.getFloat(
+                    com.android.internal.R.styleable.TextAppearance_shadowDx, 0);
+            final float dy = appearance.getFloat(
+                    com.android.internal.R.styleable.TextAppearance_shadowDy, 0);
+            final float r = appearance.getFloat(
+                    com.android.internal.R.styleable.TextAppearance_shadowRadius, 0);
+
+            setShadowLayer(r, dx, dy, shadowcolor);
+        }
+
         if (appearance.getBoolean(com.android.internal.R.styleable.TextAppearance_textAllCaps,
                 false)) {
             setTransformationMethod(new AllCapsTransformationMethod(getContext()));
diff --git a/core/jni/Android.mk b/core/jni/Android.mk
index 5337329..c6b7631 100644
--- a/core/jni/Android.mk
+++ b/core/jni/Android.mk
@@ -42,6 +42,7 @@
 	android_emoji_EmojiFactory.cpp \
 	android_view_DisplayEventReceiver.cpp \
 	android_view_Surface.cpp \
+	android_view_SurfaceControl.cpp \
 	android_view_SurfaceSession.cpp \
 	android_view_TextureView.cpp \
 	android_view_InputChannel.cpp \
diff --git a/core/jni/AndroidRuntime.cpp b/core/jni/AndroidRuntime.cpp
index aa59b43..86d3cb6 100644
--- a/core/jni/AndroidRuntime.cpp
+++ b/core/jni/AndroidRuntime.cpp
@@ -47,8 +47,6 @@
 
 using namespace android;
 
-extern void register_BindTest();
-
 extern int register_android_os_Binder(JNIEnv* env);
 extern int register_android_os_Process(JNIEnv* env);
 extern int register_android_graphics_Bitmap(JNIEnv*);
@@ -121,6 +119,7 @@
 extern int register_android_view_GLES20Canvas(JNIEnv* env);
 extern int register_android_view_HardwareRenderer(JNIEnv* env);
 extern int register_android_view_Surface(JNIEnv* env);
+extern int register_android_view_SurfaceControl(JNIEnv* env);
 extern int register_android_view_SurfaceSession(JNIEnv* env);
 extern int register_android_view_TextureView(JNIEnv* env);
 extern int register_android_database_CursorWindow(JNIEnv* env);
@@ -1113,6 +1112,7 @@
     REG_JNI(register_android_view_GLES20Canvas),
     REG_JNI(register_android_view_HardwareRenderer),
     REG_JNI(register_android_view_Surface),
+    REG_JNI(register_android_view_SurfaceControl),
     REG_JNI(register_android_view_SurfaceSession),
     REG_JNI(register_android_view_TextureView),
     REG_JNI(register_com_google_android_gles_jni_EGLImpl),
diff --git a/core/jni/android_hardware_Camera.cpp b/core/jni/android_hardware_Camera.cpp
index 0e0893b..7c65662 100644
--- a/core/jni/android_hardware_Camera.cpp
+++ b/core/jni/android_hardware_Camera.cpp
@@ -23,6 +23,7 @@
 #include "JNIHelp.h"
 #include "android_runtime/AndroidRuntime.h"
 #include <android_runtime/android_graphics_SurfaceTexture.h>
+#include <android_runtime/android_view_Surface.h>
 
 #include <cutils/properties.h>
 #include <utils/Vector.h>
@@ -36,7 +37,6 @@
 
 struct fields_t {
     jfieldID    context;
-    jfieldID    surface;
     jfieldID    facing;
     jfieldID    orientation;
     jfieldID    canDisableShutterSound;
@@ -537,10 +537,8 @@
     sp<Camera> camera = get_native_camera(env, thiz, NULL);
     if (camera == 0) return;
 
-    sp<Surface> surface = NULL;
-    if (jSurface != NULL) {
-        surface = reinterpret_cast<Surface*>(env->GetIntField(jSurface, fields.surface));
-    }
+    sp<Surface> surface = android_view_Surface_getSurface(env, jSurface);
+
     if (camera->setPreviewDisplay(surface) != NO_ERROR) {
         jniThrowException(env, "java/io/IOException", "setPreviewDisplay failed");
     }
@@ -965,7 +963,6 @@
 {
     field fields_to_find[] = {
         { "android/hardware/Camera", "mNativeContext",   "I", &fields.context },
-        { "android/view/Surface",    ANDROID_VIEW_SURFACE_JNI_ID, "I", &fields.surface },
         { "android/hardware/Camera$CameraInfo", "facing",   "I", &fields.facing },
         { "android/hardware/Camera$CameraInfo", "orientation",   "I", &fields.orientation },
         { "android/hardware/Camera$CameraInfo", "canDisableShutterSound",   "Z",
diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp
index 1f15370..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,96 +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 jint nativeGetIdentity(JNIEnv* env, jobject surfaceObj) {
-    sp<SurfaceControl> control(getSurfaceControl(env, surfaceObj));
-    if (control != NULL) {
-        return jint(control->getIdentity());
-    }
-
-    sp<Surface> surface(getSurface(env, surfaceObj));
-    if (surface != NULL) {
-        return jint(surface->getIdentity());
-    }
-
-    return -1;
-}
-
-static jboolean nativeIsConsumerRunningBehind(JNIEnv* env, jobject surfaceObj) {
-    sp<Surface> surface(getSurface(env, surfaceObj));
-    if (!Surface::isValid(surface)) {
+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;
 }
@@ -373,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;
@@ -454,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;
     }
@@ -481,395 +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 },
-    {"nativeGetIdentity", "()I",
-            (void*)nativeGetIdentity },
-    {"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 },
 };
 
@@ -880,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");
@@ -902,14 +387,6 @@
     gRectClassInfo.right = env->GetFieldID(clazz, "right", "I");
     gRectClassInfo.bottom = env->GetFieldID(clazz, "bottom", "I");
 
-    clazz = env->FindClass("android/view/Surface$PhysicalDisplayInfo");
-    gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
-    gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
-    gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
-    gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
-    gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
-    gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
-    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
     return err;
 }
 
diff --git a/core/jni/android_view_SurfaceControl.cpp b/core/jni/android_view_SurfaceControl.cpp
new file mode 100644
index 0000000..7398895
--- /dev/null
+++ b/core/jni/android_view_SurfaceControl.cpp
@@ -0,0 +1,451 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define LOG_TAG "SurfaceControl"
+
+#include <stdio.h>
+
+#include "jni.h"
+#include "JNIHelp.h"
+
+#include "android_os_Parcel.h"
+#include "android_util_Binder.h"
+#include "android/graphics/GraphicsJNI.h"
+#include "android/graphics/Region.h"
+
+#include <android_runtime/AndroidRuntime.h>
+#include <android_runtime/android_view_SurfaceSession.h>
+
+#include <gui/Surface.h>
+#include <gui/SurfaceComposerClient.h>
+
+#include <ui/DisplayInfo.h>
+#include <ui/Rect.h>
+#include <ui/Region.h>
+
+#include <utils/Log.h>
+
+#include <ScopedUtfChars.h>
+
+// ----------------------------------------------------------------------------
+
+namespace android {
+
+static const char* const OutOfResourcesException =
+    "android/view/Surface$OutOfResourcesException";
+
+static struct {
+    jfieldID width;
+    jfieldID height;
+    jfieldID refreshRate;
+    jfieldID density;
+    jfieldID xDpi;
+    jfieldID yDpi;
+    jfieldID secure;
+} gPhysicalDisplayInfoClassInfo;
+
+
+class ScreenshotPixelRef : public SkPixelRef {
+public:
+    ScreenshotPixelRef(SkColorTable* ctable) {
+        fCTable = ctable;
+        SkSafeRef(ctable);
+        setImmutable();
+    }
+
+    virtual ~ScreenshotPixelRef() {
+        SkSafeUnref(fCTable);
+    }
+
+    status_t update(const sp<IBinder>& display, int width, int height,
+            int minLayer, int maxLayer, bool allLayers) {
+        status_t res = (width > 0 && height > 0)
+                ? (allLayers
+                        ? mScreenshot.update(display, width, height)
+                        : mScreenshot.update(display, width, height, minLayer, maxLayer))
+                : mScreenshot.update(display);
+        if (res != NO_ERROR) {
+            return res;
+        }
+
+        return NO_ERROR;
+    }
+
+    uint32_t getWidth() const {
+        return mScreenshot.getWidth();
+    }
+
+    uint32_t getHeight() const {
+        return mScreenshot.getHeight();
+    }
+
+    uint32_t getStride() const {
+        return mScreenshot.getStride();
+    }
+
+    uint32_t getFormat() const {
+        return mScreenshot.getFormat();
+    }
+
+protected:
+    // overrides from SkPixelRef
+    virtual void* onLockPixels(SkColorTable** ct) {
+        *ct = fCTable;
+        return (void*)mScreenshot.getPixels();
+    }
+
+    virtual void onUnlockPixels() {
+    }
+
+private:
+    ScreenshotClient mScreenshot;
+    SkColorTable*    fCTable;
+
+    typedef SkPixelRef INHERITED;
+};
+
+
+// ----------------------------------------------------------------------------
+
+static jint nativeCreate(JNIEnv* env, jobject surfaceObj, jobject sessionObj,
+        jstring nameStr, jint w, jint h, jint format, jint flags) {
+    ScopedUtfChars name(env, nameStr);
+    sp<SurfaceComposerClient> client(android_view_SurfaceSession_getClient(env, sessionObj));
+    sp<SurfaceControl> surface = client->createSurface(
+            String8(name.c_str()), w, h, format, flags);
+    if (surface == NULL) {
+        jniThrowException(env, OutOfResourcesException, NULL);
+        return 0;
+    }
+    surface->incStrong(surfaceObj);
+    return int(surface.get());
+}
+
+static void nativeRelease(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
+    ctrl->decStrong(surfaceObj);
+}
+
+static void nativeDestroy(JNIEnv* env, jobject surfaceObj, jint nativeObject) {
+    sp<SurfaceControl> ctrl(reinterpret_cast<SurfaceControl *>(nativeObject));
+    ctrl->clear();
+    ctrl->decStrong(surfaceObj);
+}
+
+static inline SkBitmap::Config convertPixelFormat(PixelFormat format) {
+    /* note: if PIXEL_FORMAT_RGBX_8888 means that all alpha bytes are 0xFF, then
+        we can map to SkBitmap::kARGB_8888_Config, and optionally call
+        bitmap.setIsOpaque(true) on the resulting SkBitmap (as an accelerator)
+    */
+    switch (format) {
+    case PIXEL_FORMAT_RGBX_8888:    return SkBitmap::kARGB_8888_Config;
+    case PIXEL_FORMAT_RGBA_8888:    return SkBitmap::kARGB_8888_Config;
+    case PIXEL_FORMAT_RGBA_4444:    return SkBitmap::kARGB_4444_Config;
+    case PIXEL_FORMAT_RGB_565:      return SkBitmap::kRGB_565_Config;
+    case PIXEL_FORMAT_A_8:          return SkBitmap::kA8_Config;
+    default:                        return SkBitmap::kNo_Config;
+    }
+}
+
+static jobject nativeScreenshot(JNIEnv* env, jclass clazz, jobject displayTokenObj,
+        jint width, jint height, jint minLayer, jint maxLayer, bool allLayers) {
+    sp<IBinder> displayToken = ibinderForJavaObject(env, displayTokenObj);
+    if (displayToken == NULL) {
+        return NULL;
+    }
+
+    ScreenshotPixelRef* pixels = new ScreenshotPixelRef(NULL);
+    if (pixels->update(displayToken, width, height,
+            minLayer, maxLayer, allLayers) != NO_ERROR) {
+        delete pixels;
+        return NULL;
+    }
+
+    uint32_t w = pixels->getWidth();
+    uint32_t h = pixels->getHeight();
+    uint32_t s = pixels->getStride();
+    uint32_t f = pixels->getFormat();
+    ssize_t bpr = s * android::bytesPerPixel(f);
+
+    SkBitmap* bitmap = new SkBitmap();
+    bitmap->setConfig(convertPixelFormat(f), w, h, bpr);
+    if (f == PIXEL_FORMAT_RGBX_8888) {
+        bitmap->setIsOpaque(true);
+    }
+
+    if (w > 0 && h > 0) {
+        bitmap->setPixelRef(pixels)->unref();
+        bitmap->lockPixels();
+    } else {
+        // be safe with an empty bitmap.
+        delete pixels;
+        bitmap->setPixels(NULL);
+    }
+
+    return GraphicsJNI::createBitmap(env, bitmap, false, NULL);
+}
+
+static void nativeOpenTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::openGlobalTransaction();
+}
+
+static void nativeCloseTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::closeGlobalTransaction();
+}
+
+static void nativeSetAnimationTransaction(JNIEnv* env, jclass clazz) {
+    SurfaceComposerClient::setAnimationTransaction();
+}
+
+static void nativeSetLayer(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint zorder) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setLayer(zorder);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetPosition(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat x, jfloat y) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setPosition(x, y);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetSize(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint w, jint h) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setSize(w, h);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetFlags(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint flags, jint mask) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setFlags(flags, mask);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetTransparentRegionHint(JNIEnv* env, jobject surfaceObj, jint nativeObject, jobject regionObj) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    SkRegion* region = android_graphics_Region_getSkRegion(env, regionObj);
+    if (!region) {
+        doThrowIAE(env);
+        return;
+    }
+
+    const SkIRect& b(region->getBounds());
+    Region reg(Rect(b.fLeft, b.fTop, b.fRight, b.fBottom));
+    if (region->isComplex()) {
+        SkRegion::Iterator it(*region);
+        while (!it.done()) {
+            const SkIRect& r(it.rect());
+            reg.addRectUnchecked(r.fLeft, r.fTop, r.fRight, r.fBottom);
+            it.next();
+        }
+    }
+
+    status_t err = ctrl->setTransparentRegionHint(reg);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetAlpha(JNIEnv* env, jobject surfaceObj, jint nativeObject, jfloat alpha) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setAlpha(alpha);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetMatrix(JNIEnv* env, jobject surfaceObj, jint nativeObject,
+        jfloat dsdx, jfloat dtdx, jfloat dsdy, jfloat dtdy) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setMatrix(dsdx, dtdx, dsdy, dtdy);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetWindowCrop(JNIEnv* env, jobject surfaceObj, jint nativeObject,
+        jint l, jint t, jint r, jint b) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    Rect crop(l, t, r, b);
+    status_t err = ctrl->setCrop(crop);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static void nativeSetLayerStack(JNIEnv* env, jobject surfaceObj, jint nativeObject, jint layerStack) {
+    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl *>(nativeObject);
+    status_t err = ctrl->setLayerStack(layerStack);
+    if (err < 0 && err != NO_INIT) {
+        doThrowIAE(env);
+    }
+}
+
+static jobject nativeGetBuiltInDisplay(JNIEnv* env, jclass clazz, jint id) {
+    sp<IBinder> token(SurfaceComposerClient::getBuiltInDisplay(id));
+    return javaObjectForIBinder(env, token);
+}
+
+static jobject nativeCreateDisplay(JNIEnv* env, jclass clazz, jstring nameObj,
+        jboolean secure) {
+    ScopedUtfChars name(env, nameObj);
+    sp<IBinder> token(SurfaceComposerClient::createDisplay(
+            String8(name.c_str()), bool(secure)));
+    return javaObjectForIBinder(env, token);
+}
+
+static void nativeSetDisplaySurface(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint nativeSurfaceObject) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+    sp<Surface> sur(reinterpret_cast<Surface *>(nativeSurfaceObject));
+    sp<IGraphicBufferProducer> bufferProducer(sur->getSurfaceTexture());
+    SurfaceComposerClient::setDisplaySurface(token, bufferProducer);
+}
+
+static void nativeSetDisplayLayerStack(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint layerStack) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    SurfaceComposerClient::setDisplayLayerStack(token, layerStack);
+}
+
+static void nativeSetDisplayProjection(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jint orientation,
+        jint layerStackRect_left, jint layerStackRect_top, jint layerStackRect_right, jint layerStackRect_bottom,
+        jint displayRect_left, jint displayRect_top, jint displayRect_right, jint displayRect_bottom) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+    Rect layerStackRect(layerStackRect_left, layerStackRect_top, layerStackRect_right, layerStackRect_bottom);
+    Rect displayRect(displayRect_left, displayRect_top, displayRect_right, displayRect_bottom);
+    SurfaceComposerClient::setDisplayProjection(token, orientation, layerStackRect, displayRect);
+}
+
+static jboolean nativeGetDisplayInfo(JNIEnv* env, jclass clazz,
+        jobject tokenObj, jobject infoObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return JNI_FALSE;
+
+    DisplayInfo info;
+    if (SurfaceComposerClient::getDisplayInfo(token, &info)) {
+        return JNI_FALSE;
+    }
+
+    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.width, info.w);
+    env->SetIntField(infoObj, gPhysicalDisplayInfoClassInfo.height, info.h);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.refreshRate, info.fps);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.density, info.density);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.xDpi, info.xdpi);
+    env->SetFloatField(infoObj, gPhysicalDisplayInfoClassInfo.yDpi, info.ydpi);
+    env->SetBooleanField(infoObj, gPhysicalDisplayInfoClassInfo.secure, info.secure);
+    return JNI_TRUE;
+}
+
+static void nativeBlankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    ALOGD_IF_SLOW(100, "Excessive delay in blankDisplay() while turning screen off");
+    SurfaceComposerClient::blankDisplay(token);
+}
+
+static void nativeUnblankDisplay(JNIEnv* env, jclass clazz, jobject tokenObj) {
+    sp<IBinder> token(ibinderForJavaObject(env, tokenObj));
+    if (token == NULL) return;
+
+    ALOGD_IF_SLOW(100, "Excessive delay in unblankDisplay() while turning screen on");
+    SurfaceComposerClient::unblankDisplay(token);
+}
+
+// ----------------------------------------------------------------------------
+
+static JNINativeMethod sSurfaceControlMethods[] = {
+    {"nativeCreate", "(Landroid/view/SurfaceSession;Ljava/lang/String;IIII)I",
+            (void*)nativeCreate },
+    {"nativeRelease", "(I)V",
+            (void*)nativeRelease },
+    {"nativeDestroy", "(I)V",
+            (void*)nativeDestroy },
+    {"nativeScreenshot", "(Landroid/os/IBinder;IIIIZ)Landroid/graphics/Bitmap;",
+            (void*)nativeScreenshot },
+    {"nativeOpenTransaction", "()V",
+            (void*)nativeOpenTransaction },
+    {"nativeCloseTransaction", "()V",
+            (void*)nativeCloseTransaction },
+    {"nativeSetAnimationTransaction", "()V",
+            (void*)nativeSetAnimationTransaction },
+    {"nativeSetLayer", "(II)V",
+            (void*)nativeSetLayer },
+    {"nativeSetPosition", "(IFF)V",
+            (void*)nativeSetPosition },
+    {"nativeSetSize", "(III)V",
+            (void*)nativeSetSize },
+    {"nativeSetTransparentRegionHint", "(ILandroid/graphics/Region;)V",
+            (void*)nativeSetTransparentRegionHint },
+    {"nativeSetAlpha", "(IF)V",
+            (void*)nativeSetAlpha },
+    {"nativeSetMatrix", "(IFFFF)V",
+            (void*)nativeSetMatrix },
+    {"nativeSetFlags", "(III)V",
+            (void*)nativeSetFlags },
+    {"nativeSetWindowCrop", "(IIIII)V",
+            (void*)nativeSetWindowCrop },
+    {"nativeSetLayerStack", "(II)V",
+            (void*)nativeSetLayerStack },
+    {"nativeGetBuiltInDisplay", "(I)Landroid/os/IBinder;",
+            (void*)nativeGetBuiltInDisplay },
+    {"nativeCreateDisplay", "(Ljava/lang/String;Z)Landroid/os/IBinder;",
+            (void*)nativeCreateDisplay },
+    {"nativeSetDisplaySurface", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplaySurface },
+    {"nativeSetDisplayLayerStack", "(Landroid/os/IBinder;I)V",
+            (void*)nativeSetDisplayLayerStack },
+    {"nativeSetDisplayProjection", "(Landroid/os/IBinder;IIIIIIIII)V",
+            (void*)nativeSetDisplayProjection },
+    {"nativeGetDisplayInfo", "(Landroid/os/IBinder;Landroid/view/SurfaceControl$PhysicalDisplayInfo;)Z",
+            (void*)nativeGetDisplayInfo },
+    {"nativeBlankDisplay", "(Landroid/os/IBinder;)V",
+            (void*)nativeBlankDisplay },
+    {"nativeUnblankDisplay", "(Landroid/os/IBinder;)V",
+            (void*)nativeUnblankDisplay },
+};
+
+int register_android_view_SurfaceControl(JNIEnv* env)
+{
+    int err = AndroidRuntime::registerNativeMethods(env, "android/view/SurfaceControl",
+            sSurfaceControlMethods, NELEM(sSurfaceControlMethods));
+
+    jclass clazz = env->FindClass("android/view/SurfaceControl$PhysicalDisplayInfo");
+    gPhysicalDisplayInfoClassInfo.width = env->GetFieldID(clazz, "width", "I");
+    gPhysicalDisplayInfoClassInfo.height = env->GetFieldID(clazz, "height", "I");
+    gPhysicalDisplayInfoClassInfo.refreshRate = env->GetFieldID(clazz, "refreshRate", "F");
+    gPhysicalDisplayInfoClassInfo.density = env->GetFieldID(clazz, "density", "F");
+    gPhysicalDisplayInfoClassInfo.xDpi = env->GetFieldID(clazz, "xDpi", "F");
+    gPhysicalDisplayInfoClassInfo.yDpi = env->GetFieldID(clazz, "yDpi", "F");
+    gPhysicalDisplayInfoClassInfo.secure = env->GetFieldID(clazz, "secure", "Z");
+    return err;
+}
+
+};
diff --git a/core/res/AndroidManifest.xml b/core/res/AndroidManifest.xml
index 5d0614c..d77b504 100644
--- a/core/res/AndroidManifest.xml
+++ b/core/res/AndroidManifest.xml
@@ -129,6 +129,7 @@
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE" />
     <protected-broadcast android:name="android.net.conn.CONNECTIVITY_CHANGE_IMMEDIATE" />
     <protected-broadcast android:name="android.net.conn.DATA_ACTIVITY_CHANGE" />
+    <protected-broadcast android:name="android.net.conn.CAPTIVE_PORTAL_TEST_COMPLETED" />
 
     <protected-broadcast android:name="android.nfc.action.LLCP_LINK_STATE_CHANGED" />
     <protected-broadcast android:name="com.android.nfc_extras.action.RF_FIELD_ON_DETECTED" />
@@ -641,7 +642,7 @@
         android:protectionLevel="normal"
         android:description="@string/permdesc_accessWifiState"
         android:label="@string/permlab_accessWifiState" />
-        
+
     <!-- Allows applications to change Wi-Fi connectivity state -->
     <permission android:name="android.permission.CHANGE_WIFI_STATE"
         android:permissionGroup="android.permission-group.NETWORK"
@@ -681,14 +682,14 @@
         android:protectionLevel="dangerous"
         android:description="@string/permdesc_bluetooth"
         android:label="@string/permlab_bluetooth" />
-        
+
     <!-- Allows applications to discover and pair bluetooth devices -->
     <permission android:name="android.permission.BLUETOOTH_ADMIN"
         android:permissionGroup="android.permission-group.BLUETOOTH_NETWORK"
         android:protectionLevel="dangerous"
         android:description="@string/permdesc_bluetoothAdmin"
         android:label="@string/permlab_bluetoothAdmin" />
-   
+
     <!-- Allows bluetooth stack to access files
          @hide This should only be used by Bluetooth apk.
     -->
@@ -719,7 +720,7 @@
     <permission android:name="android.permission.LOOP_RADIO"
 	android:permissionGroup="android.permission-group.NETWORK"
 	android:protectionLevel="signature|system" />
-    
+
     <!-- ================================== -->
     <!-- Permissions for accessing accounts -->
     <!-- ================================== -->
@@ -1129,7 +1130,7 @@
         android:protectionLevel="signature|system"
         android:label="@string/permlab_manageUsers"
         android:description="@string/permdesc_manageUsers" />
-    
+
     <!-- Allows an application to get full detailed information about
          recently running tasks, with full fidelity to the real state.
          @hide -->
@@ -1671,7 +1672,7 @@
         android:label="@string/permlab_freezeScreen"
         android:description="@string/permdesc_freezeScreen"
         android:protectionLevel="signature" />
-    
+
     <!-- Allows an application to inject user events (keys, touch, trackball)
          into the event stream and deliver them to ANY window.  Without this
          permission, you can only deliver events to windows in your own process.
diff --git a/core/res/res/values/attrs.xml b/core/res/res/values/attrs.xml
index 0fb8a10..a3e5b2c 100644
--- a/core/res/res/values/attrs.xml
+++ b/core/res/res/values/attrs.xml
@@ -3061,6 +3061,14 @@
         <attr name="textColorLink" />
         <!-- Present the text in ALL CAPS. This may use a small-caps form when available. -->
         <attr name="textAllCaps" format="boolean" />
+        <!-- Place a shadow of the specified color behind the text. -->
+        <attr name="shadowColor" format="color" />
+        <!-- Horizontal offset of the shadow. -->
+        <attr name="shadowDx" format="float" />
+        <!-- Vertical offset of the shadow. -->
+        <attr name="shadowDy" format="float" />
+        <!-- Radius of the shadow. -->
+        <attr name="shadowRadius" format="float" />
     </declare-styleable>
     <declare-styleable name="TextClock">
         <!-- Specifies the formatting pattern used to show the time and/or date
@@ -3195,13 +3203,13 @@
              specified number. -->
         <attr name="maxLength" format="integer" min="0" />
         <!-- Place a shadow of the specified color behind the text. -->
-        <attr name="shadowColor" format="color" />
+        <attr name="shadowColor" />
         <!-- Horizontal offset of the shadow. -->
-        <attr name="shadowDx" format="float" />
+        <attr name="shadowDx" />
         <!-- Vertical offset of the shadow. -->
-        <attr name="shadowDy" format="float" />
+        <attr name="shadowDy" />
         <!-- Radius of the shadow. -->
-        <attr name="shadowRadius" format="float" />
+        <attr name="shadowRadius" />
         <attr name="autoLink" />
         <!-- If set to false, keeps the movement method from being set
              to the link movement method even if autoLink causes links
diff --git a/docs/html/google/play/billing/billing_overview.jd b/docs/html/google/play/billing/billing_overview.jd
index bda9237..14cbfdf 100644
--- a/docs/html/google/play/billing/billing_overview.jd
+++ b/docs/html/google/play/billing/billing_overview.jd
@@ -69,7 +69,8 @@
 item; only one copy can be owned at any point in time</li>
 <li>Purchased items can be consumed. When consumed, the item reverts to the 
 "unowned" state and can be purchased again from Google Play</li>
-<li>Provides support for subscriptions</li>
+<li>Provides support for <a
+  href="{@docRoot}google/play/billing/billing_subscriptions.html">subscriptions</a></li>
 </ul>
 <p>For details about other versions of In-app Billing, see the 
 <a href="{@docRoot}google/play/billing/versions.html">Version Notes</a>.</p>
diff --git a/docs/html/google/play/billing/billing_subscriptions.jd b/docs/html/google/play/billing/billing_subscriptions.jd
index 2840dbc..c2bbb49 100644
--- a/docs/html/google/play/billing/billing_subscriptions.jd
+++ b/docs/html/google/play/billing/billing_subscriptions.jd
@@ -3,7 +3,26 @@
 parent.link=index.html
 @jd:body
 
-<div id="qv-wrapper">
+<!--notice block -->
+    <div style="background-color:#fffbd9;width:100%;margin-bottom:1em;padding:8px 8px 1px;">
+      <p><em>15 February 2013</em></p>
+      <p>In-app Billing V3 now supports subscriptions and you can get
+        started developing today. A small app update is currently being
+        rolled out to Android devices. This process is automatic and
+        most devices will get the update in the next few days. However,
+        if you wish to get the update today to start developing right
+        away, simply reboot your device. </p>
+
+      <p>However, we recommend that you <em>do not publish</em> an app with 
+        V3 subscriptions until all Android devices have received the update. We'll
+        notify you here that all devices have received the update and its safe
+        to publish your apps that use V3 subscriptions. </p>
+    </div>
+
+<!-- Use non-standard wrapper to support notice block. Restore standard 
+     wrapper when notice is removed. -->
+<!--<div id="qv-wrapper"> -->
+<div id="qv-wrapper" style="margin-top:.25em;">
 <div id="qv">
   <h2>Quickview</h2>
   <ul>
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 9dd2b0d..4b69317 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -74,6 +74,10 @@
         }
     }
 
+    public boolean isUnlocked() {
+        return state() == State.UNLOCKED;
+    }
+
     public byte[] get(String key) {
         try {
             return mBinder.get(key);
diff --git a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
index d108caaa..cd031b4 100644
--- a/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyPairGeneratorTest.java
@@ -62,11 +62,10 @@
 
         assertTrue(mAndroidKeyStore.reset());
 
-        assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+        assertFalse(mAndroidKeyStore.isUnlocked());
 
         assertTrue(mAndroidKeyStore.password("1111"));
-
-        assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+        assertTrue(mAndroidKeyStore.isUnlocked());
 
         assertEquals(0, mAndroidKeyStore.saw("").length);
 
diff --git a/keystore/tests/src/android/security/AndroidKeyStoreTest.java b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
index c376f3d..8928e06 100644
--- a/keystore/tests/src/android/security/AndroidKeyStoreTest.java
+++ b/keystore/tests/src/android/security/AndroidKeyStoreTest.java
@@ -467,12 +467,10 @@
         mAndroidKeyStore = android.security.KeyStore.getInstance();
 
         assertTrue(mAndroidKeyStore.reset());
-
-        assertEquals(android.security.KeyStore.State.UNINITIALIZED, mAndroidKeyStore.state());
+        assertFalse(mAndroidKeyStore.isUnlocked());
 
         assertTrue(mAndroidKeyStore.password("1111"));
-
-        assertEquals(android.security.KeyStore.State.UNLOCKED, mAndroidKeyStore.state());
+        assertTrue(mAndroidKeyStore.isUnlocked());
 
         assertEquals(0, mAndroidKeyStore.saw("").length);
 
diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp
index 74201d1..88f1d83 100644
--- a/libs/hwui/Caches.cpp
+++ b/libs/hwui/Caches.cpp
@@ -365,11 +365,12 @@
     }
 }
 
-void Caches::bindTexCoordsVertexPointer(bool force, GLvoid* vertices) {
-    if (force || vertices != mCurrentTexCoordsPointer) {
+void Caches::bindTexCoordsVertexPointer(bool force, GLvoid* vertices, GLsizei stride) {
+    if (force || vertices != mCurrentTexCoordsPointer || stride != mCurrentTexCoordsStride) {
         GLuint slot = currentProgram->texCoords;
-        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, gMeshStride, vertices);
+        glVertexAttribPointer(slot, 2, GL_FLOAT, GL_FALSE, stride, vertices);
         mCurrentTexCoordsPointer = vertices;
+        mCurrentTexCoordsStride = stride;
     }
 }
 
@@ -390,7 +391,7 @@
     }
 }
 
-void Caches::disbaleTexCoordsVertexArray() {
+void Caches::disableTexCoordsVertexArray() {
     if (mTexCoordsArrayEnabled) {
         glDisableVertexAttribArray(Program::kBindingTexCoords);
         mTexCoordsArrayEnabled = false;
diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h
index d70c0e3..0ca2ffd 100644
--- a/libs/hwui/Caches.h
+++ b/libs/hwui/Caches.h
@@ -183,7 +183,7 @@
      * Binds an attrib to the specified float vertex pointer.
      * Assumes a stride of gMeshStride and a size of 2.
      */
-    void bindTexCoordsVertexPointer(bool force, GLvoid* vertices);
+    void bindTexCoordsVertexPointer(bool force, GLvoid* vertices, GLsizei stride = gMeshStride);
 
     /**
      * Resets the vertex pointers.
@@ -192,7 +192,7 @@
     void resetTexCoordsVertexPointer();
 
     void enableTexCoordsVertexArray();
-    void disbaleTexCoordsVertexArray();
+    void disableTexCoordsVertexArray();
 
     /**
      * Activate the specified texture unit. The texture unit must
@@ -299,6 +299,7 @@
     void* mCurrentPositionPointer;
     GLsizei mCurrentPositionStride;
     void* mCurrentTexCoordsPointer;
+    GLsizei mCurrentTexCoordsStride;
 
     bool mTexCoordsArrayEnabled;
 
diff --git a/libs/hwui/OpenGLRenderer.cpp b/libs/hwui/OpenGLRenderer.cpp
index be3cff1..57d16ae 100644
--- a/libs/hwui/OpenGLRenderer.cpp
+++ b/libs/hwui/OpenGLRenderer.cpp
@@ -317,7 +317,7 @@
     mCaches.unbindMeshBuffer();
     mCaches.unbindIndicesBuffer();
     mCaches.resetVertexPointers();
-    mCaches.disbaleTexCoordsVertexArray();
+    mCaches.disableTexCoordsVertexArray();
     debugOverdraw(false, false);
 }
 
@@ -1469,12 +1469,18 @@
     mDescription.hasAlpha8Texture = isAlpha8;
 }
 
+void OpenGLRenderer::setupDrawWithTextureAndColor(bool isAlpha8) {
+    mDescription.hasTexture = true;
+    mDescription.hasColors = true;
+    mDescription.hasAlpha8Texture = isAlpha8;
+}
+
 void OpenGLRenderer::setupDrawWithExternalTexture() {
     mDescription.hasExternalTexture = true;
 }
 
 void OpenGLRenderer::setupDrawNoTexture() {
-    mCaches.disbaleTexCoordsVertexArray();
+    mCaches.disableTexCoordsVertexArray();
 }
 
 void OpenGLRenderer::setupDrawAA() {
@@ -1682,6 +1688,23 @@
     mCaches.unbindIndicesBuffer();
 }
 
+void OpenGLRenderer::setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors) {
+    bool force = mCaches.unbindMeshBuffer();
+    GLsizei stride = sizeof(ColorTextureVertex);
+
+    mCaches.bindPositionVertexPointer(force, vertices, stride);
+    if (mCaches.currentProgram->texCoords >= 0) {
+        mCaches.bindTexCoordsVertexPointer(force, texCoords, stride);
+    }
+    int slot = mCaches.currentProgram->getAttrib("colors");
+    if (slot >= 0) {
+        glEnableVertexAttribArray(slot);
+        glVertexAttribPointer(slot, 4, GL_FLOAT, GL_FALSE, stride, colors);
+    }
+
+    mCaches.unbindIndicesBuffer();
+}
+
 void OpenGLRenderer::setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords) {
     bool force = mCaches.unbindMeshBuffer();
     mCaches.bindPositionVertexPointer(force, vertices);
@@ -1833,9 +1856,16 @@
 
     const uint32_t count = meshWidth * meshHeight * 6;
 
-    // TODO: Support the colors array
-    TextureVertex mesh[count];
-    TextureVertex* vertex = mesh;
+    ColorTextureVertex mesh[count];
+    ColorTextureVertex* vertex = mesh;
+
+    bool cleanupColors = false;
+    if (!colors) {
+        uint32_t colorsCount = (meshWidth + 1) * (meshHeight + 1);
+        colors = new int[colorsCount];
+        memset(colors, 0xff, colorsCount * sizeof(int));
+        cleanupColors = true;
+    }
 
     for (int32_t y = 0; y < meshHeight; y++) {
         for (int32_t x = 0; x < meshWidth; x++) {
@@ -1855,13 +1885,13 @@
             int dx = i + (meshWidth + 1) * 2 + 2;
             int dy = dx + 1;
 
-            TextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2);
-            TextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1);
-            TextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1);
+            ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
+            ColorTextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2, colors[ax / 2]);
+            ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
 
-            TextureVertex::set(vertex++, vertices[ax], vertices[ay], u1, v2);
-            TextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1);
-            TextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2);
+            ColorTextureVertex::set(vertex++, vertices[dx], vertices[dy], u2, v2, colors[dx / 2]);
+            ColorTextureVertex::set(vertex++, vertices[bx], vertices[by], u1, v1, colors[bx / 2]);
+            ColorTextureVertex::set(vertex++, vertices[cx], vertices[cy], u2, v1, colors[cx / 2]);
 
             left = fminf(left, fminf(vertices[ax], fminf(vertices[bx], vertices[cx])));
             top = fminf(top, fminf(vertices[ay], fminf(vertices[by], vertices[cy])));
@@ -1871,12 +1901,16 @@
     }
 
     if (quickReject(left, top, right, bottom)) {
+        if (cleanupColors) delete[] colors;
         return DrawGlInfo::kStatusDone;
     }
 
     mCaches.activeTexture(0);
     Texture* texture = mCaches.textureCache.get(bitmap);
-    if (!texture) return DrawGlInfo::kStatusDone;
+    if (!texture) {
+        if (cleanupColors) delete[] colors;
+        return DrawGlInfo::kStatusDone;
+    }
     const AutoTexture autoCleanup(texture);
 
     texture->setWrap(GL_CLAMP_TO_EDGE, true);
@@ -1886,13 +1920,35 @@
     SkXfermode::Mode mode;
     getAlphaAndMode(paint, &alpha, &mode);
 
+    float a = alpha / 255.0f;
+
     if (hasLayer()) {
         dirtyLayer(left, top, right, bottom, *mSnapshot->transform);
     }
 
-    drawTextureMesh(0.0f, 0.0f, 1.0f, 1.0f, texture->id, alpha / 255.0f,
-            mode, texture->blend, &mesh[0].position[0], &mesh[0].texture[0],
-            GL_TRIANGLES, count, false, false, 0, false, false);
+    setupDraw();
+    setupDrawWithTextureAndColor();
+    setupDrawColor(a, a, a, a);
+    setupDrawColorFilter();
+    setupDrawBlending(true, mode, false);
+    setupDrawProgram();
+    setupDrawDirtyRegionsDisabled();
+    setupDrawModelView(0.0f, 0.0f, 1.0f, 1.0f, false);
+    setupDrawTexture(texture->id);
+    setupDrawPureColorUniforms();
+    setupDrawColorFilterUniforms();
+    setupDrawMesh(&mesh[0].position[0], &mesh[0].texture[0], &mesh[0].color[0]);
+
+    glDrawArrays(GL_TRIANGLES, 0, count);
+
+    finishDrawTexture();
+
+    int slot = mCaches.currentProgram->getAttrib("colors");
+    if (slot >= 0) {
+        glDisableVertexAttribArray(slot);
+    }
+
+    if (cleanupColors) delete[] colors;
 
     return DrawGlInfo::kStatusDrew;
 }
diff --git a/libs/hwui/OpenGLRenderer.h b/libs/hwui/OpenGLRenderer.h
index 0ad81c1..ad80d36 100644
--- a/libs/hwui/OpenGLRenderer.h
+++ b/libs/hwui/OpenGLRenderer.h
@@ -777,6 +777,7 @@
      * Various methods to setup OpenGL rendering.
      */
     void setupDrawWithTexture(bool isAlpha8 = false);
+    void setupDrawWithTextureAndColor(bool isAlpha8 = false);
     void setupDrawWithExternalTexture();
     void setupDrawNoTexture();
     void setupDrawAA();
@@ -811,6 +812,7 @@
     void setupDrawTextureTransformUniforms(mat4& transform);
     void setupDrawTextGammaUniforms();
     void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords = NULL, GLuint vbo = 0);
+    void setupDrawMesh(GLvoid* vertices, GLvoid* texCoords, GLvoid* colors);
     void setupDrawMeshIndices(GLvoid* vertices, GLvoid* texCoords);
     void setupDrawVertices(GLvoid* vertices);
     void finishDrawTexture();
diff --git a/libs/hwui/Program.h b/libs/hwui/Program.h
index b1df980..7b67b3c 100644
--- a/libs/hwui/Program.h
+++ b/libs/hwui/Program.h
@@ -81,6 +81,8 @@
 
 #define PROGRAM_IS_SIMPLE_GRADIENT 41
 
+#define PROGRAM_HAS_COLORS 42
+
 ///////////////////////////////////////////////////////////////////////////////
 // Types
 ///////////////////////////////////////////////////////////////////////////////
@@ -120,6 +122,9 @@
     bool hasExternalTexture;
     bool hasTextureTransform;
 
+    // Color attribute
+    bool hasColors;
+
     // Modulate, this should only be set when setColor() return true
     bool modulate;
 
@@ -164,6 +169,8 @@
         hasExternalTexture = false;
         hasTextureTransform = false;
 
+        hasColors = false;
+
         isAA = false;
 
         modulate = false;
@@ -259,6 +266,7 @@
         if (hasTextureTransform) key |= programid(0x1) << PROGRAM_HAS_TEXTURE_TRANSFORM_SHIFT;
         if (hasGammaCorrection) key |= programid(0x1) << PROGRAM_HAS_GAMMA_CORRECTION;
         if (isSimpleGradient) key |= programid(0x1) << PROGRAM_IS_SIMPLE_GRADIENT;
+        if (hasColors) key |= programid(0x1) << PROGRAM_HAS_COLORS;
         return key;
     }
 
diff --git a/libs/hwui/ProgramCache.cpp b/libs/hwui/ProgramCache.cpp
index fb00335..74d598d 100644
--- a/libs/hwui/ProgramCache.cpp
+++ b/libs/hwui/ProgramCache.cpp
@@ -40,6 +40,8 @@
         "attribute vec4 position;\n";
 const char* gVS_Header_Attributes_TexCoords =
         "attribute vec2 texCoords;\n";
+const char* gVS_Header_Attributes_Colors =
+        "attribute vec4 colors;\n";
 const char* gVS_Header_Attributes_AAVertexShapeParameters =
         "attribute float vtxAlpha;\n";
 const char* gVS_Header_Uniforms_TextureTransform =
@@ -65,6 +67,8 @@
         "uniform mediump vec2 textureDimension;\n";
 const char* gVS_Header_Varyings_HasTexture =
         "varying vec2 outTexCoords;\n";
+const char* gVS_Header_Varyings_HasColors =
+        "varying vec4 outColors;\n";
 const char* gVS_Header_Varyings_IsAAVertexShape =
         "varying float alpha;\n";
 const char* gVS_Header_Varyings_HasBitmap =
@@ -94,6 +98,8 @@
         "\nvoid main(void) {\n";
 const char* gVS_Main_OutTexCoords =
         "    outTexCoords = texCoords;\n";
+const char* gVS_Main_OutColors =
+        "    outColors = colors;\n";
 const char* gVS_Main_OutTransformedTexCoords =
         "    outTexCoords = (mainTextureTransform * vec4(texCoords, 0.0, 1.0)).xy;\n";
 const char* gVS_Main_OutGradient[6] = {
@@ -325,6 +331,8 @@
     };
 const char* gFS_Main_FragColor =
         "    gl_FragColor = fragColor;\n";
+const char* gFS_Main_FragColor_HasColors =
+        "    gl_FragColor *= outColors;\n";
 const char* gFS_Main_FragColor_Blend =
         "    gl_FragColor = blendFramebuffer(fragColor, gl_LastFragColor);\n";
 const char* gFS_Main_FragColor_Blend_Swap =
@@ -459,6 +467,9 @@
     if (description.isAA) {
         shader.append(gVS_Header_Attributes_AAVertexShapeParameters);
     }
+    if (description.hasColors) {
+        shader.append(gVS_Header_Attributes_Colors);
+    }
     // Uniforms
     shader.append(gVS_Header_Uniforms);
     if (description.hasTextureTransform) {
@@ -480,6 +491,9 @@
     if (description.isAA) {
         shader.append(gVS_Header_Varyings_IsAAVertexShape);
     }
+    if (description.hasColors) {
+        shader.append(gVS_Header_Varyings_HasColors);
+    }
     if (description.hasGradient) {
         shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
     }
@@ -499,6 +513,9 @@
         if (description.isAA) {
             shader.append(gVS_Main_AAVertexShape);
         }
+        if (description.hasColors) {
+            shader.append(gVS_Main_OutColors);
+        }
         if (description.hasBitmap) {
             shader.append(description.isPoint ?
                     gVS_Main_OutPointBitmapTexCoords :
@@ -549,6 +566,9 @@
     if (description.isAA) {
         shader.append(gVS_Header_Varyings_IsAAVertexShape);
     }
+    if (description.hasColors) {
+        shader.append(gVS_Header_Varyings_HasColors);
+    }
     if (description.hasGradient) {
         shader.append(gVS_Header_Varyings_HasGradient[gradientIndex(description)]);
     }
@@ -583,7 +603,7 @@
     }
 
     // Optimization for common cases
-    if (!description.isAA && !blendFramebuffer &&
+    if (!description.isAA && !blendFramebuffer && !description.hasColors &&
             description.colorOp == ProgramDescription::kColorNone && !description.isPoint) {
         bool fast = false;
 
@@ -729,6 +749,9 @@
             shader.append(!description.swapSrcDst ?
                     gFS_Main_FragColor_Blend : gFS_Main_FragColor_Blend_Swap);
         }
+        if (description.hasColors) {
+            shader.append(gFS_Main_FragColor_HasColors);
+        }
     }
     // End the shader
     shader.append(gFS_Footer);
diff --git a/libs/hwui/Vertex.h b/libs/hwui/Vertex.h
index c120428..523120e 100644
--- a/libs/hwui/Vertex.h
+++ b/libs/hwui/Vertex.h
@@ -33,7 +33,7 @@
 }; // struct Vertex
 
 /**
- * Simple structure to describe a vertex with a position and a texture.
+ * Simple structure to describe a vertex with a position and texture UV.
  */
 struct TextureVertex {
     float position[2];
@@ -53,6 +53,24 @@
 }; // struct TextureVertex
 
 /**
+ * Simple structure to describe a vertex with a position, texture UV and ARGB color.
+ */
+struct ColorTextureVertex : TextureVertex {
+    float color[4];
+
+    static inline void set(ColorTextureVertex* vertex, float x, float y,
+            float u, float v, int color) {
+        TextureVertex::set(vertex, x, y, u, v);
+
+        const float a = ((color >> 24) & 0xff) / 255.0f;
+        vertex[0].color[0] = a * ((color >> 16) & 0xff) / 255.0f;
+        vertex[0].color[1] = a * ((color >>  8) & 0xff) / 255.0f;
+        vertex[0].color[2] = a * ((color      ) & 0xff) / 255.0f;
+        vertex[0].color[3] = a;
+    }
+}; // struct ColorTextureVertex
+
+/**
  * Simple structure to describe a vertex with a position and an alpha value.
  */
 struct AlphaVertex : Vertex {
diff --git a/media/jni/android_media_MediaRecorder.cpp b/media/jni/android_media_MediaRecorder.cpp
index b6e6ceb..5bf16cc 100644
--- a/media/jni/android_media_MediaRecorder.cpp
+++ b/media/jni/android_media_MediaRecorder.cpp
@@ -34,6 +34,7 @@
 #include "android_runtime/AndroidRuntime.h"
 
 #include <system/audio.h>
+#include <android_runtime/android_view_Surface.h>
 
 // ----------------------------------------------------------------------------
 
@@ -47,8 +48,6 @@
 struct fields_t {
     jfieldID    context;
     jfieldID    surface;
-    /* actually in android.view.Surface XXX */
-    jfieldID    surface_native;
 
     jmethodID   post_event;
 };
@@ -109,8 +108,7 @@
 static sp<Surface> get_surface(JNIEnv* env, jobject clazz)
 {
     ALOGV("get_surface");
-    Surface* const p = (Surface*)env->GetIntField(clazz, fields.surface_native);
-    return sp<Surface>(p);
+    return android_view_Surface_getSurface(env, clazz);
 }
 
 // Returns true if it throws an exception.
@@ -328,7 +326,7 @@
             return;
         }
 
-        ALOGI("prepare: surface=%p (identity=%d)", native_surface.get(), native_surface->getIdentity());
+        ALOGI("prepare: surface=%p", native_surface.get());
         if (process_media_recorder_call(env, mr->setPreviewSurface(native_surface), "java/lang/RuntimeException", "setPreviewSurface failed.")) {
             return;
         }
@@ -409,11 +407,6 @@
         return;
     }
 
-    fields.surface_native = env->GetFieldID(surface, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    if (fields.surface_native == NULL) {
-        return;
-    }
-
     fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
                                                "(Ljava/lang/Object;IIILjava/lang/Object;)V");
     if (fields.post_event == NULL) {
diff --git a/media/jni/mediaeditor/VideoEditorMain.cpp b/media/jni/mediaeditor/VideoEditorMain.cpp
index 41c28c0..c1ad516 100644
--- a/media/jni/mediaeditor/VideoEditorMain.cpp
+++ b/media/jni/mediaeditor/VideoEditorMain.cpp
@@ -34,6 +34,8 @@
 
 #include "VideoEditorMain.h"
 
+#include <android_runtime/android_view_Surface.h>
+
 extern "C" {
 #include <M4OSA_Clock.h>
 #include <M4OSA_CharStar.h>
@@ -628,19 +630,8 @@
                                                 (NULL == surface),
                                                 "surface is null");
 
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, surface);
 
-    jfieldID surface_native =
-            pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
-
-    Surface* const p = (Surface*)pEnv->GetIntField(surface, surface_native);
-    sp<Surface> previewSurface = sp<Surface>(p);
     // Validate the mSurface's mNativeSurface field
     videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
                                                 (NULL == previewSurface.get()),
@@ -709,19 +700,9 @@
     videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
                                                 (NULL == mSurface),
                                                 "mSurface is null");
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
 
-    jfieldID surface_native =
-            pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
 
-    Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native);
-    sp<Surface> previewSurface = sp<Surface>(p);
     // Validate the mSurface's mNativeSurface field
     videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
                                                 (NULL == previewSurface.get()),
@@ -1038,20 +1019,8 @@
     videoEditJava_checkAndThrowIllegalArgumentException(&needToBeLoaded, pEnv,
                                                 (NULL == mSurface),
                                                 "mSurface is null");
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
 
-    jfieldID surface_native =
-            pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
-
-    Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native);
-    sp<Surface> previewSurface = sp<Surface>(p);
-
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
 
     const char *pString = pEnv->GetStringUTFChars(filePath, NULL);
     if (pString == M4OSA_NULL) {
@@ -2144,21 +2113,8 @@
                                                 (NULL == mSurface),
                                                 "mSurface is null");
 
-    jclass surfaceClass = pEnv->FindClass("android/view/Surface");
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surfaceClass),
-                                             "not initialized");
-    //jfieldID surface_native = pEnv->GetFieldID(surfaceClass, "mSurface", "I");
-    jfieldID surface_native
-        = pEnv->GetFieldID(surfaceClass, ANDROID_VIEW_SURFACE_JNI_ID, "I");
+    sp<Surface> previewSurface = android_view_Surface_getSurface(pEnv, mSurface);
 
-    videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
-                                             (M4OSA_NULL == surface_native),
-                                             "not initialized");
-
-    Surface* const p = (Surface*)pEnv->GetIntField(mSurface, surface_native);
-
-    sp<Surface> previewSurface = sp<Surface>(p);
     // Validate the mSurface's mNativeSurface field
     videoEditJava_checkAndThrowIllegalStateException(&needToBeLoaded, pEnv,
                                                 (NULL == previewSurface.get()),
diff --git a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
index ddfaad5..b498368 100644
--- a/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
+++ b/packages/SystemUI/src/com/android/systemui/screenshot/GlobalScreenshot.java
@@ -50,6 +50,7 @@
 import android.view.LayoutInflater;
 import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.View;
 import android.view.ViewGroup;
 import android.view.WindowManager;
@@ -455,7 +456,7 @@
         }
 
         // Take the screenshot
-        mScreenBitmap = Surface.screenshot((int) dims[0], (int) dims[1]);
+        mScreenBitmap = SurfaceControl.screenshot((int) dims[0], (int) dims[1]);
         if (mScreenBitmap == null) {
             notifyScreenshotError(mContext, mNotificationManager);
             finisher.run();
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index e3a3ca2..c31cde7 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -3341,7 +3341,7 @@
         // Tear down existing lockdown if profile was removed
         mLockdownEnabled = LockdownVpnTracker.isEnabled();
         if (mLockdownEnabled) {
-            if (mKeyStore.state() != KeyStore.State.UNLOCKED) {
+            if (!mKeyStore.isUnlocked()) {
                 Slog.w(TAG, "KeyStore locked; unable to create LockdownTracker");
                 return false;
             }
diff --git a/services/java/com/android/server/am/ActivityStack.java b/services/java/com/android/server/am/ActivityStack.java
index 84d5a72..c54cdaa 100644
--- a/services/java/com/android/server/am/ActivityStack.java
+++ b/services/java/com/android/server/am/ActivityStack.java
@@ -2145,7 +2145,6 @@
                             }
                             mHistory.remove(srcPos);
                             mHistory.add(dstPos, p);
-//                            mService.mWindowManager.moveAppToken(dstPos, p.appToken);
                             mService.mWindowManager.setAppGroupId(p.appToken, taskId);
                             dstPos++;
                             i++;
@@ -2297,7 +2296,6 @@
                         if (DEBUG_TASKS) Slog.v(TAG, "Pulling activity " + p
                                 + " from " + srcPos + " to " + lastReparentPos
                                 + " in to resetting task " + task);
-//                        mService.mWindowManager.moveAppToken(lastReparentPos, p.appToken);
                         mService.mWindowManager.setAppGroupId(p.appToken, taskId);
                     }
                     // TODO: This is wrong because it doesn't take lastReparentPos into account.
@@ -4566,7 +4564,6 @@
             updateTransitLocked(AppTransition.TRANSIT_TASK_TO_FRONT, options);
         }
 
-//        mService.mWindowManager.moveAppTokensToTop(moved);
         mService.mWindowManager.moveTaskToTop(task);
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
@@ -4659,7 +4656,6 @@
             mService.mWindowManager.prepareAppTransition(
                     AppTransition.TRANSIT_TASK_TO_BACK, false);
         }
-//        mService.mWindowManager.moveAppTokensToBottom(moved);
         mService.mWindowManager.moveTaskToBottom(task);
         if (VALIDATE_TOKENS) {
             validateAppTokensLocked();
diff --git a/services/java/com/android/server/connectivity/Vpn.java b/services/java/com/android/server/connectivity/Vpn.java
index bb19cc7..bb7334a 100644
--- a/services/java/com/android/server/connectivity/Vpn.java
+++ b/services/java/com/android/server/connectivity/Vpn.java
@@ -462,7 +462,7 @@
      * secondary thread to perform connection work, returning quickly.
      */
     public void startLegacyVpn(VpnProfile profile, KeyStore keyStore, LinkProperties egress) {
-        if (keyStore.state() != KeyStore.State.UNLOCKED) {
+        if (!keyStore.isUnlocked()) {
             throw new IllegalStateException("KeyStore isn't unlocked");
         }
 
diff --git a/services/java/com/android/server/display/DisplayDevice.java b/services/java/com/android/server/display/DisplayDevice.java
index a3ab3c1..4161147 100644
--- a/services/java/com/android/server/display/DisplayDevice.java
+++ b/services/java/com/android/server/display/DisplayDevice.java
@@ -19,6 +19,7 @@
 import android.graphics.Rect;
 import android.os.IBinder;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 
@@ -122,7 +123,7 @@
     public final void setLayerStackInTransactionLocked(int layerStack) {
         if (mCurrentLayerStack != layerStack) {
             mCurrentLayerStack = layerStack;
-            Surface.setDisplayLayerStack(mDisplayToken, layerStack);
+            SurfaceControl.setDisplayLayerStack(mDisplayToken, layerStack);
         }
     }
 
@@ -155,7 +156,7 @@
             }
             mCurrentDisplayRect.set(displayRect);
 
-            Surface.setDisplayProjection(mDisplayToken,
+            SurfaceControl.setDisplayProjection(mDisplayToken,
                     orientation, layerStackRect, displayRect);
         }
     }
@@ -166,7 +167,7 @@
     public final void setSurfaceInTransactionLocked(Surface surface) {
         if (mCurrentSurface != surface) {
             mCurrentSurface = surface;
-            Surface.setDisplaySurface(mDisplayToken, surface);
+            SurfaceControl.setDisplaySurface(mDisplayToken, surface);
         }
     }
 
diff --git a/services/java/com/android/server/display/LocalDisplayAdapter.java b/services/java/com/android/server/display/LocalDisplayAdapter.java
index ee2d617..475f27b 100644
--- a/services/java/com/android/server/display/LocalDisplayAdapter.java
+++ b/services/java/com/android/server/display/LocalDisplayAdapter.java
@@ -25,7 +25,8 @@
 import android.view.Display;
 import android.view.DisplayEventReceiver;
 import android.view.Surface;
-import android.view.Surface.PhysicalDisplayInfo;
+import android.view.SurfaceControl;
+import android.view.SurfaceControl.PhysicalDisplayInfo;
 
 import java.io.PrintWriter;
 
@@ -39,15 +40,15 @@
     private static final String TAG = "LocalDisplayAdapter";
 
     private static final int[] BUILT_IN_DISPLAY_IDS_TO_SCAN = new int[] {
-            Surface.BUILT_IN_DISPLAY_ID_MAIN,
-            Surface.BUILT_IN_DISPLAY_ID_HDMI,
+            SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN,
+            SurfaceControl.BUILT_IN_DISPLAY_ID_HDMI,
     };
 
     private final SparseArray<LocalDisplayDevice> mDevices =
             new SparseArray<LocalDisplayDevice>();
     private HotplugDisplayEventReceiver mHotplugReceiver;
 
-    private final PhysicalDisplayInfo mTempPhys = new PhysicalDisplayInfo();
+    private final SurfaceControl.PhysicalDisplayInfo mTempPhys = new SurfaceControl.PhysicalDisplayInfo();
 
     // Called with SyncRoot lock held.
     public LocalDisplayAdapter(DisplayManagerService.SyncRoot syncRoot,
@@ -67,8 +68,8 @@
     }
 
     private void tryConnectDisplayLocked(int builtInDisplayId) {
-        IBinder displayToken = Surface.getBuiltInDisplay(builtInDisplayId);
-        if (displayToken != null && Surface.getDisplayInfo(displayToken, mTempPhys)) {
+        IBinder displayToken = SurfaceControl.getBuiltInDisplay(builtInDisplayId);
+        if (displayToken != null && SurfaceControl.getDisplayInfo(displayToken, mTempPhys)) {
             LocalDisplayDevice device = mDevices.get(builtInDisplayId);
             if (device == null) {
                 // Display was added.
@@ -97,20 +98,20 @@
 
     private final class LocalDisplayDevice extends DisplayDevice {
         private final int mBuiltInDisplayId;
-        private final PhysicalDisplayInfo mPhys;
+        private final SurfaceControl.PhysicalDisplayInfo mPhys;
 
         private DisplayDeviceInfo mInfo;
         private boolean mHavePendingChanges;
         private boolean mBlanked;
 
         public LocalDisplayDevice(IBinder displayToken, int builtInDisplayId,
-                PhysicalDisplayInfo phys) {
+                SurfaceControl.PhysicalDisplayInfo phys) {
             super(LocalDisplayAdapter.this, displayToken);
             mBuiltInDisplayId = builtInDisplayId;
-            mPhys = new PhysicalDisplayInfo(phys);
+            mPhys = new SurfaceControl.PhysicalDisplayInfo(phys);
         }
 
-        public boolean updatePhysicalDisplayInfoLocked(PhysicalDisplayInfo phys) {
+        public boolean updatePhysicalDisplayInfoLocked(SurfaceControl.PhysicalDisplayInfo phys) {
             if (!mPhys.equals(phys)) {
                 mPhys.copyFrom(phys);
                 mHavePendingChanges = true;
@@ -142,7 +143,7 @@
                             | DisplayDeviceInfo.FLAG_SUPPORTS_PROTECTED_BUFFERS;
                 }
 
-                if (mBuiltInDisplayId == Surface.BUILT_IN_DISPLAY_ID_MAIN) {
+                if (mBuiltInDisplayId == SurfaceControl.BUILT_IN_DISPLAY_ID_MAIN) {
                     mInfo.name = getContext().getResources().getString(
                             com.android.internal.R.string.display_manager_built_in_display_name);
                     mInfo.flags |= DisplayDeviceInfo.FLAG_DEFAULT_DISPLAY
@@ -172,13 +173,13 @@
         @Override
         public void blankLocked() {
             mBlanked = true;
-            Surface.blankDisplay(getDisplayTokenLocked());
+            SurfaceControl.blankDisplay(getDisplayTokenLocked());
         }
 
         @Override
         public void unblankLocked() {
             mBlanked = false;
-            Surface.unblankDisplay(getDisplayTokenLocked());
+            SurfaceControl.unblankDisplay(getDisplayTokenLocked());
         }
 
         @Override
diff --git a/services/java/com/android/server/display/OverlayDisplayAdapter.java b/services/java/com/android/server/display/OverlayDisplayAdapter.java
index 36e9f74..a18352c 100644
--- a/services/java/com/android/server/display/OverlayDisplayAdapter.java
+++ b/services/java/com/android/server/display/OverlayDisplayAdapter.java
@@ -30,6 +30,7 @@
 import android.view.Display;
 import android.view.Gravity;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 import java.util.ArrayList;
@@ -284,7 +285,7 @@
         @Override
         public void onWindowCreated(SurfaceTexture surfaceTexture, float refreshRate) {
             synchronized (getSyncRoot()) {
-                IBinder displayToken = Surface.createDisplay(mName, false);
+                IBinder displayToken = SurfaceControl.createDisplay(mName, false);
                 mDevice = new OverlayDisplayDevice(displayToken, mName,
                         mWidth, mHeight, refreshRate, mDensityDpi, surfaceTexture);
 
diff --git a/services/java/com/android/server/display/WifiDisplayAdapter.java b/services/java/com/android/server/display/WifiDisplayAdapter.java
index c8a44d2..b655b3a 100644
--- a/services/java/com/android/server/display/WifiDisplayAdapter.java
+++ b/services/java/com/android/server/display/WifiDisplayAdapter.java
@@ -41,6 +41,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 import java.util.Arrays;
@@ -332,7 +333,7 @@
 
         String name = display.getFriendlyDisplayName();
         String address = display.getDeviceAddress();
-        IBinder displayToken = Surface.createDisplay(name, secure);
+        IBinder displayToken = SurfaceControl.createDisplay(name, secure);
         mDisplayDevice = new WifiDisplayDevice(displayToken, name, width, height,
                 refreshRate, deviceFlags, address, surface);
         sendDisplayDeviceEventLocked(mDisplayDevice, DISPLAY_DEVICE_EVENT_ADDED);
diff --git a/services/java/com/android/server/power/ElectronBeam.java b/services/java/com/android/server/power/ElectronBeam.java
index 8e19e11..2828e5e 100644
--- a/services/java/com/android/server/power/ElectronBeam.java
+++ b/services/java/com/android/server/power/ElectronBeam.java
@@ -34,6 +34,7 @@
 import android.view.Display;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
 import java.io.PrintWriter;
@@ -80,7 +81,8 @@
     private int mDisplayWidth;      // real width, not rotated
     private int mDisplayHeight;     // real height, not rotated
     private SurfaceSession mSurfaceSession;
-    private Surface mSurface;
+    private SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
     private NaturalSurfaceLayout mSurfaceLayout;
     private EGLDisplay mEglDisplay;
     private EGLConfig mEglConfig;
@@ -370,7 +372,7 @@
 
     private boolean captureScreenshotTextureAndSetViewport() {
         // TODO: Use a SurfaceTexture to avoid the extra texture upload.
-        Bitmap bitmap = Surface.screenshot(mDisplayWidth, mDisplayHeight,
+        Bitmap bitmap = SurfaceControl.screenshot(mDisplayWidth, mDisplayHeight,
                 0, ELECTRON_BEAM_LAYER - 1);
         if (bitmap == null) {
             Slog.e(TAG, "Could not take a screenshot!");
@@ -525,32 +527,33 @@
             mSurfaceSession = new SurfaceSession();
         }
 
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
-            if (mSurface == null) {
+            if (mSurfaceControl == null) {
                 try {
                     int flags;
                     if (mMode == MODE_FADE) {
-                        flags = Surface.FX_SURFACE_DIM | Surface.HIDDEN;
+                        flags = SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN;
                     } else {
-                        flags = Surface.OPAQUE | Surface.HIDDEN;
+                        flags = SurfaceControl.OPAQUE | SurfaceControl.HIDDEN;
                     }
-                    mSurface = new Surface(mSurfaceSession,
+                    mSurfaceControl = new SurfaceControl(mSurfaceSession,
                             "ElectronBeam", mDisplayWidth, mDisplayHeight,
                             PixelFormat.OPAQUE, flags);
-                } catch (Surface.OutOfResourcesException ex) {
+                } catch (SurfaceControl.OutOfResourcesException ex) {
                     Slog.e(TAG, "Unable to create surface.", ex);
                     return false;
                 }
             }
 
-            mSurface.setLayerStack(mDisplayLayerStack);
-            mSurface.setSize(mDisplayWidth, mDisplayHeight);
-
-            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurface);
+            mSurfaceControl.setLayerStack(mDisplayLayerStack);
+            mSurfaceControl.setSize(mDisplayWidth, mDisplayHeight);
+            mSurface.copyFrom(mSurfaceControl);
+            
+            mSurfaceLayout = new NaturalSurfaceLayout(mDisplayManager, mSurfaceControl);
             mSurfaceLayout.onDisplayTransaction();
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
         }
         return true;
     }
@@ -560,6 +563,7 @@
             int[] eglSurfaceAttribList = new int[] {
                     EGL14.EGL_NONE
             };
+            // turn our SurfaceControl into a Surface
             mEglSurface = EGL14.eglCreateWindowSurface(mEglDisplay, mEglConfig, mSurface,
                     eglSurfaceAttribList, 0);
             if (mEglSurface == null) {
@@ -580,16 +584,17 @@
     }
 
     private void destroySurface() {
-        if (mSurface != null) {
+        if (mSurfaceControl != null) {
             mSurfaceLayout.dispose();
             mSurfaceLayout = null;
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
-                mSurface.destroy();
+                mSurfaceControl.destroy();
+                mSurface.release();
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
             }
-            mSurface = null;
+            mSurfaceControl = null;
             mSurfaceVisible = false;
             mSurfaceAlpha = 0f;
         }
@@ -597,13 +602,13 @@
 
     private boolean showSurface(float alpha) {
         if (!mSurfaceVisible || mSurfaceAlpha != alpha) {
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
-                mSurface.setLayer(ELECTRON_BEAM_LAYER);
-                mSurface.setAlpha(alpha);
-                mSurface.show();
+                mSurfaceControl.setLayer(ELECTRON_BEAM_LAYER);
+                mSurfaceControl.setAlpha(alpha);
+                mSurfaceControl.show();
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
             }
             mSurfaceVisible = true;
             mSurfaceAlpha = alpha;
@@ -708,9 +713,9 @@
      */
     private static final class NaturalSurfaceLayout implements DisplayTransactionListener {
         private final DisplayManagerService mDisplayManager;
-        private Surface mSurface;
+        private SurfaceControl mSurface;
 
-        public NaturalSurfaceLayout(DisplayManagerService displayManager, Surface surface) {
+        public NaturalSurfaceLayout(DisplayManagerService displayManager, SurfaceControl surface) {
             mDisplayManager = displayManager;
             mSurface = surface;
             mDisplayManager.registerDisplayTransactionListener(this);
diff --git a/services/java/com/android/server/wm/AppWindowAnimator.java b/services/java/com/android/server/wm/AppWindowAnimator.java
index ad68307..297324b 100644
--- a/services/java/com/android/server/wm/AppWindowAnimator.java
+++ b/services/java/com/android/server/wm/AppWindowAnimator.java
@@ -6,6 +6,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 import android.view.animation.Transformation;
@@ -38,7 +39,7 @@
     boolean allDrawn;
 
     // Special surface for thumbnail animation.
-    Surface thumbnail;
+    SurfaceControl thumbnail;
     int thumbnailTransactionSeq;
     int thumbnailX;
     int thumbnailY;
diff --git a/services/java/com/android/server/wm/BlackFrame.java b/services/java/com/android/server/wm/BlackFrame.java
index 5b77b20..a197840 100644
--- a/services/java/com/android/server/wm/BlackFrame.java
+++ b/services/java/com/android/server/wm/BlackFrame.java
@@ -23,6 +23,7 @@
 import android.graphics.Rect;
 import android.util.Slog;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
 /**
@@ -33,7 +34,7 @@
         final int left;
         final int top;
         final int layer;
-        final Surface surface;
+        final SurfaceControl surface;
 
         BlackSurface(SurfaceSession session, int layer, int l, int t, int r, int b, int layerStack)
                 throws Surface.OutOfResourcesException {
@@ -42,13 +43,17 @@
             this.layer = layer;
             int w = r-l;
             int h = b-t;
-            if (WindowManagerService.DEBUG_SURFACE_TRACE) {
-                surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
-                        + l + ", " + t + ")",
-                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
-            } else {
-                surface = new Surface(session, "BlackSurface",
-                        w, h, PixelFormat.OPAQUE, Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+            try {
+                if (WindowManagerService.DEBUG_SURFACE_TRACE) {
+                    surface = new WindowStateAnimator.SurfaceTrace(session, "BlackSurface("
+                            + l + ", " + t + ")",
+                            w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+                } else {
+                    surface = new SurfaceControl(session, "BlackSurface",
+                            w, h, PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
+                }
+            } catch (SurfaceControl.OutOfResourcesException e) {
+                throw new Surface.OutOfResourcesException(e.getMessage());
             }
             surface.setAlpha(1);
             surface.setLayerStack(layerStack);
diff --git a/services/java/com/android/server/wm/DimLayer.java b/services/java/com/android/server/wm/DimLayer.java
index 88efe2e..9bd36ba 100644
--- a/services/java/com/android/server/wm/DimLayer.java
+++ b/services/java/com/android/server/wm/DimLayer.java
@@ -7,6 +7,7 @@
 import android.util.Slog;
 import android.view.DisplayInfo;
 import android.view.Surface;
+import android.view.SurfaceControl;
 
 import java.io.PrintWriter;
 
@@ -18,7 +19,7 @@
     final DisplayContent mDisplayContent;
 
     /** Actual surface that dims */
-    Surface mDimSurface;
+    SurfaceControl mDimSurface;
 
     /** Last value passed to mDimSurface.setAlpha() */
     float mAlpha = 0;
@@ -47,17 +48,17 @@
     DimLayer(WindowManagerService service, int displayId) {
         if (DEBUG) Slog.v(TAG, "Ctor: displayId=" + displayId);
         mDisplayContent = service.getDisplayContentLocked(displayId);
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                 mDimSurface = new WindowStateAnimator.SurfaceTrace(service.mFxSession,
                     "DimSurface",
                     16, 16, PixelFormat.OPAQUE,
-                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+                    SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
             } else {
-                mDimSurface = new Surface(service.mFxSession, TAG,
+                mDimSurface = new SurfaceControl(service.mFxSession, TAG,
                     16, 16, PixelFormat.OPAQUE,
-                    Surface.FX_SURFACE_DIM | Surface.HIDDEN);
+                    SurfaceControl.FX_SURFACE_DIM | SurfaceControl.HIDDEN);
             }
             if (WindowManagerService.SHOW_TRANSACTIONS ||
                     WindowManagerService.SHOW_SURFACE_ALLOC) Slog.i(TAG,
@@ -66,7 +67,7 @@
         } catch (Exception e) {
             Slog.e(WindowManagerService.TAG, "Exception creating Dim surface", e);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
         }
     }
 
diff --git a/services/java/com/android/server/wm/DisplayContent.java b/services/java/com/android/server/wm/DisplayContent.java
index f8e779d..89e0f17 100644
--- a/services/java/com/android/server/wm/DisplayContent.java
+++ b/services/java/com/android/server/wm/DisplayContent.java
@@ -16,8 +16,9 @@
 
 package com.android.server.wm;
 
-import android.os.Debug;
-import android.util.Slog;
+import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR;
+import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR;
+
 import android.util.SparseArray;
 import android.view.Display;
 import android.view.DisplayInfo;
@@ -38,7 +39,7 @@
  * WindowManagerService.mWindowMap.
  */
 class DisplayContent {
-    private final static String TAG = "DisplayContent";
+//    private final static String TAG = "DisplayContent";
 
     /** Unique identifier of this stack. */
     private final int mDisplayId;
@@ -73,20 +74,6 @@
     final boolean isDefaultDisplay;
 
     /**
-     * List controlling the ordering of windows in different applications which must
-     * be kept in sync with ActivityManager.
-     */
-    final AppTokenList mAppTokens = new AppTokenList();
-
-    /**
-     * AppWindowTokens in the Z order they were in at the start of an animation. Between
-     * animations this list is maintained in the exact order of mAppTokens. If tokens
-     * are added to mAppTokens during an animation an attempt is made to insert them at the same
-     * logical location in this list. Note that this list is always in sync with mWindows.
-     */
-    AppTokenList mAnimatingAppTokens = new AppTokenList();
-
-    /**
      * Window tokens that are in the process of exiting, but still
      * on screen for animations.
      */
@@ -104,6 +91,8 @@
     ArrayList<TaskList> mTaskLists = new ArrayList<TaskList>();
     SparseArray<TaskList> mTaskIdToTaskList = new SparseArray<TaskList>();
 
+    private final AppTokenIterator mTmpAppIterator = new AppTokenIterator();
+
     /**
      * @param display May not be null.
      */
@@ -140,18 +129,6 @@
      * @param wtoken The token to insert.
      */
     void addAppToken(final int addPos, final AppWindowToken wtoken) {
-        mAppTokens.add(addPos, wtoken);
-
-        if (addPos == 0 || addPos == mAnimatingAppTokens.size()) {
-            // It was inserted into the beginning or end of mAppTokens. Honor that.
-            mAnimatingAppTokens.add(addPos, wtoken);
-        } else {
-            // Find the item immediately above the mAppTokens insertion point and put the token
-            // immediately below that one in mAnimatingAppTokens.
-            final AppWindowToken aboveAnchor = mAppTokens.get(addPos + 1);
-            mAnimatingAppTokens.add(mAnimatingAppTokens.indexOf(aboveAnchor), wtoken);
-        }
-
         TaskList task = mTaskIdToTaskList.get(wtoken.groupId);
         if (task == null) {
             task = new TaskList(wtoken, this);
@@ -163,8 +140,6 @@
     }
 
     void removeAppToken(final AppWindowToken wtoken) {
-        mAppTokens.remove(wtoken);
-        mAnimatingAppTokens.remove(wtoken);
         final int taskId = wtoken.groupId;
         final TaskList task = mTaskIdToTaskList.get(taskId);
         if (task != null) {
@@ -177,14 +152,6 @@
         }
     }
 
-    void refillAnimatingAppTokens() {
-        mAnimatingAppTokens.clear();
-        AppTokenIterator iterator = new AppTokenIterator();
-        while (iterator.hasNext()) {
-            mAnimatingAppTokens.add(iterator.next());
-        }
-    }
-
     void setAppTaskId(AppWindowToken wtoken, int newTaskId) {
         final int taskId = wtoken.groupId;
         TaskList task = mTaskIdToTaskList.get(taskId);
@@ -207,6 +174,18 @@
         wtoken.groupId = newTaskId;
     }
 
+    /**
+     * Return the utility iterator so we don't have to construct new iterators every time we
+     * iterate.
+     * NOTE: Do not ever nest this call or you will have a bad time!
+     * @param reverse Direction of iterator.
+     * @return The utility iterator.
+     */
+    AppTokenIterator getTmpAppIterator(boolean reverse) {
+        mTmpAppIterator.reset(reverse);
+        return mTmpAppIterator;
+    }
+
     class TaskListsIterator implements Iterator<TaskList> {
         private int mCur;
         private boolean mReverse;
@@ -216,9 +195,12 @@
         }
 
         TaskListsIterator(boolean reverse) {
+            reset(reverse);
+        }
+
+        void reset(boolean reverse) {
             mReverse = reverse;
-            int numTaskLists = mTaskLists.size();
-            mCur = reverse ? numTaskLists - 1 : 0;
+            mCur = reverse ? mTaskLists.size() - 1 : 0;
         }
 
         @Override
@@ -246,18 +228,22 @@
     }
 
     class AppTokenIterator implements Iterator<AppWindowToken> {
-        final TaskListsIterator mIterator;
-        final boolean mReverse;
+        final TaskListsIterator mIterator = new TaskListsIterator();
+        boolean mReverse;
         int mCur;
         TaskList mTaskList;
 
         public AppTokenIterator() {
-            this(false);
+            this(FORWARD_ITERATOR);
         }
 
         public AppTokenIterator(boolean reverse) {
+            reset(reverse);
+        }
+
+        void reset(boolean reverse) {
             mReverse = reverse;
-            mIterator = new TaskListsIterator(reverse);
+            mIterator.reset(reverse);
             getNextTaskList();
         }
 
@@ -307,31 +293,6 @@
         }
     }
 
-    void verifyAppTokens() {
-        AppTokenIterator iterator = new AppTokenIterator();
-        for (int i = 0; i < mAppTokens.size(); ++i) {
-            if (!iterator.hasNext()) {
-                Slog.e(TAG, "compareAppTokens: More mAppTokens than TaskList tokens. Callers="
-                        + Debug.getCallers(4));
-                while (i < mAppTokens.size()) {
-                    Slog.e(TAG, "compareAppTokens: mAppTokens[" + i + "]=" + mAppTokens.get(i));
-                    i++;
-                }
-                return;
-            }
-            AppWindowToken appToken = mAppTokens.get(i);
-            AppWindowToken taskListToken = iterator.next();
-            if (appToken != taskListToken) {
-                Slog.e(TAG, "compareAppTokens: Mismatch at " + i + " appToken=" + appToken
-                        + " taskListToken=" + taskListToken + ". Callers=" + Debug.getCallers(4));
-            }
-        }
-        if (iterator.hasNext()) {
-            Slog.e(TAG, "compareAppTokens: More TaskList tokens than mAppTokens Callers="
-                    + Debug.getCallers(4));
-        }
-    }
-
     public void dump(String prefix, PrintWriter pw) {
         pw.print(prefix); pw.print("Display: mDisplayId="); pw.println(mDisplayId);
         final String subPrefix = "  " + prefix;
@@ -355,7 +316,7 @@
             pw.print("x"); pw.print(mDisplayInfo.smallestNominalAppHeight);
             pw.print("-"); pw.print(mDisplayInfo.largestNominalAppWidth);
             pw.print("x"); pw.println(mDisplayInfo.largestNominalAppHeight);
-            AppTokenIterator iterator = new AppTokenIterator(true);
+            AppTokenIterator iterator = getTmpAppIterator(REVERSE_ITERATOR);
             int ndx = iterator.size() - 1;
             if (ndx >= 0) {
                 pw.println();
diff --git a/services/java/com/android/server/wm/DisplayMagnifier.java b/services/java/com/android/server/wm/DisplayMagnifier.java
index 61093ad..55c6fa6 100644
--- a/services/java/com/android/server/wm/DisplayMagnifier.java
+++ b/services/java/com/android/server/wm/DisplayMagnifier.java
@@ -43,6 +43,7 @@
 import android.view.MagnificationSpec;
 import android.view.Surface;
 import android.view.Surface.OutOfResourcesException;
+import android.view.SurfaceControl;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
 import android.view.animation.DecelerateInterpolator;
@@ -481,7 +482,8 @@
             private final Paint mPaint = new Paint();
 
             private final ValueAnimator mShowHideFrameAnimator;
-            private final Surface mSurface;
+            private final SurfaceControl mSurfaceControl;
+            private final Surface mSurface = new Surface();
 
             private boolean mShown;
             private int mAlpha;
@@ -489,20 +491,21 @@
             private boolean mInvalidated;
 
             public ViewportWindow(Context context) {
-                Surface surface = null;
+                SurfaceControl surface = null;
                 try {
                     mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
-                    surface = new Surface(mWindowManagerService.mFxSession, SURFACE_TITLE,
-                            mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-                } catch (OutOfResourcesException oore) {
+                    surface = new SurfaceControl(mWindowManagerService.mFxSession, SURFACE_TITLE,
+                            mTempPoint.x, mTempPoint.y, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+                } catch (SurfaceControl.OutOfResourcesException oore) {
                     /* ignore */
                 }
-                mSurface = surface;
-                mSurface.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack());
-                mSurface.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
+                mSurfaceControl = surface;
+                mSurfaceControl.setLayerStack(mWindowManager.getDefaultDisplay().getLayerStack());
+                mSurfaceControl.setLayer(mWindowManagerService.mPolicy.windowTypeToLayerLw(
                         WindowManager.LayoutParams.TYPE_MAGNIFICATION_OVERLAY)
                         * WindowManagerService.TYPE_LAYER_MULTIPLIER);
-                mSurface.setPosition(0, 0);
+                mSurfaceControl.setPosition(0, 0);
+                mSurface.copyFrom(mSurfaceControl);
 
                 TypedValue typedValue = new TypedValue();
                 context.getTheme().resolveAttribute(R.attr.colorActivatedHighlight,
@@ -591,7 +594,7 @@
             public void updateSize() {
                 synchronized (mWindowManagerService.mWindowMap) {
                     mWindowManager.getDefaultDisplay().getRealSize(mTempPoint);
-                    mSurface.setSize(mTempPoint.x, mTempPoint.y);
+                    mSurfaceControl.setSize(mTempPoint.x, mTempPoint.y);
                     invalidate(mDirtyRect);
                 }
             }
@@ -641,16 +644,17 @@
                     canvas.drawPath(path, mPaint);
 
                     mSurface.unlockCanvasAndPost(canvas);
-
+                    
                     if (mAlpha > 0) {
-                        mSurface.show();
+                        mSurfaceControl.show();
                     } else {
-                        mSurface.hide();
+                        mSurfaceControl.hide();
                     }
                 }
             }
 
             public void releaseSurface() {
+                mSurfaceControl.release();
                 mSurface.release();
             }
         }
diff --git a/services/java/com/android/server/wm/DragState.java b/services/java/com/android/server/wm/DragState.java
index 72fc180..63f306f 100644
--- a/services/java/com/android/server/wm/DragState.java
+++ b/services/java/com/android/server/wm/DragState.java
@@ -34,6 +34,7 @@
 import android.view.DragEvent;
 import android.view.InputChannel;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.View;
 import android.view.WindowManager;
 
@@ -45,7 +46,7 @@
 class DragState {
     final WindowManagerService mService;
     IBinder mToken;
-    Surface mSurface;
+    SurfaceControl mSurface;
     int mFlags;
     IBinder mLocalWin;
     ClipData mData;
@@ -64,7 +65,7 @@
 
     private final Region mTmpRegion = new Region();
 
-    DragState(WindowManagerService service, IBinder token, Surface surface,
+    DragState(WindowManagerService service, IBinder token, SurfaceControl surface,
             int flags, IBinder localWin) {
         mService = service;
         mToken = token;
@@ -293,14 +294,14 @@
         // Move the surface to the given touch
         if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                 WindowManagerService.TAG, ">>> OPEN TRANSACTION notifyMoveLw");
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             mSurface.setPosition(x - mThumbOffsetX, y - mThumbOffsetY);
             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(WindowManagerService.TAG, "  DRAG "
                     + mSurface + ": pos=(" +
                     (int)(x - mThumbOffsetX) + "," + (int)(y - mThumbOffsetY) + ")");
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                     WindowManagerService.TAG, "<<< CLOSE TRANSACTION notifyMoveLw");
         }
diff --git a/services/java/com/android/server/wm/ScreenRotationAnimation.java b/services/java/com/android/server/wm/ScreenRotationAnimation.java
index 71a61c6..05397ac 100644
--- a/services/java/com/android/server/wm/ScreenRotationAnimation.java
+++ b/services/java/com/android/server/wm/ScreenRotationAnimation.java
@@ -27,6 +27,7 @@
 import android.util.Slog;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
@@ -43,7 +44,7 @@
 
     final Context mContext;
     final Display mDisplay;
-    Surface mSurface;
+    SurfaceControl mSurface;
     BlackFrame mCustomBlackFrame;
     BlackFrame mExitingBlackFrame;
     BlackFrame mEnteringBlackFrame;
@@ -213,7 +214,7 @@
         if (!inTransaction) {
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
         }
 
         try {
@@ -221,22 +222,17 @@
                 if (WindowManagerService.DEBUG_SURFACE_TRACE) {
                     mSurface = new SurfaceTrace(session, "FreezeSurface",
                             mWidth, mHeight,
-                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
+                            PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_SCREENSHOT | SurfaceControl.HIDDEN);
                 } else {
-                    mSurface = new Surface(session, "FreezeSurface",
+                    mSurface = new SurfaceControl(session, "FreezeSurface",
                             mWidth, mHeight,
-                            PixelFormat.OPAQUE, Surface.FX_SURFACE_SCREENSHOT | Surface.HIDDEN);
-                }
-                if (!mSurface.isValid()) {
-                    // Screenshot failed, punt.
-                    mSurface = null;
-                    return;
+                            PixelFormat.OPAQUE, SurfaceControl.FX_SURFACE_SCREENSHOT | SurfaceControl.HIDDEN);
                 }
                 mSurface.setLayerStack(mDisplay.getLayerStack());
                 mSurface.setLayer(FREEZE_LAYER + 1);
                 mSurface.setAlpha(0);
                 mSurface.show();
-            } catch (Surface.OutOfResourcesException e) {
+            } catch (SurfaceControl.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate freeze surface", e);
             }
 
@@ -247,7 +243,7 @@
             setRotationInTransaction(originalRotation);
         } finally {
             if (!inTransaction) {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation");
             }
@@ -496,7 +492,7 @@
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
 
             // Compute the transformation matrix that must be applied
             // the the black frame to make it stay in the initial position
@@ -516,7 +512,7 @@
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                         WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
@@ -527,7 +523,7 @@
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 // Compute the transformation matrix that must be applied
                 // the the black frame to make it stay in the initial position
@@ -546,7 +542,7 @@
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                         WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
@@ -557,7 +553,7 @@
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                     WindowManagerService.TAG,
                     ">>> OPEN TRANSACTION ScreenRotationAnimation.startAnimation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
 
             try {
                 Rect outer = new Rect(-finalWidth*1, -finalHeight*1,
@@ -568,7 +564,7 @@
             } catch (Surface.OutOfResourcesException e) {
                 Slog.w(TAG, "Unable to allocate black surface", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS || DEBUG_STATE) Slog.i(
                         WindowManagerService.TAG,
                         "<<< CLOSE TRANSACTION ScreenRotationAnimation.startAnimation");
diff --git a/services/java/com/android/server/wm/Session.java b/services/java/com/android/server/wm/Session.java
index 3b4c1ab..7a0fa16 100644
--- a/services/java/com/android/server/wm/Session.java
+++ b/services/java/com/android/server/wm/Session.java
@@ -40,6 +40,7 @@
 import android.view.IWindowSession;
 import android.view.InputChannel;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 
@@ -313,10 +314,10 @@
             mService.mDragState.mThumbOffsetY = thumbCenterY;
 
             // Make the surface visible at the proper location
-            final Surface surface = mService.mDragState.mSurface;
+            final SurfaceControl surface = mService.mDragState.mSurface;
             if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                     WindowManagerService.TAG, ">>> OPEN TRANSACTION performDrag");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 surface.setPosition(touchX - thumbCenterX,
                         touchY - thumbCenterY);
@@ -325,7 +326,7 @@
                 surface.setLayerStack(display.getLayerStack());
                 surface.show();
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (WindowManagerService.SHOW_LIGHT_TRANSACTIONS) Slog.i(
                         WindowManagerService.TAG, "<<< CLOSE TRANSACTION performDrag");
             }
diff --git a/services/java/com/android/server/wm/StrictModeFlash.java b/services/java/com/android/server/wm/StrictModeFlash.java
index 90bbd08..31628e3 100644
--- a/services/java/com/android/server/wm/StrictModeFlash.java
+++ b/services/java/com/android/server/wm/StrictModeFlash.java
@@ -24,29 +24,32 @@
 import android.graphics.Region;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 
 class StrictModeFlash {
     private static final String TAG = "StrictModeFlash";
 
-    Surface mSurface;
-    int mLastDW;
-    int mLastDH;
-    boolean mDrawNeeded;
-    final int mThickness = 20;
+    private final SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
+    private int mLastDW;
+    private int mLastDH;
+    private boolean mDrawNeeded;
+    private final int mThickness = 20;
 
     public StrictModeFlash(Display display, SurfaceSession session) {
+        SurfaceControl ctrl = null;
         try {
-            mSurface = new Surface(session, "StrictModeFlash",
-                1, 1, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-        } catch (Surface.OutOfResourcesException e) {
-            return;
+            ctrl = new SurfaceControl(session, "StrictModeFlash",
+                1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            ctrl.setLayerStack(display.getLayerStack());
+            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
+            ctrl.setPosition(0, 0);
+            ctrl.show();
+            mSurface.copyFrom(ctrl);
+        } catch (SurfaceControl.OutOfResourcesException e) {
         }
-
-        mSurface.setLayerStack(display.getLayerStack());
-        mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER * 101);  // one more than Watermark? arbitrary.
-        mSurface.setPosition(0, 0);
-        mSurface.show();
+        mSurfaceControl = ctrl;
         mDrawNeeded = true;
     }
 
@@ -88,14 +91,14 @@
     // Note: caller responsible for being inside
     // Surface.openTransaction() / closeTransaction()
     public void setVisibility(boolean on) {
-        if (mSurface == null) {
+        if (mSurfaceControl == null) {
             return;
         }
         drawIfNeeded();
         if (on) {
-            mSurface.show();
+            mSurfaceControl.show();
         } else {
-            mSurface.hide();
+            mSurfaceControl.hide();
         }
     }
 
@@ -105,7 +108,7 @@
         }
         mLastDW = dw;
         mLastDH = dh;
-        mSurface.setSize(dw, dh);
+        mSurfaceControl.setSize(dw, dh);
         mDrawNeeded = true;
     }
 
diff --git a/services/java/com/android/server/wm/Watermark.java b/services/java/com/android/server/wm/Watermark.java
index ac152c9..fedd314 100644
--- a/services/java/com/android/server/wm/Watermark.java
+++ b/services/java/com/android/server/wm/Watermark.java
@@ -28,6 +28,7 @@
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.Surface.OutOfResourcesException;
 
@@ -35,21 +36,20 @@
  * Displays a watermark on top of the window manager's windows.
  */
 class Watermark {
-    final Display mDisplay;
-    final String[] mTokens;
-    final String mText;
-    final Paint mTextPaint;
-    final int mTextWidth;
-    final int mTextHeight;
-    final int mTextAscent;
-    final int mTextDescent;
-    final int mDeltaX;
-    final int mDeltaY;
+    private final Display mDisplay;
+    private final String[] mTokens;
+    private final String mText;
+    private final Paint mTextPaint;
+    private final int mTextWidth;
+    private final int mTextHeight;
+    private final int mDeltaX;
+    private final int mDeltaY;
 
-    Surface mSurface;
-    int mLastDW;
-    int mLastDH;
-    boolean mDrawNeeded;
+    private final SurfaceControl mSurfaceControl;
+    private final Surface mSurface = new Surface();
+    private int mLastDW;
+    private int mLastDH;
+    private boolean mDrawNeeded;
 
     Watermark(Display display, DisplayMetrics dm, SurfaceSession session, String[] tokens) {
         if (false) {
@@ -90,8 +90,6 @@
 
         FontMetricsInt fm = mTextPaint.getFontMetricsInt();
         mTextWidth = (int)mTextPaint.measureText(mText);
-        mTextAscent = fm.ascent;
-        mTextDescent = fm.descent;
         mTextHeight = fm.descent - fm.ascent;
 
         mDeltaX = WindowManagerService.getPropertyInt(tokens, 2,
@@ -112,22 +110,25 @@
         mTextPaint.setColor(color);
         mTextPaint.setShadowLayer(shadowRadius, shadowDx, shadowDy, shadowColor);
 
+        SurfaceControl ctrl = null;
         try {
-            mSurface = new Surface(session, "WatermarkSurface",
-                    1, 1, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
-            mSurface.setLayerStack(mDisplay.getLayerStack());
-            mSurface.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
-            mSurface.setPosition(0, 0);
-            mSurface.show();
-        } catch (OutOfResourcesException e) {
+            ctrl = new SurfaceControl(session, "WatermarkSurface",
+                    1, 1, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
+            ctrl.setLayerStack(mDisplay.getLayerStack());
+            ctrl.setLayer(WindowManagerService.TYPE_LAYER_MULTIPLIER*100);
+            ctrl.setPosition(0, 0);
+            ctrl.show();
+            mSurface.copyFrom(ctrl);
+        } catch (SurfaceControl.OutOfResourcesException e) {
         }
+        mSurfaceControl = ctrl;
     }
 
     void positionSurface(int dw, int dh) {
         if (mLastDW != dw || mLastDH != dh) {
             mLastDW = dw;
             mLastDH = dh;
-            mSurface.setSize(dw, dh);
+            mSurfaceControl.setSize(dw, dh);
             mDrawNeeded = true;
         }
     }
diff --git a/services/java/com/android/server/wm/WindowAnimator.java b/services/java/com/android/server/wm/WindowAnimator.java
index 546bf2f..a2c44ef 100644
--- a/services/java/com/android/server/wm/WindowAnimator.java
+++ b/services/java/com/android/server/wm/WindowAnimator.java
@@ -10,6 +10,8 @@
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_FORCE_HIDING_CHANGED;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_ORIENTATION_CHANGE_COMPLETE;
 import static com.android.server.wm.WindowManagerService.LayoutFields.SET_WALLPAPER_ACTION_PENDING;
+import static com.android.server.wm.WindowManagerService.FORWARD_ITERATOR;
+import static com.android.server.wm.WindowManagerService.REVERSE_ITERATOR;
 
 import android.content.Context;
 import android.os.Debug;
@@ -22,9 +24,11 @@
 import android.util.TypedValue;
 import android.view.Display;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.WindowManagerPolicy;
 import android.view.animation.Animation;
 
+import com.android.server.wm.DisplayContent.AppTokenIterator;
 import com.android.server.wm.WindowManagerService.DisplayContentsIterator;
 import com.android.server.wm.WindowManagerService.LayoutFields;
 
@@ -174,10 +178,9 @@
     private void updateAppWindowsLocked(int displayId) {
         int i;
         final DisplayContent displayContent = mService.getDisplayContentLocked(displayId);
-        final AppTokenList appTokens = displayContent.mAnimatingAppTokens;
-        final int NAT = appTokens.size();
-        for (i=0; i<NAT; i++) {
-            final AppWindowAnimator appAnimator = appTokens.get(i).mAppAnimator;
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
+        while (iterator.hasNext()) {
+            final AppWindowAnimator appAnimator = iterator.next().mAppAnimator;
             final boolean wasAnimating = appAnimator.animation != null
                     && appAnimator.animation != AppWindowAnimator.sDummyAnimation;
             if (appAnimator.stepAnimationLocked(mCurrentTime)) {
@@ -458,11 +461,10 @@
     private void testTokenMayBeDrawnLocked(int displayId) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final AppTokenList appTokens =
-                mService.getDisplayContentLocked(displayId).mAnimatingAppTokens;
-        final int NT = appTokens.size();
-        for (int i=0; i<NT; i++) {
-            AppWindowToken wtoken = appTokens.get(i);
+        AppTokenIterator iterator =
+                mService.getDisplayContentLocked(displayId).getTmpAppIterator(FORWARD_ITERATOR);
+        while (iterator.hasNext()) {
+            AppWindowToken wtoken = iterator.next();
             AppWindowAnimator appAnimator = wtoken.mAppAnimator;
             final boolean allDrawn = wtoken.allDrawn;
             if (allDrawn != appAnimator.allDrawn) {
@@ -529,8 +531,8 @@
 
         if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                 TAG, ">>> OPEN TRANSACTION animateLocked");
-        Surface.openTransaction();
-        Surface.setAnimationTransaction();
+        SurfaceControl.openTransaction();
+        SurfaceControl.setAnimationTransaction();
         try {
             final int numDisplays = mDisplayContentsAnimators.size();
             for (int i = 0; i < numDisplays; i++) {
@@ -622,7 +624,7 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (WindowManagerService.SHOW_TRANSACTIONS) Slog.i(
                     TAG, "<<< CLOSE TRANSACTION animateLocked");
         }
diff --git a/services/java/com/android/server/wm/WindowManagerService.java b/services/java/com/android/server/wm/WindowManagerService.java
index 8806afa..7b83c24 100644
--- a/services/java/com/android/server/wm/WindowManagerService.java
+++ b/services/java/com/android/server/wm/WindowManagerService.java
@@ -132,6 +132,7 @@
 import android.view.MagnificationSpec;
 import android.view.MotionEvent;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.View;
 import android.view.ViewTreeObserver;
@@ -207,6 +208,9 @@
     static final boolean PROFILE_ORIENTATION = false;
     static final boolean localLOGV = DEBUG;
 
+    final static boolean REVERSE_ITERATOR = true;
+    final static boolean FORWARD_ITERATOR = false;
+
     /** How much to multiply the policy's type layer, to reserve room
      * for multiple windows of the same type and Z-ordering adjustment
      * with TYPE_LAYER_OFFSET. */
@@ -421,6 +425,8 @@
     private SparseArray<DisplayContent> mTaskIdToDisplayContents =
             new SparseArray<DisplayContent>();
 
+    private final AllWindowsIterator mTmpWindowsIterator = new AllWindowsIterator();
+
     int mRotation = 0;
     int mForcedAppOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
     boolean mAltOrientation = false;
@@ -781,11 +787,11 @@
         // Add ourself to the Watchdog monitors.
         Watchdog.getInstance().addMonitor(this);
 
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             createWatermarkInTransaction();
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
         }
     }
 
@@ -888,7 +894,6 @@
         final WindowList windows = win.getWindowList();
         final int N = windows.size();
         final WindowState attached = win.mAttachedWindow;
-        int i;
         WindowList tokenWindowList = getTokenWindowsOnDisplay(token, displayContent);
         if (attached == null) {
             int tokenWindowsPos = 0;
@@ -938,13 +943,11 @@
                         + client.asBinder() + " (token=" + token + ")");
                     // Figure out where the window should go, based on the
                     // order of applications.
-                    AppTokenList animatingAppTokens = displayContent.mAnimatingAppTokens;
-                    final int NA = animatingAppTokens.size();
                     WindowState pos = null;
-                    for (i=NA-1; i>=0; i--) {
-                        AppWindowToken t = animatingAppTokens.get(i);
+                    AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
+                    while (iterator.hasNext()) {
+                        AppWindowToken t = iterator.next();
                         if (t == token) {
-                            i--;
                             break;
                         }
 
@@ -977,15 +980,14 @@
                     } else {
                         // Continue looking down until we find the first
                         // token that has windows on this display.
-                        while (i >= 0) {
-                            AppWindowToken t = animatingAppTokens.get(i);
+                        while (iterator.hasNext()) {
+                            AppWindowToken t = iterator.next();
                             tokenWindowList = getTokenWindowsOnDisplay(t, displayContent);
                             final int NW = tokenWindowList.size();
                             if (NW > 0) {
                                 pos = tokenWindowList.get(NW-1);
                                 break;
                             }
-                            i--;
                         }
                         if (pos != null) {
                             // Move in front of any windows attached to this
@@ -1004,7 +1006,8 @@
                         } else {
                             // Just search for the start of this layer.
                             final int myLayer = win.mBaseLayer;
-                            for (i=0; i<N; i++) {
+                            int i;
+                            for (i = 0; i < N; i++) {
                                 WindowState w = windows.get(i);
                                 if (w.mBaseLayer > myLayer) {
                                     break;
@@ -1022,7 +1025,8 @@
             } else {
                 // Figure out where window should go, based on layer.
                 final int myLayer = win.mBaseLayer;
-                for (i=N-1; i>=0; i--) {
+                int i;
+                for (i = N - 1; i >= 0; i--) {
                     if (windows.get(i).mBaseLayer <= myLayer) {
                         break;
                     }
@@ -1047,7 +1051,8 @@
             final int sublayer = win.mSubLayer;
             int largestSublayer = Integer.MIN_VALUE;
             WindowState windowWithLargestSublayer = null;
-            for (i=0; i<NA; i++) {
+            int i;
+            for (i = 0; i < NA; i++) {
                 WindowState w = tokenWindowList.get(i);
                 final int wSublayer = w.mSubLayer;
                 if (wSublayer >= largestSublayer) {
@@ -2452,9 +2457,9 @@
 
     public void updateAppOpsState() {
         synchronized(mWindowMap) {
-            AllWindowsIterator iterator = new AllWindowsIterator();
-            while (iterator.hasNext()) {
-                final WindowState win = iterator.next();
+            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+            while (mTmpWindowsIterator.hasNext()) {
+                final WindowState win = mTmpWindowsIterator.next();
                 if (win.mAppOp != AppOpsManager.OP_NONE) {
                     final int mode = mAppOps.checkOpNoThrow(win.mAppOp, win.getOwningUid(),
                             win.getOwningPackage());
@@ -2473,7 +2478,7 @@
         }
     }
 
-    static void logSurface(Surface s, String title, String msg, RuntimeException where) {
+    static void logSurface(SurfaceControl s, String title, String msg, RuntimeException where) {
         String str = "  SURFACE " + s + ": " + msg + " / " + title;
         if (where != null) {
             Slog.i(TAG, str, where);
@@ -2770,7 +2775,7 @@
                     if (!win.mHasSurface) {
                         surfaceChanged = true;
                     }
-                    Surface surface = winAnimator.createSurfaceLocked();
+                    SurfaceControl surface = winAnimator.createSurfaceLocked();
                     if (surface != null) {
                         outSurface.copyFrom(surface);
                         if (SHOW_TRANSACTIONS) Slog.i(TAG,
@@ -3100,54 +3105,56 @@
     // -------------------------------------------------------------
 
     public void validateAppTokens(List<TaskGroup> tasks) {
-        int t = tasks.size() - 1;
-        if (t < 0) {
-            Slog.w(TAG, "validateAppTokens: empty task list");
-            return;
-        }
-
-        TaskGroup task = tasks.get(0);
-        int taskId = task.taskId;
-        DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
-        if (displayContent == null) {
-            Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
-            return;
-        }
-
-        AppTokenIterator iterator = displayContent.new AppTokenIterator(true);
-        for ( ; t >= 0; --t) {
-            task = tasks.get(t);
-            List<IApplicationToken> tokens = task.tokens;
-            int v = task.tokens.size() - 1;
-
-            DisplayContent lastDisplayContent = displayContent;
-            displayContent = mTaskIdToDisplayContents.get(taskId);
-            if (displayContent != lastDisplayContent) {
-                Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
+        synchronized (mWindowMap) {
+            int t = tasks.size() - 1;
+            if (t < 0) {
+                Slog.w(TAG, "validateAppTokens: empty task list");
                 return;
             }
 
-            while (v >= 0 && iterator.hasNext()) {
-                AppWindowToken atoken = iterator.next();
-                if (atoken.removed) {
-                    continue;
-                }
-                if (tokens.get(v) != atoken.token) {
-                    Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
-                          + " @ " + v + ", internal is " + atoken.token);
-                }
-                v--;
+            TaskGroup task = tasks.get(0);
+            int taskId = task.taskId;
+            DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
+            if (displayContent == null) {
+                Slog.w(TAG, "validateAppTokens: no Display for taskId=" + taskId);
+                return;
             }
-            while (v >= 0) {
-                Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
-                v--;
-            }
-        }
 
-        while (iterator.hasNext()) {
-            AppWindowToken atoken = iterator.next();
-            if (!atoken.removed) {
-                Slog.w(TAG, "Invalid internal atoken: " + atoken.token);
+            AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
+            for ( ; t >= 0; --t) {
+                task = tasks.get(t);
+                List<IApplicationToken> tokens = task.tokens;
+                int v = task.tokens.size() - 1;
+
+                DisplayContent lastDisplayContent = displayContent;
+                displayContent = mTaskIdToDisplayContents.get(taskId);
+                if (displayContent != lastDisplayContent) {
+                    Slog.w(TAG, "validateAppTokens: displayContent changed in TaskGroup list!");
+                    return;
+                }
+
+                while (v >= 0 && iterator.hasNext()) {
+                    AppWindowToken atoken = iterator.next();
+                    if (atoken.removed) {
+                        continue;
+                    }
+                    if (tokens.get(v) != atoken.token) {
+                        Slog.w(TAG, "Tokens out of sync: external is " + tokens.get(v)
+                              + " @ " + v + ", internal is " + atoken.token);
+                    }
+                    v--;
+                }
+                while (v >= 0) {
+                    Slog.w(TAG, "External token not found: " + tokens.get(v) + " @ " + v);
+                    v--;
+                }
+            }
+
+            while (iterator.hasNext()) {
+                AppWindowToken atoken = iterator.next();
+                if (!atoken.removed) {
+                    Slog.w(TAG, "Invalid internal atoken: " + atoken.token);
+                }
             }
         }
     }
@@ -3379,7 +3386,7 @@
         boolean lastFullscreen = false;
         // TODO: Multi window.
         DisplayContent displayContent = getDefaultDisplayContentLocked();
-        AppTokenIterator iterator = displayContent.new AppTokenIterator(true);
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
         while (iterator.hasNext()) {
             AppWindowToken atoken = iterator.next();
 
@@ -4361,7 +4368,7 @@
         while (iterator.hasNext()) {
             DisplayContent displayContent = iterator.next();
             Slog.v(TAG, "  Display " + displayContent.getDisplayId());
-            AppTokenIterator appIterator = displayContent.new AppTokenIterator(true);
+            AppTokenIterator appIterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
             int i = appIterator.size();
             while (appIterator.hasNext()) {
                 Slog.v(TAG, "  #" + --i + ": " + appIterator.next().token);
@@ -4369,82 +4376,15 @@
         }
     }
 
-    void dumpAnimatingAppTokensLocked() {
-        DisplayContentsIterator iterator = new DisplayContentsIterator();
-        while (iterator.hasNext()) {
-            DisplayContent displayContent = iterator.next();
-            Slog.v(TAG, "  Display " + displayContent.getDisplayId());
-            AppTokenList appTokens = displayContent.mAnimatingAppTokens;
-            for (int i=appTokens.size()-1; i>=0; i--) {
-                Slog.v(TAG, "  #" + i + ": " + appTokens.get(i).token);
-            }
-        }
-    }
-
     void dumpWindowsLocked() {
         int i = 0;
-        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
-        while (iterator.hasNext()) {
-            final WindowState w = iterator.next();
+        mTmpWindowsIterator.reset(REVERSE_ITERATOR);
+        while (mTmpWindowsIterator.hasNext()) {
+            final WindowState w = mTmpWindowsIterator.next();
             Slog.v(TAG, "  #" + i++ + ": " + w);
         }
     }
 
-    private int findWindowOffsetLocked(DisplayContent displayContent, int tokenPos) {
-        final WindowList windows = displayContent.getWindowList();
-        final int NW = windows.size();
-
-        if (tokenPos >= displayContent.mAnimatingAppTokens.size()) {
-            int i = NW;
-            while (i > 0) {
-                i--;
-                WindowState win = windows.get(i);
-                if (win.getAppToken() != null) {
-                    return i+1;
-                }
-            }
-        }
-
-        final AppTokenList appTokens = displayContent.mAppTokens;
-        while (tokenPos > 0) {
-            // Find the first app token below the new position that has
-            // a window displayed.
-            final AppWindowToken wtoken = appTokens.get(tokenPos-1);
-            if (DEBUG_REORDER) Slog.v(TAG, "Looking for lower windows @ "
-                    + tokenPos + " -- " + wtoken.token);
-            if (wtoken.sendingToBottom) {
-                if (DEBUG_REORDER) Slog.v(TAG,
-                        "Skipping token -- currently sending to bottom");
-                tokenPos--;
-                continue;
-            }
-            for (int i = wtoken.windows.size() - 1; i >= 0; --i) {
-                WindowState win = wtoken.windows.get(i);
-                for (int j = win.mChildWindows.size() - 1; j >= 0; --j) {
-                    WindowState cwin = win.mChildWindows.get(j);
-                    if (cwin.mSubLayer >= 0) {
-                        for (int pos = NW - 1; pos >= 0; pos--) {
-                            if (windows.get(pos) == cwin) {
-                                if (DEBUG_REORDER) Slog.v(TAG,
-                                        "Found child win @" + (pos + 1));
-                                return pos + 1;
-                            }
-                        }
-                    }
-                }
-                for (int pos = NW - 1; pos >= 0; pos--) {
-                    if (windows.get(pos) == win) {
-                        if (DEBUG_REORDER) Slog.v(TAG, "Found win @" + (pos + 1));
-                        return pos + 1;
-                    }
-                }
-            }
-            tokenPos--;
-        }
-
-        return 0;
-    }
-
     private int findAppWindowInsertionPointLocked(AppWindowToken target) {
         final int taskId = target.groupId;
         DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
@@ -4455,7 +4395,7 @@
         final WindowList windows = displayContent.getWindowList();
         final int NW = windows.size();
 
-        AppTokenIterator iterator = displayContent.new AppTokenIterator(true);
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
         while (iterator.hasNext()) {
             if (iterator.next() == target) {
                 break;
@@ -4540,215 +4480,6 @@
         return index;
     }
 
-    @Override
-    public void moveAppToken(int index, IBinder token) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "moveAppToken()")) {
-            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
-        }
-
-        synchronized(mWindowMap) {
-            if (DEBUG_REORDER) Slog.v(TAG, "Initial app tokens:");
-            if (DEBUG_REORDER) dumpAppTokensLocked();
-            final AppWindowToken wtoken = findAppWindowToken(token);
-            DisplayContent displayContent = mTaskIdToDisplayContents.get(wtoken.groupId);
-            final AppTokenList appTokens = displayContent.mAppTokens;
-            final int oldIndex = appTokens.indexOf(wtoken);
-            if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) Slog.v(TAG,
-                    "Start moving token " + wtoken + " initially at "
-                    + oldIndex);
-            if (oldIndex > index && mAppTransition.isTransitionSet()) {
-                // animation towards back has not started, copy old list for duration of animation.
-                displayContent.refillAnimatingAppTokens();
-            }
-            if (wtoken == null || !appTokens.remove(wtoken)) {
-                Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
-                      + token + " (" + wtoken + ")");
-                return;
-            }
-            appTokens.add(index, wtoken);
-            if (DEBUG_REORDER) Slog.v(TAG, "Moved " + token + " to " + index + ":");
-            else if (DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Moved " + token + " to " + index);
-            if (DEBUG_REORDER) dumpAppTokensLocked();
-            if (!mAppTransition.isTransitionSet()) {
-                // Not animating, bring animating app list in line with mAppTokens.
-                displayContent.refillAnimatingAppTokens();
-
-                // Bring window ordering, window focus and input window in line with new app token
-                final long origId = Binder.clearCallingIdentity();
-                if (DEBUG_REORDER) Slog.v(TAG, "Removing windows in " + token + ":");
-                if (DEBUG_REORDER) dumpWindowsLocked();
-                if (tmpRemoveAppWindowsLocked(wtoken)) {
-                    if (DEBUG_REORDER) Slog.v(TAG, "Adding windows back in:");
-                    if (DEBUG_REORDER) dumpWindowsLocked();
-                    DisplayContentsIterator iterator = new DisplayContentsIterator();
-                    while(iterator.hasNext()) {
-                        displayContent = iterator.next();
-                        final int pos = findWindowOffsetLocked(displayContent, index);
-                        final int newPos = reAddAppWindowsLocked(displayContent, pos, wtoken);
-                        if (pos != newPos) {
-                            displayContent.layoutNeeded = true;
-                        }
-                    }
-                    if (DEBUG_REORDER) Slog.v(TAG, "Final window list:");
-                    if (DEBUG_REORDER) dumpWindowsLocked();
-                    updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-                            false /*updateInputWindows*/);
-                    mInputMonitor.setUpdateInputWindowsNeededLw();
-                    performLayoutAndPlaceSurfacesLocked();
-                    mInputMonitor.updateInputWindowsLw(false /*force*/);
-                }
-                Binder.restoreCallingIdentity(origId);
-            }
-        }
-    }
-
-    private void removeAppTokensLocked(List<IBinder> tokens) {
-        // XXX This should be done more efficiently!
-        // (take advantage of the fact that both lists should be
-        // ordered in the same way.)
-        int N = tokens.size();
-        for (int i=0; i<N; i++) {
-            IBinder token = tokens.get(i);
-            final AppWindowToken wtoken = findAppWindowToken(token);
-            if (wtoken != null) {
-                final DisplayContent displayContent = mTaskIdToDisplayContents.get(wtoken.groupId);
-                if (DEBUG_REORDER || DEBUG_TOKEN_MOVEMENT) Slog.v(TAG, "Temporarily removing "
-                        + wtoken);
-                if (!displayContent.mAppTokens.remove(wtoken)) {
-                    Slog.w(TAG, "Attempting to reorder token that doesn't exist: "
-                            + token + " (" + wtoken + ")");
-                    i--;
-                    N--;
-                }
-            }
-        }
-    }
-
-    WindowList mSavedWindows;
-    private void moveAppWindowsLocked(List<IBinder> tokens, DisplayContent displayContent,
-            int tokenPos) {
-        if (DEBUG_TASK_MOVEMENT) {
-            mSavedWindows = new WindowList(displayContent.getWindowList());
-        }
-        // First remove all of the windows from the list.
-        final int N = tokens.size();
-        int i;
-        for (i=0; i<N; i++) {
-            WindowToken token = mTokenMap.get(tokens.get(i));
-            if (token != null) {
-                tmpRemoveAppWindowsLocked(token);
-            }
-        }
-
-        // And now add them back at the correct place.
-        // Where to start adding?
-        int pos = findWindowOffsetLocked(displayContent, tokenPos);
-        for (i=0; i<N; i++) {
-            WindowToken token = mTokenMap.get(tokens.get(i));
-            if (token != null) {
-                final int newPos = reAddAppWindowsLocked(displayContent, pos, token);
-                if (newPos != pos) {
-                    displayContent.layoutNeeded = true;
-                }
-                pos = newPos;
-            }
-        }
-        if (!updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
-            false /*updateInputWindows*/)) {
-            assignLayersLocked(displayContent.getWindowList());
-        }
-
-        mInputMonitor.setUpdateInputWindowsNeededLw();
-
-        // Note that the above updateFocusedWindowLocked used to sit here.
-
-        performLayoutAndPlaceSurfacesLocked();
-        mInputMonitor.updateInputWindowsLw(false /*force*/);
-
-        //dump();
-    }
-
-    @Override
-    public void moveAppTokensToTop(List<IBinder> tokens) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "moveAppTokensToTop()")) {
-            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
-        }
-
-        final long origId = Binder.clearCallingIdentity();
-        synchronized(mWindowMap) {
-            DisplayContent displayContent = null;
-            removeAppTokensLocked(tokens);
-            final int N = tokens.size();
-            for (int i=0; i<N; i++) {
-                AppWindowToken wt = findAppWindowToken(tokens.get(i));
-                if (wt != null) {
-                    if (DEBUG_TOKEN_MOVEMENT || DEBUG_REORDER) {
-                        Slog.v(TAG, "Adding next to top: " + wt);
-                        if (displayContent != null &&
-                                displayContent != mTaskIdToDisplayContents.get(wt.groupId)) Slog.e(
-                                    TAG, "moveAppTokensToTop: Not all tokens on same display");
-                    }
-                    displayContent = mTaskIdToDisplayContents.get(wt.groupId);
-                    displayContent.mAppTokens.add(wt);
-                    if (mAppTransition.isTransitionSet()) {
-                        wt.sendingToBottom = false;
-                    }
-                }
-            }
-
-            displayContent.refillAnimatingAppTokens();
-            moveAppWindowsLocked(tokens, displayContent, displayContent.mAppTokens.size());
-        }
-        Binder.restoreCallingIdentity(origId);
-    }
-
-    @Override
-    public void moveAppTokensToBottom(List<IBinder> tokens) {
-        if (!checkCallingPermission(android.Manifest.permission.MANAGE_APP_TOKENS,
-                "moveAppTokensToBottom()")) {
-            throw new SecurityException("Requires MANAGE_APP_TOKENS permission");
-        }
-
-        final long origId = Binder.clearCallingIdentity();
-        synchronized(mWindowMap) {
-            DisplayContent displayContent = null;
-            final int N = tokens.size();
-            if (N > 0) {
-                // animating towards back, hang onto old list for duration of animation.
-                AppWindowToken wt = findAppWindowToken(tokens.get(0));
-                if (wt != null) {
-                    displayContent = mTaskIdToDisplayContents.get(wt.groupId);
-                    displayContent.refillAnimatingAppTokens();
-                }
-            }
-            removeAppTokensLocked(tokens);
-            int pos = 0;
-            for (int i=0; i<N; i++) {
-                AppWindowToken wt = findAppWindowToken(tokens.get(i));
-                if (wt != null) {
-                    if (DEBUG_TOKEN_MOVEMENT) {
-                        Slog.v(TAG, "Adding next to bottom: " + wt + " at " + pos);
-                        if (displayContent != null &&
-                                displayContent != mTaskIdToDisplayContents.get(wt.groupId)) Slog.e(
-                                    TAG, "moveAppTokensToBottom: Not all tokens on same display");
-                    }
-                    displayContent = mTaskIdToDisplayContents.get(wt.groupId);
-                    displayContent.mAppTokens.add(pos, wt);
-                    if (mAppTransition.isTransitionSet()) {
-                        wt.sendingToBottom = true;
-                    }
-                    pos++;
-                }
-            }
-
-            displayContent.refillAnimatingAppTokens();
-            moveAppWindowsLocked(tokens, displayContent, 0);
-        }
-        Binder.restoreCallingIdentity(origId);
-    }
-
     private void moveTaskWindowsLocked(int taskId) {
         DisplayContent displayContent = mTaskIdToDisplayContents.get(taskId);
         if (displayContent == null) {
@@ -4756,15 +4487,6 @@
             return;
         }
 
-        WindowList windows;
-        WindowList windowsAtStart;
-        if (DEBUG_TASK_MOVEMENT) {
-            windows = displayContent.getWindowList();
-            windowsAtStart = new WindowList(windows);
-            windows.clear();
-            windows.addAll(mSavedWindows);
-        }
-
         TaskList taskList = displayContent.mTaskIdToTaskList.get(taskId);
         if (taskList == null) {
             Slog.w(TAG, "moveTaskWindowsLocked: can't find TaskList for taskId=" + taskId);
@@ -4793,19 +4515,6 @@
             assignLayersLocked(displayContent.getWindowList());
         }
 
-        if (DEBUG_TASK_MOVEMENT) {
-            // Compare windowsAtStart with current windows.
-            if (windowsAtStart.size() != windows.size()) {
-                Slog.e(TAG, "moveTaskWindowsLocked: Mismatch in size!");
-            }
-            for (int i = 0; i < windowsAtStart.size(); i++) {
-                if (windowsAtStart.get(i) != windows.get(i)) {
-                    Slog.e(TAG, "moveTaskWindowsLocked: Mismatch at " + i
-                            + " app=" + windowsAtStart.get(i) + " task=" + windows.get(i));
-                }
-            }
-        }
-
         updateFocusedWindowLocked(UPDATE_FOCUS_WILL_PLACE_SURFACES,
                 false /*updateInputWindows*/);
         mInputMonitor.setUpdateInputWindowsNeededLw();
@@ -4835,9 +4544,7 @@
                     Slog.e(TAG, "moveTaskToTop: taskId=" + taskId + " not found in mTaskLists");
                 }
                 displayContent.mTaskLists.add(taskList);
-                displayContent.verifyAppTokens();
 
-                displayContent.refillAnimatingAppTokens();
                 moveTaskWindowsLocked(taskId);
             }
         } finally {
@@ -4865,9 +4572,7 @@
                     Slog.e(TAG, "moveTaskToBottom: taskId=" + taskId + " not found in mTaskLists");
                 }
                 displayContent.mTaskLists.add(0, taskList);
-                displayContent.verifyAppTokens();
 
-                displayContent.refillAnimatingAppTokens();
                 moveTaskWindowsLocked(taskId);
             }
         } finally {
@@ -4993,9 +4698,9 @@
     @Override
     public void closeSystemDialogs(String reason) {
         synchronized(mWindowMap) {
-            final AllWindowsIterator iterator = new AllWindowsIterator();
-            while (iterator.hasNext()) {
-                final WindowState w = iterator.next();
+            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+            while (mTmpWindowsIterator.hasNext()) {
+                final WindowState w = mTmpWindowsIterator.next();
                 if (w.mHasSurface) {
                     try {
                         w.mClient.closeSystemDialogs(reason);
@@ -5389,9 +5094,9 @@
             // the background..)
             if (on) {
                 boolean isVisible = false;
-                final AllWindowsIterator iterator = new AllWindowsIterator();
-                while (iterator.hasNext()) {
-                    final WindowState ws = iterator.next();
+                mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+                while (mTmpWindowsIterator.hasNext()) {
+                    final WindowState ws = mTmpWindowsIterator.next();
                     if (ws.mSession.mPid == pid && ws.isVisibleLw()) {
                         isVisible = true;
                         break;
@@ -5404,7 +5109,7 @@
 
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     ">>> OPEN TRANSACTION showStrictModeViolation");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 // TODO(multi-display): support multiple displays
                 if (mStrictModeFlash == null) {
@@ -5413,7 +5118,7 @@
                 }
                 mStrictModeFlash.setVisibility(on);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                         "<<< CLOSE TRANSACTION showStrictModeViolation");
             }
@@ -5568,7 +5273,7 @@
                             + " surfaceLayer=" + win.mWinAnimator.mSurfaceLayer);
                 }
             }
-            rawss = Surface.screenshot(dw, dh, 0, maxLayer);
+            rawss = SurfaceControl.screenshot(dw, dh, 0, maxLayer);
         }
 
         if (rawss == null) {
@@ -5778,7 +5483,7 @@
             if (SHOW_TRANSACTIONS) {
                 Slog.i(TAG, ">>> OPEN TRANSACTION setRotationUnchecked");
             }
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
         }
         try {
             // NOTE: We disable the rotation in the emulator because
@@ -5796,7 +5501,7 @@
             mDisplayManagerService.performTraversalInTransactionFromWindowManager();
         } finally {
             if (!inTransaction) {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) {
                     Slog.i(TAG, "<<< CLOSE TRANSACTION setRotationUnchecked");
                 }
@@ -6267,9 +5972,9 @@
         }
 
         synchronized (mWindowMap) {
-            final AllWindowsIterator iterator = new AllWindowsIterator();
-            while (iterator.hasNext()) {
-                final WindowState w = iterator.next();
+            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+            while (mTmpWindowsIterator.hasNext()) {
+                final WindowState w = mTmpWindowsIterator.next();
                 if (System.identityHashCode(w) == hashCode) {
                     return w;
                 }
@@ -6618,8 +6323,8 @@
                         // TODO(multi-display): support other displays
                         final DisplayContent displayContent = getDefaultDisplayContentLocked();
                         final Display display = displayContent.getDisplay();
-                        Surface surface = new Surface(session, "drag surface",
-                                width, height, PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                        SurfaceControl surface = new SurfaceControl(session, "drag surface",
+                                width, height, PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
                         surface.setLayerStack(display.getLayerStack());
                         if (SHOW_TRANSACTIONS) Slog.i(TAG, "  DRAG "
                                 + surface + ": CREATE");
@@ -6636,7 +6341,7 @@
                     } else {
                         Slog.w(TAG, "Drag already in progress");
                     }
-                } catch (Surface.OutOfResourcesException e) {
+                } catch (SurfaceControl.OutOfResourcesException e) {
                     Slog.e(TAG, "Can't allocate drag surface w=" + width + " h=" + height, e);
                     if (mDragState != null) {
                         mDragState.reset();
@@ -6818,10 +6523,10 @@
     // TODO(multidisplay): Call isScreenOn for each display.
     private void sendScreenStatusToClientsLocked() {
         final boolean on = mPowerManager.isScreenOn();
-        final AllWindowsIterator iterator = new AllWindowsIterator();
-        while (iterator.hasNext()) {
+        mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+        while (mTmpWindowsIterator.hasNext()) {
             try {
-                iterator.next().mClient.dispatchScreenState(on);
+                mTmpWindowsIterator.next().mClient.dispatchScreenState(on);
             } catch (RemoteException e) {
                 // Ignored
             }
@@ -7117,7 +6822,6 @@
                         if (mAppTransition.isTransitionSet()) {
                             if (DEBUG_APP_TRANSITIONS) Slog.v(TAG, "*** APP TRANSITION TIMEOUT");
                             mAppTransition.setTimeout();
-                            getDefaultDisplayContentLocked().refillAnimatingAppTokens();
                             performLayoutAndPlaceSurfacesLocked();
                         }
                     }
@@ -7163,7 +6867,8 @@
                     synchronized (mWindowMap) {
                         Slog.w(TAG, "App freeze timeout expired.");
                         DisplayContent displayContent = getDefaultDisplayContentLocked();
-                        AppTokenIterator iterator = displayContent.new AppTokenIterator(true);
+                        AppTokenIterator iterator =
+                                displayContent.getTmpAppIterator(REVERSE_ITERATOR);
                         while (iterator.hasNext()) {
                             AppWindowToken tok = iterator.next();
                             if (tok.mAppAnimator.freezingScreen) {
@@ -7626,10 +7331,9 @@
         }
 
         // And add in the still active app tokens in Z order.
-        AppTokenList animatingAppTokens = displayContent.mAnimatingAppTokens;
-        NT = animatingAppTokens.size();
-        for (int j=0; j<NT; j++) {
-            i = reAddAppWindowsLocked(displayContent, i, animatingAppTokens.get(j));
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
+        while (iterator.hasNext()) {
+            i = reAddAppWindowsLocked(displayContent, i, iterator.next());
         }
 
         i -= lastBelow;
@@ -7649,7 +7353,7 @@
                 }
             }
             Slog.w(TAG, "Current app token list:");
-            dumpAnimatingAppTokensLocked();
+            dumpAppTokensLocked();
             Slog.w(TAG, "Final window list:");
             dumpWindowsLocked();
         }
@@ -8231,10 +7935,10 @@
                     // TODO(multi-display): support other displays
                     final DisplayContent displayContent = getDefaultDisplayContentLocked();
                     final Display display = displayContent.getDisplay();
-                    Surface surface = new Surface(mFxSession,
+                    SurfaceControl surface = new SurfaceControl(mFxSession,
                             "thumbnail anim",
                             dirty.width(), dirty.height(),
-                            PixelFormat.TRANSLUCENT, Surface.HIDDEN);
+                            PixelFormat.TRANSLUCENT, SurfaceControl.HIDDEN);
                     surface.setLayerStack(display.getLayerStack());
                     appAnimator.thumbnail = surface;
                     if (SHOW_TRANSACTIONS) Slog.i(TAG, "  THUMBNAIL " + surface + ": CREATE");
@@ -8255,10 +7959,14 @@
                     mAppTransition.getStartingPoint(p);
                     appAnimator.thumbnailX = p.x;
                     appAnimator.thumbnailY = p.y;
-                } catch (Surface.OutOfResourcesException e) {
+                } catch (SurfaceControl.OutOfResourcesException e) {
                     Slog.e(TAG, "Can't allocate thumbnail surface w=" + dirty.width()
                             + " h=" + dirty.height(), e);
                     appAnimator.clearThumbnail();
+                } catch (Surface.OutOfResourcesException e) {
+                    Slog.e(TAG, "Can't allocate Canvas surface w=" + dirty.width()
+                            + " h=" + dirty.height(), e);
+                    appAnimator.clearThumbnail();
                 }
             }
 
@@ -8296,11 +8004,10 @@
         mAppTransition.setIdle();
         // Restore window app tokens to the ActivityManager views
         final DisplayContent displayContent = getDefaultDisplayContentLocked();
-        final AppTokenList animatingAppTokens = displayContent.mAnimatingAppTokens;
-        for (int i = animatingAppTokens.size() - 1; i >= 0; i--) {
-            animatingAppTokens.get(i).sendingToBottom = false;
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
+        while (iterator.hasNext()) {
+            iterator.next().sendingToBottom = false;
         }
-        displayContent.refillAnimatingAppTokens();
         rebuildAppWindowListLocked();
 
         changes |= PhoneWindowManager.FINISH_LAYOUT_REDO_LAYOUT;
@@ -8457,10 +8164,9 @@
     private void updateAllDrawnLocked(DisplayContent displayContent) {
         // See if any windows have been drawn, so they (and others
         // associated with them) can now be shown.
-        final AppTokenList appTokens = displayContent.mAnimatingAppTokens;
-        final int NT = appTokens.size();
-        for (int i=0; i<NT; i++) {
-            AppWindowToken wtoken = appTokens.get(i);
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(FORWARD_ITERATOR);
+        while (iterator.hasNext()) {
+            AppWindowToken wtoken = iterator.next();
             if (!wtoken.allDrawn) {
                 int numInteresting = wtoken.numInterestingWindows;
                 if (numInteresting > 0 && wtoken.numDrawnWindows >= numInteresting) {
@@ -8520,7 +8226,7 @@
 
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                 ">>> OPEN TRANSACTION performLayoutAndPlaceSurfaces");
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
 
             if (mWatermark != null) {
@@ -8795,7 +8501,7 @@
         } catch (RuntimeException e) {
             Log.wtf(TAG, "Unhandled exception in Window Manager", e);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     "<<< CLOSE TRANSACTION performLayoutAndPlaceSurfaces");
         }
@@ -9208,7 +8914,7 @@
 
     boolean reclaimSomeSurfaceMemoryLocked(WindowStateAnimator winAnimator, String operation,
                                            boolean secure) {
-        final Surface surface = winAnimator.mSurface;
+        final SurfaceControl surface = winAnimator.mSurface;
         boolean leakedSurface = false;
         boolean killedApps = false;
 
@@ -9225,10 +8931,10 @@
             // window list to make sure we haven't left any dangling surfaces
             // around.
 
-            AllWindowsIterator iterator = new AllWindowsIterator();
+            mTmpWindowsIterator.reset(FORWARD_ITERATOR);
             Slog.i(TAG, "Out of memory for surface!  Looking for leaks...");
-            while (iterator.hasNext()) {
-                WindowState ws = iterator.next();
+            while (mTmpWindowsIterator.hasNext()) {
+                WindowState ws = mTmpWindowsIterator.next();
                 WindowStateAnimator wsa = ws.mWinAnimator;
                 if (wsa.mSurface != null) {
                     if (!mSessions.contains(wsa.mSession)) {
@@ -9261,9 +8967,9 @@
             if (!leakedSurface) {
                 Slog.w(TAG, "No leaked surfaces; killing applicatons!");
                 SparseIntArray pidCandidates = new SparseIntArray();
-                iterator = new AllWindowsIterator();
-                while (iterator.hasNext()) {
-                    WindowState ws = iterator.next();
+                mTmpWindowsIterator.reset(FORWARD_ITERATOR);
+                while (mTmpWindowsIterator.hasNext()) {
+                    WindowState ws = mTmpWindowsIterator.next();
                     if (mForceRemoves.contains(ws)) {
                         continue;
                     }
@@ -9389,7 +9095,7 @@
     }
 
     private WindowState findFocusedWindowLocked(DisplayContent displayContent) {
-        AppTokenIterator iterator = displayContent.new AppTokenIterator(true);
+        AppTokenIterator iterator = displayContent.getTmpAppIterator(REVERSE_ITERATOR);
         WindowToken nextApp = iterator.hasNext() ? iterator.next() : null;
 
         final WindowList windows = displayContent.getWindowList();
@@ -9821,23 +9527,6 @@
                 }
             }
         }
-        final AppTokenList animatingAppTokens =
-                getDefaultDisplayContentLocked().mAnimatingAppTokens;
-        if (mAppTransition.isRunning() && animatingAppTokens.size() > 0) {
-            pw.println();
-            pw.println("  Application tokens during animation:");
-            for (int i=animatingAppTokens.size()-1; i>=0; i--) {
-                WindowToken token = animatingAppTokens.get(i);
-                pw.print("  App moving to bottom #"); pw.print(i);
-                        pw.print(' '); pw.print(token);
-                if (dumpAll) {
-                    pw.println(':');
-                    token.dump(pw, "    ");
-                } else {
-                    pw.println();
-                }
-            }
-        }
         if (mOpeningApps.size() > 0 || mClosingApps.size() > 0) {
             pw.println();
             if (mOpeningApps.size() > 0) {
@@ -9870,9 +9559,9 @@
     void dumpWindowsNoHeaderLocked(PrintWriter pw, boolean dumpAll,
             ArrayList<WindowState> windows) {
         int j = 0;
-        final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
-        while (iterator.hasNext()) {
-            final WindowState w = iterator.next();
+        mTmpWindowsIterator.reset(REVERSE_ITERATOR);
+        while (mTmpWindowsIterator.hasNext()) {
+            final WindowState w = mTmpWindowsIterator.next();
             if (windows == null || windows.contains(w)) {
                 pw.print("  Window #"); pw.print(j++); pw.print(' ');
                         pw.print(w); pw.println(":");
@@ -10067,9 +9756,9 @@
         WindowList windows = new WindowList();
         if ("visible".equals(name)) {
             synchronized(mWindowMap) {
-                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
-                while (iterator.hasNext()) {
-                    final WindowState w = iterator.next();
+                mTmpWindowsIterator.reset(REVERSE_ITERATOR);
+                while (mTmpWindowsIterator.hasNext()) {
+                    final WindowState w = mTmpWindowsIterator.next();
                     if (w.mWinAnimator.mSurfaceShown) {
                         windows.add(w);
                     }
@@ -10084,9 +9773,9 @@
             } catch (RuntimeException e) {
             }
             synchronized(mWindowMap) {
-                final AllWindowsIterator iterator = new AllWindowsIterator(REVERSE_ITERATOR);
-                while (iterator.hasNext()) {
-                    final WindowState w = iterator.next();
+                mTmpWindowsIterator.reset(REVERSE_ITERATOR);
+                while (mTmpWindowsIterator.hasNext()) {
+                    final WindowState w = mTmpWindowsIterator.next();
                     if (name != null) {
                         if (w.mAttrs.getTitle().toString().contains(name)) {
                             windows.add(w);
@@ -10313,6 +10002,10 @@
     class DisplayContentsIterator implements Iterator<DisplayContent> {
         private int cur;
 
+        void reset() {
+            cur = 0;
+        }
+
         @Override
         public boolean hasNext() {
             return cur < mDisplayContents.size();
@@ -10332,7 +10025,6 @@
         }
     }
 
-    final static boolean REVERSE_ITERATOR = true;
     class AllWindowsIterator implements Iterator<WindowState> {
         private DisplayContent mDisplayContent;
         private DisplayContentsIterator mDisplayContentsIterator;
@@ -10341,19 +10033,33 @@
         private boolean mReverse;
 
         AllWindowsIterator() {
-            mDisplayContentsIterator = new DisplayContentsIterator();
-            mDisplayContent = mDisplayContentsIterator.next();
-            mWindowList = mDisplayContent.getWindowList();
+            this(false);
         }
 
         AllWindowsIterator(boolean reverse) {
-            this();
+            mDisplayContentsIterator = new DisplayContentsIterator();
+            reset(reverse);
+        }
+
+        void reset(boolean reverse) {
             mReverse = reverse;
-            mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
+            mDisplayContentsIterator.reset();
+            if (mDisplayContentsIterator.hasNext()) {
+                mDisplayContent = mDisplayContentsIterator.next();
+                mWindowList = mDisplayContent.getWindowList();
+                mWindowListIndex = reverse ? mWindowList.size() - 1 : 0;
+            } else {
+                mDisplayContent = null;
+                mWindowList = null;
+                mWindowListIndex = 0;
+            }
         }
 
         @Override
         public boolean hasNext() {
+            if (mDisplayContent == null) {
+                return false;
+            }
             if (mReverse) {
                 return mWindowListIndex >= 0;
             }
diff --git a/services/java/com/android/server/wm/WindowStateAnimator.java b/services/java/com/android/server/wm/WindowStateAnimator.java
index a4c6a9e..82e59a8 100644
--- a/services/java/com/android/server/wm/WindowStateAnimator.java
+++ b/services/java/com/android/server/wm/WindowStateAnimator.java
@@ -20,6 +20,7 @@
 import android.view.DisplayInfo;
 import android.view.MagnificationSpec;
 import android.view.Surface;
+import android.view.SurfaceControl;
 import android.view.SurfaceSession;
 import android.view.WindowManager;
 import android.view.WindowManagerPolicy;
@@ -87,8 +88,8 @@
     int mAnimLayer;
     int mLastLayer;
 
-    Surface mSurface;
-    Surface mPendingDestroySurface;
+    SurfaceControl mSurface;
+    SurfaceControl mPendingDestroySurface;
 
     /**
      * Set when we have changed the size of the surface, to know that
@@ -477,7 +478,7 @@
         return true;
     }
 
-    static class SurfaceTrace extends Surface {
+    static class SurfaceTrace extends SurfaceControl {
         private final static String SURFACE_TAG = "SurfaceTrace";
         final static ArrayList<SurfaceTrace> sSurfaces = new ArrayList<SurfaceTrace>();
 
@@ -623,7 +624,7 @@
         }
     }
 
-    Surface createSurfaceLocked() {
+    SurfaceControl createSurfaceLocked() {
         if (mSurface == null) {
             if (DEBUG_ANIM || DEBUG_ORIENTATION) Slog.i(TAG,
                     "createSurface " + this + ": mDrawState=DRAW_PENDING");
@@ -641,11 +642,11 @@
 
             mService.makeWindowFreezingScreenIfNeededLocked(mWin);
 
-            int flags = Surface.HIDDEN;
+            int flags = SurfaceControl.HIDDEN;
             final WindowManager.LayoutParams attrs = mWin.mAttrs;
 
             if ((attrs.flags&WindowManager.LayoutParams.FLAG_SECURE) != 0) {
-                flags |= Surface.SECURE;
+                flags |= SurfaceControl.SECURE;
             }
             if (WindowState.DEBUG_VISIBILITY) Slog.v(
                 TAG, "Creating surface in session "
@@ -681,7 +682,7 @@
                         WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED) != 0;
                 final int format = isHwAccelerated ? PixelFormat.TRANSLUCENT : attrs.format;
                 if (!PixelFormat.formatHasAlpha(attrs.format)) {
-                    flags |= Surface.OPAQUE;
+                    flags |= SurfaceControl.OPAQUE;
                 }
                 if (DEBUG_SURFACE_TRACE) {
                     mSurface = new SurfaceTrace(
@@ -689,7 +690,7 @@
                             attrs.getTitle().toString(),
                             w, h, format, flags);
                 } else {
-                    mSurface = new Surface(
+                    mSurface = new SurfaceControl(
                         mSession.mSurfaceSession,
                         attrs.getTitle().toString(),
                         w, h, format, flags);
@@ -703,7 +704,7 @@
                         + attrs.format + " flags=0x"
                         + Integer.toHexString(flags)
                         + " / " + this);
-            } catch (Surface.OutOfResourcesException e) {
+            } catch (SurfaceControl.OutOfResourcesException e) {
                 mWin.mHasSurface = false;
                 Slog.w(TAG, "OutOfResourcesException creating surface");
                 mService.reclaimSomeSurfaceMemoryLocked(this, "create", true);
@@ -727,7 +728,7 @@
                         + mWin.mCompatFrame.width() + "x" + mWin.mCompatFrame.height()
                         + "), layer=" + mAnimLayer + " HIDE", null);
             }
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 try {
                     mSurfaceX = mWin.mFrame.left + mWin.mXOffset;
@@ -744,7 +745,7 @@
                 }
                 mLastHidden = true;
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                         "<<< CLOSE TRANSACTION createSurfaceLocked");
             }
@@ -1324,13 +1325,13 @@
         }
         if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
             ">>> OPEN TRANSACTION setTransparentRegion");
-        Surface.openTransaction();
+        SurfaceControl.openTransaction();
         try {
             if (SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
                     "transparentRegionHint=" + region, null);
             mSurface.setTransparentRegionHint(region);
         } finally {
-            Surface.closeTransaction();
+            SurfaceControl.closeTransaction();
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     "<<< CLOSE TRANSACTION setTransparentRegion");
         }
@@ -1351,7 +1352,7 @@
             }
             if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                     ">>> OPEN TRANSACTION setWallpaperOffset");
-            Surface.openTransaction();
+            SurfaceControl.openTransaction();
             try {
                 if (WindowManagerService.SHOW_TRANSACTIONS) WindowManagerService.logSurface(mWin,
                         "POS " + left + ", " + top, null);
@@ -1361,7 +1362,7 @@
                 Slog.w(TAG, "Error positioning surface of " + mWin
                         + " pos=(" + left + "," + top + ")", e);
             } finally {
-                Surface.closeTransaction();
+                SurfaceControl.closeTransaction();
                 if (SHOW_LIGHT_TRANSACTIONS) Slog.i(TAG,
                         "<<< CLOSE TRANSACTION setWallpaperOffset");
             }
diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
index 854dd69..69d34a5 100644
--- a/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
+++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BitmapMeshActivity.java
@@ -54,7 +54,7 @@
                 0.0f, height * 2, width, height * 2, width * 2, height * 2, width * 3, height * 2,
                 0.0f, height * 4, width, height * 4, width * 2, height * 4, width * 4, height * 4,
             };
-            
+
             mColors = new int[] {
                 0xffff0000, 0xff00ff00, 0xff0000ff, 0xffff0000,
                 0xff0000ff, 0xffff0000, 0xff00ff00, 0xff00ff00,
diff --git a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
index 746ac06..03871f6 100644
--- a/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
+++ b/tests/permission/src/com/android/framework/permission/tests/WindowManagerPermissionTests.java
@@ -222,37 +222,7 @@
         } catch (RemoteException e) {
             fail("Unexpected remote exception");
         }
-        
-        try {
-            mWm.moveAppToken(0, null);
-            fail("IWindowManager.moveAppToken did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.moveAppTokensToTop(null);
-            fail("IWindowManager.moveAppTokensToTop did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-        
-        try {
-            mWm.moveAppTokensToBottom(null);
-            fail("IWindowManager.moveAppTokensToBottom did not throw SecurityException as"
-                    + " expected");
-        } catch (SecurityException e) {
-            // expected
-        } catch (RemoteException e) {
-            fail("Unexpected remote exception");
-        }
-	}    
+    }
 
     @SmallTest
     public void testDISABLE_KEYGUARD() {
diff --git a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
index 9f116fc..ed44b04 100644
--- a/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
+++ b/tools/layoutlib/bridge/src/android/view/IWindowManagerImpl.java
@@ -204,24 +204,6 @@
     }
 
     @Override
-    public void moveAppToken(int arg0, IBinder arg1) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void moveAppTokensToBottom(List<IBinder> arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
-    public void moveAppTokensToTop(List<IBinder> arg0) throws RemoteException {
-        // TODO Auto-generated method stub
-
-    }
-
-    @Override
     public IWindowSession openSession(IInputMethodClient arg0, IInputContext arg1)
             throws RemoteException {
         // TODO Auto-generated method stub