/*
 * 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_GUI_FRAMETIMESTAMPS_H
#define ANDROID_GUI_FRAMETIMESTAMPS_H

#include <ui/FenceTime.h>
#include <utils/Flattenable.h>
#include <utils/StrongPointer.h>
#include <utils/Timers.h>

#include <array>
#include <bitset>
#include <vector>

namespace android {

struct FrameEvents;
class FrameEventHistoryDelta;


// Identifiers for all the events that may be recorded or reported.
enum class FrameEvent {
    POSTED,
    REQUESTED_PRESENT,
    LATCH,
    ACQUIRE,
    FIRST_REFRESH_START,
    LAST_REFRESH_START,
    GPU_COMPOSITION_DONE,
    DISPLAY_PRESENT,
    DEQUEUE_READY,
    RELEASE,
    EVENT_COUNT, // Not an actual event.
};


// A collection of timestamps corresponding to a single frame.
struct FrameEvents {
    static constexpr auto EVENT_COUNT =
            static_cast<size_t>(FrameEvent::EVENT_COUNT);
    static_assert(EVENT_COUNT <= 32, "Event count sanity check failed.");
    static constexpr nsecs_t TIMESTAMP_PENDING = -2;

    static inline bool isValidTimestamp(nsecs_t time) {
        return time != TIMESTAMP_PENDING;
    }

    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 hasReleaseInfo() const;
    bool hasDequeueReadyInfo() const;

    void checkFencesForCompletion();
    void dump(std::string& outString) const;

    bool valid{false};
    int connectId{0};
    uint64_t frameNumber{0};

    // Whether or not certain points in the frame's life cycle have been
    // encountered help us determine if timestamps aren't available because
    // a) we'll just never get them or b) they're not ready yet.
    bool addPostCompositeCalled{false};
    bool addReleaseCalled{false};

    nsecs_t postedTime{TIMESTAMP_PENDING};
    nsecs_t requestedPresentTime{TIMESTAMP_PENDING};
    nsecs_t latchTime{TIMESTAMP_PENDING};
    nsecs_t firstRefreshStartTime{TIMESTAMP_PENDING};
    nsecs_t lastRefreshStartTime{TIMESTAMP_PENDING};
    nsecs_t dequeueReadyTime{TIMESTAMP_PENDING};

    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> releaseFence{FenceTime::NO_FENCE};
};

struct CompositorTiming {
    nsecs_t deadline{0};
    nsecs_t interval{16666667};
    nsecs_t presentLatency{16666667};
};

// 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(std::string& outString) const;

    static constexpr size_t MAX_FRAME_HISTORY = 8;

protected:
    std::array<FrameEvents, MAX_FRAME_HISTORY> mFrames;

    CompositorTiming mCompositorTiming;
};


// The producer's interface to FrameEventHistory
class ProducerFrameEventHistory : public FrameEventHistory {
public:
    ~ProducerFrameEventHistory() override;

    // Public for testing.
    static nsecs_t snapToNextTick(
            nsecs_t timestamp, nsecs_t tickPhase, nsecs_t tickInterval);

    nsecs_t getNextCompositeDeadline(const nsecs_t now) const;
    nsecs_t getCompositeInterval() const { return mCompositorTiming.interval; }
    nsecs_t getCompositeToPresentLatency() const {
        return mCompositorTiming.presentLatency;
    }

    // virtual for testing.
    virtual void updateAcquireFence(
            uint64_t frameNumber, std::shared_ptr<FenceTime>&& acquire);
    void applyDelta(const FrameEventHistoryDelta& delta);

    void updateSignalTimes();

protected:
    void applyFenceDelta(FenceTimeline* timeline,
            std::shared_ptr<FenceTime>* dst,
            const FenceTime::Snapshot& src) const;

    // virtual for testing.
    virtual std::shared_ptr<FenceTime> createFenceTime(
            const sp<Fence>& fence) const;

    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 mReleaseTimeline;
};


// 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};
    nsecs_t requestedPresentTime{0};
    std::shared_ptr<FenceTime> acquireFence{FenceTime::NO_FENCE};
};


// Used by the consumer to keep track of which fields it already sent to
// the producer.
class FrameEventDirtyFields {
public:
    inline void reset() { mBitset.reset(); }
    inline bool anyDirty() const { return mBitset.any(); }

    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 onDisconnect();

    void initializeCompositorTiming(const CompositorTiming& compositorTiming);

    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,
            const std::shared_ptr<FenceTime>& gpuCompositionDone,
            const std::shared_ptr<FenceTime>& displayPresent,
            const CompositorTiming& compositorTiming);
    void addRelease(uint64_t frameNumber, nsecs_t dequeueReadyTime,
            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};
    size_t mReleaseOffset{0};

    int mCurrentConnectId{0};
    bool mProducerWantsEvents{false};
};


// 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);

    // 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;
    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 constexpr size_t minFlattenedSize();

    size_t mIndex{0};
    uint64_t mFrameNumber{0};

    bool mAddPostCompositeCalled{0};
    bool mAddReleaseCalled{0};

    nsecs_t mPostedTime{FrameEvents::TIMESTAMP_PENDING};
    nsecs_t mRequestedPresentTime{FrameEvents::TIMESTAMP_PENDING};
    nsecs_t mLatchTime{FrameEvents::TIMESTAMP_PENDING};
    nsecs_t mFirstRefreshStartTime{FrameEvents::TIMESTAMP_PENDING};
    nsecs_t mLastRefreshStartTime{FrameEvents::TIMESTAMP_PENDING};
    nsecs_t mDequeueReadyTime{FrameEvents::TIMESTAMP_PENDING};

    FenceTime::Snapshot mGpuCompositionDoneFence;
    FenceTime::Snapshot mDisplayPresentFence;
    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.
    template <typename ThisT>
    static inline auto allFences(ThisT fed) ->
            std::array<decltype(&fed->mReleaseFence), 3> {
        return {{
            &fed->mGpuCompositionDoneFence, &fed->mDisplayPresentFence,
            &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:
    FrameEventHistoryDelta() = default;

    // Movable.
    FrameEventHistoryDelta(FrameEventHistoryDelta&& src) = default;
    FrameEventHistoryDelta& operator=(FrameEventHistoryDelta&& src) noexcept;
    // Not copyable.
    FrameEventHistoryDelta(const FrameEventHistoryDelta& src) = delete;
    FrameEventHistoryDelta& operator=(
            const FrameEventHistoryDelta& src) = delete;

    // 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 constexpr size_t minFlattenedSize();

    std::vector<FrameEventsDelta> mDeltas;
    CompositorTiming mCompositorTiming;
};


} // namespace android
#endif
