Cache frame event history producer-side.

* Producer maintains a recent history of frames.
* Producer only does a binder call if requested
    informatiVon doesn't exist in the cache.
* Consumer sends fences to the producer, which
    can be queried for timestamps without a
    binder call.

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

Change-Id: I8a64579407cc2935f5c659462cb227b07ba27e43
diff --git a/include/gui/BufferQueue.h b/include/gui/BufferQueue.h
index 8cf8b67..a523cd8 100644
--- a/include/gui/BufferQueue.h
+++ b/include/gui/BufferQueue.h
@@ -66,9 +66,9 @@
         virtual void onFrameReplaced(const BufferItem& item) override;
         virtual void onBuffersReleased() override;
         virtual void onSidebandStreamChanged() override;
-        virtual bool addAndGetFrameTimestamps(
+        virtual void addAndGetFrameTimestamps(
                 const NewFrameEventsEntry* newTimestamps,
-                uint64_t frameNumber, FrameTimestamps* outTimestamps) override;
+                FrameEventHistoryDelta* outDelta) override;
     private:
         // mConsumerListener is a weak reference to the IConsumerListener.  This is
         // the raison d'etre of ProxyConsumerListener.
diff --git a/include/gui/BufferQueueProducer.h b/include/gui/BufferQueueProducer.h
index 9cfb383..e6ee6c6 100644
--- a/include/gui/BufferQueueProducer.h
+++ b/include/gui/BufferQueueProducer.h
@@ -177,8 +177,7 @@
             sp<Fence>* outFence, float outTransformMatrix[16]) override;
 
     // See IGraphicBufferProducer::getFrameTimestamps
-    virtual bool getFrameTimestamps(uint64_t frameNumber,
-            FrameTimestamps* outTimestamps) override;
+    virtual void getFrameTimestamps(FrameEventHistoryDelta* outDelta) override;
 
     // See IGraphicBufferProducer::getUniqueId
     virtual status_t getUniqueId(uint64_t* outId) const override;
@@ -195,9 +194,8 @@
     // BufferQueueCore::INVALID_BUFFER_SLOT otherwise
     int getFreeSlotLocked() const;
 
-    bool addAndGetFrameTimestamps(
-            const NewFrameEventsEntry* newTimestamps,
-            uint64_t frameNumber, FrameTimestamps* outTimestamps);
+    void addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps,
+            FrameEventHistoryDelta* outDelta);
 
     // waitForFreeSlotThenRelock finds the oldest slot in the FREE state. It may
     // block if there are no available slots and we are not in non-blocking
diff --git a/include/gui/FrameTimestamps.h b/include/gui/FrameTimestamps.h
index 6d3bd6c..5076597 100644
--- a/include/gui/FrameTimestamps.h
+++ b/include/gui/FrameTimestamps.h
@@ -23,47 +23,52 @@
 #include <utils/Timers.h>
 
 #include <array>
+#include <bitset>
+#include <vector>
 
 namespace android {
 
 
 struct FrameEvents;
+class FrameEventHistoryDelta;
 class String8;
 
 
-enum class SupportableFrameTimestamps {
+enum class FrameEvent {
+    POSTED,
     REQUESTED_PRESENT,
+    LATCH,
     ACQUIRE,
-    REFRESH_START,
-    GL_COMPOSITION_DONE_TIME,
-    DISPLAY_PRESENT_TIME,
-    DISPLAY_RETIRE_TIME,
-    RELEASE_TIME,
-};
-
-
-// The timestamps the consumer sends to the producer over binder.
-struct FrameTimestamps : public LightFlattenablePod<FrameTimestamps> {
-    FrameTimestamps() = default;
-    explicit FrameTimestamps(const FrameEvents& fences);
-
-    uint64_t frameNumber{0};
-    nsecs_t postedTime{0};
-    nsecs_t requestedPresentTime{0};
-    nsecs_t acquireTime{0};
-    nsecs_t refreshStartTime{0};
-    nsecs_t glCompositionDoneTime{0};
-    nsecs_t displayPresentTime{0};
-    nsecs_t displayRetireTime{0};
-    nsecs_t releaseTime{0};
+    FIRST_REFRESH_START,
+    LAST_REFRESH_START,
+    GL_COMPOSITION_DONE,
+    DISPLAY_PRESENT,
+    DISPLAY_RETIRE,
+    RELEASE,
+    EVENT_COUNT, // Not an actual event.
 };
 
 
 // A collection of timestamps corresponding to a single frame.
 struct FrameEvents {
+    bool hasPostedInfo() const;
+    bool hasRequestedPresentInfo() const;
+    bool hasLatchInfo() const;
+    bool hasFirstRefreshStartInfo() const;
+    bool hasLastRefreshStartInfo() const;
+    bool hasAcquireInfo() const;
+    bool hasGpuCompositionDoneInfo() const;
+    bool hasDisplayPresentInfo() const;
+    bool hasDisplayRetireInfo() const;
+    bool hasReleaseInfo() const;
+
     void checkFencesForCompletion();
     void dump(String8& outString) const;
 
+    static constexpr size_t EVENT_COUNT =
+            static_cast<size_t>(FrameEvent::EVENT_COUNT);
+    static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
+
     bool valid{false};
     uint64_t frameNumber{0};
 
@@ -72,6 +77,7 @@
     // a) we'll just never get them or b) they're not ready yet.
     bool addPostCompositeCalled{false};
     bool addRetireCalled{false};
+    bool addReleaseCalled{false};
 
     nsecs_t postedTime{0};
     nsecs_t requestedPresentTime{0};
@@ -93,6 +99,39 @@
 };
 
 
+// A short history of frames that are synchronized between the consumer and
+// producer via deltas.
+class FrameEventHistory {
+public:
+    virtual ~FrameEventHistory();
+
+    FrameEvents* getFrame(uint64_t frameNumber);
+    FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint);
+    void checkFencesForCompletion();
+    void dump(String8& outString) const;
+
+    static constexpr size_t MAX_FRAME_HISTORY = 8;
+
+protected:
+    std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
+};
+
+
+// The producer's interface to FrameEventHistory
+class ProducerFrameEventHistory : public FrameEventHistory {
+public:
+    ~ProducerFrameEventHistory() override;
+
+    void updateAcquireFence(uint64_t frameNumber, sp<Fence> acquire);
+    void applyDelta(const FrameEventHistoryDelta& delta);
+
+private:
+    size_t mAcquireOffset{0};
+};
+
+
+// Used by the consumer to create a new frame event record that is
+// partially complete.
 struct NewFrameEventsEntry {
     uint64_t frameNumber{0};
     nsecs_t postedTime{0};
@@ -101,14 +140,38 @@
 };
 
 
-class FrameEventHistory {
+// Used by the consumer to keep track of which fields it already sent to
+// the producer.
+class FrameEventDirtyFields {
 public:
-    FrameEvents* getFrame(uint64_t frameNumber);
-    FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint);
-    void checkFencesForCompletion();
-    void dump(String8& outString) const;
+    inline void reset() { mBitset.reset(); }
+    inline bool anyDirty() const { return mBitset.any(); }
 
-    void addQueue(const NewFrameEventsEntry& newFrameEntry);
+    template <FrameEvent event>
+    inline void setDirty() {
+        constexpr size_t eventIndex = static_cast<size_t>(event);
+        static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index.");
+        mBitset.set(eventIndex);
+    }
+
+    template <FrameEvent event>
+    inline bool isDirty() const {
+        constexpr size_t eventIndex = static_cast<size_t>(event);
+        static_assert(eventIndex < FrameEvents::EVENT_COUNT, "Bad index.");
+        return mBitset[eventIndex];
+    }
+
+private:
+    std::bitset<FrameEvents::EVENT_COUNT> mBitset;
+};
+
+
+// The consumer's interface to FrameEventHistory
+class ConsumerFrameEventHistory : public FrameEventHistory {
+public:
+    ~ConsumerFrameEventHistory() override;
+
+    void addQueue(const NewFrameEventsEntry& newEntry);
     void addLatch(uint64_t frameNumber, nsecs_t latchTime);
     void addPreComposition(uint64_t frameNumber, nsecs_t refreshStartTime);
     void addPostComposition(uint64_t frameNumber,
@@ -116,14 +179,96 @@
     void addRetire(uint64_t frameNumber, sp<Fence> displayRetire);
     void addRelease(uint64_t frameNumber, sp<Fence> release);
 
+    void getAndResetDelta(FrameEventHistoryDelta* delta);
+
 private:
-    static constexpr size_t MAX_FRAME_HISTORY = 8;
-    std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;
+    std::array<FrameEventDirtyFields, MAX_FRAME_HISTORY> mFramesDirty;
     size_t mQueueOffset{0};
     size_t mCompositionOffset{0};
     size_t mRetireOffset{0};
     size_t mReleaseOffset{0};
 };
 
+
+// A single frame update from the consumer to producer that can be sent
+// through Binder.
+// Although this may be sent multiple times for the same frame as new
+// timestamps are set, Fences only need to be sent once.
+class FrameEventsDelta : public Flattenable<FrameEventsDelta> {
+friend class ProducerFrameEventHistory;
+public:
+    FrameEventsDelta() = default;
+    FrameEventsDelta(size_t index,
+            const FrameEvents& frameTimestamps,
+            const FrameEventDirtyFields& dirtyFields);
+
+    // Flattenable implementation
+    size_t getFlattenedSize() const;
+    size_t getFdCount() const;
+    status_t flatten(void*& buffer, size_t& size, int*& fds,
+            size_t& count) const;
+    status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
+            size_t& count);
+
+private:
+    static size_t minFlattenedSize();
+
+    size_t mIndex{0};
+    uint64_t mFrameNumber{0};
+
+    bool mAddPostCompositeCalled{0};
+    bool mAddRetireCalled{0};
+    bool mAddReleaseCalled{0};
+
+    nsecs_t mPostedTime{0};
+    nsecs_t mRequestedPresentTime{0};
+    nsecs_t mLatchTime{0};
+    nsecs_t mFirstRefreshStartTime{0};
+    nsecs_t mLastRefreshStartTime{0};
+
+    sp<Fence> mAcquireFence{Fence::NO_FENCE};
+    sp<Fence> mGpuCompositionDoneFence{Fence::NO_FENCE};
+    sp<Fence> mDisplayPresentFence{Fence::NO_FENCE};
+    sp<Fence> mDisplayRetireFence{Fence::NO_FENCE};
+    sp<Fence> mReleaseFence{Fence::NO_FENCE};
+
+    // This is a static method with an auto return value so we can call
+    // it without needing const and non-const versions.
+    template <typename ThisType>
+    static inline auto allFences(ThisType fed) ->
+            std::array<decltype(&fed->mAcquireFence), 5> {
+        return {{
+            &fed->mAcquireFence, &fed->mGpuCompositionDoneFence,
+            &fed->mDisplayPresentFence, &fed->mDisplayRetireFence,
+            &fed->mReleaseFence
+        }};
+    }
+};
+
+
+// A collection of updates from consumer to producer that can be sent
+// through Binder.
+class FrameEventHistoryDelta
+        : public Flattenable<FrameEventHistoryDelta> {
+
+friend class ConsumerFrameEventHistory;
+friend class ProducerFrameEventHistory;
+
+public:
+    // Flattenable implementation.
+    size_t getFlattenedSize() const;
+    size_t getFdCount() const;
+    status_t flatten(void*& buffer, size_t& size, int*& fds,
+            size_t& count) const;
+    status_t unflatten(void const*& buffer, size_t& size, int const*& fds,
+            size_t& count);
+
+private:
+    static size_t minFlattenedSize();
+
+    std::vector<FrameEventsDelta> mDeltas;
+};
+
+
 } // namespace android
 #endif
diff --git a/include/gui/IConsumerListener.h b/include/gui/IConsumerListener.h
index 8eab3c5..93dd4ac 100644
--- a/include/gui/IConsumerListener.h
+++ b/include/gui/IConsumerListener.h
@@ -82,13 +82,11 @@
     // different stream.
     virtual void onSidebandStreamChanged() = 0; /* Asynchronous */
 
-    // Notifies the consumer of any new producer-side events and then queries
-    // the consumer timestamps
-    virtual bool addAndGetFrameTimestamps(
+    // Notifies the consumer of any new producer-side timestamps and
+    // returns the combined frame history that hasn't already been retrieved.
+    virtual void addAndGetFrameTimestamps(
             const NewFrameEventsEntry* /*newTimestamps*/,
-            uint64_t /*frameNumber*/, FrameTimestamps* /*outTimestamps*/) {
-        return false;
-    }
+            FrameEventHistoryDelta* /*outDelta*/) {}
 };
 
 
diff --git a/include/gui/IGraphicBufferProducer.h b/include/gui/IGraphicBufferProducer.h
index 493143a..612a902 100644
--- a/include/gui/IGraphicBufferProducer.h
+++ b/include/gui/IGraphicBufferProducer.h
@@ -588,13 +588,8 @@
     virtual status_t getLastQueuedBuffer(sp<GraphicBuffer>* outBuffer,
             sp<Fence>* outFence, float outTransformMatrix[16]) = 0;
 
-    // Attempts to retrieve timestamp information for the given frame number.
-    // If information for the given frame number is not found, returns false.
-    // Returns true otherwise.
-    //
-    // If a fence has not yet signaled the timestamp returned will be 0;
-    virtual bool getFrameTimestamps(uint64_t /*frameNumber*/,
-            FrameTimestamps* /*outTimestamps*/) { return false; }
+    // Gets the frame events that haven't already been retrieved.
+    virtual void getFrameTimestamps(FrameEventHistoryDelta* /*outDelta*/) {}
 
     // Returns a unique id for this BufferQueue
     virtual status_t getUniqueId(uint64_t* outId) const = 0;
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h
index bc36970..824e5c4 100644
--- a/include/gui/ISurfaceComposer.h
+++ b/include/gui/ISurfaceComposer.h
@@ -45,7 +45,7 @@
 class IDisplayEventConnection;
 class IMemoryHeap;
 class Rect;
-enum class SupportableFrameTimestamps;
+enum class FrameEvent;
 
 /*
  * This class defines the Binder IPC interface for accessing various
@@ -118,7 +118,7 @@
     /* Returns the frame timestamps supported by SurfaceFlinger.
      */
     virtual status_t getSupportedFrameTimestamps(
-            std::vector<SupportableFrameTimestamps>* outSupported) const = 0;
+            std::vector<FrameEvent>* outSupported) const = 0;
 
     /* set display power mode. depending on the mode, it can either trigger
      * screen on, off or low power mode and wait for it to complete.
diff --git a/include/gui/Surface.h b/include/gui/Surface.h
index aa5657f..c12d452 100644
--- a/include/gui/Surface.h
+++ b/include/gui/Surface.h
@@ -388,6 +388,9 @@
     mutable bool mQueriedSupportedTimestamps;
     mutable bool mFrameTimestampsSupportsPresent;
     mutable bool mFrameTimestampsSupportsRetire;
+
+    // A cached copy of the FrameEventHistory maintained by the consumer.
+    ProducerFrameEventHistory mFrameEventHistory;
 };
 
 namespace view {