Merge "ActionBar overlay mode, height fetching, show/hide"
diff --git a/core/java/android/os/Looper.java b/core/java/android/os/Looper.java
index 69b3540..a9d7342 100644
--- a/core/java/android/os/Looper.java
+++ b/core/java/android/os/Looper.java
@@ -180,6 +180,11 @@
         return mThread;
     }
     
+    /** @hide */
+    public MessageQueue getQueue() {
+        return mQueue;
+    }
+    
     public void dump(Printer pw, String prefix) {
         pw.println(prefix + this);
         pw.println(prefix + "mRun=" + mRun);
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index d6b9212..e86e3bf 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -28,6 +28,7 @@
 import android.view.KeyEvent;
 import android.view.InputEvent;
 import android.view.MotionEvent;
+import android.view.InputChannel;
 
 /**
  * System private interface to the window manager.
@@ -119,6 +120,7 @@
     int getKeycodeStateForDevice(int devid, int sw);
     int getTrackballKeycodeState(int sw);
     int getDPadKeycodeState(int sw);
+    InputChannel monitorInput(String inputChannelName);
     
     // Report whether the hardware supports the given keys; returns true if successful
     boolean hasKeys(in int[] keycodes, inout boolean[] keyExists);
diff --git a/core/java/android/view/WindowManagerPolicy.java b/core/java/android/view/WindowManagerPolicy.java
index 33757f0..659f9cd 100644
--- a/core/java/android/view/WindowManagerPolicy.java
+++ b/core/java/android/view/WindowManagerPolicy.java
@@ -779,11 +779,6 @@
      */
     public void enableScreenAfterBoot();
     
-    /**
-     * Called every time the window manager is dispatching a pointer event.
-     */
-    public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY);
-    
     public void setCurrentOrientationLw(int newOrientation);
     
     /**
diff --git a/include/utils/String8.h b/include/utils/String8.h
index 4e41410..ef0b51a 100644
--- a/include/utils/String8.h
+++ b/include/utils/String8.h
@@ -171,7 +171,8 @@
             status_t            append(const char* other);
             status_t            append(const char* other, size_t numChars);
 
-            status_t            appendFormat(const char* fmt, ...);
+            status_t            appendFormat(const char* fmt, ...)
+                    __attribute__((format (printf, 2, 3)));
 
             // Note that this function takes O(N) time to calculate the value.
             // No cache value is stored.
diff --git a/libs/hwui/Program.cpp b/libs/hwui/Program.cpp
index dbae38e..6528d91 100644
--- a/libs/hwui/Program.cpp
+++ b/libs/hwui/Program.cpp
@@ -51,6 +51,8 @@
             LOGE("Error while linking shaders: %s", log);
             delete log;
         }
+        glDeleteShader(vertexShader);
+        glDeleteShader(fragmentShader);
         glDeleteProgram(id);
     }
 
diff --git a/libs/hwui/ProgramCache.h b/libs/hwui/ProgramCache.h
index 54850ee..fa4b8c4 100644
--- a/libs/hwui/ProgramCache.h
+++ b/libs/hwui/ProgramCache.h
@@ -35,7 +35,7 @@
 ///////////////////////////////////////////////////////////////////////////////
 
 // Debug
-#define DEBUG_PROGRAM_CACHE 1
+#define DEBUG_PROGRAM_CACHE 0
 
 // Debug
 #if DEBUG_PROGRAM_CACHE
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index cb7fe06..a07c385 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -37,6 +37,7 @@
 import android.os.Handler;
 import android.os.IBinder;
 import android.os.LocalPowerManager;
+import android.os.Looper;
 import android.os.PowerManager;
 import android.os.RemoteException;
 import android.os.ServiceManager;
@@ -48,15 +49,20 @@
 import com.android.internal.policy.PolicyManager;
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.internal.telephony.ITelephony;
+import com.android.internal.view.BaseInputHandler;
 import com.android.internal.widget.PointerLocationView;
 
 import android.util.Config;
 import android.util.EventLog;
 import android.util.Log;
+import android.util.Slog;
 import android.view.Display;
 import android.view.Gravity;
 import android.view.HapticFeedbackConstants;
 import android.view.IWindowManager;
+import android.view.InputChannel;
+import android.view.InputQueue;
+import android.view.InputHandler;
 import android.view.KeyEvent;
 import android.view.MotionEvent;
 import android.view.WindowOrientationListener;
@@ -221,6 +227,17 @@
     
     int mPointerLocationMode = 0;
     PointerLocationView mPointerLocationView = null;
+    InputChannel mPointerLocationInputChannel;
+    
+    private final InputHandler mPointerLocationInputHandler = new BaseInputHandler() {
+        @Override
+        public void handleMotion(MotionEvent event, Runnable finishedCallback) {
+            finishedCallback.run();
+            synchronized (mLock) {
+                mPointerLocationView.addTouchEvent(event);
+            }
+        }
+    };
     
     // The current size of the screen.
     int mW, mH;
@@ -617,8 +634,26 @@
             WindowManagerImpl wm = (WindowManagerImpl)
                     mContext.getSystemService(Context.WINDOW_SERVICE);
             wm.addView(addView, lp);
+            
+            if (mPointerLocationInputChannel == null) {
+                try {
+                    mPointerLocationInputChannel =
+                        mWindowManager.monitorInput("PointerLocationView");
+                    InputQueue.registerInputChannel(mPointerLocationInputChannel,
+                            mPointerLocationInputHandler, mHandler.getLooper().getQueue());
+                } catch (RemoteException ex) {
+                    Slog.e(TAG, "Could not set up input monitoring channel for PointerLocation.",
+                            ex);
+                }
+            }
         }
         if (removeView != null) {
+            if (mPointerLocationInputChannel != null) {
+                InputQueue.unregisterInputChannel(mPointerLocationInputChannel);
+                mPointerLocationInputChannel.dispose();
+                mPointerLocationInputChannel = null;
+            }
+            
             WindowManagerImpl wm = (WindowManagerImpl)
                     mContext.getSystemService(Context.WINDOW_SERVICE);
             wm.removeView(removeView);
@@ -732,20 +767,6 @@
                 : Configuration.KEYBOARDHIDDEN_YES;
     }
     
-    public void dispatchedPointerEventLw(MotionEvent ev, int targetX, int targetY) {
-        if (mPointerLocationView == null) {
-            return;
-        }
-        synchronized (mLock) {
-            if (mPointerLocationView == null) {
-                return;
-            }
-            ev.offsetLocation(targetX, targetY);
-            mPointerLocationView.addTouchEvent(ev);
-            ev.offsetLocation(-targetX, -targetY);
-        }
-    }
-    
     /** {@inheritDoc} */
     public int windowTypeToLayerLw(int type) {
         if (type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) {
diff --git a/services/java/com/android/server/InputManager.java b/services/java/com/android/server/InputManager.java
index 91951233..c2c799b 100644
--- a/services/java/com/android/server/InputManager.java
+++ b/services/java/com/android/server/InputManager.java
@@ -75,7 +75,8 @@
             int sw);
     private static native boolean nativeHasKeys(int deviceId, int sourceMask,
             int[] keyCodes, boolean[] keyExists);
-    private static native void nativeRegisterInputChannel(InputChannel inputChannel);
+    private static native void nativeRegisterInputChannel(InputChannel inputChannel,
+            boolean monitor);
     private static native void nativeUnregisterInputChannel(InputChannel inputChannel);
     private static native int nativeInjectInputEvent(InputEvent event,
             int injectorPid, int injectorUid, int syncMode, int timeoutMillis);
@@ -225,14 +226,38 @@
         return nativeHasKeys(deviceId, sourceMask, keyCodes, keyExists);
     }
     
+    /**
+     * Creates an input channel that will receive all input from the input dispatcher.
+     * @param inputChannelName The input channel name.
+     * @return The input channel.
+     */
+    public InputChannel monitorInput(String inputChannelName) {
+        if (inputChannelName == null) {
+            throw new IllegalArgumentException("inputChannelName must not be null.");
+        }
+        
+        InputChannel[] inputChannels = InputChannel.openInputChannelPair(inputChannelName);
+        nativeRegisterInputChannel(inputChannels[0], true);
+        inputChannels[0].dispose(); // don't need to retain the Java object reference
+        return inputChannels[1];
+    }
+
+    /**
+     * Registers an input channel so that it can be used as an input event target.
+     * @param inputChannel The input channel to register.
+     */
     public void registerInputChannel(InputChannel inputChannel) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
         }
         
-        nativeRegisterInputChannel(inputChannel);
+        nativeRegisterInputChannel(inputChannel, false);
     }
     
+    /**
+     * Unregisters an input channel.
+     * @param inputChannel The input channel to unregister.
+     */
     public void unregisterInputChannel(InputChannel inputChannel) {
         if (inputChannel == null) {
             throw new IllegalArgumentException("inputChannel must not be null.");
diff --git a/services/java/com/android/server/WindowManagerService.java b/services/java/com/android/server/WindowManagerService.java
index e4ef09c..f952a83 100644
--- a/services/java/com/android/server/WindowManagerService.java
+++ b/services/java/com/android/server/WindowManagerService.java
@@ -4373,11 +4373,19 @@
         }
         return mInputManager.getKeyCodeState(-1, InputDevice.SOURCE_DPAD, sw);
     }
-
+    
     public boolean hasKeys(int[] keycodes, boolean[] keyExists) {
         return mInputManager.hasKeys(-1, InputDevice.SOURCE_ANY, keycodes, keyExists);
     }
 
+    public InputChannel monitorInput(String inputChannelName) {
+        if (!checkCallingPermission(android.Manifest.permission.READ_INPUT_STATE,
+                "monitorInput()")) {
+            throw new SecurityException("Requires READ_INPUT_STATE permission");
+        }
+        return mInputManager.monitorInput(inputChannelName);
+    }
+
     public void enableScreenAfterBoot() {
         synchronized(mWindowMap) {
             if (mSystemBooted) {
diff --git a/services/jni/com_android_server_InputManager.cpp b/services/jni/com_android_server_InputManager.cpp
index 0982b32..ebe71ab 100644
--- a/services/jni/com_android_server_InputManager.cpp
+++ b/services/jni/com_android_server_InputManager.cpp
@@ -213,7 +213,7 @@
     void setDisplayOrientation(int32_t displayId, int32_t orientation);
 
     status_t registerInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel,
-            jweak inputChannelObjWeak);
+            jweak inputChannelObjWeak, bool monitor);
     status_t unregisterInputChannel(JNIEnv* env, const sp<InputChannel>& inputChannel);
 
     void setInputWindows(JNIEnv* env, jobjectArray windowObjArray);
@@ -334,6 +334,7 @@
     bool mWindowsReady;
     Vector<InputWindow> mWindows;
     Vector<InputWindow*> mWallpaperWindows;
+    Vector<sp<InputChannel> > mMonitoringChannels;
 
     // Focus tracking for keys, trackball, etc.
     InputWindow* mFocusedWindow;
@@ -382,6 +383,10 @@
     static void addTarget(const InputWindow* window, int32_t targetFlags,
             nsecs_t timeSpentWaitingForApplication, Vector<InputTarget>& outTargets);
 
+    void registerMonitoringChannel(const sp<InputChannel>& inputChannel);
+    void unregisterMonitoringChannel(const sp<InputChannel>& inputChannel);
+    void addMonitoringTargetsLd(Vector<InputTarget>& outTargets);
+
     static inline JNIEnv* jniEnv() {
         return AndroidRuntime::getJNIEnv();
     }
@@ -492,7 +497,7 @@
 }
 
 status_t NativeInputManager::registerInputChannel(JNIEnv* env,
-        const sp<InputChannel>& inputChannel, jobject inputChannelObj) {
+        const sp<InputChannel>& inputChannel, jobject inputChannelObj, bool monitor) {
     jweak inputChannelObjWeak = env->NewWeakGlobalRef(inputChannelObj);
     if (! inputChannelObjWeak) {
         LOGE("Could not create weak reference for input channel.");
@@ -519,9 +524,14 @@
 
     status = mInputManager->registerInputChannel(inputChannel);
     if (! status) {
+        // Success.
+        if (monitor) {
+            registerMonitoringChannel(inputChannel);
+        }
         return OK;
     }
 
+    // Failed!
     {
         AutoMutex _l(mInputChannelRegistryLock);
         mInputChannelObjWeakByReceiveFd.removeItem(inputChannel->getReceivePipeFd());
@@ -552,6 +562,8 @@
 
     env->DeleteWeakGlobalRef(inputChannelObjWeak);
 
+    unregisterMonitoringChannel(inputChannel);
+
     return mInputManager->unregisterInputChannel(inputChannel);
 }
 
@@ -829,6 +841,8 @@
 
         env->DeleteLocalRef(inputChannelObjLocal);
     }
+
+    unregisterMonitoringChannel(inputChannel);
 }
 
 bool NativeInputManager::notifyInputChannelANR(const sp<InputChannel>& inputChannel,
@@ -1429,7 +1443,9 @@
 
             // If there is no currently touched window then fail.
             if (! mTouchedWindow) {
-                LOGW("Dropping event because there is no touched window to receive it.");
+#if DEBUG_INPUT_DISPATCHER_POLICY
+                LOGD("Dropping event because there is no touched window to receive it.");
+#endif
                 injectionResult = INPUT_EVENT_INJECTION_FAILED;
                 injectionPermission = INJECTION_PERMISSION_GRANTED;
                 break; // failed, exit wait loop
@@ -1587,6 +1603,8 @@
             outTargets.clear();
             return INPUT_EVENT_INJECTION_SUCCEEDED;
         }
+
+        addMonitoringTargetsLd(outTargets);
     }
 
     pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
@@ -1631,6 +1649,8 @@
         }
 
         windowType = focusedWindow->layoutParamsType;
+
+        addMonitoringTargetsLd(outTargets);
     } // release lock
 
     pokeUserActivityIfNeeded(windowType, POWER_MANAGER_BUTTON_EVENT);
@@ -1657,6 +1677,8 @@
         }
 
         windowType = touchedWindow->layoutParamsType;
+
+        addMonitoringTargetsLd(outTargets);
     } // release lock
 
     int32_t eventType;
@@ -1714,6 +1736,39 @@
     android_server_PowerManagerService_userActivity(eventTime, eventType);
 }
 
+void NativeInputManager::registerMonitoringChannel(const sp<InputChannel>& inputChannel) {
+    { // acquire lock
+         AutoMutex _l(mDispatchLock);
+         mMonitoringChannels.push(inputChannel);
+    } // release lock
+}
+
+void NativeInputManager::unregisterMonitoringChannel(const sp<InputChannel>& inputChannel) {
+    { // acquire lock
+         AutoMutex _l(mDispatchLock);
+
+         for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+             if (mMonitoringChannels[i] == inputChannel) {
+                 mMonitoringChannels.removeAt(i);
+                 break;
+             }
+         }
+    } // release lock
+}
+
+void NativeInputManager::addMonitoringTargetsLd(Vector<InputTarget>& outTargets) {
+    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+        outTargets.push();
+
+        InputTarget& target = outTargets.editTop();
+        target.inputChannel = mMonitoringChannels[i];
+        target.flags = 0;
+        target.timeout = -1;
+        target.xOffset = 0;
+        target.yOffset = 0;
+    }
+}
+
 static void dumpMotionRange(String8& dump,
         const char* name, const InputDeviceInfo::MotionRange* range) {
     if (range) {
@@ -1805,6 +1860,11 @@
                 mWindows[i].ownerPid, mWindows[i].ownerUid,
                 mWindows[i].dispatchingTimeout / 1000000.0);
     }
+
+    for (size_t i = 0; i < mMonitoringChannels.size(); i++) {
+        dump.appendFormat("  monitoringChannel[%d]: '%s'\n",
+                i, mMonitoringChannels[i]->getName().string());
+    }
 }
 
 // ----------------------------------------------------------------------------
@@ -2012,7 +2072,7 @@
 }
 
 static void android_server_InputManager_nativeRegisterInputChannel(JNIEnv* env, jclass clazz,
-        jobject inputChannelObj) {
+        jobject inputChannelObj, jboolean monitor) {
     if (checkInputManagerUnitialized(env)) {
         return;
     }
@@ -2026,15 +2086,17 @@
 
 
     status_t status = gNativeInputManager->registerInputChannel(
-            env, inputChannel, inputChannelObj);
+            env, inputChannel, inputChannelObj, monitor);
     if (status) {
         jniThrowRuntimeException(env, "Failed to register input channel.  "
                 "Check logs for details.");
         return;
     }
 
-    android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
-            android_server_InputManager_handleInputChannelDisposed, NULL);
+    if (! monitor) {
+        android_view_InputChannel_setDisposeCallback(env, inputChannelObj,
+                android_server_InputManager_handleInputChannelDisposed, NULL);
+    }
 }
 
 static void android_server_InputManager_nativeUnregisterInputChannel(JNIEnv* env, jclass clazz,
@@ -2149,7 +2211,7 @@
             (void*) android_server_InputManager_nativeGetSwitchState },
     { "nativeHasKeys", "(II[I[Z)Z",
             (void*) android_server_InputManager_nativeHasKeys },
-    { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;)V",
+    { "nativeRegisterInputChannel", "(Landroid/view/InputChannel;Z)V",
             (void*) android_server_InputManager_nativeRegisterInputChannel },
     { "nativeUnregisterInputChannel", "(Landroid/view/InputChannel;)V",
             (void*) android_server_InputManager_nativeUnregisterInputChannel },
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index a14bfb5..79772ed 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -5,6 +5,7 @@
     clz.cpp.arm \
     DisplayHardware/DisplayHardware.cpp \
     DisplayHardware/DisplayHardwareBase.cpp \
+    DisplayHardware/HWComposer.cpp \
     BlurFilter.cpp.arm \
     GLExtensions.cpp \
     Layer.cpp \
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
index 2eac0a8..166c528 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.cpp
@@ -36,11 +36,11 @@
 
 #include "DisplayHardware/DisplayHardware.h"
 
-#include <hardware/copybit.h>
 #include <hardware/overlay.h>
 #include <hardware/gralloc.h>
 
 #include "GLExtensions.h"
+#include "HWComposer.h"
 
 using namespace android;
 
@@ -76,7 +76,7 @@
         const sp<SurfaceFlinger>& flinger,
         uint32_t dpy)
     : DisplayHardwareBase(flinger, dpy),
-      mFlags(0)
+      mFlags(0), mHwc(0)
 {
     init(dpy);
 }
@@ -262,6 +262,17 @@
 
     // Unbind the context from this thread
     eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+
+
+    // initialize the H/W composer
+    mHwc = new HWComposer();
+    if (mHwc->initCheck() == NO_ERROR) {
+        mHwc->setFrameBuffer(mDisplay, mSurface);
+    }
+}
+
+HWComposer& DisplayHardware::getHwComposer() const {
+    return *mHwc;
 }
 
 /*
@@ -317,7 +328,12 @@
     }
     
     mPageFlipCount++;
-    eglSwapBuffers(dpy, surface);
+
+    if (mHwc->initCheck() == NO_ERROR) {
+        mHwc->commit();
+    } else {
+        eglSwapBuffers(dpy, surface);
+    }
     checkEGLErrors("eglSwapBuffers");
 
     // for debugging
diff --git a/services/surfaceflinger/DisplayHardware/DisplayHardware.h b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
index 66bf521..f2cfd2d 100644
--- a/services/surfaceflinger/DisplayHardware/DisplayHardware.h
+++ b/services/surfaceflinger/DisplayHardware/DisplayHardware.h
@@ -34,12 +34,11 @@
 #include "DisplayHardware/DisplayHardwareBase.h"
 
 struct overlay_control_device_t;
-struct framebuffer_device_t;
-struct copybit_image_t;
 
 namespace android {
 
 class FramebufferNativeWindow;
+class HWComposer;
 
 class DisplayHardware : public DisplayHardwareBase
 {
@@ -80,6 +79,9 @@
     uint32_t getPageFlipCount() const;
     EGLDisplay getEGLDisplay() const { return mDisplay; }
     overlay_control_device_t* getOverlayEngine() const { return mOverlayEngine; }
+
+    // Hardware Composer
+    HWComposer& getHwComposer() const;
     
     status_t compositionComplete() const;
     
@@ -107,6 +109,8 @@
     GLint           mMaxViewportDims;
     GLint           mMaxTextureSize;
     
+    HWComposer*     mHwc;
+
     sp<FramebufferNativeWindow> mNativeWindow;
     overlay_control_device_t* mOverlayEngine;
 };
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
new file mode 100644
index 0000000..518c5fe
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <utils/Errors.h>
+
+#include <hardware/hardware.h>
+
+#include <cutils/log.h>
+
+#include <EGL/egl.h>
+
+#include "HWComposer.h"
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+HWComposer::HWComposer()
+    : mModule(0), mHwc(0), mList(0),
+      mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
+{
+    int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
+    LOGW_IF(err, "%s module not found", HWC_HARDWARE_MODULE_ID);
+    if (err == 0) {
+        err = hwc_open(mModule, &mHwc);
+        LOGE_IF(err, "%s device failed to initialize (%s)",
+                HWC_HARDWARE_COMPOSER, strerror(-err));
+    }
+}
+
+HWComposer::~HWComposer() {
+    free(mList);
+    if (mHwc) {
+        hwc_close(mHwc);
+    }
+}
+
+status_t HWComposer::initCheck() const {
+    return mHwc ? NO_ERROR : NO_INIT;
+}
+
+void HWComposer::setFrameBuffer(EGLDisplay dpy, EGLSurface sur) {
+    mDpy = (hwc_display_t)dpy;
+    mSur = (hwc_surface_t)sur;
+}
+
+status_t HWComposer::createWorkList(size_t numLayers) {
+    if (mHwc && (!mList || mList->numHwLayers < numLayers)) {
+        free(mList);
+        size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
+        mList = (hwc_layer_list_t*)malloc(size);
+        mList->flags = HWC_GEOMETRY_CHANGED;
+        mList->numHwLayers = numLayers;
+    }
+    return NO_ERROR;
+}
+
+status_t HWComposer::prepare() const {
+    int err = mHwc->prepare(mHwc, mList);
+    return (status_t)err;
+}
+
+status_t HWComposer::commit() const {
+    int err = mHwc->set(mHwc, mDpy, mSur, mList);
+    mList->flags &= ~HWC_GEOMETRY_CHANGED;
+    return (status_t)err;
+}
+
+HWComposer::iterator HWComposer::begin() {
+    return mList ? &(mList->hwLayers[0]) : NULL;
+}
+
+HWComposer::iterator HWComposer::end() {
+    return mList ? &(mList->hwLayers[mList->numHwLayers]) : NULL;
+}
+
+// ---------------------------------------------------------------------------
+}; // namespace android
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
new file mode 100644
index 0000000..729f23b
--- /dev/null
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ANDROID_SF_HWCOMPOSER_H
+#define ANDROID_SF_HWCOMPOSER_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#include <EGL/egl.h>
+
+#include <hardware/hwcomposer.h>
+
+namespace android {
+// ---------------------------------------------------------------------------
+
+class HWComposer
+{
+public:
+
+    HWComposer();
+    ~HWComposer();
+
+    status_t initCheck() const;
+
+    // tells the HAL what the framebuffer is
+    void setFrameBuffer(EGLDisplay dpy, EGLSurface sur);
+
+    // create a work list for numLayers layer
+    status_t createWorkList(size_t numLayers);
+
+    // Asks the HAL what it can do
+    status_t prepare() const;
+
+    // commits the list
+    status_t commit() const;
+
+
+    typedef hwc_layer_t const * const_iterator;
+    typedef hwc_layer_t* iterator;
+
+    iterator begin();
+    iterator end();
+
+private:
+    hw_module_t const*      mModule;
+    hwc_composer_device_t*  mHwc;
+    hwc_layer_list_t*       mList;
+    hwc_display_t           mDpy;
+    hwc_surface_t           mSur;
+};
+
+
+// ---------------------------------------------------------------------------
+}; // namespace android
+
+#endif // ANDROID_SF_HWCOMPOSER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 629d993..3720e1669 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -35,6 +35,7 @@
 #include "Layer.h"
 #include "SurfaceFlinger.h"
 #include "DisplayHardware/DisplayHardware.h"
+#include "DisplayHardware/HWComposer.h"
 
 
 #define DEBUG_RESIZE    0
@@ -177,6 +178,62 @@
     return NO_ERROR;
 }
 
+void Layer::setGeometry(hwc_layer_t* hwcl)
+{
+    hwcl->compositionType = HWC_FRAMEBUFFER;
+    hwcl->hints = 0;
+    hwcl->flags = 0;
+    hwcl->transform = 0;
+    hwcl->blending = HWC_BLENDING_NONE;
+
+    // we can't do alpha-fade with the hwc HAL
+    const State& s(drawingState());
+    if (s.alpha < 0xFF) {
+        hwcl->flags = HWC_SKIP_LAYER;
+        return;
+    }
+
+    // we can only handle simple transformation
+    if (mOrientation & Transform::ROT_INVALID) {
+        hwcl->flags = HWC_SKIP_LAYER;
+        return;
+    }
+
+    hwcl->transform = mOrientation;
+
+    if (needsBlending()) {
+        hwcl->blending = mPremultipliedAlpha ?
+                HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
+    }
+
+    hwcl->displayFrame.left   = mTransformedBounds.left;
+    hwcl->displayFrame.top    = mTransformedBounds.top;
+    hwcl->displayFrame.right  = mTransformedBounds.right;
+    hwcl->displayFrame.bottom = mTransformedBounds.bottom;
+
+    hwcl->visibleRegionScreen.rects =
+            reinterpret_cast<hwc_rect_t const *>(
+                    visibleRegionScreen.getArray(
+                            &hwcl->visibleRegionScreen.numRects));
+}
+
+void Layer::setPerFrameData(hwc_layer_t* hwcl) {
+    sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
+    if (buffer == NULL) {
+        // this situation can happen if we ran out of memory for instance.
+        // not much we can do. continue to use whatever texture was bound
+        // to this context.
+        hwcl->handle = NULL;
+        return;
+    }
+    hwcl->handle = const_cast<native_handle_t*>(buffer->handle);
+    // TODO: set the crop value properly
+    hwcl->sourceCrop.left   = 0;
+    hwcl->sourceCrop.top    = 0;
+    hwcl->sourceCrop.right  = buffer->width;
+    hwcl->sourceCrop.bottom = buffer->height;
+}
+
 void Layer::reloadTexture(const Region& dirty)
 {
     sp<GraphicBuffer> buffer(mBufferManager.getActiveBuffer());
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index e1d283b..188da6a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -68,6 +68,8 @@
     bool isFixedSize() const;
 
     // LayerBase interface
+    virtual void setGeometry(hwc_layer_t* hwcl);
+    virtual void setPerFrameData(hwc_layer_t* hwcl);
     virtual void onDraw(const Region& clip) const;
     virtual uint32_t doTransaction(uint32_t transactionFlags);
     virtual void lockPageFlip(bool& recomputeVisibleRegions);
diff --git a/services/surfaceflinger/LayerBase.cpp b/services/surfaceflinger/LayerBase.cpp
index d5aa53f..043d54d 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -39,8 +39,11 @@
 
 // ---------------------------------------------------------------------------
 
+int32_t LayerBase::sSequence = 1;
+
 LayerBase::LayerBase(SurfaceFlinger* flinger, DisplayID display)
     : dpy(display), contentDirty(false),
+      sequence(uint32_t(android_atomic_inc(&sSequence))),
       mFlinger(flinger),
       mNeedsFiltering(false),
       mOrientation(0),
@@ -304,22 +307,17 @@
     }
 }
 
-void LayerBase::draw(const Region& inClip) const
+void LayerBase::setGeometry(hwc_layer_t* hwcl) {
+    hwcl->flags |= HWC_SKIP_LAYER;
+}
+
+void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
+    hwcl->compositionType = HWC_FRAMEBUFFER;
+    hwcl->handle = NULL;
+}
+
+void LayerBase::draw(const Region& clip) const
 {
-    // invalidate the region we'll update
-    Region clip(inClip);  // copy-on-write, so no-op most of the time
-
-    // Remove the transparent area from the clipping region
-    const State& s = drawingState();
-    if (LIKELY(!s.transparentRegion.isEmpty())) {
-        clip.subtract(transparentRegionScreen);
-        if (clip.isEmpty()) {
-            // usually this won't happen because this should be taken care of
-            // by SurfaceFlinger::computeVisibleRegions()
-            return;
-        }        
-    }
-
     // reset GL state
     glEnable(GL_SCISSOR_TEST);
 
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index 4288cf7..dd1cd05 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -35,6 +35,8 @@
 
 #include <pixelflinger/pixelflinger.h>
 
+#include <hardware/hwcomposer.h>
+
 #include "Transform.h"
 
 namespace android {
@@ -53,6 +55,8 @@
 
 class LayerBase : public RefBase
 {
+    static int32_t sSequence;
+
 public:
             LayerBase(SurfaceFlinger* flinger, DisplayID display);
 
@@ -61,6 +65,7 @@
             Region      visibleRegionScreen;
             Region      transparentRegionScreen;
             Region      coveredRegionScreen;
+            int32_t     sequence;
             
             struct State {
                 uint32_t        w;
@@ -105,6 +110,10 @@
 
     virtual const char* getTypeId() const { return "LayerBase"; }
 
+    virtual void setGeometry(hwc_layer_t* hwcl);
+
+    virtual void setPerFrameData(hwc_layer_t* hwcl);
+
     /**
      * draw - performs some global clipping optimizations
      * and calls onDraw().
@@ -210,12 +219,6 @@
     inline  const State&    currentState() const    { return mCurrentState; }
     inline  State&          currentState()          { return mCurrentState; }
 
-    static int compareCurrentStateZ(
-            sp<LayerBase> const * layerA,
-            sp<LayerBase> const * layerB) {
-        return layerA[0]->currentState().z - layerB[0]->currentState().z;
-    }
-
     int32_t  getOrientation() const { return mOrientation; }
     int  tx() const             { return mLeft; }
     int  ty() const             { return mTop; }
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 3167c4c..47bb4c1 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -52,6 +52,7 @@
 #include "SurfaceFlinger.h"
 
 #include "DisplayHardware/DisplayHardware.h"
+#include "DisplayHardware/HWComposer.h"
 
 /* ideally AID_GRAPHICS would be in a semi-public header
  * or there would be a way to map a user/group name to its id
@@ -65,95 +66,6 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
-SurfaceFlinger::LayerVector::LayerVector(const SurfaceFlinger::LayerVector& rhs)
-    : lookup(rhs.lookup), layers(rhs.layers)
-{
-}
-
-ssize_t SurfaceFlinger::LayerVector::indexOf(
-        const sp<LayerBase>& key, size_t guess) const
-{
-    if (guess<size() && lookup.keyAt(guess) == key)
-        return guess;
-    const ssize_t i = lookup.indexOfKey(key);
-    if (i>=0) {
-        const size_t idx = lookup.valueAt(i);
-        LOGE_IF(layers[idx]!=key,
-            "LayerVector[%p]: layers[%d]=%p, key=%p",
-            this, int(idx), layers[idx].get(), key.get());
-        return idx;
-    }
-    return i;
-}
-
-ssize_t SurfaceFlinger::LayerVector::add(
-        const sp<LayerBase>& layer,
-        Vector< sp<LayerBase> >::compar_t cmp)
-{
-    size_t count = layers.size();
-    ssize_t l = 0;
-    ssize_t h = count-1;
-    ssize_t mid;
-    sp<LayerBase> const* a = layers.array();
-    while (l <= h) {
-        mid = l + (h - l)/2;
-        const int c = cmp(a+mid, &layer);
-        if (c == 0)     { l = mid; break; }
-        else if (c<0)   { l = mid+1; }
-        else            { h = mid-1; }
-    }
-    size_t order = l;
-    while (order<count && !cmp(&layer, a+order)) {
-        order++;
-    }
-    count = lookup.size();
-    for (size_t i=0 ; i<count ; i++) {
-        if (lookup.valueAt(i) >= order) {
-            lookup.editValueAt(i)++;
-        }
-    }
-    layers.insertAt(layer, order);
-    lookup.add(layer, order);
-    return order;
-}
-
-ssize_t SurfaceFlinger::LayerVector::remove(const sp<LayerBase>& layer)
-{
-    const ssize_t keyIndex = lookup.indexOfKey(layer);
-    if (keyIndex >= 0) {
-        const size_t index = lookup.valueAt(keyIndex);
-        LOGE_IF(layers[index]!=layer,
-                "LayerVector[%p]: layers[%u]=%p, layer=%p",
-                this, int(index), layers[index].get(), layer.get());
-        layers.removeItemsAt(index);
-        lookup.removeItemsAt(keyIndex);
-        const size_t count = lookup.size();
-        for (size_t i=0 ; i<count ; i++) {
-            if (lookup.valueAt(i) >= size_t(index)) {
-                lookup.editValueAt(i)--;
-            }
-        }
-        return index;
-    }
-    return NAME_NOT_FOUND;
-}
-
-ssize_t SurfaceFlinger::LayerVector::reorder(
-        const sp<LayerBase>& layer,
-        Vector< sp<LayerBase> >::compar_t cmp)
-{
-    // XXX: it's a little lame. but oh well...
-    ssize_t err = remove(layer);
-    if (err >=0)
-        err = add(layer, cmp);
-    return err;
-}
-
-// ---------------------------------------------------------------------------
-#if 0
-#pragma mark -
-#endif
-
 SurfaceFlinger::SurfaceFlinger()
     :   BnSurfaceComposer(), Thread(false),
         mTransactionFlags(0),
@@ -165,6 +77,7 @@
         mAccessSurfaceFlinger("android.permission.ACCESS_SURFACE_FLINGER"),
         mDump("android.permission.DUMP"),
         mVisibleRegionsDirty(false),
+        mHwWorkListDirty(false),
         mDeferReleaseConsole(false),
         mFreezeDisplay(false),
         mFreezeCount(0),
@@ -457,6 +370,11 @@
     // post surfaces (if needed)
     handlePageFlip();
 
+    if (UNLIKELY(mHwWorkListDirty)) {
+        // build the h/w work list
+        handleWorkList();
+    }
+
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     if (LIKELY(hw.canDraw() && !isFrozen())) {
         // repaint the framebuffer (if needed)
@@ -521,6 +439,10 @@
 {
     Vector< sp<LayerBase> > ditchedLayers;
 
+    /*
+     * Perform and commit the transaction
+     */
+
     { // scope for the lock
         Mutex::Autolock _l(mStateLock);
         const nsecs_t now = systemTime();
@@ -528,9 +450,15 @@
         handleTransactionLocked(transactionFlags, ditchedLayers);
         mLastTransactionTime = systemTime() - now;
         mDebugInTransaction = 0;
+        mHwWorkListDirty = true;
+        // here the transaction has been committed
     }
 
-    // do this without lock held
+    /*
+     * Clean-up all layers that went away
+     * (do this without the lock held)
+     */
+
     const size_t count = ditchedLayers.size();
     for (size_t i=0 ; i<count ; i++) {
         if (ditchedLayers[i] != 0) {
@@ -764,8 +692,8 @@
 void SurfaceFlinger::handlePageFlip()
 {
     bool visibleRegions = mVisibleRegionsDirty;
-    LayerVector& currentLayers = const_cast<LayerVector&>(
-            mDrawingState.layersSortedByZ);
+    LayerVector& currentLayers(
+            const_cast<LayerVector&>(mDrawingState.layersSortedByZ));
     visibleRegions |= lockPageFlip(currentLayers);
 
         const DisplayHardware& hw = graphicPlane(0).displayHardware();
@@ -773,8 +701,22 @@
         if (visibleRegions) {
             Region opaqueRegion;
             computeVisibleRegions(currentLayers, mDirtyRegion, opaqueRegion);
+
+            /*
+             *  rebuild the visible layer list
+             */
+            mVisibleLayersSortedByZ.clear();
+            const LayerVector& currentLayers(mDrawingState.layersSortedByZ);
+            size_t count = currentLayers.size();
+            mVisibleLayersSortedByZ.setCapacity(count);
+            for (size_t i=0 ; i<count ; i++) {
+                if (!currentLayers[i]->visibleRegionScreen.isEmpty())
+                    mVisibleLayersSortedByZ.add(currentLayers[i]);
+            }
+
             mWormholeRegion = screenRegion.subtract(opaqueRegion);
             mVisibleRegionsDirty = false;
+            mHwWorkListDirty = true;
         }
 
     unlockPageFlip(currentLayers);
@@ -805,6 +747,21 @@
     }
 }
 
+void SurfaceFlinger::handleWorkList()
+{
+    mHwWorkListDirty = false;
+    HWComposer& hwc(graphicPlane(0).displayHardware().getHwComposer());
+    if (hwc.initCheck() == NO_ERROR) {
+        const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
+        const size_t count = currentLayers.size();
+        hwc.createWorkList(count);
+        HWComposer::iterator cur(hwc.begin());
+        HWComposer::iterator last(hwc.end());
+        for (size_t i=0 ; (i<count) && (cur!=last) ; ++i, ++cur) {
+            currentLayers[i]->setGeometry(cur);
+        }
+    }
+}
 
 void SurfaceFlinger::handleRepaint()
 {
@@ -869,18 +826,61 @@
         // draw something...
         drawWormhole();
     }
-    const SurfaceFlinger& flinger(*this);
-    const LayerVector& drawingLayers(mDrawingState.layersSortedByZ);
-    const size_t count = drawingLayers.size();
-    sp<LayerBase> const* const layers = drawingLayers.array();
+
+    status_t err = NO_ERROR;
+    const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
+    const size_t count = layers.size();
+
+    const DisplayHardware& hw(graphicPlane(0).displayHardware());
+    HWComposer& hwc(hw.getHwComposer());
+    HWComposer::iterator cur(hwc.begin());
+    HWComposer::iterator last(hwc.end());
+
+    // update the per-frame h/w composer data for each layer
+    if (cur != last) {
+        for (size_t i=0 ; i<count && cur!=last ; ++i, ++cur) {
+            layers[i]->setPerFrameData(cur);
+        }
+        err = hwc.prepare();
+        LOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
+    }
+
+    // and then, render the layers targeted at the framebuffer
+    Region transparent(hw.bounds());
     for (size_t i=0 ; i<count ; ++i) {
-        const sp<LayerBase>& layer = layers[i];
-        const Region& visibleRegion(layer->visibleRegionScreen);
-        if (!visibleRegion.isEmpty())  {
-            const Region clip(dirty.intersect(visibleRegion));
-            if (!clip.isEmpty()) {
-                layer->draw(clip);
+
+        // see if we need to skip this layer
+        if (!err && cur != last) {
+            if (!((cur->compositionType == HWC_FRAMEBUFFER) ||
+                    (cur->flags & HWC_SKIP_LAYER))) {
+                ++cur;
+                continue;
             }
+            ++cur;
+        }
+
+        // draw the layer into the framebuffer
+        const sp<LayerBase>& layer(layers[i]);
+        transparent.subtractSelf(layer->visibleRegionScreen);
+        const Region clip(dirty.intersect(layer->visibleRegionScreen));
+        if (!clip.isEmpty()) {
+            layer->draw(clip);
+        }
+    }
+
+    // finally clear everything we didn't draw as a result of calling
+    // prepare (this leaves the FB transparent).
+    transparent.andSelf(dirty);
+    if (!transparent.isEmpty()) {
+        glClearColor(0,0,0,0);
+        Region::const_iterator it = transparent.begin();
+        Region::const_iterator const end = transparent.end();
+        const int32_t height = hw.getHeight();
+        while (it != end) {
+            const Rect& r(*it++);
+            const GLint sy = height - (r.top + r.height());
+            glScissor(r.left, sy, r.width(), r.height());
+            glClear(GL_COLOR_BUFFER_BIT);
         }
     }
 }
@@ -1029,8 +1029,7 @@
 
 status_t SurfaceFlinger::addLayer_l(const sp<LayerBase>& layer)
 {
-    ssize_t i = mCurrentState.layersSortedByZ.add(
-                layer, &LayerBase::compareCurrentStateZ);
+    ssize_t i = mCurrentState.layersSortedByZ.add(layer);
     return (i < 0) ? status_t(i) : status_t(NO_ERROR);
 }
 
@@ -1372,9 +1371,10 @@
                     flags |= eTraversalNeeded;
             }
             if (what & eLayerChanged) {
+                ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer);
                 if (layer->setLayer(s.z)) {
-                    mCurrentState.layersSortedByZ.reorder(
-                            layer, &Layer::compareCurrentStateZ);
+                    mCurrentState.layersSortedByZ.removeAt(idx);
+                    mCurrentState.layersSortedByZ.add(layer);
                     // we need traversal (state changed)
                     // AND transaction (list changed)
                     flags |= eTransactionNeeded|eTraversalNeeded;
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 8821e5c..8e286e5 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -40,9 +40,6 @@
 
 #include "MessageQueue.h"
 
-struct copybit_device_t;
-struct overlay_device_t;
-
 namespace android {
 
 // ---------------------------------------------------------------------------
@@ -246,21 +243,19 @@
     status_t setClientState(const sp<Client>& client,
             int32_t count, const layer_state_t* states);
 
-
-    class LayerVector {
+    class LayerVector : public SortedVector< sp<LayerBase> > {
     public:
-        inline              LayerVector() { }
-                            LayerVector(const LayerVector&);
-        inline size_t       size() const { return layers.size(); }
-        inline sp<LayerBase> const* array() const { return layers.array(); }
-        ssize_t             add(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
-        ssize_t             remove(const sp<LayerBase>&);
-        ssize_t             reorder(const sp<LayerBase>&, Vector< sp<LayerBase> >::compar_t);
-        ssize_t             indexOf(const sp<LayerBase>& key, size_t guess=0) const;
-        inline sp<LayerBase> operator [] (size_t i) const { return layers[i]; }
-    private:
-        KeyedVector< sp<LayerBase> , size_t> lookup;
-        Vector< sp<LayerBase> >              layers;
+        LayerVector() { }
+        LayerVector(const LayerVector& rhs) : SortedVector< sp<LayerBase> >(rhs) { }
+        virtual int do_compare(const void* lhs, const void* rhs) const {
+            const sp<LayerBase>& l(*reinterpret_cast<const sp<LayerBase>*>(lhs));
+            const sp<LayerBase>& r(*reinterpret_cast<const sp<LayerBase>*>(rhs));
+            // sort layers by Z order
+            uint32_t lz = l->currentState().z;
+            uint32_t rz = r->currentState().z;
+            // then by sequence, so we get a stable ordering
+            return (lz != rz) ? (lz - rz) : (l->sequence - r->sequence);
+        }
     };
 
     struct State {
@@ -301,6 +296,7 @@
             void        handlePageFlip();
             bool        lockPageFlip(const LayerVector& currentLayers);
             void        unlockPageFlip(const LayerVector& currentLayers);
+            void        handleWorkList();
             void        handleRepaint();
             void        postFramebuffer();
             void        composeSurfaces(const Region& dirty);
@@ -375,10 +371,13 @@
                 Region                      mInvalidRegion;
                 Region                      mWormholeRegion;
                 bool                        mVisibleRegionsDirty;
+                bool                        mHwWorkListDirty;
                 bool                        mDeferReleaseConsole;
                 bool                        mFreezeDisplay;
                 int32_t                     mFreezeCount;
                 nsecs_t                     mFreezeDisplayTime;
+                Vector< sp<LayerBase> >     mVisibleLayersSortedByZ;
+
 
                 // don't use a lock for these, we don't care
                 int                         mDebugRegion;