fix [3223749] media server crashes when switching mode from video capture to still image capture

there was an issue were in some situation SF would call prepare() on hwc
with a NULL handle and never call prepare again.
in this situation, we onw set the SKIP flag to make sure that hwc
won't process this layer and as soon as we receive our first buffer we
trigger a recompute of the visible regions which will end-up calling
prepare() again.

Change-Id: I6b400b2df79712408b9315a9859290c7fcb1609e
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 2b2f557..5a0f115 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -246,9 +246,10 @@
 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.
+        // 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;
         return;
     }
@@ -581,12 +582,20 @@
     }
 
     // we retired a buffer, which becomes the new front buffer
+
+    const bool noActiveBuffer = !mBufferManager.hasActiveBuffer();
     if (mBufferManager.setActiveBufferIndex(buf) < NO_ERROR) {
         LOGE("retireAndLock() buffer index (%d) out of range", int(buf));
         mPostedDirtyRegion.clear();
         return;
     }
 
+    if (noActiveBuffer) {
+        // we didn't have an active buffer, we need to recompute
+        // our visible region
+        recomputeVisibleRegions = true;
+    }
+
     sp<GraphicBuffer> newFrontBuffer(getBuffer(buf));
     if (newFrontBuffer != NULL) {
         // get the dirty region
@@ -888,6 +897,10 @@
     return result;
 }
 
+bool Layer::BufferManager::hasActiveBuffer() const {
+    return mActiveBuffer >= 0;
+}
+
 sp<GraphicBuffer> Layer::BufferManager::detachBuffer(size_t index)
 {
     BufferData* const buffers = mBufferData;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 30021d3..c367a8d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -188,6 +188,8 @@
         size_t getActiveBufferIndex() const;
         // return the active buffer
         sp<GraphicBuffer> getActiveBuffer() const;
+        // return wether we have an active buffer
+        bool hasActiveBuffer() const;
         // return the active texture (or fail-over)
         Texture getActiveTexture() const;
         // frees resources associated with all buffers