Fix a couple issues with the new hwcomposer HAL

- we now clear the framebuffer upon request from the HAL
- the HAL list size could get out of sync with reality
- there was also an issue where sometime we could run past the list

Change-Id: Ic3a34314aed24181f2d8cc787096af83c046ef27
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index 8ca880b..0291d78 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -34,7 +34,7 @@
 // ---------------------------------------------------------------------------
 
 HWComposer::HWComposer()
-    : mModule(0), mHwc(0), mList(0),
+    : mModule(0), mHwc(0), mList(0), mCapacity(0),
       mDpy(EGL_NO_DISPLAY), mSur(EGL_NO_SURFACE)
 {
     int err = hw_get_module(HWC_HARDWARE_MODULE_ID, &mModule);
@@ -63,10 +63,13 @@
 }
 
 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);
+    if (mHwc) {
+        if (!mList || mCapacity < numLayers) {
+            free(mList);
+            size_t size = sizeof(hwc_layer_list) + numLayers*sizeof(hwc_layer_t);
+            mList = (hwc_layer_list_t*)malloc(size);
+            mCapacity = numLayers;
+        }
         mList->flags = HWC_GEOMETRY_CHANGED;
         mList->numHwLayers = numLayers;
     }
@@ -84,12 +87,12 @@
     return (status_t)err;
 }
 
-HWComposer::iterator HWComposer::begin() {
-    return mList ? &(mList->hwLayers[0]) : NULL;
+size_t HWComposer::getNumLayers() const {
+    return mList ? mList->numHwLayers : 0;
 }
 
-HWComposer::iterator HWComposer::end() {
-    return mList ? &(mList->hwLayers[mList->numHwLayers]) : NULL;
+hwc_layer_t* HWComposer::getLayers() const {
+    return mList ? mList->hwLayers : 0;
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index 729f23b..c5d5c2b 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -49,16 +49,14 @@
     status_t commit() const;
 
 
-    typedef hwc_layer_t const * const_iterator;
-    typedef hwc_layer_t* iterator;
-
-    iterator begin();
-    iterator end();
+    size_t getNumLayers() const;
+    hwc_layer_t* getLayers() const;
 
 private:
     hw_module_t const*      mModule;
     hwc_composer_device_t*  mHwc;
     hwc_layer_list_t*       mList;
+    size_t                  mCapacity;
     hwc_display_t           mDpy;
     hwc_surface_t           mSur;
 };
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 47bb4c1..006bb10 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -755,10 +755,9 @@
         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);
+        hwc_layer_t* const cur(hwc.getLayers());
+        for (size_t i=0 ; cur && i<count ; i++) {
+            currentLayers[i]->setGeometry(&cur[i]);
         }
     }
 }
@@ -829,47 +828,41 @@
 
     status_t err = NO_ERROR;
     const Vector< sp<LayerBase> >& layers(mVisibleLayersSortedByZ);
-    const size_t count = layers.size();
+    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());
+    hwc_layer_t* const cur(hwc.getLayers());
 
-    // 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);
+    LOGE_IF(cur && hwc.getNumLayers() != count,
+            "HAL number of layers (%d) doesn't match surfaceflinger (%d)",
+            hwc.getNumLayers(), count);
+
+    // just to be extra-safe, use the smallest count
+    count = count < hwc.getNumLayers() ? count : hwc.getNumLayers();
+
+    /*
+     *  update the per-frame h/w composer data for each layer
+     *  and build the transparent region of the FB
+     */
+    Region transparent;
+    if (cur) {
+        for (size_t i=0 ; i<count ; i++) {
+            const sp<LayerBase>& layer(layers[i]);
+            layer->setPerFrameData(&cur[i]);
+            if (cur[i].hints & HWC_HINT_CLEAR_FB) {
+                if (!(layer->needsBlending())) {
+                    transparent.orSelf(layer->visibleRegionScreen);
+                }
+            }
         }
         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) {
-
-        // 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).
+    /*
+     *  clear the area of the FB that need to be transparent
+     */
     transparent.andSelf(dirty);
     if (!transparent.isEmpty()) {
         glClearColor(0,0,0,0);
@@ -883,6 +876,25 @@
             glClear(GL_COLOR_BUFFER_BIT);
         }
     }
+
+
+    /*
+     * and then, render the layers targeted at the framebuffer
+     */
+    for (size_t i=0 ; i<count ; i++) {
+        if (cur) {
+            if (!(cur[i].compositionType == HWC_FRAMEBUFFER) ||
+                    cur[i].flags & HWC_SKIP_LAYER) {
+                // skip layers handled by the HAL
+                continue;
+            }
+        }
+        const sp<LayerBase>& layer(layers[i]);
+        const Region clip(dirty.intersect(layer->visibleRegionScreen));
+        if (!clip.isEmpty()) {
+            layer->draw(clip);
+        }
+    }
 }
 
 void SurfaceFlinger::unlockClients()