Add Surface::waitForNextFrame

We can use this for cases like SurfaceView
where one thread (e.g. the framework code)
wants to wait for an unknown client thread
to render a frame in to the surface before
we report it as shown to the window manager.

Bug: 22207948
Change-Id: I9d3344aa1c0ab0f0efd9df24e90ce0410d5f2e22
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index 5d1d7bf..f76a9be 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -122,6 +122,13 @@
     // See IGraphicBufferProducer::setDequeueTimeout
     status_t setDequeueTimeout(nsecs_t timeout);
 
+    /*
+     * Wait for frame number to increase past lastFrame for at most
+     * timeoutNs. Useful for one thread to wait for another unknown
+     * thread to queue a buffer.
+     */
+    bool waitForNextFrame(uint64_t lastFrame, nsecs_t timeout);
+
 protected:
     virtual ~Surface();
 
@@ -348,6 +355,8 @@
     // This is true if the shared buffer has already been queued/canceled. It's
     // used to prevent a mismatch between the number of queue/dequeue calls.
     bool mSharedBufferHasBeenQueued;
+
+    Condition mQueueBufferCondition;
 };
 
 namespace view {
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 76b62f1..5efc333 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -480,6 +480,8 @@
         mSharedBufferHasBeenQueued = true;
     }
 
+    mQueueBufferCondition.broadcast();
+
     return err;
 }
 
@@ -1259,6 +1261,15 @@
     return err;
 }
 
+bool Surface::waitForNextFrame(uint64_t lastFrame, nsecs_t timeout) {
+    Mutex::Autolock lock(mMutex);
+    uint64_t currentFrame = mGraphicBufferProducer->getNextFrameNumber();
+    if (currentFrame > lastFrame) {
+      return true;
+    }
+    return mQueueBufferCondition.waitRelative(mMutex, timeout) == OK;
+}
+
 namespace view {
 
 status_t Surface::writeToParcel(Parcel* parcel) const {