From 3da8d2748580b2575e368e203ce2c7f8d34dea05 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Thu, 28 Jul 2016 16:20:47 -0700 Subject: Surface unit tests for getFrameTimestamps. Verifies the following: 1) The timestamps and fences aren't transferred if the feature isn't explicitly enabled. 2) Attempts to get the timestamps will fail if not enabled. 3) Timestamps are transferred if enabled. 4) The support for Present/Retire timestamps are properly queried from the ISurfaceComposer. 5) Timestamps correspond to the correct frame. 6) The consumer doesn't send the acquire fence back to the producer and a sync call isn't made to try and get it from the producer. 7) A sync call isn't made when no timestamps are requested. 8) If the consumer sent the producer fences, the consumer can get the timestamps without a sync call. 9) If there was no GL composite performed, a sync call isn't made to get a non-existant fence/time. 10) When asking for the retire or release time of the most recent frame, a sync call isn't made. 11) Requests for unsupported timestamps return an error and do not result in a sync call. Test: Test: adb shell /data/nativetest/libgui_test/libgui_test --gtest_filter=*GetFrameTimestamps* Change-Id: I6f728af0d4a0f431c9e47131da64584a589559e7 --- libs/ui/FenceTime.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 83 insertions(+), 1 deletion(-) (limited to 'libs/ui/FenceTime.cpp') diff --git a/libs/ui/FenceTime.cpp b/libs/ui/FenceTime.cpp index c0245ebb89..edcec99a23 100644 --- a/libs/ui/FenceTime.cpp +++ b/libs/ui/FenceTime.cpp @@ -130,6 +130,14 @@ nsecs_t FenceTime::getSignalTime() { // Make the system call without the lock held. signalTime = fence->getSignalTime(); + // Allow tests to override SIGNAL_TIME_INVALID behavior, since tests + // use invalid underlying Fences without real file descriptors. + if (CC_UNLIKELY(mState == State::FORCED_VALID_FOR_TEST)) { + if (signalTime == Fence::SIGNAL_TIME_INVALID) { + signalTime = Fence::SIGNAL_TIME_PENDING; + } + } + // Make the signal time visible to everyone if it is no longer pending // and remove the class' reference to the fence. if (signalTime != Fence::SIGNAL_TIME_PENDING) { @@ -163,10 +171,28 @@ FenceTime::Snapshot FenceTime::getSnapshot() const { return Snapshot(mFence); } +// For tests only. If forceValidForTest is true, then getSignalTime will +// never return SIGNAL_TIME_INVALID and isValid will always return true. +FenceTime::FenceTime(const sp& fence, bool forceValidForTest) + : mState(forceValidForTest ? + State::FORCED_VALID_FOR_TEST : State::INVALID), + mFence(fence), + mSignalTime(mState == State::INVALID ? + Fence::SIGNAL_TIME_INVALID : Fence::SIGNAL_TIME_PENDING) { +} + +void FenceTime::signalForTest(nsecs_t signalTime) { + // To be realistic, this should really set a hidden value that + // gets picked up in the next call to getSignalTime, but this should + // be good enough. + std::lock_guard lock(mMutex); + mFence.clear(); + mSignalTime.store(signalTime, std::memory_order_relaxed); +} + // ============================================================================ // FenceTime::Snapshot // ============================================================================ - FenceTime::Snapshot::Snapshot(const sp& srcFence) : state(State::FENCE), fence(srcFence) { } @@ -279,4 +305,60 @@ void FenceTimeline::updateSignalTimes() { } } +// ============================================================================ +// FenceToFenceTimeMap +// ============================================================================ +std::shared_ptr FenceToFenceTimeMap::createFenceTimeForTest( + const sp& fence) { + std::lock_guard lock(mMutex); + // Always garbage collecting isn't efficient, but this is only for testing. + garbageCollectLocked(); + std::shared_ptr fenceTime(new FenceTime(fence, true)); + mMap[fence.get()].push_back(fenceTime); + return fenceTime; +} + +void FenceToFenceTimeMap::signalAllForTest( + const sp& fence, nsecs_t signalTime) { + bool signaled = false; + + std::lock_guard lock(mMutex); + auto it = mMap.find(fence.get()); + if (it != mMap.end()) { + for (auto& weakFenceTime : it->second) { + std::shared_ptr fenceTime = weakFenceTime.lock(); + if (!fenceTime) { + continue; + } + ALOGE_IF(!fenceTime->isValid(), + "FenceToFenceTimeMap::signalAllForTest: " + "Signaling invalid fence."); + fenceTime->signalForTest(signalTime); + signaled = true; + } + } + + if (!signaled) { + ALOGE("FenceToFenceTimeMap::signalAllForTest: Nothing to signal."); + } +} + +void FenceToFenceTimeMap::garbageCollectLocked() { + for (auto& it : mMap) { + // Erase all expired weak pointers from the vector. + auto& vect = it.second; + vect.erase( + std::remove_if(vect.begin(), vect.end(), + [](const std::weak_ptr& ft) { + return ft.expired(); + }), + vect.end()); + + // Also erase the map entry if the vector is now empty. + if (vect.empty()) { + mMap.erase(it.first); + } + } +} + } // namespace android -- cgit v1.2.3-59-g8ed1b