Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 91190781 authored by Brian C. Anderson's avatar Brian C. Anderson Committed by Android (Google) Code Review
Browse files

Merge changes I6f728af0,I580409f0

* changes:
  Surface unit tests for getFrameTimestamps.
  Avoid sync calls for unsupported/non-existant times
parents e1903795 3da8d274
Loading
Loading
Loading
Loading
+11 −2
Original line number Original line Diff line number Diff line
@@ -116,13 +116,22 @@ class ProducerFrameEventHistory : public FrameEventHistory {
public:
public:
    ~ProducerFrameEventHistory() override;
    ~ProducerFrameEventHistory() override;


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


    void updateSignalTimes();
    void updateSignalTimes();


private:
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};
    size_t mAcquireOffset{0};


    // The consumer updates it's timelines in Layer and SurfaceFlinger since
    // The consumer updates it's timelines in Layer and SurfaceFlinger since
+10 −4
Original line number Original line Diff line number Diff line
@@ -33,6 +33,8 @@ struct ANativeWindow_Buffer;


namespace android {
namespace android {


class ISurfaceComposer;

/*
/*
 * An implementation of ANativeWindow that feeds graphics buffers into a
 * An implementation of ANativeWindow that feeds graphics buffers into a
 * BufferQueue.
 * BufferQueue.
@@ -66,7 +68,8 @@ public:
     * the controlledByApp flag indicates that this Surface (producer) is
     * the controlledByApp flag indicates that this Surface (producer) is
     * controlled by the application. This flag is used at connect time.
     * controlled by the application. This flag is used at connect time.
     */
     */
    explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer, bool controlledByApp = false);
    explicit Surface(const sp<IGraphicBufferProducer>& bufferProducer,
            bool controlledByApp = false);


    /* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
    /* getIGraphicBufferProducer() returns the IGraphicBufferProducer this
     * Surface was created with. Usually it's an error to use the
     * Surface was created with. Usually it's an error to use the
@@ -152,6 +155,9 @@ public:
protected:
protected:
    virtual ~Surface();
    virtual ~Surface();


    // Virtual for testing.
    virtual sp<ISurfaceComposer> composerService() const;

private:
private:
    // can't be copied
    // can't be copied
    Surface& operator = (const Surface& rhs);
    Surface& operator = (const Surface& rhs);
@@ -245,7 +251,6 @@ protected:
    enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
    enum { NUM_BUFFER_SLOTS = BufferQueue::NUM_BUFFER_SLOTS };
    enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };
    enum { DEFAULT_FORMAT = PIXEL_FORMAT_RGBA_8888 };


private:
    void querySupportedTimestampsLocked() const;
    void querySupportedTimestampsLocked() const;


    void freeAllBuffers();
    void freeAllBuffers();
@@ -389,7 +394,8 @@ private:


    Condition mQueueBufferCondition;
    Condition mQueueBufferCondition;


    uint64_t mNextFrameNumber;
    uint64_t mNextFrameNumber = 1;
    uint64_t mLastFrameNumber = 0;


    // Mutable because ANativeWindow::query needs this class const.
    // Mutable because ANativeWindow::query needs this class const.
    mutable bool mQueriedSupportedTimestamps;
    mutable bool mQueriedSupportedTimestamps;
@@ -398,7 +404,7 @@ private:


    // A cached copy of the FrameEventHistory maintained by the consumer.
    // A cached copy of the FrameEventHistory maintained by the consumer.
    bool mEnableFrameTimestamps = false;
    bool mEnableFrameTimestamps = false;
    ProducerFrameEventHistory mFrameEventHistory;
    std::unique_ptr<ProducerFrameEventHistory> mFrameEventHistory;
};
};


namespace view {
namespace view {
+47 −0
Original line number Original line Diff line number Diff line
@@ -24,13 +24,17 @@
#include <atomic>
#include <atomic>
#include <mutex>
#include <mutex>
#include <queue>
#include <queue>
#include <unordered_map>


namespace android {
namespace android {


class FenceToFenceTimeMap;

// A wrapper around fence that only implements isValid and getSignalTime.
// A wrapper around fence that only implements isValid and getSignalTime.
// It automatically closes the fence in a thread-safe manner once the signal
// It automatically closes the fence in a thread-safe manner once the signal
// time is known.
// time is known.
class FenceTime {
class FenceTime {
friend class FenceToFenceTimeMap;
public:
public:
    // An atomic snapshot of the FenceTime that is flattenable.
    // An atomic snapshot of the FenceTime that is flattenable.
    //
    //
@@ -107,15 +111,22 @@ public:
    // Returns a snapshot of the FenceTime in its current state.
    // Returns a snapshot of the FenceTime in its current state.
    Snapshot getSnapshot() const;
    Snapshot getSnapshot() const;


    void signalForTest(nsecs_t signalTime);

    // Override new and delete since this needs 8-byte alignment, which
    // Override new and delete since this needs 8-byte alignment, which
    // is not guaranteed on x86.
    // is not guaranteed on x86.
    static void* operator new(size_t nbytes) noexcept;
    static void* operator new(size_t nbytes) noexcept;
    static void operator delete(void *p);
    static void operator delete(void *p);


private:
private:
    // For tests only. If forceValidForTest is true, then getSignalTime will
    // never return SIGNAL_TIME_INVALID and isValid will always return true.
    FenceTime(const sp<Fence>& fence, bool forceValidForTest);

    enum class State {
    enum class State {
        VALID,
        VALID,
        INVALID,
        INVALID,
        FORCED_VALID_FOR_TEST,
    };
    };


    const State mState{State::INVALID};
    const State mState{State::INVALID};
@@ -156,6 +167,42 @@ private:
    std::queue<std::weak_ptr<FenceTime>> mQueue;
    std::queue<std::weak_ptr<FenceTime>> mQueue;
};
};


// Used by test code to create or get FenceTimes for a given Fence.
//
// By design, Fences cannot be signaled from user space. However, this class
// allows test code to set the apparent signalTime of a Fence and
// have it be visible to all FenceTimes. Release code should not use
// FenceToFenceTimeMap.
//
// FenceToFenceTimeMap keeps a weak reference to the FenceTime and automatically
// garbage collects entries every time a new FenceTime is created to avoid
// leaks. This prevents us from having to make the Fence destructor
// automatically notify that the underlying fence has been destroyed, which
// would affect release code paths. Garbage collecting so often is inefficient,
// but acceptable for testing.
//
// Since FenceTimes maintain a strong reference to underlying Fences, there
// should not be any aliasing issues where a new Fence happens to have the same
// address as a previous Fence; the previous entry will be garbage collected
// before the new one is added.
class FenceToFenceTimeMap {
public:
    // Create a new FenceTime with that wraps the provided Fence.
    std::shared_ptr<FenceTime> createFenceTimeForTest(const sp<Fence>& fence);

    // Signals all FenceTimes created through this class that are wrappers
    // around |fence|.
    void signalAllForTest(const sp<Fence>& fence, nsecs_t signalTime);

private:
    // Cleans up the entries that no longer have a strong reference.
    void garbageCollectLocked();

    mutable std::mutex mMutex;
    std::unordered_map<Fence*, std::vector<std::weak_ptr<FenceTime>>> mMap;
};


}; // namespace android
}; // namespace android


#endif // ANDROID_FENCE_TIME_H
#endif // ANDROID_FENCE_TIME_H
+32 −27
Original line number Original line Diff line number Diff line
@@ -241,33 +241,6 @@ void ProducerFrameEventHistory::updateAcquireFence(
    }
    }
}
}


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

void ProducerFrameEventHistory::applyDelta(
void ProducerFrameEventHistory::applyDelta(
        const FrameEventHistoryDelta& delta) {
        const FrameEventHistoryDelta& delta) {
    for (auto& d : delta.mDeltas) {
    for (auto& d : delta.mDeltas) {
@@ -320,6 +293,38 @@ void ProducerFrameEventHistory::updateSignalTimes() {
    mReleaseTimeline.updateSignalTimes();
    mReleaseTimeline.updateSignalTimes();
}
}


void ProducerFrameEventHistory::applyFenceDelta(FenceTimeline* timeline,
        std::shared_ptr<FenceTime>* dst, const FenceTime::Snapshot& src) const {
    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 = createFenceTime(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;
    }
}

std::shared_ptr<FenceTime> ProducerFrameEventHistory::createFenceTime(
        const sp<Fence>& fence) const {
    return std::make_shared<FenceTime>(fence);
}



// ============================================================================
// ============================================================================
// ConsumerFrameEventHistory
// ConsumerFrameEventHistory
+59 −31
Original line number Original line Diff line number Diff line
@@ -49,11 +49,11 @@ Surface::Surface(
      mAutoRefresh(false),
      mAutoRefresh(false),
      mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
      mSharedBufferSlot(BufferItem::INVALID_BUFFER_SLOT),
      mSharedBufferHasBeenQueued(false),
      mSharedBufferHasBeenQueued(false),
      mNextFrameNumber(1),
      mQueriedSupportedTimestamps(false),
      mQueriedSupportedTimestamps(false),
      mFrameTimestampsSupportsPresent(false),
      mFrameTimestampsSupportsPresent(false),
      mFrameTimestampsSupportsRetire(false),
      mFrameTimestampsSupportsRetire(false),
      mEnableFrameTimestamps(false)
      mEnableFrameTimestamps(false),
      mFrameEventHistory(std::make_unique<ProducerFrameEventHistory>())
{
{
    // Initialize the ANativeWindow function pointers.
    // Initialize the ANativeWindow function pointers.
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
    ANativeWindow::setSwapInterval  = hook_setSwapInterval;
@@ -97,6 +97,10 @@ Surface::~Surface() {
    }
    }
}
}


sp<ISurfaceComposer> Surface::composerService() const {
    return ComposerService::getComposerService();
}

sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
sp<IGraphicBufferProducer> Surface::getIGraphicBufferProducer() const {
    return mGraphicBufferProducer;
    return mGraphicBufferProducer;
}
}
@@ -144,6 +148,31 @@ void Surface::enableFrameTimestamps(bool enable) {
    mEnableFrameTimestamps = enable;
    mEnableFrameTimestamps = enable;
}
}


static bool checkConsumerForUpdates(
        const FrameEvents* e, const uint64_t lastFrameNumber,
        const nsecs_t* outRefreshStartTime,
        const nsecs_t* outGlCompositionDoneTime,
        const nsecs_t* outDisplayPresentTime,
        const nsecs_t* outDisplayRetireTime,
        const nsecs_t* outReleaseTime) {
    bool checkForRefreshStart = (outRefreshStartTime != nullptr) &&
            !e->hasFirstRefreshStartInfo();
    bool checkForGlCompositionDone = (outGlCompositionDoneTime != nullptr) &&
            !e->hasGpuCompositionDoneInfo();
    bool checkForDisplayPresent = (outDisplayPresentTime != nullptr) &&
            !e->hasDisplayPresentInfo();

    // DisplayRetire and Release are never available for the last frame.
    bool checkForDisplayRetire = (outDisplayRetireTime != nullptr) &&
            !e->hasDisplayRetireInfo() && (e->frameNumber != lastFrameNumber);
    bool checkForRelease = (outReleaseTime != nullptr) &&
            !e->hasReleaseInfo() && (e->frameNumber != lastFrameNumber);

    // RequestedPresent and Acquire info are always available producer-side.
    return checkForRefreshStart || checkForGlCompositionDone ||
            checkForDisplayPresent || checkForDisplayRetire || checkForRelease;
}

static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
static void getFrameTimestamp(nsecs_t *dst, const nsecs_t& src) {
    if (dst != nullptr) {
    if (dst != nullptr) {
        *dst = Fence::isValidTimestamp(src) ? src : 0;
        *dst = Fence::isValidTimestamp(src) ? src : 0;
@@ -179,25 +208,26 @@ status_t Surface::getFrameTimestamps(uint64_t frameNumber,
        return BAD_VALUE;
        return BAD_VALUE;
    }
    }


    FrameEvents* events = mFrameEventHistory.getFrame(frameNumber);
    FrameEvents* events = mFrameEventHistory->getFrame(frameNumber);
    if (events == nullptr) {
        // If the entry isn't available in the producer, it's definitely not
        // available in the consumer.
        return NAME_NOT_FOUND;
    }


    // Update our cache of events if the requested events are not available.
    // Update our cache of events if the requested events are not available.
    if (events == nullptr ||
    if (checkConsumerForUpdates(events, mLastFrameNumber,
        (outRequestedPresentTime && !events->hasRequestedPresentInfo()) ||
            outRefreshStartTime, outGlCompositionDoneTime,
        (outAcquireTime && !events->hasAcquireInfo()) ||
            outDisplayPresentTime, outDisplayRetireTime, outReleaseTime)) {
        (outRefreshStartTime && !events->hasFirstRefreshStartInfo()) ||
        (outGlCompositionDoneTime && !events->hasGpuCompositionDoneInfo()) ||
        (outDisplayPresentTime && !events->hasDisplayPresentInfo()) ||
        (outDisplayRetireTime && !events->hasDisplayRetireInfo()) ||
        (outReleaseTime && !events->hasReleaseInfo())) {
        FrameEventHistoryDelta delta;
        FrameEventHistoryDelta delta;
        mGraphicBufferProducer->getFrameTimestamps(&delta);
        mGraphicBufferProducer->getFrameTimestamps(&delta);
            mFrameEventHistory.applyDelta(delta);
        mFrameEventHistory->applyDelta(delta);
            events = mFrameEventHistory.getFrame(frameNumber);
        events = mFrameEventHistory->getFrame(frameNumber);
    }
    }


    // A record for the requested frame does not exist.
    if (events == nullptr) {
    if (events == nullptr) {
        // The entry was available before the update, but was overwritten
        // after the update. Make sure not to send the wrong frame's data.
        return NAME_NOT_FOUND;
        return NAME_NOT_FOUND;
    }
    }


@@ -347,11 +377,9 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    nsecs_t now = systemTime();
    nsecs_t now = systemTime();


    FrameEventHistoryDelta frameTimestamps;
    FrameEventHistoryDelta frameTimestamps;
    FrameEventHistoryDelta* frameTimestampsOrNull =
            enableFrameTimestamps ? &frameTimestamps : nullptr;

    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
    status_t result = mGraphicBufferProducer->dequeueBuffer(&buf, &fence,
            reqWidth, reqHeight, reqFormat, reqUsage, frameTimestampsOrNull);
            reqWidth, reqHeight, reqFormat, reqUsage,
            enableFrameTimestamps ? &frameTimestamps : nullptr);
    mLastDequeueDuration = systemTime() - now;
    mLastDequeueDuration = systemTime() - now;


    if (result < 0) {
    if (result < 0) {
@@ -373,7 +401,7 @@ int Surface::dequeueBuffer(android_native_buffer_t** buffer, int* fenceFd) {
    }
    }


    if (enableFrameTimestamps) {
    if (enableFrameTimestamps) {
         mFrameEventHistory.applyDelta(frameTimestamps);
         mFrameEventHistory->applyDelta(frameTimestamps);
    }
    }


    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
    if ((result & IGraphicBufferProducer::BUFFER_NEEDS_REALLOCATION) || gbuf == 0) {
@@ -567,18 +595,20 @@ int Surface::queueBuffer(android_native_buffer_t* buffer, int fenceFd) {
    }
    }


    if (mEnableFrameTimestamps) {
    if (mEnableFrameTimestamps) {
        mFrameEventHistory.applyDelta(output.frameTimestamps);
        mFrameEventHistory->applyDelta(output.frameTimestamps);
        // Update timestamps with the local acquire fence.
        // Update timestamps with the local acquire fence.
        // The consumer doesn't send it back to prevent us from having two
        // The consumer doesn't send it back to prevent us from having two
        // file descriptors of the same fence.
        // file descriptors of the same fence.
        mFrameEventHistory.updateAcquireFence(mNextFrameNumber,
        mFrameEventHistory->updateAcquireFence(mNextFrameNumber,
                std::make_shared<FenceTime>(std::move(fence)));
                std::make_shared<FenceTime>(std::move(fence)));


        // Cache timestamps of signaled fences so we can close their file
        // Cache timestamps of signaled fences so we can close their file
        // descriptors.
        // descriptors.
        mFrameEventHistory.updateSignalTimes();
        mFrameEventHistory->updateSignalTimes();
    }
    }


    mLastFrameNumber = mNextFrameNumber;

    mDefaultWidth = output.width;
    mDefaultWidth = output.width;
    mDefaultHeight = output.height;
    mDefaultHeight = output.height;
    mNextFrameNumber = output.nextFrameNumber;
    mNextFrameNumber = output.nextFrameNumber;
@@ -613,8 +643,7 @@ void Surface::querySupportedTimestampsLocked() const {
    mQueriedSupportedTimestamps = true;
    mQueriedSupportedTimestamps = true;


    std::vector<FrameEvent> supportedFrameTimestamps;
    std::vector<FrameEvent> supportedFrameTimestamps;
    sp<ISurfaceComposer> composer(ComposerService::getComposerService());
    status_t err = composerService()->getSupportedFrameTimestamps(
    status_t err = composer->getSupportedFrameTimestamps(
            &supportedFrameTimestamps);
            &supportedFrameTimestamps);


    if (err != NO_ERROR) {
    if (err != NO_ERROR) {
@@ -643,9 +672,8 @@ int Surface::query(int what, int* value) const {
                }
                }
                break;
                break;
            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
            case NATIVE_WINDOW_QUEUES_TO_WINDOW_COMPOSER: {
                sp<ISurfaceComposer> composer(
                if (composerService()->authenticateSurfaceTexture(
                        ComposerService::getComposerService());
                        mGraphicBufferProducer)) {
                if (composer->authenticateSurfaceTexture(mGraphicBufferProducer)) {
                    *value = 1;
                    *value = 1;
                } else {
                } else {
                    *value = 0;
                    *value = 0;
Loading