Merge "Implement SurfaceFlinger's ANW on top of BufferQueue"
diff --git a/include/android/keycodes.h b/include/android/keycodes.h
index 65ccb8d..282e729 100644
--- a/include/android/keycodes.h
+++ b/include/android/keycodes.h
@@ -262,6 +262,7 @@
     AKEYCODE_YEN             = 216,
     AKEYCODE_RO              = 217,
     AKEYCODE_KANA            = 218,
+    AKEYCODE_ASSIST          = 219,
 
     // NOTE: If you add a new keycode here you must also add it to several other files.
     //       Refer to frameworks/base/core/java/android/view/KeyEvent.java for the full list.
diff --git a/opengl/libs/Android.mk b/opengl/libs/Android.mk
index c5c2618..42aaa24 100644
--- a/opengl/libs/Android.mk
+++ b/opengl/libs/Android.mk
@@ -41,7 +41,12 @@
 endif
 
 ifeq ($(TARGET_BOARD_PLATFORM),msm7k)
-LOCAL_CFLAGS += -DADRENO130=1
+  LOCAL_CFLAGS += -DADRENO130=1
+endif
+
+ifeq ($(TARGET_BOARD_PLATFORM), s5pc110)
+  # see Loader.cpp for details
+  LOCAL_CFLAGS += -DSYSTEMUI_PBSIZE_HACK=1
 endif
 
 ifeq ($(ARCH_ARM_HAVE_TLS_REGISTER),true)
diff --git a/opengl/libs/EGL/Loader.cpp b/opengl/libs/EGL/Loader.cpp
index 0b1016c..9ee3686 100644
--- a/opengl/libs/EGL/Loader.cpp
+++ b/opengl/libs/EGL/Loader.cpp
@@ -81,6 +81,24 @@
 
 // ----------------------------------------------------------------------------
 
+static char const * getProcessCmdline() {
+    long pid = getpid();
+    char procPath[128];
+    snprintf(procPath, 128, "/proc/%ld/cmdline", pid);
+    FILE * file = fopen(procPath, "r");
+    if (file) {
+        static char cmdline[256];
+        char *str = fgets(cmdline, sizeof(cmdline) - 1, file);
+        fclose(file);
+        if (str) {
+            return cmdline;
+        }
+    }
+    return NULL;
+}
+
+// ----------------------------------------------------------------------------
+
 Loader::driver_t::driver_t(void* gles) 
 {
     dso[0] = gles;
@@ -280,6 +298,35 @@
         ALOGE_IF(!getProcAddress, 
                 "can't find eglGetProcAddress() in %s", driver_absolute_path);
 
+#ifdef SYSTEMUI_PBSIZE_HACK
+#warning "SYSTEMUI_PBSIZE_HACK enabled"
+        /*
+         * TODO: replace SYSTEMUI_PBSIZE_HACK by something less hackish
+         *
+         * Here we adjust the PB size from its default value to 512KB which
+         * is the minimum acceptable for the systemui process.
+         * We do this on low-end devices only because it allows us to enable
+         * h/w acceleration in the systemui process while keeping the
+         * memory usage down.
+         *
+         * Obviously, this is the wrong place and wrong way to make this
+         * adjustment, but at the time of this writing this was the safest
+         * solution.
+         */
+        const char *cmdline = getProcessCmdline();
+        if (strstr(cmdline, "systemui")) {
+            void *imgegl = dlopen("/vendor/lib/libIMGegl.so", RTLD_LAZY);
+            if (imgegl) {
+                unsigned int *PVRDefaultPBS =
+                        (unsigned int *)dlsym(imgegl, "PVRDefaultPBS");
+                if (PVRDefaultPBS) {
+                    ALOGD("setting default PBS to 512KB, was %d KB", *PVRDefaultPBS / 1024);
+                    *PVRDefaultPBS = 512*1024;
+                }
+            }
+        }
+#endif
+
         egl_t* egl = &cnx->egl;
         __eglMustCastToProperFunctionPointerType* curr =
             (__eglMustCastToProperFunctionPointerType*)egl;
diff --git a/opengl/libs/EGL/egl_display.cpp b/opengl/libs/EGL/egl_display.cpp
index a46aa38..80072ab 100644
--- a/opengl/libs/EGL/egl_display.cpp
+++ b/opengl/libs/EGL/egl_display.cpp
@@ -263,7 +263,13 @@
     Mutex::Autolock _l(lock);
 
     if (refs == 0) {
-        return setError(EGL_NOT_INITIALIZED, EGL_FALSE);
+        /*
+         * From the EGL spec (3.2):
+         * "Termination of a display that has already been terminated,
+         *  (...), is allowed, but the only effect of such a call is
+         *  to return EGL_TRUE (...)
+         */
+        return EGL_TRUE;
     }
 
     // this is specific to Android, display termination is ref-counted.
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.cpp b/opengl/libs/GLES_trace/src/gltrace_context.cpp
index 45dbb43..91b291e 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_context.cpp
@@ -119,7 +119,7 @@
 
     const size_t DEFAULT_BUFFER_SIZE = 8192;
     BufferedOutputStream *stream = new BufferedOutputStream(mStream, DEFAULT_BUFFER_SIZE);
-    GLTraceContext *traceContext = new GLTraceContext(id, this, stream);
+    GLTraceContext *traceContext = new GLTraceContext(id, version, this, stream);
     mPerContextState[eglContext] = traceContext;
 
     return traceContext;
@@ -129,8 +129,10 @@
     return mPerContextState[c];
 }
 
-GLTraceContext::GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream) :
+GLTraceContext::GLTraceContext(int id, int version, GLTraceState *state,
+        BufferedOutputStream *stream) :
     mId(id),
+    mVersion(version),
     mState(state),
     mBufferedOutputStream(stream),
     mElementArrayBuffers(DefaultKeyedVector<GLuint, ElementArrayBuffer*>(NULL))
@@ -143,6 +145,10 @@
     return mId;
 }
 
+int GLTraceContext::getVersion() {
+    return mVersion;
+}
+
 GLTraceState *GLTraceContext::getGlobalTraceState() {
     return mState;
 }
diff --git a/opengl/libs/GLES_trace/src/gltrace_context.h b/opengl/libs/GLES_trace/src/gltrace_context.h
index 323cfdc..4c38bba 100644
--- a/opengl/libs/GLES_trace/src/gltrace_context.h
+++ b/opengl/libs/GLES_trace/src/gltrace_context.h
@@ -50,6 +50,7 @@
 /** GL Trace Context info associated with each EGLContext */
 class GLTraceContext {
     int mId;                    /* unique context id */
+    int mVersion;               /* GL version, e.g: egl_connection_t::GLESv2_INDEX */
     GLTraceState *mState;       /* parent GL Trace state (for per process GL Trace State Info) */
 
     void *fbcontents;           /* memory area to read framebuffer contents */
@@ -65,8 +66,9 @@
 public:
     gl_hooks_t *hooks;
 
-    GLTraceContext(int id, GLTraceState *state, BufferedOutputStream *stream);
+    GLTraceContext(int id, int version, GLTraceState *state, BufferedOutputStream *stream);
     int getId();
+    int getVersion();
     GLTraceState *getGlobalTraceState();
     void getCompressedFB(void **fb, unsigned *fbsize,
                             unsigned *fbwidth, unsigned *fbheight,
diff --git a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
index 3597b26..1bd790e 100644
--- a/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
+++ b/opengl/libs/GLES_trace/src/gltrace_fixup.cpp
@@ -15,6 +15,7 @@
  */
 
 #include <cutils/log.h>
+#include <EGL/egldefs.h>
 #include <GLES/gl.h>
 #include <GLES/glext.h>
 #include <GLES2/gl2.h>
@@ -592,6 +593,11 @@
 }
 
 void trace_VertexAttribPointerDataForGlDrawArrays(GLTraceContext *context, GLMessage *glmsg) {
+    if (context->getVersion() == egl_connection_t::GLESv1_INDEX) {
+        // only supported for GLES2 and above
+        return;
+    }
+
     /* void glDrawArrays(GLenum mode, GLint first, GLsizei count) */
     GLsizei count = glmsg->args(2).intvalue(0);
 
@@ -604,6 +610,11 @@
 
 void trace_VertexAttribPointerDataForGlDrawElements(GLTraceContext *context, GLMessage *glmsg,
                             GLvoid *indices) {
+    if (context->getVersion() == egl_connection_t::GLESv1_INDEX) {
+        // only supported for GLES2 and above
+        return;
+    }
+
     /* void glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices) */
     GLsizei count = glmsg->args(1).intvalue(0);
     GLenum type = glmsg->args(2).intvalue(0);
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 65763db..ce63ee7 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -43,6 +43,19 @@
 namespace android {
 // ---------------------------------------------------------------------------
 
+struct HWComposer::cb_context {
+    struct callbacks : public hwc_procs_t {
+        // these are here to facilitate the transition when adding
+        // new callbacks (an implementation can check for NULL before
+        // calling a new callback).
+        void (*zero[4])(void);
+    };
+    callbacks procs;
+    HWComposer* hwc;
+};
+
+// ---------------------------------------------------------------------------
+
 HWComposer::HWComposer(
         const sp<SurfaceFlinger>& flinger,
         EventHandler& handler,
@@ -51,6 +64,7 @@
       mModule(0), mHwc(0), mList(0), mCapacity(0),
       mNumOVLayers(0), mNumFBLayers(0),
       mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE),
+      mCBContext(new cb_context),
       mEventHandler(handler),
       mRefreshPeriod(refreshPeriod),
       mVSyncCount(0), mDebugForceFakeVSync(false)
@@ -68,11 +82,11 @@
                 HWC_HARDWARE_COMPOSER, strerror(-err));
         if (err == 0) {
             if (mHwc->registerProcs) {
-                mCBContext.hwc = this;
-                mCBContext.procs.invalidate = &hook_invalidate;
-                mCBContext.procs.vsync = &hook_vsync;
-                mHwc->registerProcs(mHwc, &mCBContext.procs);
-                memset(mCBContext.procs.zero, 0, sizeof(mCBContext.procs.zero));
+                mCBContext->hwc = this;
+                mCBContext->procs.invalidate = &hook_invalidate;
+                mCBContext->procs.vsync = &hook_vsync;
+                mHwc->registerProcs(mHwc, &mCBContext->procs);
+                memset(mCBContext->procs.zero, 0, sizeof(mCBContext->procs.zero));
             }
             if (mHwc->common.version >= HWC_DEVICE_API_VERSION_0_3) {
                 if (mDebugForceFakeVSync) {
@@ -102,6 +116,7 @@
     if (mHwc) {
         hwc_close(mHwc);
     }
+    delete mCBContext;
 }
 
 status_t HWComposer::initCheck() const {
@@ -230,10 +245,117 @@
     return mList ? mList->numHwLayers : 0;
 }
 
-hwc_layer_t* HWComposer::getLayers() const {
-    return mList ? mList->hwLayers : 0;
+/*
+ * Helper template to implement a concrete HWCLayer
+ * This holds the pointer to the concrete hwc layer type
+ * and implements the "iterable" side of HWCLayer.
+ */
+template<typename CONCRETE, typename HWCTYPE>
+class Iterable : public HWComposer::HWCLayer {
+protected:
+    HWCTYPE* const mLayerList;
+    HWCTYPE* mCurrentLayer;
+    Iterable(HWCTYPE* layer) : mLayerList(layer), mCurrentLayer(layer) { }
+    inline HWCTYPE const * getLayer() const { return mCurrentLayer; }
+    inline HWCTYPE* getLayer() { return mCurrentLayer; }
+    virtual ~Iterable() { }
+private:
+    // returns a copy of ourselves
+    virtual HWComposer::HWCLayer* dup() {
+        return new CONCRETE( static_cast<const CONCRETE&>(*this) );
+    }
+    virtual status_t setLayer(size_t index) {
+        mCurrentLayer = &mLayerList[index];
+        return NO_ERROR;
+    }
+};
+
+/*
+ * Concrete implementation of HWCLayer for HWC_DEVICE_API_VERSION_0_3
+ * This implements the HWCLayer side of HWCIterableLayer.
+ */
+class HWCLayerVersion03 : public Iterable<HWCLayerVersion03, hwc_layer_t> {
+public:
+    HWCLayerVersion03(hwc_layer_t* layer)
+        : Iterable<HWCLayerVersion03, hwc_layer_t>(layer) { }
+
+    virtual int32_t getCompositionType() const {
+        return getLayer()->compositionType;
+    }
+    virtual uint32_t getHints() const {
+        return getLayer()->hints;
+    }
+
+    virtual void setDefaultState() {
+        getLayer()->compositionType = HWC_FRAMEBUFFER;
+        getLayer()->hints = 0;
+        getLayer()->flags = HWC_SKIP_LAYER;
+        getLayer()->transform = 0;
+        getLayer()->blending = HWC_BLENDING_NONE;
+        getLayer()->visibleRegionScreen.numRects = 0;
+        getLayer()->visibleRegionScreen.rects = NULL;
+    }
+    virtual void setSkip(bool skip) {
+        if (skip) {
+            getLayer()->flags |= HWC_SKIP_LAYER;
+        } else {
+            getLayer()->flags &= ~HWC_SKIP_LAYER;
+        }
+    }
+    virtual void setBlending(uint32_t blending) {
+        getLayer()->blending = blending;
+    }
+    virtual void setTransform(uint32_t transform) {
+        getLayer()->transform = transform;
+    }
+    virtual void setFrame(const Rect& frame) {
+        reinterpret_cast<Rect&>(getLayer()->displayFrame) = frame;
+    }
+    virtual void setCrop(const Rect& crop) {
+        reinterpret_cast<Rect&>(getLayer()->sourceCrop) = crop;
+    }
+    virtual void setVisibleRegionScreen(const Region& reg) {
+        getLayer()->visibleRegionScreen.rects =
+                reinterpret_cast<hwc_rect_t const *>(
+                        reg.getArray(&getLayer()->visibleRegionScreen.numRects));
+    }
+    virtual void setBuffer(const sp<GraphicBuffer>& buffer) {
+        if (buffer == 0 || buffer->handle == 0) {
+            getLayer()->compositionType = HWC_FRAMEBUFFER;
+            getLayer()->flags |= HWC_SKIP_LAYER;
+            getLayer()->handle = 0;
+        } else {
+            getLayer()->handle = buffer->handle;
+        }
+    }
+};
+
+/*
+ * returns an iterator initialized at a given index in the layer list
+ */
+HWComposer::LayerListIterator HWComposer::getLayerIterator(size_t index) {
+    if (!mList || index > mList->numHwLayers) {
+        return LayerListIterator();
+    }
+    return LayerListIterator(new HWCLayerVersion03(mList->hwLayers), index);
 }
 
+/*
+ * returns an iterator on the beginning of the layer list
+ */
+HWComposer::LayerListIterator HWComposer::begin() {
+    return getLayerIterator(0);
+}
+
+/*
+ * returns an iterator on the end of the layer list
+ */
+HWComposer::LayerListIterator HWComposer::end() {
+    return getLayerIterator(getNumLayers());
+}
+
+
+
 void HWComposer::dump(String8& result, char* buffer, size_t SIZE,
         const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const {
     if (mHwc && mList) {
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index aada3cd..cafa247 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -22,7 +22,7 @@
 
 #include <EGL/egl.h>
 
-#include <hardware/hwcomposer.h>
+#include <hardware/hwcomposer_defs.h>
 
 #include <utils/StrongPointer.h>
 #include <utils/Vector.h>
@@ -31,12 +31,17 @@
                            const struct timespec *request,
                            struct timespec *remain);
 
+struct hwc_composer_device;
+struct hwc_layer_list;
+struct hwc_procs;
+
 namespace android {
 // ---------------------------------------------------------------------------
 
 class String8;
 class SurfaceFlinger;
 class LayerBase;
+class GraphicBuffer;
 
 class HWComposer
 {
@@ -57,9 +62,6 @@
     // tells the HAL what the framebuffer is
     void setFrameBuffer(EGLDisplay dpy, EGLSurface sur);
 
-    // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
-    status_t createWorkList(size_t numLayers);
-
     // Asks the HAL what it can do
     status_t prepare() const;
 
@@ -72,14 +74,109 @@
     // release hardware resources
     status_t release() const;
 
+    // create a work list for numLayers layer. sets HWC_GEOMETRY_CHANGED.
+    status_t createWorkList(size_t numLayers);
+
     // get the layer array created by createWorkList()
     size_t getNumLayers() const;
-    hwc_layer_t* getLayers() const;
 
     // get number of layers of the given type as updated in prepare().
     // type is HWC_OVERLAY or HWC_FRAMEBUFFER
     size_t getLayerCount(int type) const;
 
+    // needed forward declarations
+    class LayerListIterator;
+
+    /*
+     * Interface to hardware composer's layers functionality.
+     * This abstracts the HAL interface to layers which can evolve in
+     * incompatible ways from one release to another.
+     * The idea is that we could extend this interface as we add
+     * features to h/w composer.
+     */
+    class HWCLayerInterface {
+    protected:
+        virtual ~HWCLayerInterface() { }
+    public:
+        virtual int32_t getCompositionType() const = 0;
+        virtual uint32_t getHints() const = 0;
+        virtual void setDefaultState() = 0;
+        virtual void setSkip(bool skip) = 0;
+        virtual void setBlending(uint32_t blending) = 0;
+        virtual void setTransform(uint32_t transform) = 0;
+        virtual void setFrame(const Rect& frame) = 0;
+        virtual void setCrop(const Rect& crop) = 0;
+        virtual void setVisibleRegionScreen(const Region& reg) = 0;
+        virtual void setBuffer(const sp<GraphicBuffer>& buffer) = 0;
+    };
+
+    /*
+     * Interface used to implement an iterator to a list
+     * of HWCLayer.
+     */
+    class HWCLayer : public HWCLayerInterface {
+        friend class LayerListIterator;
+        // select the layer at the given index
+        virtual status_t setLayer(size_t index) = 0;
+        virtual HWCLayer* dup() = 0;
+        static HWCLayer* copy(HWCLayer *rhs) {
+            return rhs ? rhs->dup() : NULL;
+        }
+    protected:
+        virtual ~HWCLayer() { }
+    };
+
+    /*
+     * Iterator through a HWCLayer list.
+     * This behaves more or less like a forward iterator.
+     */
+    class LayerListIterator {
+        friend struct HWComposer;
+        HWCLayer* const mLayerList;
+        size_t mIndex;
+
+        LayerListIterator() : mLayerList(NULL), mIndex(0) { }
+
+        LayerListIterator(HWCLayer* layer, size_t index)
+            : mLayerList(layer), mIndex(index) { }
+
+        // we don't allow assignment, because we don't need it for now
+        LayerListIterator& operator = (const LayerListIterator& rhs);
+
+    public:
+        // copy operators
+        LayerListIterator(const LayerListIterator& rhs)
+            : mLayerList(HWCLayer::copy(rhs.mLayerList)), mIndex(rhs.mIndex) {
+        }
+
+        ~LayerListIterator() { delete mLayerList; }
+
+        // pre-increment
+        LayerListIterator& operator++() {
+            mLayerList->setLayer(++mIndex);
+            return *this;
+        }
+
+        // dereference
+        HWCLayerInterface& operator * () { return *mLayerList; }
+        HWCLayerInterface* operator -> () { return mLayerList; }
+
+        // comparison
+        bool operator == (const LayerListIterator& rhs) const {
+            return mIndex == rhs.mIndex;
+        }
+        bool operator != (const LayerListIterator& rhs) const {
+            return !operator==(rhs);
+        }
+    };
+
+    // Returns an iterator to the beginning of the layer list
+    LayerListIterator begin();
+
+    // Returns an iterator to the end of the layer list
+    LayerListIterator end();
+
+
     // Events handling ---------------------------------------------------------
 
     enum {
@@ -111,18 +208,9 @@
             const Vector< sp<LayerBase> >& visibleLayersSortedByZ) const;
 
 private:
+    LayerListIterator getLayerIterator(size_t index);
 
-    struct callbacks : public hwc_procs_t {
-        // these are here to facilitate the transition when adding
-        // new callbacks (an implementation can check for NULL before
-        // calling a new callback).
-        void (*zero[4])(void);
-    };
-
-    struct cb_context {
-        callbacks procs;
-        HWComposer* hwc;
-    };
+    struct cb_context;
 
     static void hook_invalidate(struct hwc_procs* procs);
     static void hook_vsync(struct hwc_procs* procs, int dpy, int64_t timestamp);
@@ -132,14 +220,14 @@
 
     sp<SurfaceFlinger>      mFlinger;
     hw_module_t const*      mModule;
-    hwc_composer_device_t*  mHwc;
-    hwc_layer_list_t*       mList;
+    struct hwc_composer_device*  mHwc;
+    struct hwc_layer_list*  mList;
     size_t                  mCapacity;
     mutable size_t          mNumOVLayers;
     mutable size_t          mNumFBLayers;
-    hwc_display_t           mDpy;
-    hwc_surface_t           mSur;
-    cb_context              mCBContext;
+    EGLDisplay              mDpy;
+    EGLSurface              mSur;
+    cb_context*             mCBContext;
     EventHandler&           mEventHandler;
     nsecs_t                 mRefreshPeriod;
     size_t                  mVSyncCount;
@@ -147,7 +235,6 @@
     bool                    mDebugForceFakeVSync;
 };
 
-
 // ---------------------------------------------------------------------------
 }; // namespace android
 
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4062340..890bcb4 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -259,16 +259,17 @@
     return crop;
 }
 
-void Layer::setGeometry(hwc_layer_t* hwcl)
+void Layer::setGeometry(HWComposer::HWCLayerInterface& layer)
 {
-    LayerBaseClient::setGeometry(hwcl);
+    LayerBaseClient::setGeometry(layer);
 
-    hwcl->flags &= ~HWC_SKIP_LAYER;
+    // enable this layer
+    layer.setSkip(false);
 
     // we can't do alpha-fade with the hwc HAL
     const State& s(drawingState());
     if (s.alpha < 0xFF) {
-        hwcl->flags = HWC_SKIP_LAYER;
+        layer.setSkip(true);
     }
 
     /*
@@ -288,29 +289,18 @@
 
     // we can only handle simple transformation
     if (finalTransform & Transform::ROT_INVALID) {
-        hwcl->flags = HWC_SKIP_LAYER;
+        layer.setSkip(true);
     } else {
-        hwcl->transform = finalTransform;
+        layer.setTransform(finalTransform);
     }
-
-    Rect crop = computeBufferCrop();
-    hwcl->sourceCrop.left   = crop.left;
-    hwcl->sourceCrop.top    = crop.top;
-    hwcl->sourceCrop.right  = crop.right;
-    hwcl->sourceCrop.bottom = crop.bottom;
+    layer.setCrop(computeBufferCrop());
 }
 
-void Layer::setPerFrameData(hwc_layer_t* hwcl) {
+void Layer::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
     const sp<GraphicBuffer>& buffer(mActiveBuffer);
-    if (buffer == NULL) {
-        // this can happen if the client never drew into this layer yet,
-        // or if we ran out of memory. In that case, don't let
-        // HWC handle it.
-        hwcl->flags |= HWC_SKIP_LAYER;
-        hwcl->handle = NULL;
-    } else {
-        hwcl->handle = buffer->handle;
-    }
+    // NOTE: buffer can be NULL if the client never drew into this
+    // layer yet, or if we ran out of memory
+    layer.setBuffer(buffer);
 }
 
 void Layer::onDraw(const Region& clip) const
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 393599f..7a164aa 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -64,8 +64,8 @@
     bool isFixedSize() const;
 
     // LayerBase interface
-    virtual void setGeometry(hwc_layer_t* hwcl);
-    virtual void setPerFrameData(hwc_layer_t* hwcl);
+    virtual void setGeometry(HWComposer::HWCLayerInterface& layer);
+    virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer);
     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 16bac8f..fe15dc9 100644
--- a/services/surfaceflinger/LayerBase.cpp
+++ b/services/surfaceflinger/LayerBase.cpp
@@ -281,48 +281,34 @@
         const Transform& planeTransform, Region& outDirtyRegion) {
 }
 
-void LayerBase::setGeometry(hwc_layer_t* hwcl)
+void LayerBase::setGeometry(HWComposer::HWCLayerInterface& layer)
 {
-    hwcl->compositionType = HWC_FRAMEBUFFER;
-    hwcl->hints = 0;
-    hwcl->flags = HWC_SKIP_LAYER;
-    hwcl->transform = 0;
-    hwcl->blending = HWC_BLENDING_NONE;
+    layer.setDefaultState();
 
     // this gives us only the "orientation" component of the transform
     const State& s(drawingState());
     const uint32_t finalTransform = s.transform.getOrientation();
     // we can only handle simple transformation
     if (finalTransform & Transform::ROT_INVALID) {
-        hwcl->flags = HWC_SKIP_LAYER;
+        layer.setTransform(0);
     } else {
-        hwcl->transform = finalTransform;
+        layer.setTransform(finalTransform);
     }
 
     if (!isOpaque()) {
-        hwcl->blending = mPremultipliedAlpha ?
-                HWC_BLENDING_PREMULT : HWC_BLENDING_COVERAGE;
+        layer.setBlending(mPremultipliedAlpha ?
+                HWC_BLENDING_PREMULT :
+                HWC_BLENDING_COVERAGE);
     }
 
     // scaling is already applied in mTransformedBounds
-    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));
-
-    hwcl->sourceCrop.left   = 0;
-    hwcl->sourceCrop.top    = 0;
-    hwcl->sourceCrop.right  = mTransformedBounds.width();
-    hwcl->sourceCrop.bottom = mTransformedBounds.height();
+    layer.setFrame(mTransformedBounds);
+    layer.setVisibleRegionScreen(visibleRegionScreen);
+    layer.setCrop(mTransformedBounds.getBounds());
 }
 
-void LayerBase::setPerFrameData(hwc_layer_t* hwcl) {
-    hwcl->compositionType = HWC_FRAMEBUFFER;
-    hwcl->handle = NULL;
+void LayerBase::setPerFrameData(HWComposer::HWCLayerInterface& layer) {
+    layer.setBuffer(0);
 }
 
 void LayerBase::setFiltering(bool filtering)
diff --git a/services/surfaceflinger/LayerBase.h b/services/surfaceflinger/LayerBase.h
index c547a40..4d5d1e4 100644
--- a/services/surfaceflinger/LayerBase.h
+++ b/services/surfaceflinger/LayerBase.h
@@ -32,8 +32,6 @@
 
 #include <private/gui/LayerState.h>
 
-#include <hardware/hwcomposer.h>
-
 #include "DisplayHardware/DisplayHardware.h"
 #include "Transform.h"
 
@@ -116,8 +114,8 @@
 
     virtual const char* getTypeId() const { return "LayerBase"; }
 
-    virtual void setGeometry(hwc_layer_t* hwcl);
-    virtual void setPerFrameData(hwc_layer_t* hwcl);
+    virtual void setGeometry(HWComposer::HWCLayerInterface& layer);
+    virtual void setPerFrameData(HWComposer::HWCLayerInterface& layer);
 
 
     /**
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 61b5f71..e2c7aed 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -800,12 +800,13 @@
         const Vector< sp<LayerBase> >& currentLayers(mVisibleLayersSortedByZ);
         const size_t count = currentLayers.size();
         hwc.createWorkList(count);
-        hwc_layer_t* const cur(hwc.getLayers());
-        for (size_t i=0 ; cur && i<count ; i++) {
-            currentLayers[i]->setGeometry(&cur[i]);
+
+        HWComposer::LayerListIterator cur = hwc.begin();
+        const HWComposer::LayerListIterator end = hwc.end();
+        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
+            currentLayers[i]->setGeometry(*cur);
             if (mDebugDisableHWC || mDebugRegion) {
-                cur[i].compositionType = HWC_FRAMEBUFFER;
-                cur[i].flags |= HWC_SKIP_LAYER;
+                cur->setSkip(true);
             }
         }
     }
@@ -859,8 +860,10 @@
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     HWComposer& hwc(hw.getHwComposer());
-    hwc_layer_t* const cur(hwc.getLayers());
-    if (!cur) {
+
+    HWComposer::LayerListIterator cur = hwc.begin();
+    const HWComposer::LayerListIterator end = hwc.end();
+    if (cur == end) {
         return;
     }
 
@@ -880,9 +883,9 @@
      *  update the per-frame h/w composer data for each layer
      *  and build the transparent region of the FB
      */
-    for (size_t i=0 ; i<count ; i++) {
+    for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
         const sp<LayerBase>& layer(layers[i]);
-        layer->setPerFrameData(&cur[i]);
+        layer->setPerFrameData(*cur);
     }
     status_t err = hwc.prepare();
     ALOGE_IF(err, "HWComposer::prepare failed (%s)", strerror(-err));
@@ -892,10 +895,11 @@
 {
     const DisplayHardware& hw(graphicPlane(0).displayHardware());
     HWComposer& hwc(hw.getHwComposer());
-    hwc_layer_t* const cur(hwc.getLayers());
+    HWComposer::LayerListIterator cur = hwc.begin();
+    const HWComposer::LayerListIterator end = hwc.end();
 
     const size_t fbLayerCount = hwc.getLayerCount(HWC_FRAMEBUFFER);
-    if (!cur || fbLayerCount) {
+    if (cur==end || fbLayerCount) {
         // Never touch the framebuffer if we don't have any framebuffer layers
 
         if (hwc.getLayerCount(HWC_OVERLAY)) {
@@ -920,13 +924,12 @@
 
         const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
         const size_t count = layers.size();
-
-        for (size_t i=0 ; i<count ; i++) {
+        for (size_t i=0 ; cur!=end && i<count ; ++i, ++cur) {
             const sp<LayerBase>& layer(layers[i]);
             const Region clip(dirty.intersect(layer->visibleRegionScreen));
             if (!clip.isEmpty()) {
-                if (cur && (cur[i].compositionType == HWC_OVERLAY)) {
-                    if (i && (cur[i].hints & HWC_HINT_CLEAR_FB)
+                if (cur->getCompositionType() == HWC_OVERLAY) {
+                    if (i && (cur->getHints() & HWC_HINT_CLEAR_FB)
                             && layer->isOpaque()) {
                         // never clear the very first layer since we're
                         // guaranteed the FB is already cleared