SF: Force refresh when in single buffer mode

- Add a boolean to BufferItem to track whether single buffer mode is
  enabled. When it is, force SurfaceFlinger to acquire a new buffer
  and refresh on every vsync.

Bug 24940410

Change-Id: Iea67330c416b6fb14500865f98c67f1c12f23197
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index a7b167f..ad53226 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1254,7 +1254,7 @@
 // ----------------------------------------------------------------------------
 
 bool Layer::shouldPresentNow(const DispSync& dispSync) const {
-    if (mSidebandStreamChanged) {
+    if (mSidebandStreamChanged || mSingleBufferMode) {
         return true;
     }
 
@@ -1278,7 +1278,7 @@
 
 bool Layer::onPreComposition() {
     mRefreshPending = false;
-    return mQueuedFrames > 0 || mSidebandStreamChanged;
+    return mQueuedFrames > 0 || mSidebandStreamChanged || mSingleBufferMode;
 }
 
 void Layer::onPostComposition() {
@@ -1335,7 +1335,7 @@
     }
 
     Region outDirtyRegion;
-    if (mQueuedFrames > 0) {
+    if (mQueuedFrames > 0 || mSingleBufferMode) {
 
         // if we've already called updateTexImage() without going through
         // a composition step, we have to skip this layer at this point
@@ -1492,8 +1492,14 @@
             }
         }
 
+        // This boolean is used to make sure that SurfaceFlinger's shadow copy
+        // of the buffer queue isn't modified when the buffer queue is returning
+        // BufferItem's that weren't actually queued. This can happen in single
+        // buffer mode.
+        bool queuedBuffer = false;
         status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
-                mFlinger->mPrimaryDispSync, maxFrameNumber);
+                mFlinger->mPrimaryDispSync, &mSingleBufferMode, &queuedBuffer,
+                maxFrameNumber);
         if (updateResult == BufferQueue::PRESENT_LATER) {
             // Producer doesn't want buffer to be displayed yet.  Signal a
             // layer update so we check again at the next opportunity.
@@ -1502,16 +1508,18 @@
         } else if (updateResult == SurfaceFlingerConsumer::BUFFER_REJECTED) {
             // If the buffer has been rejected, remove it from the shadow queue
             // and return early
-            Mutex::Autolock lock(mQueueItemLock);
-            mQueueItems.removeAt(0);
-            android_atomic_dec(&mQueuedFrames);
+            if (queuedBuffer) {
+                Mutex::Autolock lock(mQueueItemLock);
+                mQueueItems.removeAt(0);
+                android_atomic_dec(&mQueuedFrames);
+            }
             return outDirtyRegion;
         } else if (updateResult != NO_ERROR || mUpdateTexImageFailed) {
             // This can occur if something goes wrong when trying to create the
             // EGLImage for this buffer. If this happens, the buffer has already
             // been released, so we need to clean up the queue and bug out
             // early.
-            {
+            if (queuedBuffer) {
                 Mutex::Autolock lock(mQueueItemLock);
                 mQueueItems.clear();
                 android_atomic_and(0, &mQueuedFrames);
@@ -1526,7 +1534,8 @@
             return outDirtyRegion;
         }
 
-        { // Autolock scope
+        if (queuedBuffer) {
+            // Autolock scope
             auto currentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
 
             Mutex::Autolock lock(mQueueItemLock);
@@ -1544,7 +1553,8 @@
 
         // Decrement the queued-frames count.  Signal another event if we
         // have more frames pending.
-        if (android_atomic_dec(&mQueuedFrames) > 1) {
+        if ((queuedBuffer && android_atomic_dec(&mQueuedFrames) > 1)
+                || mSingleBufferMode) {
             mFlinger->signalLayerUpdate();
         }