Track frame events incrementally and per layer.

* Replaces FenceTracker, which was owned by SurfaceFlinger,
    with FrameEventHistory, which is owned by Layer.
* Updates FrameEventHistory as events occur.
* Changes SurfaceFlinger flag "--fences" to
    "--frame-events".

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

Change-Id: I868c2ef93964656d7e41848243433499e7f45fe7
diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk
index 7135ed3..dd8719a 100644
--- a/services/surfaceflinger/Android.mk
+++ b/services/surfaceflinger/Android.mk
@@ -10,7 +10,6 @@
     DispSync.cpp \
     EventControlThread.cpp \
     EventThread.cpp \
-    FenceTracker.cpp \
     FrameTracker.cpp \
     GpuService.cpp \
     Layer.cpp \
diff --git a/services/surfaceflinger/FenceTracker.cpp b/services/surfaceflinger/FenceTracker.cpp
deleted file mode 100644
index 4dac0db..0000000
--- a/services/surfaceflinger/FenceTracker.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#define ATRACE_TAG ATRACE_TAG_GRAPHICS
-
-#include <inttypes.h>
-#include "FenceTracker.h"
-#include "Layer.h"
-#include <utils/Trace.h>
-
-namespace android {
-
-FenceTracker::FenceTracker() :
-        mFrameCounter(0),
-        mOffset(0),
-        mFrames(),
-        mMutex() {
-}
-
-void FenceTracker::dump(String8* outString) {
-    Mutex::Autolock lock(mMutex);
-    checkFencesForCompletion();
-
-    for (size_t i = 0; i < MAX_FRAME_HISTORY; i++) {
-        int index = (mOffset + i) % MAX_FRAME_HISTORY;
-        const FrameRecord& frame = mFrames[index];
-
-        outString->appendFormat("Frame %" PRIu64 "\n", frame.frameId);
-        outString->appendFormat("- Refresh start\t%" PRId64 "\n",
-                frame.refreshStartTime);
-
-        if (frame.glesCompositionDoneTime) {
-            outString->appendFormat("- GLES done\t%" PRId64 "\n",
-                    frame.glesCompositionDoneTime);
-        } else if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
-            outString->append("- GLES done\tNot signaled\n");
-        }
-
-        if (frame.presentTime) {
-            outString->appendFormat("- Present\t%" PRId64 "\n",
-                    frame.presentTime);
-        } else if (frame.presentFence != Fence::NO_FENCE) {
-            outString->append("- Present\tNot signaled\n");
-        }
-
-        if (frame.retireTime) {
-            outString->appendFormat("- Retire\t%" PRId64 "\n",
-                    frame.retireTime);
-        } else if (frame.retireFence != Fence::NO_FENCE) {
-            outString->append("- Retire\tNot signaled\n");
-        }
-
-        for (const auto& kv : frame.layers) {
-            const LayerRecord& layer = kv.second;
-            outString->appendFormat("-- %s\n", layer.name.string());
-            outString->appendFormat("---- Frame # %" PRIu64 " (%s)\n",
-                    layer.frameNumber,
-                    layer.isGlesComposition ? "GLES" : "HWC");
-            outString->appendFormat("---- Req.Present.\t%" PRId64 "\n",
-                    layer.requestedPresentTime);
-            if (layer.acquireTime) {
-                outString->appendFormat("---- Acquire\t%" PRId64 "\n",
-                        layer.acquireTime);
-            } else {
-                outString->append("---- Acquire\tNot signaled\n");
-            }
-            if (layer.releaseTime) {
-                outString->appendFormat("---- Release\t%" PRId64 "\n",
-                        layer.releaseTime);
-            } else {
-                outString->append("---- Release\tNot signaled\n");
-            }
-        }
-    }
-}
-
-static inline bool isValidTimestamp(nsecs_t time) {
-    return time > 0 && time < INT64_MAX;
-}
-
-void FenceTracker::checkFencesForCompletion() {
-    ATRACE_CALL();
-    for (auto& frame : mFrames) {
-        if (frame.presentFence != Fence::NO_FENCE) {
-            nsecs_t time = frame.presentFence->getSignalTime();
-            if (isValidTimestamp(time)) {
-                frame.presentTime = time;
-                frame.presentFence = Fence::NO_FENCE;
-            }
-        }
-        if (frame.retireFence != Fence::NO_FENCE) {
-            nsecs_t time = frame.retireFence->getSignalTime();
-            if (isValidTimestamp(time)) {
-                frame.retireTime = time;
-                frame.retireFence = Fence::NO_FENCE;
-            }
-        }
-        if (frame.glesCompositionDoneFence != Fence::NO_FENCE) {
-            nsecs_t time = frame.glesCompositionDoneFence->getSignalTime();
-            if (isValidTimestamp(time)) {
-                frame.glesCompositionDoneTime = time;
-                frame.glesCompositionDoneFence = Fence::NO_FENCE;
-            }
-        }
-        for (auto& kv : frame.layers) {
-            LayerRecord& layer = kv.second;
-            if (layer.acquireFence != Fence::NO_FENCE) {
-                nsecs_t time = layer.acquireFence->getSignalTime();
-                if (isValidTimestamp(time)) {
-                    layer.acquireTime = time;
-                    layer.acquireFence = Fence::NO_FENCE;
-                }
-            }
-            if (layer.releaseFence != Fence::NO_FENCE) {
-                nsecs_t time = layer.releaseFence->getSignalTime();
-                if (isValidTimestamp(time)) {
-                    layer.releaseTime = time;
-                    layer.releaseFence = Fence::NO_FENCE;
-                }
-            }
-        }
-    }
-}
-
-void FenceTracker::addFrame(nsecs_t refreshStartTime, sp<Fence> presentFence,
-        sp<Fence> retireFence, const Vector<sp<Layer>>& layers,
-        sp<Fence> glDoneFence) {
-    ATRACE_CALL();
-    Mutex::Autolock lock(mMutex);
-    FrameRecord& frame = mFrames[mOffset];
-    FrameRecord& prevFrame = mFrames[(mOffset + MAX_FRAME_HISTORY - 1) %
-                                     MAX_FRAME_HISTORY];
-    frame.layers.clear();
-
-    bool wasGlesCompositionDone = false;
-    const size_t count = layers.size();
-    for (size_t i = 0; i < count; i++) {
-        String8 name;
-        uint64_t frameNumber;
-        bool glesComposition;
-        nsecs_t requestedPresentTime;
-        sp<Fence> acquireFence;
-        sp<Fence> prevReleaseFence;
-        int32_t layerId = layers[i]->getSequence();
-
-        layers[i]->getFenceData(&name, &frameNumber, &glesComposition,
-                &requestedPresentTime, &acquireFence, &prevReleaseFence);
-
-        frame.layers.emplace(std::piecewise_construct,
-                std::forward_as_tuple(layerId),
-                std::forward_as_tuple(name, frameNumber, glesComposition,
-                requestedPresentTime, 0, 0, acquireFence, Fence::NO_FENCE));
-        auto prevLayer = prevFrame.layers.find(layerId);
-        if (prevLayer != prevFrame.layers.end()) {
-            if (frameNumber != prevLayer->second.frameNumber) {
-               prevLayer->second.releaseFence = prevReleaseFence;
-            }
-        }
-    }
-
-    frame.frameId = mFrameCounter;
-    frame.refreshStartTime = refreshStartTime;
-    frame.presentTime = 0;
-    frame.retireTime = 0;
-    frame.glesCompositionDoneTime = 0;
-    frame.presentFence = presentFence;
-    prevFrame.retireFence = retireFence;
-    frame.retireFence = Fence::NO_FENCE;
-    frame.glesCompositionDoneFence = wasGlesCompositionDone ? glDoneFence :
-            Fence::NO_FENCE;
-
-    mOffset = (mOffset + 1) % MAX_FRAME_HISTORY;
-    mFrameCounter++;
-}
-
-bool FenceTracker::getFrameTimestamps(const Layer& layer,
-        uint64_t frameNumber, FrameTimestamps* outTimestamps) {
-    Mutex::Autolock lock(mMutex);
-    checkFencesForCompletion();
-    int32_t layerId = layer.getSequence();
-
-    size_t i = 0;
-    for (; i < MAX_FRAME_HISTORY; i++) {
-       if (mFrames[i].layers.count(layerId) &&
-               mFrames[i].layers[layerId].frameNumber == frameNumber) {
-           break;
-       }
-    }
-    if (i == MAX_FRAME_HISTORY) {
-        return false;
-    }
-
-    const FrameRecord& frameRecord = mFrames[i];
-    const LayerRecord& layerRecord = mFrames[i].layers[layerId];
-    outTimestamps->frameNumber = frameNumber;
-    outTimestamps->requestedPresentTime = layerRecord.requestedPresentTime;
-    outTimestamps->acquireTime = layerRecord.acquireTime;
-    outTimestamps->refreshStartTime = frameRecord.refreshStartTime;
-    outTimestamps->glCompositionDoneTime = frameRecord.glesCompositionDoneTime;
-    outTimestamps->displayPresentTime = frameRecord.presentTime;
-    outTimestamps->displayRetireTime = frameRecord.retireTime;
-    outTimestamps->releaseTime = layerRecord.releaseTime;
-    return true;
-}
-
-} // namespace android
diff --git a/services/surfaceflinger/FenceTracker.h b/services/surfaceflinger/FenceTracker.h
deleted file mode 100644
index 3b429d1..0000000
--- a/services/surfaceflinger/FenceTracker.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * Copyright 2016 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef ANDROID_FENCETRACKER_H
-#define ANDROID_FENCETRACKER_H
-
-#include <ui/Fence.h>
-#include <utils/Mutex.h>
-#include <utils/RefBase.h>
-#include <utils/String8.h>
-#include <utils/Timers.h>
-#include <utils/Vector.h>
-
-#include <unordered_map>
-
-namespace android {
-
-class Layer;
-struct FrameTimestamps;
-/*
- * Keeps a circular buffer of fence/timestamp data for the last N frames in
- * SurfaceFlinger. Gets timestamps for fences after they have signaled.
- */
-class FenceTracker {
-public:
-     FenceTracker();
-     void dump(String8* outString);
-     void addFrame(nsecs_t refreshStartTime, sp<Fence> presentFence,
-             sp<Fence> retireFence, const Vector<sp<Layer>>& layers,
-             sp<Fence> glDoneFence);
-     bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber,
-             FrameTimestamps* outTimestamps);
-
-protected:
-     static constexpr size_t MAX_FRAME_HISTORY = 8;
-
-     struct LayerRecord {
-         String8 name; // layer name
-         uint64_t frameNumber; // frame number for this layer
-         bool isGlesComposition; // was GLES composition used for this layer?
-         // time the producer requested this frame be presented
-         nsecs_t requestedPresentTime;
-         nsecs_t acquireTime; // timestamp from the acquire fence
-         nsecs_t releaseTime; // timestamp from the release fence
-         sp<Fence> acquireFence; // acquire fence
-         sp<Fence> releaseFence; // release fence
-
-         LayerRecord(const String8& name, uint64_t frameNumber,
-                 bool isGlesComposition, nsecs_t requestedPresentTime,
-                 nsecs_t acquireTime, nsecs_t releaseTime,
-                 sp<Fence> acquireFence, sp<Fence> releaseFence) :
-                 name(name), frameNumber(frameNumber),
-                 isGlesComposition(isGlesComposition),
-                 requestedPresentTime(requestedPresentTime),
-                 acquireTime(acquireTime), releaseTime(releaseTime),
-                 acquireFence(acquireFence), releaseFence(releaseFence) {};
-         LayerRecord() : name("uninitialized"), frameNumber(0),
-                 isGlesComposition(false), requestedPresentTime(0),
-                 acquireTime(0), releaseTime(0), acquireFence(Fence::NO_FENCE),
-                 releaseFence(Fence::NO_FENCE) {};
-     };
-
-     struct FrameRecord {
-         // global SurfaceFlinger frame counter
-         uint64_t frameId;
-         // layer data for this frame
-         std::unordered_map<int32_t, LayerRecord> layers;
-         // timestamp for when SurfaceFlinger::handleMessageRefresh() was called
-         nsecs_t refreshStartTime;
-         // timestamp from the present fence
-         nsecs_t presentTime;
-         // timestamp from the retire fence
-         nsecs_t retireTime;
-         // timestamp from the GLES composition completion fence
-         nsecs_t glesCompositionDoneTime;
-         // primary display present fence for this frame
-         sp<Fence> presentFence;
-         // primary display retire fence for this frame
-         sp<Fence> retireFence;
-         // if GLES composition was done, the fence for its completion
-         sp<Fence> glesCompositionDoneFence;
-
-         FrameRecord() : frameId(0), layers(), refreshStartTime(0),
-                 presentTime(0), retireTime(0), glesCompositionDoneTime(0),
-                 presentFence(Fence::NO_FENCE), retireFence(Fence::NO_FENCE),
-                 glesCompositionDoneFence(Fence::NO_FENCE) {}
-     };
-
-     uint64_t mFrameCounter;
-     uint32_t mOffset;
-     FrameRecord mFrames[MAX_FRAME_HISTORY];
-     Mutex mMutex;
-
-     void checkFencesForCompletion();
-};
-
-}
-
-#endif // ANDROID_FRAMETRACKER_H
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 4772fc1..c16af59 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -80,7 +80,9 @@
         mCurrentScalingMode(NATIVE_WINDOW_SCALING_MODE_FREEZE),
         mOverrideScalingMode(-1),
         mCurrentOpacity(true),
+        mBufferLatched(false),
         mCurrentFrameNumber(0),
+        mPreviousFrameNumber(-1U),
         mRefreshPending(false),
         mFrameLatencyNeeded(false),
         mFiltering(false),
@@ -1729,14 +1731,53 @@
     return isDue || !isPlausible;
 }
 
-bool Layer::onPreComposition() {
+bool Layer::onPreComposition(nsecs_t refreshStartTime) {
+    if (mBufferLatched) {
+        Mutex::Autolock lock(mFrameEventHistoryMutex);
+        mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime);
+    }
     mRefreshPending = false;
     return mQueuedFrames > 0 || mSidebandStreamChanged || mAutoRefresh;
 }
 
-bool Layer::onPostComposition() {
+bool Layer::onPostComposition(sp<Fence> glDoneFence) {
+    // mFrameLatencyNeeded is true when a new frame was latched for the
+    // composition.
     bool frameLatencyNeeded = mFrameLatencyNeeded;
     if (mFrameLatencyNeeded) {
+        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.getRetireFence(HWC_DISPLAY_PRIMARY);
+            presentOrRetireFence = presentFence;
+        } else {
+            retireFence = hwc.getRetireFence(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);
+            mFrameEventHistory.addRetire(mPreviousFrameNumber,
+                    retireFence);
+        }
+
+        // Update mFrameTracker.
         nsecs_t desiredPresentTime = mSurfaceFlingerConsumer->getTimestamp();
         mFrameTracker.setDesiredPresentTime(desiredPresentTime);
 
@@ -1749,14 +1790,8 @@
             mFrameTracker.setFrameReadyTime(desiredPresentTime);
         }
 
-        const HWComposer& hwc = mFlinger->getHwComposer();
-#ifdef USE_HWC2
-        sp<Fence> presentFence = hwc.getRetireFence(HWC_DISPLAY_PRIMARY);
-#else
-        sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
-#endif
-        if (presentFence->isValid()) {
-            mFrameTracker.setActualPresentFence(presentFence);
+        if (presentOrRetireFence->isValid()) {
+            mFrameTracker.setActualPresentFence(presentOrRetireFence);
         } else {
             // The HWC doesn't support present fences, so use the refresh
             // timestamp instead.
@@ -1773,6 +1808,9 @@
 #ifdef USE_HWC2
 void Layer::releasePendingBuffer() {
     mSurfaceFlingerConsumer->releasePendingBuffer();
+    Mutex::Autolock lock(mFrameEventHistoryMutex);
+    mFrameEventHistory.addRelease(mPreviousFrameNumber,
+            mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
 }
 #endif
 
@@ -1813,7 +1851,7 @@
     return !matchingFramesFound || allTransactionsApplied;
 }
 
-Region Layer::latchBuffer(bool& recomputeVisibleRegions)
+Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime)
 {
     ATRACE_CALL();
 
@@ -1937,6 +1975,19 @@
         return outDirtyRegion;
     }
 
+    mBufferLatched = true;
+    mPreviousFrameNumber = mCurrentFrameNumber;
+    mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+
+    {
+        Mutex::Autolock lock(mFrameEventHistoryMutex);
+        mFrameEventHistory.addLatch(mCurrentFrameNumber, latchTime);
+#ifndef USE_HWC2
+        mFrameEventHistory.addRelease(mPreviousFrameNumber,
+                mSurfaceFlingerConsumer->getPrevFinalReleaseFence());
+#endif
+    }
+
     mRefreshPending = true;
     mFrameLatencyNeeded = true;
     if (oldActiveBuffer == NULL) {
@@ -1972,8 +2023,6 @@
         recomputeVisibleRegions = true;
     }
 
-    mCurrentFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
-
     // Remove any sync points corresponding to the buffer which was just
     // latched
     {
@@ -2158,22 +2207,32 @@
     mFrameTracker.getStats(outStats);
 }
 
-void Layer::getFenceData(String8* outName, uint64_t* outFrameNumber,
-        bool* outIsGlesComposition, nsecs_t* outRequestedPresentTime,
-        sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const {
-    *outName = mName;
-    *outFrameNumber = mSurfaceFlingerConsumer->getFrameNumber();
+void Layer::dumpFrameEvents(String8& result) {
+    result.appendFormat("- Layer %s (%s, %p)\n",
+            getName().string(), getTypeId(), this);
+    Mutex::Autolock lock(mFrameEventHistoryMutex);
+    mFrameEventHistory.checkFencesForCompletion();
+    mFrameEventHistory.dump(result);
+}
 
-#ifdef USE_HWC2
-    *outIsGlesComposition = mHwcLayers.count(HWC_DISPLAY_PRIMARY) ?
-            mHwcLayers.at(HWC_DISPLAY_PRIMARY).compositionType ==
-            HWC2::Composition::Client : true;
-#else
-    *outIsGlesComposition = mIsGlesComposition;
-#endif
-    *outRequestedPresentTime = mSurfaceFlingerConsumer->getTimestamp();
-    *outAcquireFence = mSurfaceFlingerConsumer->getCurrentFence();
-    *outPrevReleaseFence = mSurfaceFlingerConsumer->getPrevFinalReleaseFence();
+bool Layer::addAndGetFrameTimestamps(
+        const NewFrameEventsEntry* newTimestamps,
+        uint64_t frameNumber, FrameTimestamps *outTimestamps) {
+    Mutex::Autolock lock(mFrameEventHistoryMutex);
+    if (newTimestamps) {
+        mFrameEventHistory.addQueue(*newTimestamps);
+    }
+
+    if (outTimestamps) {
+        FrameEvents* frameEvents = mFrameEventHistory.getFrame(frameNumber);
+        if (frameEvents) {
+            frameEvents->checkFencesForCompletion();
+            *outTimestamps = FrameTimestamps(*frameEvents);
+            return true;
+        }
+    }
+
+    return false;
 }
 
 std::vector<OccupancyTracker::Segment> Layer::getOccupancyHistory(
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 5aba69b..98ea053 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -270,13 +270,13 @@
      * called before composition.
      * returns true if the layer has pending updates.
      */
-    bool onPreComposition();
+    bool onPreComposition(nsecs_t refreshStartTime);
 
     /*
      * called after composition.
      * returns true if the layer latched a new buffer this frame.
      */
-    bool onPostComposition();
+    bool onPostComposition(sp<Fence> glCompositionDoneFence);
 
 #ifdef USE_HWC2
     // If a buffer was replaced this frame, release the former buffer
@@ -323,7 +323,7 @@
      * operation, so this should be set only if needed). Typically this is used
      * to figure out if the content or size of a surface has changed.
      */
-    Region latchBuffer(bool& recomputeVisibleRegions);
+    Region latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime);
 
     bool isPotentialCursor() const { return mPotentialCursor;}
 
@@ -402,20 +402,17 @@
     void miniDump(String8& result, int32_t hwcId) const;
 #endif
     void dumpFrameStats(String8& result) const;
+    void dumpFrameEvents(String8& result);
     void clearFrameStats();
     void logFrameStats();
     void getFrameStats(FrameStats* outStats) const;
 
-    void getFenceData(String8* outName, uint64_t* outFrameNumber,
-            bool* outIsGlesComposition, nsecs_t* outRequestedPresentTime,
-            sp<Fence>* outAcquireFence, sp<Fence>* outPrevReleaseFence) const;
 
     std::vector<OccupancyTracker::Segment> getOccupancyHistory(bool forceFlush);
 
-    bool getFrameTimestamps(uint64_t frameNumber,
-            FrameTimestamps* outTimestamps) const {
-        return mFlinger->getFrameTimestamps(*this, frameNumber, outTimestamps);
-    }
+    bool addAndGetFrameTimestamps(
+            const NewFrameEventsEntry* newTimestamps,
+            uint64_t frameNumber, FrameTimestamps* outTimestamps);
 
     bool getTransformToDisplayInverse() const;
 
@@ -583,8 +580,15 @@
     // thread-safe
     volatile int32_t mQueuedFrames;
     volatile int32_t mSidebandStreamChanged; // used like an atomic boolean
+
+    // Timestamp history for UIAutomation. Thread safe.
     FrameTracker mFrameTracker;
 
+    // Timestamp history for the consumer to query.
+    // Accessed by both consumer and producer on main and binder threads.
+    Mutex mFrameEventHistoryMutex;
+    FrameEventHistory mFrameEventHistory;
+
     // main thread
     sp<GraphicBuffer> mActiveBuffer;
     sp<NativeHandle> mSidebandStream;
@@ -594,7 +598,9 @@
     // We encode unset as -1.
     int32_t mOverrideScalingMode;
     bool mCurrentOpacity;
+    bool mBufferLatched = false;  // TODO: Use mActiveBuffer?
     std::atomic<uint64_t> mCurrentFrameNumber;
+    uint64_t mPreviousFrameNumber; // Only accessed on the main thread.
     bool mRefreshPending;
     bool mFrameLatencyNeeded;
     // Whether filtering is forced on or not
@@ -644,7 +650,7 @@
     Condition mQueueItemCondition;
     Vector<BufferItem> mQueueItems;
     std::atomic<uint64_t> mLastFrameNumberReceived;
-    bool mUpdateTexImageFailed; // This is only modified from the main thread
+    bool mUpdateTexImageFailed; // This is only accessed on the main thread.
 
     bool mAutoRefresh;
     bool mFreezePositionUpdates;
diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp
index ffaee7a..4604e01 100644
--- a/services/surfaceflinger/MonitoredProducer.cpp
+++ b/services/surfaceflinger/MonitoredProducer.cpp
@@ -145,6 +145,11 @@
             outTransformMatrix);
 }
 
+bool MonitoredProducer::getFrameTimestamps(
+        uint64_t frameNumber, FrameTimestamps* outTimestamps) {
+    return mProducer->getFrameTimestamps(frameNumber, outTimestamps);
+}
+
 status_t MonitoredProducer::getUniqueId(uint64_t* outId) const {
     return mProducer->getUniqueId(outId);
 }
diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h
index 66f6cf0..5a2351f 100644
--- a/services/surfaceflinger/MonitoredProducer.h
+++ b/services/surfaceflinger/MonitoredProducer.h
@@ -63,6 +63,8 @@
     virtual IBinder* onAsBinder();
     virtual status_t setSharedBufferMode(bool sharedBufferMode) override;
     virtual status_t setAutoRefresh(bool autoRefresh) override;
+    virtual bool getFrameTimestamps(uint64_t frameNumber,
+            FrameTimestamps* outTimestamps) override;
     virtual status_t getUniqueId(uint64_t* outId) const override;
 
 private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 2f273ae..8400136 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -1132,12 +1132,12 @@
 
     nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
 
-    preComposition();
+    preComposition(refreshStartTime);
     rebuildLayerStacks();
     setUpHWComposer();
     doDebugFlashRegions();
     doComposition();
-    postComposition(refreshStartTime);
+    postComposition();
 
     mPreviousPresentFence = mHwc->getRetireFence(HWC_DISPLAY_PRIMARY);
 
@@ -1195,7 +1195,7 @@
     }
 }
 
-void SurfaceFlinger::preComposition()
+void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
 {
     ATRACE_CALL();
     ALOGV("preComposition");
@@ -1204,7 +1204,7 @@
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        if (layers[i]->onPreComposition()) {
+        if (layers[i]->onPreComposition(refreshStartTime)) {
             needExtraInvalidate = true;
         }
     }
@@ -1213,7 +1213,7 @@
     }
 }
 
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::postComposition()
 {
     ATRACE_CALL();
     ALOGV("postComposition");
@@ -1223,10 +1223,16 @@
         layer->releasePendingBuffer();
     }
 
+    bool hadClientComposition = mHwc->hasClientComposition(HWC_DISPLAY_PRIMARY);
+
+    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
+    sp<Fence> glCompositionDoneFence = hadClientComposition
+                                     ? hw->getClientTargetAcquireFence()
+                                     : Fence::NO_FENCE;
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        bool frameLatched = layers[i]->onPostComposition();
+        bool frameLatched = layers[i]->onPostComposition(glCompositionDoneFence);
         if (frameLatched) {
             recordBufferingStats(layers[i]->getName().string(),
                     layers[i]->getOccupancyHistory(false));
@@ -1243,26 +1249,12 @@
         }
     }
 
-    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
     if (kIgnorePresentFences) {
         if (hw->isDisplayOn()) {
             enableHardwareVsync();
         }
     }
 
-    sp<Fence> fenceTrackerPresentFence;
-    sp<Fence> fenceTrackerRetireFence;
-    if (mHwc->retireFenceRepresentsStartOfScanout()) {
-        fenceTrackerPresentFence = presentFence;
-        fenceTrackerRetireFence = Fence::NO_FENCE;
-    } else {
-        fenceTrackerPresentFence = Fence::NO_FENCE;
-        fenceTrackerRetireFence = presentFence;
-    }
-    mFenceTracker.addFrame(refreshStartTime,
-            fenceTrackerPresentFence, fenceTrackerRetireFence,
-            hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
-
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
@@ -2019,6 +2011,7 @@
 {
     ALOGV("handlePageFlip");
 
+    nsecs_t latchTime = systemTime();
     Region dirtyRegion;
 
     bool visibleRegions = false;
@@ -2048,7 +2041,7 @@
         }
     }
     for (auto& layer : mLayersWithQueuedFrames) {
-        const Region dirty(layer->latchBuffer(visibleRegions));
+        const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
         const Layer::State& s(layer->getDrawingState());
         invalidateLayerStack(s.layerStack, dirty);
@@ -2845,9 +2838,9 @@
             }
 
             if ((index < numArgs) &&
-                    (args[index] == String16("--fences"))) {
+                    (args[index] == String16("--frame-events"))) {
                 index++;
-                mFenceTracker.dump(&result);
+                dumpFrameEventsLocked(result);
                 dumpAll = false;
             }
         }
@@ -2988,6 +2981,16 @@
     }
 }
 
+void SurfaceFlinger::dumpFrameEventsLocked(String8& result) {
+    result.appendFormat("Layer frame timestamps:\n");
+
+    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    const size_t count = currentLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        currentLayers[i]->dumpFrameEvents(result);
+    }
+}
+
 void SurfaceFlinger::dumpBufferingStats(String8& result) const {
     result.append("Buffering stats:\n");
     result.append("  [Layer name] <Active time> <Two buffer> "
@@ -3907,11 +3910,6 @@
     }
 }
 
-bool SurfaceFlinger::getFrameTimestamps(const Layer& layer,
-        uint64_t frameNumber, FrameTimestamps* outTimestamps) {
-    return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps);
-}
-
 // ---------------------------------------------------------------------------
 
 SurfaceFlinger::LayerVector::LayerVector() {
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index bdb2614..5b216dd 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -53,7 +53,6 @@
 #include "Barrier.h"
 #include "DisplayDevice.h"
 #include "DispSync.h"
-#include "FenceTracker.h"
 #include "FrameTracker.h"
 #include "MessageQueue.h"
 #include "SurfaceInterceptor.h"
@@ -401,8 +400,8 @@
             const LayerVector& currentLayers, uint32_t layerStack,
             Region& dirtyRegion, Region& opaqueRegion);
 
-    void preComposition();
-    void postComposition(nsecs_t refreshStartTime);
+    void preComposition(nsecs_t refreshStartTime);
+    void postComposition();
     void rebuildLayerStacks();
     void setUpHWComposer();
     void doComposition();
@@ -446,14 +445,13 @@
     void logFrameStats();
 
     void dumpStaticScreenStats(String8& result) const;
+    // Not const because each Layer needs to query Fences and cache timestamps.
+    void dumpFrameEventsLocked(String8& result);
 
     void recordBufferingStats(const char* layerName,
             std::vector<OccupancyTracker::Segment>&& history);
     void dumpBufferingStats(String8& result) const;
 
-    bool getFrameTimestamps(const Layer& layer, uint64_t frameNumber,
-            FrameTimestamps* outTimestamps);
-
     /* ------------------------------------------------------------------------
      * Attributes
      */
@@ -519,7 +517,6 @@
     nsecs_t mLastTransactionTime;
     bool mBootFinished;
     bool mForceFullDamage;
-    FenceTracker mFenceTracker;
 #ifdef USE_HWC2
     bool mPropagateBackpressure = true;
 #endif
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.cpp b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
index 5317cc7..1ef7065 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.cpp
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.cpp
@@ -248,10 +248,15 @@
     }
 }
 
-bool SurfaceFlingerConsumer::getFrameTimestamps(uint64_t frameNumber,
-        FrameTimestamps* outTimestamps) const {
-    sp<const Layer> l = mLayer.promote();
-    return l.get() ? l->getFrameTimestamps(frameNumber, outTimestamps) : false;
+bool SurfaceFlingerConsumer::addAndGetFrameTimestamps(
+        const NewFrameEventsEntry* newTimestamps,
+        uint64_t frameNumber, FrameTimestamps *outTimestamps) {
+    sp<Layer> l = mLayer.promote();
+    if (!l.get()) {
+        return false;
+    }
+    return l->addAndGetFrameTimestamps(
+            newTimestamps, frameNumber, outTimestamps);
 }
 
 // ---------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlingerConsumer.h b/services/surfaceflinger/SurfaceFlingerConsumer.h
index cb4c334..0f46ddc 100644
--- a/services/surfaceflinger/SurfaceFlingerConsumer.h
+++ b/services/surfaceflinger/SurfaceFlingerConsumer.h
@@ -37,7 +37,7 @@
     };
 
     SurfaceFlingerConsumer(const sp<IGraphicBufferConsumer>& consumer,
-            uint32_t tex, const Layer* layer)
+            uint32_t tex, Layer* layer)
         : GLConsumer(consumer, tex, GLConsumer::TEXTURE_EXTERNAL, false, false),
           mTransformToDisplayInverse(false), mSurfaceDamage(), mLayer(layer)
     {}
@@ -84,8 +84,9 @@
     void releasePendingBuffer();
 #endif
 
-    virtual bool getFrameTimestamps(uint64_t frameNumber,
-            FrameTimestamps* outTimestamps) const override;
+    virtual bool addAndGetFrameTimestamps(
+            const NewFrameEventsEntry* newTimestamps,
+            uint64_t frameNumber, FrameTimestamps* outTimestamps) override;
 
 private:
     virtual void onSidebandStreamChanged();
@@ -107,7 +108,7 @@
 #endif
 
     // The layer for this SurfaceFlingerConsumer
-    wp<const Layer> mLayer;
+    const wp<Layer> mLayer;
 };
 
 // ----------------------------------------------------------------------------
diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
index 0143d99..3bdb021 100644
--- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
+++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp
@@ -1068,12 +1068,12 @@
 
     nsecs_t refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC);
 
-    preComposition();
+    preComposition(refreshStartTime);
     rebuildLayerStacks();
     setUpHWComposer();
     doDebugFlashRegions();
     doComposition();
-    postComposition(refreshStartTime);
+    postComposition();
 }
 
 void SurfaceFlinger::doDebugFlashRegions()
@@ -1116,13 +1116,13 @@
     }
 }
 
-void SurfaceFlinger::preComposition()
+void SurfaceFlinger::preComposition(nsecs_t refreshStartTime)
 {
     bool needExtraInvalidate = false;
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        if (layers[i]->onPreComposition()) {
+        if (layers[i]->onPreComposition(refreshStartTime)) {
             needExtraInvalidate = true;
         }
     }
@@ -1131,19 +1131,28 @@
     }
 }
 
-void SurfaceFlinger::postComposition(nsecs_t refreshStartTime)
+void SurfaceFlinger::postComposition()
 {
+    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;
+
     const LayerVector& layers(mDrawingState.layersSortedByZ);
     const size_t count = layers.size();
     for (size_t i=0 ; i<count ; i++) {
-        bool frameLatched = layers[i]->onPostComposition();
+        bool frameLatched = layers[i]->onPostComposition(
+                glCompositionDoneFence);
         if (frameLatched) {
             recordBufferingStats(layers[i]->getName().string(),
                     layers[i]->getOccupancyHistory(false));
         }
     }
 
-    const HWComposer& hwc = getHwComposer();
     sp<Fence> presentFence = hwc.getDisplayFence(HWC_DISPLAY_PRIMARY);
 
     if (presentFence->isValid()) {
@@ -1154,17 +1163,12 @@
         }
     }
 
-    const sp<const DisplayDevice> hw(getDefaultDisplayDevice());
     if (kIgnorePresentFences) {
         if (hw->isDisplayOn()) {
             enableHardwareVsync();
         }
     }
 
-    // The present fence is actually a retire fence in HWC1.
-    mFenceTracker.addFrame(refreshStartTime, Fence::NO_FENCE, presentFence,
-            hw->getVisibleLayersSortedByZ(), hw->getClientTargetAcquireFence());
-
     if (mAnimCompositionPending) {
         mAnimCompositionPending = false;
 
@@ -1932,6 +1936,7 @@
 
 bool SurfaceFlinger::handlePageFlip()
 {
+    nsecs_t latchTime = systemTime();
     Region dirtyRegion;
 
     bool visibleRegions = false;
@@ -1963,7 +1968,7 @@
     }
     for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) {
         Layer* layer = layersWithQueuedFrames[i];
-        const Region dirty(layer->latchBuffer(visibleRegions));
+        const Region dirty(layer->latchBuffer(visibleRegions, latchTime));
         layer->useSurfaceDamage();
         const Layer::State& s(layer->getDrawingState());
         invalidateLayerStack(s.layerStack, dirty);
@@ -2755,9 +2760,9 @@
             }
 
             if ((index < numArgs) &&
-                    (args[index] == String16("--fences"))) {
+                    (args[index] == String16("--frame-events"))) {
                 index++;
-                mFenceTracker.dump(&result);
+                dumpFrameEventsLocked(result);
                 dumpAll = false;
             }
         }
@@ -2880,6 +2885,16 @@
             NUM_BUCKETS - 1, bucketTimeSec, percent);
 }
 
+void SurfaceFlinger::dumpFrameEventsLocked(String8& result) {
+    result.appendFormat("Layer frame timestamps:\n");
+
+    const LayerVector& currentLayers = mCurrentState.layersSortedByZ;
+    const size_t count = currentLayers.size();
+    for (size_t i=0 ; i<count ; i++) {
+        currentLayers[i]->dumpFrameEvents(result);
+    }
+}
+
 void SurfaceFlinger::recordBufferingStats(const char* layerName,
         std::vector<OccupancyTracker::Segment>&& history) {
     Mutex::Autolock lock(mBufferingStatsMutex);
@@ -3754,11 +3769,6 @@
     return result;
 }
 
-bool SurfaceFlinger::getFrameTimestamps(const Layer& layer,
-        uint64_t frameNumber, FrameTimestamps* outTimestamps) {
-    return mFenceTracker.getFrameTimestamps(layer, frameNumber, outTimestamps);
-}
-
 void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr,
         const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ) {
     if (DEBUG_SCREENSHOTS) {