Support SurfaceView synchronization.

Add API for fetching the next frame number to be produced by
a given buffer producer. Add an API to SurfaceComposer to 
defer execution of the current transaction until a given frame number. 
Together these may be used to synchronize app drawing and surface 
control updates.

Change-Id: I8e0f4993332ac0199c768c88581a453fefbaff1d
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 48971bc..392b1cc 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -539,6 +539,10 @@
     return String8("VirtualDisplaySurface");
 }
 
+uint64_t VirtualDisplaySurface::getNextFrameNumber() const {
+    return 0;
+}
+
 void VirtualDisplaySurface::updateQueueBufferOutput(
         const QueueBufferOutput& qbo) {
     uint32_t w, h, transformHint, numPendingBuffers;
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index d53d43c..fb37373 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -119,6 +119,7 @@
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
+    virtual uint64_t getNextFrameNumber() const override;
 
     //
     // Utility methods
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 33af4a5..a7b167f 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -66,6 +66,8 @@
         mName("unnamed"),
         mFormat(PIXEL_FORMAT_NONE),
         mTransactionFlags(0),
+        mPendingStateMutex(),
+        mPendingStates(),
         mQueuedFrames(0),
         mSidebandStreamChanged(false),
         mCurrentTransform(0),
@@ -164,6 +166,20 @@
     }
 }
 
+void Layer::markSyncPointsAvailable(const BufferItem& item) {
+    auto pointIter = mLocalSyncPoints.begin();
+    while (pointIter != mLocalSyncPoints.end()) {
+        if ((*pointIter)->getFrameNumber() == item.mFrameNumber) {
+            auto syncPoint = *pointIter;
+            pointIter = mLocalSyncPoints.erase(pointIter);
+            Mutex::Autolock lock(mAvailableFrameMutex);
+            mAvailableFrames.push_back(std::move(syncPoint));
+        } else {
+            ++pointIter;
+        }
+    }
+}
+
 void Layer::onFrameAvailable(const BufferItem& item) {
     // Add this buffer from our internal queue tracker
     { // Autolock scope
@@ -192,30 +208,36 @@
         mQueueItemCondition.broadcast();
     }
 
+    markSyncPointsAvailable(item);
+
     mFlinger->signalLayerUpdate();
 }
 
 void Layer::onFrameReplaced(const BufferItem& item) {
-    Mutex::Autolock lock(mQueueItemLock);
+    { // Autolock scope
+        Mutex::Autolock lock(mQueueItemLock);
 
-    // Ensure that callbacks are handled in order
-    while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
-        status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
-                ms2ns(500));
-        if (result != NO_ERROR) {
-            ALOGE("[%s] Timed out waiting on callback", mName.string());
+        // Ensure that callbacks are handled in order
+        while (item.mFrameNumber != mLastFrameNumberReceived + 1) {
+            status_t result = mQueueItemCondition.waitRelative(mQueueItemLock,
+                    ms2ns(500));
+            if (result != NO_ERROR) {
+                ALOGE("[%s] Timed out waiting on callback", mName.string());
+            }
         }
+
+        if (mQueueItems.empty()) {
+            ALOGE("Can't replace a frame on an empty queue");
+            return;
+        }
+        mQueueItems.editItemAt(0) = item;
+
+        // Wake up any pending callbacks
+        mLastFrameNumberReceived = item.mFrameNumber;
+        mQueueItemCondition.broadcast();
     }
 
-    if (mQueueItems.empty()) {
-        ALOGE("Can't replace a frame on an empty queue");
-        return;
-    }
-    mQueueItems.editItemAt(0) = item;
-
-    // Wake up any pending callbacks
-    mLastFrameNumberReceived = item.mFrameNumber;
-    mQueueItemCondition.broadcast();
+    markSyncPointsAvailable(item);
 }
 
 void Layer::onSidebandStreamChanged() {
@@ -266,6 +288,22 @@
     return NO_ERROR;
 }
 
+/*
+ * The layer handle is just a BBinder object passed to the client
+ * (remote process) -- we don't keep any reference on our side such that
+ * the dtor is called when the remote side let go of its reference.
+ *
+ * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
+ * this layer when the handle is destroyed.
+ */
+class Layer::Handle : public BBinder, public LayerCleaner {
+    public:
+        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
+            : LayerCleaner(flinger, layer), owner(layer) {}
+
+        wp<Layer> owner;
+};
+
 sp<IBinder> Layer::getHandle() {
     Mutex::Autolock _l(mLock);
 
@@ -274,23 +312,6 @@
 
     mHasSurface = true;
 
-    /*
-     * The layer handle is just a BBinder object passed to the client
-     * (remote process) -- we don't keep any reference on our side such that
-     * the dtor is called when the remote side let go of its reference.
-     *
-     * LayerCleaner ensures that mFlinger->onLayerDestroyed() is called for
-     * this layer when the handle is destroyed.
-     */
-
-    class Handle : public BBinder, public LayerCleaner {
-        wp<const Layer> mOwner;
-    public:
-        Handle(const sp<SurfaceFlinger>& flinger, const sp<Layer>& layer)
-            : LayerCleaner(flinger, layer), mOwner(layer) {
-        }
-    };
-
     return new Handle(mFlinger, this);
 }
 
@@ -781,6 +802,24 @@
     return static_cast<uint32_t>(producerStickyTransform);
 }
 
+void Layer::addSyncPoint(std::shared_ptr<SyncPoint> point) {
+    uint64_t headFrameNumber = 0;
+    {
+        Mutex::Autolock lock(mQueueItemLock);
+        if (!mQueueItems.empty()) {
+            headFrameNumber = mQueueItems[0].mFrameNumber;
+        } else {
+            headFrameNumber = mLastFrameNumberReceived;
+        }
+    }
+
+    if (point->getFrameNumber() <= headFrameNumber) {
+        point->setFrameAvailable();
+    } else {
+        mLocalSyncPoints.push_back(std::move(point));
+    }
+}
+
 void Layer::setFiltering(bool filtering) {
     mFiltering = filtering;
 }
@@ -895,9 +934,103 @@
 // transaction
 // ----------------------------------------------------------------------------
 
+void Layer::pushPendingState() {
+    if (!mCurrentState.modified) {
+        return;
+    }
+
+    Mutex::Autolock lock(mPendingStateMutex);
+
+    // If this transaction is waiting on the receipt of a frame, generate a sync
+    // point and send it to the remote layer.
+    if (mCurrentState.handle != nullptr) {
+        sp<Handle> handle = static_cast<Handle*>(mCurrentState.handle.get());
+        sp<Layer> handleLayer = handle->owner.promote();
+        if (handleLayer == nullptr) {
+            ALOGE("[%s] Unable to promote Layer handle", mName.string());
+            // If we can't promote the layer we are intended to wait on,
+            // then it is expired or otherwise invalid. Allow this transaction
+            // to be applied as per normal (no synchronization).
+            mCurrentState.handle = nullptr;
+        }
+
+        auto syncPoint = std::make_shared<SyncPoint>(mCurrentState.frameNumber);
+        handleLayer->addSyncPoint(syncPoint);
+        mRemoteSyncPoints.push_back(std::move(syncPoint));
+
+        // Wake us up to check if the frame has been received
+        setTransactionFlags(eTransactionNeeded);
+    }
+    mPendingStates.push_back(mCurrentState);
+}
+
+void Layer::popPendingState() {
+    auto oldFlags = mCurrentState.flags;
+    mCurrentState = mPendingStates[0];
+    mCurrentState.flags = (oldFlags & ~mCurrentState.mask) | 
+            (mCurrentState.flags & mCurrentState.mask);
+
+    mPendingStates.removeAt(0);
+}
+
+bool Layer::applyPendingStates() {
+    Mutex::Autolock lock(mPendingStateMutex);
+
+    bool stateUpdateAvailable = false;
+    while (!mPendingStates.empty()) {
+        if (mPendingStates[0].handle != nullptr) {
+            if (mRemoteSyncPoints.empty()) {
+                // If we don't have a sync point for this, apply it anyway. It
+                // will be visually wrong, but it should keep us from getting
+                // into too much trouble.
+                ALOGE("[%s] No local sync point found", mName.string());
+                popPendingState();
+                stateUpdateAvailable = true;
+                continue;
+            }
+
+            if (mRemoteSyncPoints.front()->frameIsAvailable()) {
+                // Apply the state update
+                popPendingState();
+                stateUpdateAvailable = true;
+
+                // Signal our end of the sync point and then dispose of it
+                mRemoteSyncPoints.front()->setTransactionApplied();
+                mRemoteSyncPoints.pop_front();
+            }
+            break;
+        } else {
+            popPendingState();
+            stateUpdateAvailable = true;
+        }
+    }
+
+    // If we still have pending updates, wake SurfaceFlinger back up and point
+    // it at this layer so we can process them
+    if (!mPendingStates.empty()) {
+        setTransactionFlags(eTransactionNeeded);
+        mFlinger->setTransactionFlags(eTraversalNeeded);
+    }
+
+    mCurrentState.modified = false;
+    return stateUpdateAvailable;
+}
+
+void Layer::notifyAvailableFrames() {
+    Mutex::Autolock lock(mAvailableFrameMutex);
+    for (auto frame : mAvailableFrames) {
+        frame->setFrameAvailable();
+    }
+}
+
 uint32_t Layer::doTransaction(uint32_t flags) {
     ATRACE_CALL();
 
+    pushPendingState();
+    if (!applyPendingStates()) {
+        return 0;
+    }
+
     const Layer::State& s(getDrawingState());
     const Layer::State& c(getCurrentState());
 
@@ -1017,6 +1150,7 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.transform.set(x, y);
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1025,6 +1159,7 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.z = z;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1033,6 +1168,7 @@
         return false;
     mCurrentState.requested.w = w;
     mCurrentState.requested.h = h;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1041,6 +1177,7 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.alpha = alpha;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1048,11 +1185,13 @@
     mCurrentState.sequence++;
     mCurrentState.transform.set(
             matrix.dsdx, matrix.dsdy, matrix.dtdx, matrix.dtdy);
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 bool Layer::setTransparentRegionHint(const Region& transparent) {
     mCurrentState.requestedTransparentRegion = transparent;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1062,6 +1201,8 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.flags = newFlags;
+    mCurrentState.mask = mask;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1070,6 +1211,7 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.requested.crop = crop;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
@@ -1079,10 +1221,22 @@
         return false;
     mCurrentState.sequence++;
     mCurrentState.layerStack = layerStack;
+    mCurrentState.modified = true;
     setTransactionFlags(eTransactionNeeded);
     return true;
 }
 
+void Layer::deferTransactionUntil(const sp<IBinder>& handle,
+        uint64_t frameNumber) {
+    mCurrentState.handle = handle;
+    mCurrentState.frameNumber = frameNumber;
+    // We don't set eTransactionNeeded, because just receiving a deferral
+    // request without any other state updates shouldn't actually induce a delay
+    mCurrentState.modified = true;
+    pushPendingState();
+    mCurrentState.modified = false;
+}
+
 void Layer::useSurfaceDamage() {
     if (mFlinger->mForceFullDamage) {
         surfaceDamageRegion = Region::INVALID_REGION;
@@ -1307,9 +1461,35 @@
                 getProducerStickyTransform() != 0);
 
         uint64_t maxFrameNumber = 0;
+        uint64_t headFrameNumber = 0;
         {
             Mutex::Autolock lock(mQueueItemLock);
             maxFrameNumber = mLastFrameNumberReceived;
+            if (!mQueueItems.empty()) {
+                headFrameNumber = mQueueItems[0].mFrameNumber;
+            }
+        }
+
+        bool availableFramesEmpty = true;
+        {
+            Mutex::Autolock lock(mAvailableFrameMutex);
+            availableFramesEmpty = mAvailableFrames.empty();
+        }
+        if (!availableFramesEmpty) {
+            Mutex::Autolock lock(mAvailableFrameMutex);
+            bool matchingFramesFound = false;
+            bool allTransactionsApplied = true;
+            for (auto& frame : mAvailableFrames) {
+                if (headFrameNumber != frame->getFrameNumber()) {
+                    break;
+                }
+                matchingFramesFound = true;
+                allTransactionsApplied &= frame->transactionIsApplied();
+            }
+            if (matchingFramesFound && !allTransactionsApplied) {
+                mFlinger->signalLayerUpdate();
+                return outDirtyRegion;
+            }
         }
 
         status_t updateResult = mSurfaceFlingerConsumer->updateTexImage(&r,
@@ -1368,6 +1548,15 @@
             mFlinger->signalLayerUpdate();
         }
 
+        if (!availableFramesEmpty) {
+            Mutex::Autolock lock(mAvailableFrameMutex);
+            auto frameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+            while (!mAvailableFrames.empty() &&
+                    frameNumber == mAvailableFrames.front()->getFrameNumber()) {
+                mAvailableFrames.pop_front();
+            }
+        }
+
         if (updateResult != NO_ERROR) {
             // something happened!
             recomputeVisibleRegions = true;
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index c1e5e9f..4ff9006 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -36,6 +36,8 @@
 
 #include <private/gui/LayerState.h>
 
+#include <list>
+
 #include "FrameTracker.h"
 #include "Client.h"
 #include "MonitoredProducer.h"
@@ -107,9 +109,17 @@
         uint32_t layerStack;
         uint8_t alpha;
         uint8_t flags;
+        uint8_t mask;
         uint8_t reserved[2];
         int32_t sequence; // changes when visible regions can change
         Transform transform;
+        bool modified;
+
+        // If set, defers this state update until the Layer identified by handle
+        // receives a frame with the given frameNumber
+        sp<IBinder> handle;
+        uint64_t frameNumber;
+
         // the transparentRegion hint is a bit special, it's latched only
         // when we receive a buffer -- this is because it's "content"
         // dependent.
@@ -137,6 +147,7 @@
     bool setFlags(uint8_t flags, uint8_t mask);
     bool setCrop(const Rect& crop);
     bool setLayerStack(uint32_t layerStack);
+    void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber);
 
     // If we have received a new buffer this frame, we will pass its surface
     // damage down to hardware composer. Otherwise, we must send a region with
@@ -152,6 +163,7 @@
     Rect computeBounds(const Region& activeTransparentRegion) const;
     Rect computeBounds() const;
 
+    class Handle;
     sp<IBinder> getHandle();
     sp<IGraphicBufferProducer> getProducer() const;
     const String8& getName() const;
@@ -343,6 +355,10 @@
     virtual void onFrameReplaced(const BufferItem& item) override;
     virtual void onSidebandStreamChanged() override;
 
+    // Move frames made available by item in to a list which will
+    // be signalled at the beginning of the next transaction
+    virtual void markSyncPointsAvailable(const BufferItem& item);
+
     void commitTransaction();
 
     // needsLinearFiltering - true if this surface's state requires filtering
@@ -362,6 +378,56 @@
     // Temporary - Used only for LEGACY camera mode.
     uint32_t getProducerStickyTransform() const;
 
+    // -----------------------------------------------------------------------
+
+    class SyncPoint
+    {
+    public:
+        SyncPoint(uint64_t frameNumber) : mFrameNumber(frameNumber),
+                mFrameIsAvailable(false), mTransactionIsApplied(false) {}
+
+        uint64_t getFrameNumber() const {
+            return mFrameNumber;
+        }
+
+        bool frameIsAvailable() const {
+            return mFrameIsAvailable;
+        }
+
+        void setFrameAvailable() {
+            mFrameIsAvailable = true;
+        }
+
+        bool transactionIsApplied() const {
+            return mTransactionIsApplied;
+        }
+
+        void setTransactionApplied() {
+            mTransactionIsApplied = true;
+        }
+
+    private:
+        const uint64_t mFrameNumber;
+        std::atomic<bool> mFrameIsAvailable;
+        std::atomic<bool> mTransactionIsApplied;
+    };
+
+    std::list<std::shared_ptr<SyncPoint>> mLocalSyncPoints;
+
+    // Guarded by mPendingStateMutex
+    std::list<std::shared_ptr<SyncPoint>> mRemoteSyncPoints;
+
+    void addSyncPoint(std::shared_ptr<SyncPoint> point);
+
+    void pushPendingState();
+    void popPendingState();
+    bool applyPendingStates();
+
+    Mutex mAvailableFrameMutex;
+    std::list<std::shared_ptr<SyncPoint>> mAvailableFrames;
+public:
+    void notifyAvailableFrames();
+private:
 
     // -----------------------------------------------------------------------
 
@@ -378,6 +444,10 @@
     State mDrawingState;
     volatile int32_t mTransactionFlags;
 
+    // Accessed from main thread and binder threads
+    Mutex mPendingStateMutex;
+    Vector<State> mPendingStates;
+
     // thread-safe
     volatile int32_t mQueuedFrames;
     volatile int32_t mSidebandStreamChanged; // used like an atomic boolean
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index 79ef92f..68b6b86 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -127,6 +127,10 @@
     return mProducer->getConsumerName();
 }
 
+uint64_t MonitoredProducer::getNextFrameNumber() const {
+    return mProducer->getNextFrameNumber();
+}
+
 IBinder* MonitoredProducer::onAsBinder() {
     return IInterface::asBinder(mProducer).get();
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 3df6f0f..4d2ed6e 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -57,6 +57,7 @@
     virtual status_t allowAllocation(bool allow);
     virtual status_t setGenerationNumber(uint32_t generationNumber);
     virtual String8 getConsumerName() const override;
+    virtual uint64_t getNextFrameNumber() const override;
     virtual IBinder* onAsBinder();
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 285b829..093ca12 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1326,6 +1326,11 @@
     const LayerVector& currentLayers(mCurrentState.layersSortedByZ);
     const size_t count = currentLayers.size();
 
+    // Notify all layers of available frames
+    for (size_t i = 0; i < count; ++i) {
+        currentLayers[i]->notifyAvailableFrames();
+    }
+
     /*
      * Traversal of the children
      * (perform the transaction for each of them if needed)
@@ -2280,6 +2285,11 @@
                 flags |= eTransactionNeeded|eTraversalNeeded;
             }
         }
+        if (what & layer_state_t::eDeferTransaction) {
+            layer->deferTransactionUntil(s.handle, s.frameNumber);
+            // We don't trigger a traversal here because if no other state is
+            // changed, we don't want this to cause any more work
+        }
     }
     return flags;
 }