/*
 * 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:
    FrameEventHistory();
    virtual ~FrameEventHistory();

    FrameEvents* getFrame(uint64_t frameNumber);
    FrameEvents* getFrame(uint64_t frameNumber, size_t* iHint);
    void checkFencesForCompletion();
    void dump(std::string& outString) const;

    static const size_t MAX_FRAME_HISTORY;

protected:
    std::vector<FrameEvents> 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();
    ~ConsumerFrameEventHistory() override;

    void onDisconnect();
    void setProducerWantsEvents();

    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::vector<FrameEvents>::iterator& frame);

    std::vector<FrameEventDirtyFields> 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
