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();
         }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 4ff9006..9e3c4db 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -306,7 +306,8 @@
     /*
      * Returns if a frame is queued.
      */
-    bool hasQueuedFrame() const { return mQueuedFrames > 0 || mSidebandStreamChanged; }
+    bool hasQueuedFrame() const { return mQueuedFrames > 0 ||
+            mSidebandStreamChanged || mSingleBufferMode; }
 
     // -----------------------------------------------------------------------
 
@@ -489,6 +490,8 @@
     Vector<BufferItem> mQueueItems;
     uint64_t mLastFrameNumberReceived;
     bool mUpdateTexImageFailed; // This is only modified from the main thread
+
+    bool mSingleBufferMode;
 };
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 930e7c7..5722fb4 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -32,7 +32,8 @@
 // ---------------------------------------------------------------------------
 
 status_t SurfaceFlingerConsumer::updateTexImage(BufferRejecter* rejecter,
-        const DispSync& dispSync, uint64_t maxFrameNumber)
+        const DispSync& dispSync, bool* singleBufferMode, bool* queuedBuffer,
+        uint64_t maxFrameNumber)
 {
     ATRACE_CALL();
     ALOGV("updateTexImage");
@@ -68,7 +69,6 @@
         return err;
     }
 
-
     // We call the rejecter here, in case the caller has a reason to
     // not accept this buffer.  This is used by SurfaceFlinger to
     // reject buffers which have the wrong size
@@ -78,6 +78,14 @@
         return BUFFER_REJECTED;
     }
 
+    if (singleBufferMode) {
+        *singleBufferMode = item.mSingleBufferMode;
+    }
+
+    if (queuedBuffer) {
+        *queuedBuffer = item.mQueuedBuffer;
+    }
+
     // Release the previous buffer.
     err = updateAndReleaseLocked(item);
     if (err != NO_ERROR) {
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index 779e5b7..207c243 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -57,6 +57,7 @@
     // this does not guarantee that the buffer has been bound to the GL
     // texture.
     status_t updateTexImage(BufferRejecter* rejecter, const DispSync& dispSync,
+            bool* singleBufferMode, bool* queuedBuffer,
             uint64_t maxFrameNumber = 0);
 
     // See GLConsumer::bindTextureImageLocked().