Use FenceTime to share fence times and reduce open fds.

FenceTimes are created and shared for each Fence that
FrameTimestampHistory and FrameTracker care about.

On the consumer side, the FenceTimes are also added to
shared timelines that are owned by SurfaceFlinger or
unshared timelines owned by Layer.  The timelines are
checked at the end of every frame to minimize the number
of file descriptors open.

On the producer side, the FenceTimes are added to
the ConsumerFrameEventHistory instead, since the timelines
that would be tracked by SurfaceFlinger are not shared
with anyone else in the consumer's process. The timelines
are checked just after a frame is queued to minimize
the number of file descriptors open.

Test: adb shell /data/nativetest/libgui_test/libgui_test
--gtest_filter=*GetFrameTimestamps*

Change-Id: Ifd4301affe1b24705b2bee7608c5a2c09dfb4041
diff --git a/include/gui/BufferItem.h b/include/gui/BufferItem.h
index 5232d0f..ab676cc 100644
--- a/include/gui/BufferItem.h
+++ b/include/gui/BufferItem.h
@@ -20,6 +20,7 @@
 #include <EGL/egl.h>
 #include <EGL/eglext.h>
 
+#include <ui/FenceTime.h>
 #include <ui/Rect.h>
 #include <ui/Region.h>
 
@@ -59,6 +60,9 @@
     // mFence is a fence that will signal when the buffer is idle.
     sp<Fence> mFence;
 
+    // The std::shared_ptr<FenceTime> wrapper around mFence.
+    std::shared_ptr<FenceTime> mFenceTime{FenceTime::NO_FENCE};
+
     // mCrop is the current crop rectangle for this buffer slot.
     Rect mCrop;
 
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 0e95ec3..a1d4e07 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -17,7 +17,7 @@
 #ifndef ANDROID_GUI_FRAMETIMESTAMPS_H
 #define ANDROID_GUI_FRAMETIMESTAMPS_H
 
-#include <ui/Fence.h>
+#include <ui/FenceTime.h>
 #include <utils/Flattenable.h>
 #include <utils/StrongPointer.h>
 #include <utils/Timers.h>
@@ -28,12 +28,12 @@
 
 namespace android {
 
-
 struct FrameEvents;
 class FrameEventHistoryDelta;
 class String8;
 
 
+// Identifiers for all the events that may be recorded or reported.
 enum class FrameEvent {
     POSTED,
     REQUESTED_PRESENT,
@@ -79,23 +79,17 @@
     bool addRetireCalled{false};
     bool addReleaseCalled{false};
 
-    nsecs_t postedTime{0};
-    nsecs_t requestedPresentTime{0};
-    nsecs_t latchTime{0};
-    nsecs_t firstRefreshStartTime{0};
-    nsecs_t lastRefreshStartTime{0};
+    nsecs_t postedTime{-1};
+    nsecs_t requestedPresentTime{-1};
+    nsecs_t latchTime{-1};
+    nsecs_t firstRefreshStartTime{-1};
+    nsecs_t lastRefreshStartTime{-1};
 
-    nsecs_t acquireTime{0};
-    nsecs_t gpuCompositionDoneTime{0};
-    nsecs_t displayPresentTime{0};
-    nsecs_t displayRetireTime{0};
-    nsecs_t releaseTime{0};
-
-    sp<Fence> acquireFence{Fence::NO_FENCE};
-    sp<Fence> gpuCompositionDoneFence{Fence::NO_FENCE};
-    sp<Fence> displayPresentFence{Fence::NO_FENCE};
-    sp<Fence> displayRetireFence{Fence::NO_FENCE};
-    sp<Fence> releaseFence{Fence::NO_FENCE};
+    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> gpuCompositionDoneFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> displayPresentFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> displayRetireFence{FenceTime::NO_FENCE};
+    std::shared_ptr<FenceTime> releaseFence{FenceTime::NO_FENCE};
 };
 
 
@@ -122,11 +116,23 @@
 public:
     ~ProducerFrameEventHistory() override;
 
-    void updateAcquireFence(uint64_t frameNumber, sp<Fence> acquire);
+    void updateAcquireFence(
+            uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire);
     void applyDelta(const FrameEventHistoryDelta& delta);
 
+    void updateSignalTimes();
+
 private:
     size_t mAcquireOffset{0};
+
+    // The consumer updates it's timelines in Layer and SurfaceFlinger since
+    // they can coordinate shared timelines better. The producer doesn't have
+    // shared timelines though, so just let it own and update all of them.
+    FenceTimeline mAcquireTimeline;
+    FenceTimeline mGpuCompositionDoneTimeline;
+    FenceTimeline mPresentTimeline;
+    FenceTimeline mRetireTimeline;
+    FenceTimeline mReleaseTimeline;
 };
 
 
@@ -136,7 +142,7 @@
     uint64_t frameNumber{0};
     nsecs_t postedTime{0};
     nsecs_t requestedPresentTime{0};
-    sp<Fence> acquireFence{Fence::NO_FENCE};
+    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
 };
 
 
@@ -175,13 +181,19 @@
     void addLatch(uint64_t frameNumber, nsecs_t latchTime);
     void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
     void addPostComposition(uint64_t frameNumber,
-            sp<Fence> gpuCompositionDone, sp<Fence> displayPresent);
-    void addRetire(uint64_t frameNumber, sp<Fence> displayRetire);
-    void addRelease(uint64_t frameNumber, sp<Fence> release);
+            const std::shared_ptr<FenceTime>& gpuCompositionDone,
+            const std::shared_ptr<FenceTime>& displayPresent);
+    void addRetire(uint64_t frameNumber,
+            const std::shared_ptr<FenceTime>& displayRetire);
+    void addRelease(uint64_t frameNumber,
+            std::shared_ptr<FenceTime>&& release);
 
     void getAndResetDelta(FrameEventHistoryDelta* delta);
 
 private:
+    void getFrameDelta(FrameEventHistoryDelta* delta,
+            const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame);
+
     std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
     size_t mQueueOffset{0};
     size_t mCompositionOffset{0};
@@ -202,6 +214,13 @@
             const FrameEvents& frameTimestamps,
             const FrameEventDirtyFields& dirtyFields);
 
+    // Movable.
+    FrameEventsDelta(FrameEventsDelta&& src) = default;
+    FrameEventsDelta& operator=(FrameEventsDelta&& src) = default;
+    // Not copyable.
+    FrameEventsDelta(const FrameEventsDelta& src) = delete;
+    FrameEventsDelta& operator=(const FrameEventsDelta& src) = delete;
+
     // Flattenable implementation
     size_t getFlattenedSize() const;
     size_t getFdCount() const;
@@ -226,10 +245,10 @@
     nsecs_t mFirstRefreshStartTime{0};
     nsecs_t mLastRefreshStartTime{0};
 
-    sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
-    sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
-    sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
-    sp<Fence> mReleaseFence{Fence::NO_FENCE};
+    FenceTime::Snapshot mGpuCompositionDoneFence;
+    FenceTime::Snapshot mDisplayPresentFence;
+    FenceTime::Snapshot mDisplayRetireFence;
+    FenceTime::Snapshot mReleaseFence;
 
     // This is a static method with an auto return value so we can call
     // it without needing const and non-const versions.
@@ -253,6 +272,16 @@
 friend class ProducerFrameEventHistory;
 
 public:
+    FrameEventHistoryDelta() = default;
+
+    // Movable.
+    FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
+    FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src);
+    // Not copyable.
+    FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
+    FrameEventHistoryDelta& operator=(
+            const FrameEventHistoryDelta& src) = delete;
+
     // Flattenable implementation.
     size_t getFlattenedSize() const;
     size_t getFdCount() const;
diff --git a/include/gui/GLConsumer.h b/include/gui/GLConsumer.h
index 6ff1303..493ecde 100644
--- a/include/gui/GLConsumer.h
+++ b/include/gui/GLConsumer.h
@@ -187,6 +187,10 @@
     // ready to be read from.
     sp<Fence> getCurrentFence() const;
 
+    // getCurrentFence returns the FenceTime indicating when the current
+    // buffer is ready to be read from.
+    std::shared_ptr<FenceTime> getCurrentFenceTime() const;
+
     // doGLFenceWait inserts a wait command into the OpenGL ES command stream
     // to ensure that it is safe for future OpenGL ES commands to access the
     // current texture buffer.
@@ -398,6 +402,9 @@
     // mCurrentFence is the fence received from BufferQueue in updateTexImage.
     sp<Fence> mCurrentFence;
 
+    // The FenceTime wrapper around mCurrentFence.
+    std::shared_ptr<FenceTime> mCurrentFenceTime{FenceTime::NO_FENCE};
+
     // mCurrentTransformMatrix is the transform matrix for the current texture.
     // It gets computed by computeTransformMatrix each time updateTexImage is
     // called.
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 492db35..304a0c0 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -363,6 +363,15 @@
     };
 
     struct QueueBufferOutput : public Flattenable<QueueBufferOutput> {
+        QueueBufferOutput() = default;
+
+        // Moveable.
+        QueueBufferOutput(QueueBufferOutput&& src) = default;
+        QueueBufferOutput& operator=(QueueBufferOutput&& src) = default;
+        // Not copyable.
+        QueueBufferOutput(const QueueBufferOutput& src) = delete;
+        QueueBufferOutput& operator=(const QueueBufferOutput& src) = delete;
+
         // Flattenable protocol
         static constexpr size_t minFlattenedSize();
         size_t getFlattenedSize() const;
diff --git a/libs/gui/BufferItem.cpp b/libs/gui/BufferItem.cpp
index 669124e..ec2a9a6 100644
--- a/libs/gui/BufferItem.cpp
+++ b/libs/gui/BufferItem.cpp
@@ -204,6 +204,8 @@
         status_t err = mFence->unflatten(buffer, size, fds, count);
         if (err) return err;
         size -= FlattenableUtils::align<4>(buffer);
+
+        mFenceTime = std::make_shared<FenceTime>(mFence);
     }
 
     status_t err = mSurfaceDamage.unflatten(buffer, size);
diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp
index ee4c58c..d66aa1a 100644
--- a/libs/gui/BufferQueueConsumer.cpp
+++ b/libs/gui/BufferQueueConsumer.cpp
@@ -205,6 +205,7 @@
             // was cached when it was last queued.
             outBuffer->mGraphicBuffer = mSlots[slot].mGraphicBuffer;
             outBuffer->mFence = Fence::NO_FENCE;
+            outBuffer->mFenceTime = FenceTime::NO_FENCE;
             outBuffer->mCrop = mCore->mSharedBufferCache.crop;
             outBuffer->mTransform = mCore->mSharedBufferCache.transform &
                     ~static_cast<uint32_t>(
diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp
index 75198d7..39b9a0b 100644
--- a/libs/gui/BufferQueueProducer.cpp
+++ b/libs/gui/BufferQueueProducer.cpp
@@ -762,6 +762,8 @@
         return BAD_VALUE;
     }
 
+    auto acquireFenceTime = std::make_shared<FenceTime>(acquireFence);
+
     switch (scalingMode) {
         case NATIVE_WINDOW_SCALING_MODE_FREEZE:
         case NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW:
@@ -858,6 +860,7 @@
         item.mFrameNumber = currentFrameNumber;
         item.mSlot = slot;
         item.mFence = acquireFence;
+        item.mFenceTime = acquireFenceTime;
         item.mIsDroppable = mCore->mAsyncMode ||
                 mCore->mDequeueBufferCannotBlock ||
                 (mCore->mSharedBufferMode && mCore->mSharedBufferSlot == slot);
@@ -969,7 +972,7 @@
         // small trade-off in favor of latency rather than throughput.
         mLastQueueBufferFence->waitForever("Throttling EGL Production");
     }
-    mLastQueueBufferFence = acquireFence;
+    mLastQueueBufferFence = std::move(acquireFence);
     mLastQueuedCrop = item.mCrop;
     mLastQueuedTransform = item.mTransform;
 
@@ -979,7 +982,7 @@
         currentFrameNumber,
         postedTime,
         requestedPresentTimestamp,
-        acquireFence
+        std::move(acquireFenceTime)
     };
     addAndGetFrameTimestamps(&newFrameEventsEntry,
             getFrameTimestamps ? &output->frameTimestamps : nullptr);
diff --git a/libs/gui/FrameTimestamps.cpp b/libs/gui/FrameTimestamps.cpp
index 30ff65f..6503e9c 100644
--- a/libs/gui/FrameTimestamps.cpp
+++ b/libs/gui/FrameTimestamps.cpp
@@ -16,6 +16,7 @@
 
 #include <gui/FrameTimestamps.h>
 
+#include <cutils/compiler.h>  // For CC_[UN]LIKELY
 #include <inttypes.h>
 #include <utils/String8.h>
 
@@ -25,28 +26,25 @@
 
 namespace android {
 
-static inline bool isValidTimestamp(nsecs_t time) {
-    return time > 0 && time < INT64_MAX;
-}
 
 // ============================================================================
 // FrameEvents
 // ============================================================================
 
 bool FrameEvents::hasPostedInfo() const {
-    return isValidTimestamp(postedTime);
+    return Fence::isValidTimestamp(postedTime);
 }
 
 bool FrameEvents::hasRequestedPresentInfo() const {
-    return isValidTimestamp(requestedPresentTime);
+    return Fence::isValidTimestamp(requestedPresentTime);
 }
 
 bool FrameEvents::hasLatchInfo() const {
-    return isValidTimestamp(latchTime);
+    return Fence::isValidTimestamp(latchTime);
 }
 
 bool FrameEvents::hasFirstRefreshStartInfo() const {
-    return isValidTimestamp(firstRefreshStartTime);
+    return Fence::isValidTimestamp(firstRefreshStartTime);
 }
 
 bool FrameEvents::hasLastRefreshStartInfo() const {
@@ -57,7 +55,7 @@
 }
 
 bool FrameEvents::hasAcquireInfo() const {
-    return isValidTimestamp(acquireTime) || acquireFence->isValid();
+    return acquireFence->isValid();
 }
 
 bool FrameEvents::hasGpuCompositionDoneInfo() const {
@@ -80,22 +78,27 @@
     return addReleaseCalled;
 }
 
-static void checkFenceForCompletion(sp<Fence>* fence, nsecs_t* dstTime) {
-    if ((*fence)->isValid()) {
-        nsecs_t time = (*fence)->getSignalTime();
-        if (isValidTimestamp(time)) {
-            *dstTime = time;
-            *fence = Fence::NO_FENCE;
-        }
-    }
+void FrameEvents::checkFencesForCompletion() {
+    acquireFence->getSignalTime();
+    gpuCompositionDoneFence->getSignalTime();
+    displayPresentFence->getSignalTime();
+    displayRetireFence->getSignalTime();
+    releaseFence->getSignalTime();
 }
 
-void FrameEvents::checkFencesForCompletion() {
-    checkFenceForCompletion(&acquireFence, &acquireTime);
-    checkFenceForCompletion(&gpuCompositionDoneFence, &gpuCompositionDoneTime);
-    checkFenceForCompletion(&displayPresentFence, &displayPresentTime);
-    checkFenceForCompletion(&displayRetireFence, &displayRetireTime);
-    checkFenceForCompletion(&releaseFence, &releaseTime);
+static void dumpFenceTime(String8& outString, const char* name,
+        bool pending, const FenceTime& fenceTime) {
+    outString.appendFormat("--- %s", name);
+    nsecs_t signalTime = fenceTime.getCachedSignalTime();
+    if (Fence::isValidTimestamp(signalTime)) {
+        outString.appendFormat("%" PRId64 "\n", signalTime);
+    } else if (pending || signalTime == Fence::SIGNAL_TIME_PENDING) {
+        outString.appendFormat("Pending\n");
+    } else if (&fenceTime == FenceTime::NO_FENCE.get()){
+        outString.appendFormat("N/A\n");
+    } else {
+        outString.appendFormat("Error\n");
+    }
 }
 
 void FrameEvents::dump(String8& outString) const
@@ -109,66 +112,36 @@
     outString.appendFormat("--- Req. Present\t%" PRId64 "\n", requestedPresentTime);
 
     outString.appendFormat("--- Latched     \t");
-    if (isValidTimestamp(latchTime)) {
+    if (Fence::isValidTimestamp(latchTime)) {
         outString.appendFormat("%" PRId64 "\n", latchTime);
     } else {
         outString.appendFormat("Pending\n");
     }
 
     outString.appendFormat("--- Refresh (First)\t");
-    if (isValidTimestamp(firstRefreshStartTime)) {
+    if (Fence::isValidTimestamp(firstRefreshStartTime)) {
         outString.appendFormat("%" PRId64 "\n", firstRefreshStartTime);
     } else {
         outString.appendFormat("Pending\n");
     }
 
     outString.appendFormat("--- Refresh (Last)\t");
-    if (isValidTimestamp(lastRefreshStartTime)) {
+    if (Fence::isValidTimestamp(lastRefreshStartTime)) {
         outString.appendFormat("%" PRId64 "\n", lastRefreshStartTime);
     } else {
         outString.appendFormat("Pending\n");
     }
 
-    outString.appendFormat("--- Acquire     \t");
-    if (isValidTimestamp(acquireTime)) {
-        outString.appendFormat("%" PRId64 "\n", acquireTime);
-    } else {
-        outString.appendFormat("Pending\n");
-    }
-
-    outString.appendFormat("--- GPU Composite Done\t");
-    if (isValidTimestamp(gpuCompositionDoneTime)) {
-        outString.appendFormat("%" PRId64 "\n", gpuCompositionDoneTime);
-    } else if (!addPostCompositeCalled || gpuCompositionDoneFence->isValid()) {
-        outString.appendFormat("Pending\n");
-    } else {
-        outString.appendFormat("N/A\n");
-    }
-
-    outString.appendFormat("--- Display Present\t");
-    if (isValidTimestamp(displayPresentTime)) {
-        outString.appendFormat("%" PRId64 "\n", displayPresentTime);
-    } else if (!addPostCompositeCalled || displayPresentFence->isValid()) {
-        outString.appendFormat("Pending\n");
-    } else {
-        outString.appendFormat("N/A\n");
-    }
-
-    outString.appendFormat("--- Display Retire\t");
-    if (isValidTimestamp(displayRetireTime)) {
-        outString.appendFormat("%" PRId64 "\n", displayRetireTime);
-    } else if (!addRetireCalled || displayRetireFence->isValid()) {
-        outString.appendFormat("Pending\n");
-    } else {
-        outString.appendFormat("N/A\n");
-    }
-
-    outString.appendFormat("--- Release     \t");
-    if (isValidTimestamp(releaseTime)) {
-        outString.appendFormat("%" PRId64 "\n", releaseTime);
-    } else {
-        outString.appendFormat("Pending\n");
-    }
+    dumpFenceTime(outString, "Acquire           \t",
+            true, *acquireFence);
+    dumpFenceTime(outString, "GPU Composite Done\t",
+            !addPostCompositeCalled, *gpuCompositionDoneFence);
+    dumpFenceTime(outString, "Display Present   \t",
+            !addPostCompositeCalled, *displayPresentFence);
+    dumpFenceTime(outString, "Display Retire    \t",
+            !addRetireCalled, *displayRetireFence);
+    dumpFenceTime(outString, "Release           \t",
+            true, *releaseFence);
 }
 
 
@@ -250,7 +223,7 @@
 ProducerFrameEventHistory::~ProducerFrameEventHistory() = default;
 
 void ProducerFrameEventHistory::updateAcquireFence(
-        uint64_t frameNumber, sp<Fence> acquire) {
+        uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire) {
     FrameEvents* frame = getFrame(frameNumber, &mAcquireOffset);
     if (frame == nullptr) {
         ALOGE("ProducerFrameEventHistory::updateAcquireFence: "
@@ -259,20 +232,39 @@
     }
 
     if (acquire->isValid()) {
-        frame->acquireFence = acquire;
+        mAcquireTimeline.push(acquire);
+        frame->acquireFence = std::move(acquire);
     } else {
         // If there isn't an acquire fence, assume that buffer was
         // ready for the consumer when posted.
-        frame->acquireTime = frame->postedTime;
+        frame->acquireFence = std::make_shared<FenceTime>(frame->postedTime);
     }
 }
 
-static void applyFenceDelta(sp<Fence>* dst, const sp<Fence>& src) {
-    if (src->isValid()) {
-        if ((*dst)->isValid()) {
-            ALOGE("applyFenceDelta: Unexpected fence.");
-        }
-        *dst = src;
+static void applyFenceDelta(FenceTimeline* timeline,
+        std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) {
+    if (CC_UNLIKELY(dst == nullptr)) {
+        ALOGE("applyFenceDelta: dst is null.");
+        return;
+    }
+
+    switch (src.state) {
+        case FenceTime::Snapshot::State::EMPTY:
+            return;
+        case FenceTime::Snapshot::State::FENCE:
+            if (CC_UNLIKELY((*dst)->isValid())) {
+                ALOGE("applyFenceDelta: Unexpected fence.");
+            }
+            *dst = std::make_shared<FenceTime>(src.fence);
+            timeline->push(*dst);
+            return;
+        case FenceTime::Snapshot::State::SIGNAL_TIME:
+            if ((*dst)->isValid()) {
+                (*dst)->applyTrustedSnapshot(src);
+            } else {
+                *dst = std::make_shared<FenceTime>(src.signalTime);
+            }
+            return;
     }
 }
 
@@ -297,40 +289,37 @@
         frame.firstRefreshStartTime = d.mFirstRefreshStartTime;
         frame.lastRefreshStartTime = d.mLastRefreshStartTime;
 
-        if (frame.frameNumber == d.mFrameNumber) {
-            // Existing frame. Merge.
-            // Consumer never sends timestamps of fences, only the fences
-            // themselves, so we never need to update the fence timestamps here.
-            applyFenceDelta(
-                    &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
-            applyFenceDelta(&frame.displayPresentFence, d.mDisplayPresentFence);
-            applyFenceDelta(&frame.displayRetireFence, d.mDisplayRetireFence);
-            applyFenceDelta(&frame.releaseFence, d.mReleaseFence);
-        } else {
-            // New frame. Overwrite.
+        if (frame.frameNumber != d.mFrameNumber) {
+            // We got a new frame. Initialize some of the fields.
             frame.frameNumber = d.mFrameNumber;
-
-            frame.gpuCompositionDoneFence = d.mGpuCompositionDoneFence;
-            frame.displayPresentFence = d.mDisplayPresentFence;
-            frame.displayRetireFence = d.mDisplayRetireFence;
-            frame.releaseFence = d.mReleaseFence;
-
-            // Set aquire fence and time at this point.
-            frame.acquireTime = 0;
-            frame.acquireFence = Fence::NO_FENCE;
-
-            // Reset fence-related timestamps
-            frame.gpuCompositionDoneTime = 0;
-            frame.displayPresentTime = 0;
-            frame.displayRetireTime = 0;
-            frame.releaseTime = 0;
-
+            frame.acquireFence = FenceTime::NO_FENCE;
+            frame.gpuCompositionDoneFence = FenceTime::NO_FENCE;
+            frame.displayPresentFence = FenceTime::NO_FENCE;
+            frame.displayRetireFence = FenceTime::NO_FENCE;
+            frame.releaseFence = FenceTime::NO_FENCE;
             // The consumer only sends valid frames.
             frame.valid = true;
         }
+
+        applyFenceDelta(&mGpuCompositionDoneTimeline,
+                &frame.gpuCompositionDoneFence, d.mGpuCompositionDoneFence);
+        applyFenceDelta(&mPresentTimeline,
+                &frame.displayPresentFence, d.mDisplayPresentFence);
+        applyFenceDelta(&mRetireTimeline,
+                &frame.displayRetireFence, d.mDisplayRetireFence);
+        applyFenceDelta(&mReleaseTimeline,
+                &frame.releaseFence, d.mReleaseFence);
     }
 }
 
+void ProducerFrameEventHistory::updateSignalTimes() {
+    mAcquireTimeline.updateSignalTimes();
+    mGpuCompositionDoneTimeline.updateSignalTimes();
+    mPresentTimeline.updateSignalTimes();
+    mRetireTimeline.updateSignalTimes();
+    mReleaseTimeline.updateSignalTimes();
+}
+
 
 // ============================================================================
 // ConsumerFrameEventHistory
@@ -377,14 +366,15 @@
     }
     frame->lastRefreshStartTime = refreshStartTime;
     mFramesDirty[mCompositionOffset].setDirty<FrameEvent::LAST_REFRESH_START>();
-    if (!isValidTimestamp(frame->firstRefreshStartTime)) {
+    if (!Fence::isValidTimestamp(frame->firstRefreshStartTime)) {
         frame->firstRefreshStartTime = refreshStartTime;
         mFramesDirty[mCompositionOffset].setDirty<FrameEvent::FIRST_REFRESH_START>();
     }
 }
 
 void ConsumerFrameEventHistory::addPostComposition(uint64_t frameNumber,
-        sp<Fence> gpuCompositionDone, sp<Fence> displayPresent) {
+        const std::shared_ptr<FenceTime>& gpuCompositionDone,
+        const std::shared_ptr<FenceTime>& displayPresent) {
     FrameEvents* frame = getFrame(frameNumber, &mCompositionOffset);
     if (frame == nullptr) {
         ALOGE("ConsumerFrameEventHistory::addPostComposition: "
@@ -404,7 +394,7 @@
 }
 
 void ConsumerFrameEventHistory::addRetire(
-        uint64_t frameNumber, sp<Fence> displayRetire) {
+        uint64_t frameNumber, const std::shared_ptr<FenceTime>& displayRetire) {
     FrameEvents* frame = getFrame(frameNumber, &mRetireOffset);
     if (frame == nullptr) {
         ALOGE("ConsumerFrameEventHistory::addRetire: Did not find frame.");
@@ -416,26 +406,39 @@
 }
 
 void ConsumerFrameEventHistory::addRelease(
-        uint64_t frameNumber, sp<Fence> release) {
+        uint64_t frameNumber, std::shared_ptr<FenceTime>&& release) {
     FrameEvents* frame = getFrame(frameNumber, &mReleaseOffset);
     if (frame == nullptr) {
         ALOGE("ConsumerFrameEventHistory::addRelease: Did not find frame.");
         return;
     }
     frame->addReleaseCalled = true;
-    frame->releaseFence = release;
+    frame->releaseFence = std::move(release);
     mFramesDirty[mReleaseOffset].setDirty<FrameEvent::RELEASE>();
 }
 
+void ConsumerFrameEventHistory::getFrameDelta(
+        FrameEventHistoryDelta* delta,
+        const std::array<FrameEvents, MAX_FRAME_HISTORY>::iterator& frame) {
+    size_t i = static_cast<size_t>(std::distance(mFrames.begin(), frame));
+    if (mFramesDirty[i].anyDirty()) {
+        delta->mDeltas.emplace_back(i, *frame, mFramesDirty[i]);
+        mFramesDirty[i].reset();
+    }
+}
+
 void ConsumerFrameEventHistory::getAndResetDelta(
         FrameEventHistoryDelta* delta) {
+    // Write these in order of frame number so that it is easy to
+    // add them to a FenceTimeline in the proper order producer side.
     delta->mDeltas.reserve(mFramesDirty.size());
-    for (size_t i = 0; i < mFramesDirty.size(); i++) {
-        if (mFramesDirty[i].anyDirty()) {
-            delta->mDeltas.push_back(
-                    FrameEventsDelta(i, mFrames[i], mFramesDirty[i]));
-            mFramesDirty[i].reset();
-        }
+    auto earliestFrame = std::min_element(
+            mFrames.begin(), mFrames.end(), &FrameNumberLessThan);
+    for (auto frame = earliestFrame; frame != mFrames.end(); ++frame) {
+        getFrameDelta(delta, frame);
+    }
+    for (auto frame = mFrames.begin(); frame != earliestFrame; ++frame) {
+        getFrameDelta(delta, frame);
     }
 }
 
@@ -458,15 +461,20 @@
       mLatchTime(frameTimestamps.latchTime),
       mFirstRefreshStartTime(frameTimestamps.firstRefreshStartTime),
       mLastRefreshStartTime(frameTimestamps.lastRefreshStartTime) {
-    mGpuCompositionDoneFence =
-            dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>() ?
-                    frameTimestamps.gpuCompositionDoneFence : Fence::NO_FENCE;
-    mDisplayPresentFence = dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>() ?
-            frameTimestamps.displayPresentFence : Fence::NO_FENCE;
-    mDisplayRetireFence = dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>() ?
-            frameTimestamps.displayRetireFence : Fence::NO_FENCE;
-    mReleaseFence = dirtyFields.isDirty<FrameEvent::RELEASE>() ?
-            frameTimestamps.releaseFence : Fence::NO_FENCE;
+    if (dirtyFields.isDirty<FrameEvent::GL_COMPOSITION_DONE>()) {
+        mGpuCompositionDoneFence =
+                frameTimestamps.gpuCompositionDoneFence->getSnapshot();
+    }
+    if (dirtyFields.isDirty<FrameEvent::DISPLAY_PRESENT>()) {
+        mDisplayPresentFence =
+                frameTimestamps.displayPresentFence->getSnapshot();
+    }
+    if (dirtyFields.isDirty<FrameEvent::DISPLAY_RETIRE>()) {
+        mDisplayRetireFence = frameTimestamps.displayRetireFence->getSnapshot();
+    }
+    if (dirtyFields.isDirty<FrameEvent::RELEASE>()) {
+        mReleaseFence = frameTimestamps.releaseFence->getSnapshot();
+    }
 }
 
 size_t FrameEventsDelta::minFlattenedSize() {
@@ -489,16 +497,16 @@
     auto fences = allFences(this);
     return minFlattenedSize() +
             std::accumulate(fences.begin(), fences.end(), size_t(0),
-                    [](size_t a, const sp<Fence>* fence) {
-                            return a + (*fence)->getFlattenedSize();
+                    [](size_t a, const FenceTime::Snapshot* fence) {
+                            return a + fence->getFlattenedSize();
                     });
 }
 
 size_t FrameEventsDelta::getFdCount() const {
     auto fences = allFences(this);
     return std::accumulate(fences.begin(), fences.end(), size_t(0),
-            [](size_t a, const sp<Fence>* fence) {
-                return a + (*fence)->getFdCount();
+            [](size_t a, const FenceTime::Snapshot* fence) {
+                return a + fence->getFdCount();
             });
 }
 
@@ -532,7 +540,7 @@
 
     // Fences
     for (auto fence : allFences(this)) {
-        status_t status = (*fence)->flatten(buffer, size, fds, count);
+        status_t status = fence->flatten(buffer, size, fds, count);
         if (status != NO_ERROR) {
             return status;
         }
@@ -570,8 +578,7 @@
 
     // Fences
     for (auto fence : allFences(this)) {
-        *fence = new Fence;
-        status_t status = (*fence)->unflatten(buffer, size, fds, count);
+        status_t status = fence->unflatten(buffer, size, fds, count);
         if (status != NO_ERROR) {
             return status;
         }
@@ -584,6 +591,16 @@
 // FrameEventHistoryDelta
 // ============================================================================
 
+FrameEventHistoryDelta& FrameEventHistoryDelta::operator=(
+        FrameEventHistoryDelta&& src) {
+    if (CC_UNLIKELY(!mDeltas.empty())) {
+        ALOGE("FrameEventHistoryDelta: Clobbering history.");
+    }
+    mDeltas = std::move(src.mDeltas);
+    ALOGE_IF(src.mDeltas.empty(), "Source mDeltas not empty.");
+    return *this;
+}
+
 size_t FrameEventHistoryDelta::minFlattenedSize() {
     return sizeof(uint32_t);
 }
diff --git a/libs/gui/GLConsumer.cpp b/libs/gui/GLConsumer.cpp
index 10e999c..316e1d6 100644
--- a/libs/gui/GLConsumer.cpp
+++ b/libs/gui/GLConsumer.cpp
@@ -322,6 +322,7 @@
         mCurrentTransform = 0;
         mCurrentTimestamp = 0;
         mCurrentFence = Fence::NO_FENCE;
+        mCurrentFenceTime = FenceTime::NO_FENCE;
 
         if (mAttached) {
             // This binds a dummy buffer (mReleasedTexImage).
@@ -488,6 +489,7 @@
     mCurrentScalingMode = item.mScalingMode;
     mCurrentTimestamp = item.mTimestamp;
     mCurrentFence = item.mFence;
+    mCurrentFenceTime = item.mFenceTime;
     mCurrentFrameNumber = item.mFrameNumber;
 
     computeCurrentTransformMatrixLocked();
@@ -981,6 +983,11 @@
     return mCurrentFence;
 }
 
+std::shared_ptr<FenceTime> GLConsumer::getCurrentFenceTime() const {
+    Mutex::Autolock lock(mMutex);
+    return mCurrentFenceTime;
+}
+
 status_t GLConsumer::doGLFenceWait() const {
     Mutex::Autolock lock(mMutex);
     return doGLFenceWaitLocked();
diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp
index 6a02a77..c9e1c6c 100644
--- a/libs/gui/Surface.cpp
+++ b/libs/gui/Surface.cpp
@@ -144,6 +144,19 @@
     mEnableFrameTimestamps = enable;
 }
 
+static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
+    if (dst != nullptr) {
+        *dst = Fence::isValidTimestamp(src) ? src : 0;
+    }
+}
+
+static void getFrameTimestampFence(nsecs_t *dst, const std::shared_ptr<FenceTime>& src) {
+    if (dst != nullptr) {
+        nsecs_t signalTime = src->getSignalTime();
+        *dst = Fence::isValidTimestamp(signalTime) ? signalTime : 0;
+    }
+}
+
 status_t Surface::getFrameTimestamps(uint64_t frameNumber,
         nsecs_t* outRequestedPresentTime, nsecs_t* outAcquireTime,
         nsecs_t* outRefreshStartTime, nsecs_t* outGlCompositionDoneTime,
@@ -188,29 +201,16 @@
         return NAME_NOT_FOUND;
     }
 
-    events->checkFencesForCompletion();
+    getFrameTimestamp(outRequestedPresentTime, events->requestedPresentTime);
+    getFrameTimestamp(outRefreshStartTime, events->firstRefreshStartTime);
 
-    if (outRequestedPresentTime) {
-        *outRequestedPresentTime = events->requestedPresentTime;
-    }
-    if (outAcquireTime) {
-        *outAcquireTime = events->acquireTime;
-    }
-    if (outRefreshStartTime) {
-        *outRefreshStartTime = events->firstRefreshStartTime;
-    }
-    if (outGlCompositionDoneTime) {
-        *outGlCompositionDoneTime = events->gpuCompositionDoneTime;
-    }
-    if (outDisplayPresentTime) {
-        *outDisplayPresentTime = events->displayPresentTime;
-    }
-    if (outDisplayRetireTime) {
-        *outDisplayRetireTime = events->displayRetireTime;
-    }
-    if (outReleaseTime) {
-        *outReleaseTime = events->releaseTime;
-    }
+    getFrameTimestampFence(outAcquireTime, events->acquireFence);
+    getFrameTimestampFence(
+            outGlCompositionDoneTime, events->gpuCompositionDoneFence);
+    getFrameTimestampFence(
+            outDisplayPresentTime, events->displayPresentFence);
+    getFrameTimestampFence(outDisplayRetireTime, events->displayRetireFence);
+    getFrameTimestampFence(outReleaseTime, events->releaseFence);
 
     return NO_ERROR;
 }
@@ -571,7 +571,12 @@
         // Update timestamps with the local acquire fence.
         // The consumer doesn't send it back to prevent us from having two
         // file descriptors of the same fence.
-        mFrameEventHistory.updateAcquireFence(mNextFrameNumber, fence);
+        mFrameEventHistory.updateAcquireFence(mNextFrameNumber,
+                std::make_shared<FenceTime>(std::move(fence)));
+
+        // Cache timestamps of signaled fences so we can close their file
+        // descriptors.
+        mFrameEventHistory.updateSignalTimes();
     }
 
     mDefaultWidth = output.width;
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
index c82b0c4..034a394 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp
@@ -602,7 +602,7 @@
     return mDisplayData[displayId].lastPresentFence;
 }
 
-bool HWComposer::retireFenceRepresentsStartOfScanout() const {
+bool HWComposer::presentFenceRepresentsStartOfScanout() const {
     return mAdapter ? false : true;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h
index e63bdd4..2713505 100644
--- a/services/surfaceflinger/DisplayHardware/HWComposer.h
+++ b/services/surfaceflinger/DisplayHardware/HWComposer.h
@@ -121,10 +121,10 @@
     // get the present fence received from the last call to present.
     sp<Fence> getPresentFence(int32_t displayId) const;
 
-    // Returns true if the retire fence represents the start of the display
+    // Returns true if the present fence represents the start of the display
     // controller's scan out. This should be true for all HWC2 implementations,
     // except for the wrapper around HWC1 implementations.
-    bool retireFenceRepresentsStartOfScanout() const;
+    bool presentFenceRepresentsStartOfScanout() const;
 
     // Get last release fence for the given layer
     sp<Fence> getLayerReleaseFence(int32_t displayId,
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
index 0511df2..6a98f03 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp
@@ -281,7 +281,7 @@
 #endif
                     &qbo);
             if (result == NO_ERROR) {
-                updateQueueBufferOutput(qbo);
+                updateQueueBufferOutput(std::move(qbo));
             }
         } else {
             // If the surface hadn't actually been updated, then we only went
@@ -516,7 +516,8 @@
         mOutputFence = mFbFence;
     }
 
-    *output = mQueueBufferOutput;
+    // This moves the frame timestamps and keeps a copy of all other fields.
+    *output = std::move(mQueueBufferOutput);
     return NO_ERROR;
 }
 
@@ -555,8 +556,9 @@
     status_t result = mSource[SOURCE_SINK]->connect(listener, api,
             producerControlledByApp, &qbo);
     if (result == NO_ERROR) {
-        updateQueueBufferOutput(qbo);
-        *output = mQueueBufferOutput;
+        updateQueueBufferOutput(std::move(qbo));
+        // This moves the frame timestamps and keeps a copy of all other fields.
+        *output = std::move(mQueueBufferOutput);
     }
     return result;
 }
@@ -615,8 +617,8 @@
 }
 
 void VirtualDisplaySurface::updateQueueBufferOutput(
-        const QueueBufferOutput& qbo) {
-    mQueueBufferOutput = qbo;
+        QueueBufferOutput&& qbo) {
+    mQueueBufferOutput = std::move(qbo);
     mQueueBufferOutput.transformHint = 0;
 }
 
diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
index b435bf5..d37dc0a 100644
--- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
+++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.h
@@ -136,7 +136,7 @@
     static Source fbSourceForCompositionType(CompositionType type);
     status_t dequeueBuffer(Source source, PixelFormat format, uint32_t usage,
             int* sslot, sp<Fence>* fence);
-    void updateQueueBufferOutput(const QueueBufferOutput& qbo);
+    void updateQueueBufferOutput(QueueBufferOutput&& qbo);
     void resetPerFrameState();
     status_t refreshOutputBuffer();
 
@@ -181,6 +181,8 @@
     // The QueueBufferOutput with the latest info from the sink, and with the
     // transform hint cleared. Since we defer queueBuffer from the GLES driver
     // to the sink, we have to return the previous version.
+    // Moves instead of copies are performed to avoid duplicate
+    // FrameEventHistoryDeltas.
     QueueBufferOutput mQueueBufferOutput;
 
     // Details of the current sink buffer. These become valid when a buffer is
diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp
index c09bbe4..319c2a7 100644
--- a/services/surfaceflinger/FrameTracker.cpp
+++ b/services/surfaceflinger/FrameTracker.cpp
@@ -21,7 +21,6 @@
 
 #include <cutils/log.h>
 
-#include <ui/Fence.h>
 #include <ui/FrameStats.h>
 
 #include <utils/String8.h>
@@ -48,9 +47,10 @@
     mFrameRecords[mOffset].frameReadyTime = readyTime;
 }
 
-void FrameTracker::setFrameReadyFence(const sp<Fence>& readyFence) {
+void FrameTracker::setFrameReadyFence(
+        std::shared_ptr<FenceTime>&& readyFence) {
     Mutex::Autolock lock(mMutex);
-    mFrameRecords[mOffset].frameReadyFence = readyFence;
+    mFrameRecords[mOffset].frameReadyFence = std::move(readyFence);
     mNumFences++;
 }
 
@@ -59,9 +59,10 @@
     mFrameRecords[mOffset].actualPresentTime = presentTime;
 }
 
-void FrameTracker::setActualPresentFence(const sp<Fence>& readyFence) {
+void FrameTracker::setActualPresentFence(
+        std::shared_ptr<FenceTime>&& readyFence) {
     Mutex::Autolock lock(mMutex);
-    mFrameRecords[mOffset].actualPresentFence = readyFence;
+    mFrameRecords[mOffset].actualPresentFence = std::move(readyFence);
     mNumFences++;
 }
 
@@ -95,10 +96,6 @@
         mFrameRecords[mOffset].actualPresentFence = NULL;
         mNumFences--;
     }
-
-    // Clean up the signaled fences to keep the number of open fence FDs in
-    // this process reasonable.
-    processFencesLocked();
 }
 
 void FrameTracker::clearStats() {
@@ -107,8 +104,8 @@
         mFrameRecords[i].desiredPresentTime = 0;
         mFrameRecords[i].frameReadyTime = 0;
         mFrameRecords[i].actualPresentTime = 0;
-        mFrameRecords[i].frameReadyFence.clear();
-        mFrameRecords[i].actualPresentFence.clear();
+        mFrameRecords[i].frameReadyFence.reset();
+        mFrameRecords[i].actualPresentFence.reset();
     }
     mNumFences = 0;
     mFrameRecords[mOffset].desiredPresentTime = INT64_MAX;
@@ -156,7 +153,7 @@
         size_t idx = (mOffset+NUM_FRAME_RECORDS-i) % NUM_FRAME_RECORDS;
         bool updated = false;
 
-        const sp<Fence>& rfence = records[idx].frameReadyFence;
+        const std::shared_ptr<FenceTime>& rfence = records[idx].frameReadyFence;
         if (rfence != NULL) {
             records[idx].frameReadyTime = rfence->getSignalTime();
             if (records[idx].frameReadyTime < INT64_MAX) {
@@ -166,7 +163,8 @@
             }
         }
 
-        const sp<Fence>& pfence = records[idx].actualPresentFence;
+        const std::shared_ptr<FenceTime>& pfence =
+                records[idx].actualPresentFence;
         if (pfence != NULL) {
             records[idx].actualPresentTime = pfence->getSignalTime();
             if (records[idx].actualPresentTime < INT64_MAX) {
diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h
index cd5e3f3..adcdfb5 100644
--- a/services/surfaceflinger/FrameTracker.h
+++ b/services/surfaceflinger/FrameTracker.h
@@ -17,6 +17,8 @@
 #ifndef ANDROID_FRAMETRACKER_H
 #define ANDROID_FRAMETRACKER_H
 
+#include <ui/FenceTime.h>
+
 #include <stddef.h>
 
 #include <utils/Mutex.h>
@@ -26,7 +28,6 @@
 namespace android {
 
 class String8;
-class Fence;
 
 // FrameTracker tracks information about the most recently rendered frames. It
 // uses a circular buffer of frame records, and is *NOT* thread-safe -
@@ -60,7 +61,7 @@
 
     // setFrameReadyFence sets the fence that is used to get the time at which
     // the current frame became ready to be presented to the user.
-    void setFrameReadyFence(const sp<Fence>& readyFence);
+    void setFrameReadyFence(std::shared_ptr<FenceTime>&& readyFence);
 
     // setActualPresentTime sets the timestamp at which the current frame became
     // visible to the user.
@@ -68,7 +69,7 @@
 
     // setActualPresentFence sets the fence that is used to get the time
     // at which the current frame became visible to the user.
-    void setActualPresentFence(const sp<Fence>& fence);
+    void setActualPresentFence(std::shared_ptr<FenceTime>&& fence);
 
     // setDisplayRefreshPeriod sets the display refresh period in nanoseconds.
     // This is used to compute frame presentation duration statistics relative
@@ -100,8 +101,8 @@
         nsecs_t desiredPresentTime;
         nsecs_t frameReadyTime;
         nsecs_t actualPresentTime;
-        sp<Fence> frameReadyFence;
-        sp<Fence> actualPresentFence;
+        std::shared_ptr<FenceTime> frameReadyFence;
+        std::shared_ptr<FenceTime> actualPresentFence;
     };
 
     // processFences iterates over all the frame records that have a fence set
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9ae9752..395757b 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1740,41 +1740,23 @@
     return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
 }
 
-bool Layer::onPostComposition(sp<Fence> glDoneFence) {
+bool Layer::onPostComposition(
+        const std::shared_ptr<FenceTime>& glDoneFence,
+        const std::shared_ptr<FenceTime>& presentFence,
+        const std::shared_ptr<FenceTime>& retireFence) {
+    mAcquireTimeline.updateSignalTimes();
+    mReleaseTimeline.updateSignalTimes();
+
     // mFrameLatencyNeeded is true when a new frame was latched for the
     // composition.
-
     if (!mFrameLatencyNeeded)
         return false;
 
-    const HWComposer& hwc = mFlinger->getHwComposer();
-#ifdef USE_HWC2
-    sp<Fence> retireFence = Fence::NO_FENCE;
-    sp<Fence> presentFence = Fence::NO_FENCE;
-    sp<Fence> presentOrRetireFence = Fence::NO_FENCE;
-    if (hwc.retireFenceRepresentsStartOfScanout()) {
-        presentFence = hwc.getPresentFence(HWC_DISPLAY_PRIMARY);
-        presentOrRetireFence = presentFence;
-    } else {
-        retireFence = hwc.getPresentFence(HWC_DISPLAY_PRIMARY);
-        presentOrRetireFence = retireFence;
-    }
-    bool wasGpuComposited = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ?
-            mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType ==
-            HWC2::Composition::Client : true;
-#else
-    sp<Fence> retireFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
-    sp<Fence> presentFence = Fence::NO_FENCE;
-    sp<Fence> presentOrRetireFence = retireFence;
-    bool wasGpuComposited = mIsGlesComposition;
-#endif
-
     // Update mFrameEventHistory.
     {
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addPostComposition(mCurrentFrameNumber,
-                wasGpuComposited ? glDoneFence : Fence::NO_FENCE,
-                presentFence);
+                glDoneFence, presentFence);
         mFrameEventHistory.addRetire(mPreviousFrameNumber,
                 retireFence);
     }
@@ -1783,22 +1765,28 @@
     nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
     mFrameTracker.setDesiredPresentTime(desiredPresentTime);
 
-    sp<Fence> frameReadyFence = mSurfaceFlingerConsumer->getCurrentFence();
+    std::shared_ptr<FenceTime> frameReadyFence =
+            mSurfaceFlingerConsumer->getCurrentFenceTime();
     if (frameReadyFence->isValid()) {
-        mFrameTracker.setFrameReadyFence(frameReadyFence);
+        mFrameTracker.setFrameReadyFence(std::move(frameReadyFence));
     } else {
         // There was no fence for this frame, so assume that it was ready
         // to be presented at the desired present time.
         mFrameTracker.setFrameReadyTime(desiredPresentTime);
     }
 
-    if (presentOrRetireFence->isValid()) {
-        mFrameTracker.setActualPresentFence(presentOrRetireFence);
+    if (presentFence->isValid()) {
+        mFrameTracker.setActualPresentFence(
+                std::shared_ptr<FenceTime>(presentFence));
+    } else if (retireFence->isValid()) {
+        mFrameTracker.setActualPresentFence(
+                std::shared_ptr<FenceTime>(retireFence));
     } else {
         // The HWC doesn't support present fences, so use the refresh
         // timestamp instead.
-        nsecs_t presentTime = hwc.getRefreshTimestamp(HWC_DISPLAY_PRIMARY);
-        mFrameTracker.setActualPresentTime(presentTime);
+        mFrameTracker.setActualPresentTime(
+            mFlinger->getHwComposer().getRefreshTimestamp(
+                HWC_DISPLAY_PRIMARY));
     }
 
     mFrameTracker.advanceFrame();
@@ -1809,9 +1797,13 @@
 #ifdef USE_HWC2
 void Layer::releasePendingBuffer() {
     mSurfaceFlingerConsumer->releasePendingBuffer();
-    Mutex::Autolock lock(mFrameEventHistoryMutex);
-    mFrameEventHistory.addRelease(mPreviousFrameNumber,
+    auto releaseFenceTime = std::make_shared<FenceTime>(
             mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+    mReleaseTimeline.push(releaseFenceTime);
+
+    Mutex::Autolock lock(mFrameEventHistoryMutex);
+    mFrameEventHistory.addRelease(
+            mPreviousFrameNumber, std::move(releaseFenceTime));
 }
 #endif
 
@@ -1984,8 +1976,11 @@
         Mutex::Autolock lock(mFrameEventHistoryMutex);
         mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
 #ifndef USE_HWC2
-        mFrameEventHistory.addRelease(mPreviousFrameNumber,
+        auto releaseFenceTime = std::make_shared<FenceTime>(
                 mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+        mReleaseTimeline.push(releaseFenceTime);
+        mFrameEventHistory.addRelease(
+                mPreviousFrameNumber, std::move(releaseFenceTime));
 #endif
     }
 
@@ -2220,6 +2215,7 @@
         FrameEventHistoryDelta *outDelta) {
     Mutex::Autolock lock(mFrameEventHistoryMutex);
     if (newTimestamps) {
+        mAcquireTimeline.push(newTimestamps->acquireFence);
         mFrameEventHistory.addQueue(*newTimestamps);
     }
 
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index a051292..612fb0d 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -276,7 +276,10 @@
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
      */
-    bool onPostComposition(sp<Fence> glCompositionDoneFence);
+    bool onPostComposition(
+            const std::shared_ptr<FenceTime>& glDoneFence,
+            const std::shared_ptr<FenceTime>& presentFence,
+            const std::shared_ptr<FenceTime>& retireFence);
 
 #ifdef USE_HWC2
     // If a buffer was replaced this frame, release the former buffer
@@ -586,6 +589,8 @@
     // Accessed by both consumer and producer on main and binder threads.
     Mutex mFrameEventHistoryMutex;
     ConsumerFrameEventHistory mFrameEventHistory;
+    FenceTimeline mAcquireTimeline;
+    FenceTimeline mReleaseTimeline;
 
     // main thread
     sp<GraphicBuffer> mActiveBuffer;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index dde8d11..6625a8b 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -573,7 +573,7 @@
         FrameEvent::ACQUIRE,
         FrameEvent::FIRST_REFRESH_START,
         FrameEvent::GL_COMPOSITION_DONE,
-        getHwComposer().retireFenceRepresentsStartOfScanout() ?
+        getHwComposer().presentFenceRepresentsStartOfScanout() ?
                 FrameEvent::DISPLAY_PRESENT : FrameEvent::DISPLAY_RETIRE,
         FrameEvent::RELEASE,
     };
@@ -1226,26 +1226,45 @@
         layer->releasePendingBuffer();
     }
 
-    bool hadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);
-
     const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
-    sp<Fence> glCompositionDoneFence = hadClientComposition
-                                     ? hw->getClientTargetAcquireFence()
-                                     : Fence::NO_FENCE;
+
+    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+    if (mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY)) {
+        glCompositionDoneFenceTime =
+                std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
+        mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
+    } else {
+        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
+    }
+    mGlCompositionDoneTimeline.updateSignalTimes();
+
+    sp<Fence> displayFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
+    auto displayFenceTime = std::make_shared<FenceTime>(displayFence);
+    mDisplayTimeline.push(displayFenceTime);
+    mDisplayTimeline.updateSignalTimes();
+
+    const std::shared_ptr<FenceTime>* presentFenceTime = &FenceTime::NO_FENCE;
+    const std::shared_ptr<FenceTime>* retireFenceTime = &FenceTime::NO_FENCE;
+    if (mHwc->presentFenceRepresentsStartOfScanout()) {
+        presentFenceTime = &displayFenceTime;
+    } else {
+        retireFenceTime = &displayFenceTime;
+    }
+
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        bool frameLatched = layers[i]->onPostComposition(glCompositionDoneFence);
+        bool frameLatched =
+                layers[i]->onPostComposition(glCompositionDoneFenceTime,
+                        *presentFenceTime, *retireFenceTime);
         if (frameLatched) {
             recordBufferingStats(layers[i]->getName().string(),
                     layers[i]->getOccupancyHistory(false));
         }
     }
 
-    sp<Fence> presentFence = mHwc->getPresentFence(HWC_DISPLAY_PRIMARY);
-
-    if (presentFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(presentFence)) {
+    if (displayFence->isValid()) {
+        if (mPrimaryDispSync.addPresentFence(displayFence)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -1261,8 +1280,9 @@
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
-        if (presentFence->isValid()) {
-            mAnimFrameTracker.setActualPresentFence(presentFence);
+        if (displayFenceTime->isValid()) {
+            mAnimFrameTracker.setActualPresentFence(
+                    std::move(displayFenceTime));
         } else {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index 4ec1a72..2d6f9f6 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -37,6 +37,7 @@
 
 #include <binder/IMemory.h>
 
+#include <ui/FenceTime.h>
 #include <ui/PixelFormat.h>
 #include <ui/mat4.h>
 
@@ -501,6 +502,8 @@
     sp<Fence> mPreviousPresentFence = Fence::NO_FENCE;
     bool mHadClientComposition = false;
 #endif
+    FenceTimeline mGlCompositionDoneTimeline;
+    FenceTimeline mDisplayTimeline;
 
     // this may only be written from the main thread with mStateLock held
     // it may be read from other threads with mStateLock held
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 55edc15..ada0046 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1136,27 +1136,35 @@
     const HWComposer& hwc = getHwComposer();
     const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
 
-    bool hadGlesComposition =
-            getHwComposer().hasGlesComposition(hw->getHwcDisplayId());
-    sp<Fence> glCompositionDoneFence = hadGlesComposition
-                                     ? hw->getClientTargetAcquireFence()
-                                     : Fence::NO_FENCE;
+    std::shared_ptr<FenceTime> glCompositionDoneFenceTime;
+    if (getHwComposer().hasGlesComposition(hw->getHwcDisplayId())) {
+        glCompositionDoneFenceTime =
+                std::make_shared<FenceTime>(hw->getClientTargetAcquireFence());
+        mGlCompositionDoneTimeline.push(glCompositionDoneFenceTime);
+    } else {
+        glCompositionDoneFenceTime = FenceTime::NO_FENCE;
+    }
+    mGlCompositionDoneTimeline.updateSignalTimes();
+
+    sp<Fence> displayFence = mHwc->getDisplayFence(HWC_DISPLAY_PRIMARY);
+    const std::shared_ptr<FenceTime>& presentFenceTime = FenceTime::NO_FENCE;
+    auto retireFenceTime = std::make_shared<FenceTime>(displayFence);
+    mDisplayTimeline.push(retireFenceTime);
+    mDisplayTimeline.updateSignalTimes();
 
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
         bool frameLatched = layers[i]->onPostComposition(
-                glCompositionDoneFence);
+                glCompositionDoneFenceTime, presentFenceTime, retireFenceTime);
         if (frameLatched) {
             recordBufferingStats(layers[i]->getName().string(),
                     layers[i]->getOccupancyHistory(false));
         }
     }
 
-    sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
-
-    if (presentFence->isValid()) {
-        if (mPrimaryDispSync.addPresentFence(presentFence)) {
+    if (displayFence->isValid()) {
+        if (mPrimaryDispSync.addPresentFence(displayFence)) {
             enableHardwareVsync();
         } else {
             disableHardwareVsync(false);
@@ -1172,8 +1180,8 @@
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
-        if (presentFence->isValid()) {
-            mAnimFrameTracker.setActualPresentFence(presentFence);
+        if (retireFenceTime->isValid()) {
+            mAnimFrameTracker.setActualPresentFence(std::move(retireFenceTime));
         } else {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.