From f527548dd751bd62b1302cf357fdb4840bc115a9 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 29 Jan 2019 18:42:42 -0800 Subject: SF: Move/Refactor Layer::setPerFrameData Moves functionality out of ColorLayer, BufferLayer, BufferStateLayer and BufferQueueLayer related to setting the per-frame data. Instead each of the front-end classes now implements a minimal function to set the per-frame state into the LayerFECompositionState structure. compositionengine::OutputLayer now takes care of sending the state to the HWC, and in particular with detecting when client composition needs to be forced due to lack of HWC support (though the front-end can also set a flag to force client composition for a few things it knows about). SurfaceFlinger::calculateWorkingSet is also refactored to work with the changes made, and prepare it to be moved over to CompositionEngine. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Bug: 121291683 Change-Id: I2cb0442f68ec5c5f65f5b4cb418dda4c42e5dc39 --- services/surfaceflinger/BufferQueueLayer.cpp | 34 ++++++++-------------------- 1 file changed, 9 insertions(+), 25 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d6853661a5..2c3da1aa21 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -377,7 +377,6 @@ status_t BufferQueueLayer::updateActiveBuffer() { mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; layerCompositionState.buffer = mActiveBuffer; - layerCompositionState.bufferSlot = mActiveBufferSlot; if (mActiveBuffer == nullptr) { // this can only happen if the very first buffer was rejected. @@ -397,32 +396,17 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::setHwcLayerBuffer(const sp& display) { - const auto outputLayer = findOutputLayerForDisplay(display); - LOG_FATAL_IF(!outputLayer); - LOG_FATAL_IF(!outputLayer->getState.hwc); - auto& hwcLayer = (*outputLayer->getState().hwc).hwcLayer; - - uint32_t hwcSlot = 0; - sp hwcBuffer; - - // INVALID_BUFFER_SLOT is used to identify BufferStateLayers. Default to 0 - // for BufferQueueLayers - int slot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; - (*outputLayer->editState().hwc) - .hwcBufferCache.getHwcBuffer(slot, mActiveBuffer, &hwcSlot, &hwcBuffer); - - auto acquireFence = mConsumer->getCurrentFence(); - auto error = hwcLayer->setBuffer(hwcSlot, hwcBuffer, acquireFence); - if (error != HWC2::Error::None) { - ALOGE("[%s] Failed to set buffer %p: %s (%d)", mName.string(), mActiveBuffer->handle, - to_string(error).c_str(), static_cast(error)); +void BufferQueueLayer::latchPerFrameState( + compositionengine::LayerFECompositionState& compositionState) const { + BufferLayer::latchPerFrameState(compositionState); + if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { + return; } - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.bufferSlot = mActiveBufferSlot; - layerCompositionState.buffer = mActiveBuffer; - layerCompositionState.acquireFence = acquireFence; + compositionState.buffer = mActiveBuffer; + compositionState.bufferSlot = + (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; + compositionState.acquireFence = mConsumer->getCurrentFence(); } // ----------------------------------------------------------------------- -- cgit v1.2.3-59-g8ed1b From a8955dd64c0c7fd355a7a3973403c3ba916d6f27 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Wed, 10 Jul 2019 10:19:09 -0700 Subject: SF: Factor out expected present time computation Compute expected present time once and pass it to traversed layers instead of calling back into SF for each layer. This will simplify synchronization for per-display refresh. Also, recompute on Binder transaction, since the cached value computed on invalidate may be stale. Bug: 130554049 Bug: 123715322 Test: go/wm-smoke Change-Id: I7153a728360e789dc4f97d2c39c4bdaa14183624 --- services/surfaceflinger/BufferLayer.cpp | 21 +++++++------ services/surfaceflinger/BufferLayer.h | 16 +++++----- services/surfaceflinger/BufferQueueLayer.cpp | 15 ++++----- services/surfaceflinger/BufferQueueLayer.h | 7 +++-- services/surfaceflinger/BufferStateLayer.cpp | 17 +++++----- services/surfaceflinger/BufferStateLayer.h | 7 +++-- services/surfaceflinger/Layer.h | 7 +++-- services/surfaceflinger/SurfaceFlinger.cpp | 36 ++++++++++++++-------- services/surfaceflinger/SurfaceFlinger.h | 21 ++++++------- .../tests/unittests/CompositionTest.cpp | 2 +- 10 files changed, 81 insertions(+), 68 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index f51fbb45f6..4cf37a4d30 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -395,7 +395,8 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, return true; } -bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) { +bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) { ATRACE_CALL(); bool refreshRequired = latchSidebandStream(recomputeVisibleRegions); @@ -430,12 +431,12 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) const bool oldOpacity = isOpaque(s); sp oldBuffer = mActiveBuffer; - if (!allTransactionsSignaled()) { + if (!allTransactionsSignaled(expectedPresentTime)) { mFlinger->setTransactionFlags(eTraversalNeeded); return false; } - status_t err = updateTexImage(recomputeVisibleRegions, latchTime); + status_t err = updateTexImage(recomputeVisibleRegions, latchTime, expectedPresentTime); if (err != NO_ERROR) { return false; } @@ -540,10 +541,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) } // transaction -void BufferLayer::notifyAvailableFrames() { - const auto headFrameNumber = getHeadFrameNumber(); +void BufferLayer::notifyAvailableFrames(nsecs_t expectedPresentTime) { + const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime); const bool headFenceSignaled = fenceHasSignaled(); - const bool presentTimeIsCurrent = framePresentTimeIsCurrent(); + const bool presentTimeIsCurrent = framePresentTimeIsCurrent(expectedPresentTime); Mutex::Autolock lock(mLocalSyncPointMutex); for (auto& point : mLocalSyncPoints) { if (headFrameNumber >= point->getFrameNumber() && headFenceSignaled && @@ -591,8 +592,8 @@ bool BufferLayer::latchUnsignaledBuffers() { } // h/w composer set-up -bool BufferLayer::allTransactionsSignaled() { - auto headFrameNumber = getHeadFrameNumber(); +bool BufferLayer::allTransactionsSignaled(nsecs_t expectedPresentTime) { + const auto headFrameNumber = getHeadFrameNumber(expectedPresentTime); bool matchingFramesFound = false; bool allTransactionsApplied = true; Mutex::Autolock lock(mLocalSyncPointMutex); @@ -658,9 +659,9 @@ bool BufferLayer::needsFiltering(const sp& displayDevice) c sourceCrop.getWidth() != displayFrame.getWidth(); } -uint64_t BufferLayer::getHeadFrameNumber() const { +uint64_t BufferLayer::getHeadFrameNumber(nsecs_t expectedPresentTime) const { if (hasFrameUpdate()) { - return getFrameNumber(); + return getFrameNumber(expectedPresentTime); } else { return mCurrentFrameNumber; } diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b679380b79..c793550625 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -96,11 +96,12 @@ public: // the visible regions need to be recomputed (this is a fairly heavy // operation, so this should be set only if needed). Typically this is used // to figure out if the content or size of a surface has changed. - bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + bool latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) override; bool isBufferLatched() const override { return mRefreshPending; } - void notifyAvailableFrames() override; + void notifyAvailableFrames(nsecs_t expectedPresentTime) override; bool hasReadyFrame() const override; @@ -114,7 +115,7 @@ public: // ----------------------------------------------------------------------- private: virtual bool fenceHasSignaled() const = 0; - virtual bool framePresentTimeIsCurrent() const = 0; + virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; virtual nsecs_t getDesiredPresentTime() = 0; virtual std::shared_ptr getCurrentFenceTime() const = 0; @@ -129,7 +130,7 @@ private: virtual int getDrawingApi() const = 0; virtual PixelFormat getPixelFormat() const = 0; - virtual uint64_t getFrameNumber() const = 0; + virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; virtual bool getAutoRefresh() const = 0; virtual bool getSidebandStreamChanged() const = 0; @@ -142,7 +143,8 @@ private: virtual void setFilteringEnabled(bool enabled) = 0; virtual status_t bindTextureImage() = 0; - virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) = 0; + virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) = 0; virtual status_t updateActiveBuffer() = 0; virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; @@ -156,7 +158,7 @@ protected: // Check all of the local sync points to ensure that all transactions // which need to have been applied prior to the frame which is about to // be latched have signaled - bool allTransactionsSignaled(); + bool allTransactionsSignaled(nsecs_t expectedPresentTime); static bool getOpacityForFormat(uint32_t format); @@ -175,7 +177,7 @@ private: // Returns true if this layer requires filtering bool needsFiltering(const sp& displayDevice) const; - uint64_t getHeadFrameNumber() const; + uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d6853661a5..fe9edfe895 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -137,13 +137,13 @@ bool BufferQueueLayer::fenceHasSignaled() const { return mQueueItems[0].mFenceTime->getSignalTime() != Fence::SIGNAL_TIME_PENDING; } -bool BufferQueueLayer::framePresentTimeIsCurrent() const { +bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const { if (!hasFrameUpdate() || isRemovedFromCurrentState()) { return true; } Mutex::Autolock lock(mQueueItemLock); - return mQueueItems[0].mTimestamp <= mFlinger->getExpectedPresentTime(); + return mQueueItems[0].mTimestamp <= expectedPresentTime; } nsecs_t BufferQueueLayer::getDesiredPresentTime() { @@ -196,13 +196,11 @@ PixelFormat BufferQueueLayer::getPixelFormat() const { return mFormat; } -uint64_t BufferQueueLayer::getFrameNumber() const { +uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); uint64_t frameNumber = mQueueItems[0].mFrameNumber; // The head of the queue will be dropped if there are signaled and timely frames behind it - nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime(); - if (isRemovedFromCurrentState()) { expectedPresentTime = 0; } @@ -268,7 +266,8 @@ status_t BufferQueueLayer::bindTextureImage() { return mConsumer->bindTextureImage(); } -status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) { +status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) { // This boolean is used to make sure that SurfaceFlinger's shadow copy // of the buffer queue isn't modified when the buffer queue is returning // BufferItem's that weren't actually queued. This can happen in shared @@ -279,8 +278,6 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, getTransformToDisplayInverse(), mFreezeGeometryUpdates); - nsecs_t expectedPresentTime = mFlinger->getExpectedPresentTime(); - if (isRemovedFromCurrentState()) { expectedPresentTime = 0; } @@ -432,7 +429,7 @@ void BufferQueueLayer::setHwcLayerBuffer(const sp& display) void BufferQueueLayer::fakeVsync() { mRefreshPending = false; bool ignored = false; - latchBuffer(ignored, systemTime()); + latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); usleep(16000); releasePendingBuffer(systemTime()); } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 7def33ad78..e60a083cff 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -61,7 +61,7 @@ public: // ----------------------------------------------------------------------- public: bool fenceHasSignaled() const override; - bool framePresentTimeIsCurrent() const override; + bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: nsecs_t getDesiredPresentTime() override; @@ -77,7 +77,7 @@ private: int getDrawingApi() const override; PixelFormat getPixelFormat() const override; - uint64_t getFrameNumber() const override; + uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; bool getSidebandStreamChanged() const override; @@ -89,7 +89,8 @@ private: void setFilteringEnabled(bool enabled) override; status_t bindTextureImage() override; - status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) override; status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4b01301467..06b2364bcf 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -216,7 +216,7 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - mFlinger->mTimeStats->setPostTime(getSequence(), getFrameNumber(), getName().c_str(), postTime); + mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime); mDesiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -369,12 +369,12 @@ bool BufferStateLayer::fenceHasSignaled() const { return getDrawingState().acquireFence->getStatus() == Fence::Status::Signaled; } -bool BufferStateLayer::framePresentTimeIsCurrent() const { +bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const { if (!hasFrameUpdate() || isRemovedFromCurrentState()) { return true; } - return mDesiredPresentTime <= mFlinger->getExpectedPresentTime(); + return mDesiredPresentTime <= expectedPresentTime; } nsecs_t BufferStateLayer::getDesiredPresentTime() { @@ -446,7 +446,7 @@ PixelFormat BufferStateLayer::getPixelFormat() const { return mActiveBuffer->format; } -uint64_t BufferStateLayer::getFrameNumber() const { +uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { return mFrameNumber; } @@ -494,7 +494,8 @@ status_t BufferStateLayer::bindTextureImage() { return engine.bindExternalTextureBuffer(mTextureName, s.buffer, s.acquireFence); } -status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime) { +status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nsecs_t latchTime, + nsecs_t /*expectedPresentTime*/) { const State& s(getDrawingState()); if (!s.buffer) { @@ -528,7 +529,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); - mFlinger->mTimeStats->removeTimeRecord(layerID, getFrameNumber()); + mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); return BAD_VALUE; } @@ -550,8 +551,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } - mFlinger->mTimeStats->setAcquireFence(layerID, getFrameNumber(), getCurrentFenceTime()); - mFlinger->mTimeStats->setLatchTime(layerID, getFrameNumber(), latchTime); + mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); + mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); mCurrentStateModified = false; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index db8ae0d337..18e8cfa481 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -100,7 +100,7 @@ public: // Interface implementation for BufferLayer // ----------------------------------------------------------------------- bool fenceHasSignaled() const override; - bool framePresentTimeIsCurrent() const override; + bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; // Inherit from ClientCache::ErasedRecipient void bufferErased(const client_cache_t& clientCacheId) override; @@ -119,7 +119,7 @@ private: int getDrawingApi() const override; PixelFormat getPixelFormat() const override; - uint64_t getFrameNumber() const override; + uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; bool getSidebandStreamChanged() const override; @@ -131,7 +131,8 @@ private: void setFilteringEnabled(bool enabled) override; status_t bindTextureImage() override; - status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime) override; + status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, + nsecs_t expectedPresentTime) override; status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b693a47f39..f7e188f3ec 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -561,8 +561,9 @@ public: * operation, so this should be set only if needed). Typically this is used * to figure out if the content or size of a surface has changed. */ - virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/) { - return {}; + virtual bool latchBuffer(bool& /*recomputeVisibleRegions*/, nsecs_t /*latchTime*/, + nsecs_t /*expectedPresentTime*/) { + return false; } virtual bool isBufferLatched() const { return false; } @@ -812,7 +813,7 @@ public: // this to be called once. sp getHandle(); const String8& getName() const; - virtual void notifyAvailableFrames() {} + virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {} virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 99440a6d5e..cd80f2b359 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1693,15 +1693,15 @@ bool SurfaceFlinger::previousFrameMissed() NO_THREAD_SAFETY_ANALYSIS { return fence != Fence::NO_FENCE && (fence->getStatus() == Fence::Status::Unsignaled); } -void SurfaceFlinger::populateExpectedPresentTime() NO_THREAD_SAFETY_ANALYSIS { +void SurfaceFlinger::populateExpectedPresentTime() { DisplayStatInfo stats; mScheduler->getDisplayStatInfo(&stats); const nsecs_t presentTime = mScheduler->getDispSyncExpectedPresentTime(); // Inflate the expected present time if we're targetting the next vsync. - mExpectedPresentTime = - mVsyncModulator.getOffsets().sf < mPhaseOffsets->getOffsetThresholdForNextVsync() - ? presentTime - : presentTime + stats.vsyncPeriod; + mExpectedPresentTime.store(mVsyncModulator.getOffsets().sf < + mPhaseOffsets->getOffsetThresholdForNextVsync() + ? presentTime + : presentTime + stats.vsyncPeriod); } void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { @@ -2856,9 +2856,11 @@ void SurfaceFlinger::processDisplayChangesLocked() { void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { + const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); + // Notify all layers of available frames - mCurrentState.traverseInZOrder([](Layer* layer) { - layer->notifyAvailableFrames(); + mCurrentState.traverseInZOrder([expectedPresentTime](Layer* layer) { + layer->notifyAvailableFrames(expectedPresentTime); }); /* @@ -3057,7 +3059,7 @@ void SurfaceFlinger::updateCursorAsync() void SurfaceFlinger::latchAndReleaseBuffer(const sp& layer) { if (layer->hasReadyFrame()) { bool ignored = false; - layer->latchBuffer(ignored, systemTime()); + layer->latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); } layer->releasePendingBuffer(systemTime()); } @@ -3305,6 +3307,8 @@ bool SurfaceFlinger::handlePageFlip() bool frameQueued = false; bool newDataLatched = false; + const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); + // Store the set of layers that need updates. This set must not change as // buffers are being latched, as this could result in a deadlock. // Example: Two producers share the same command stream and: @@ -3317,7 +3321,6 @@ bool SurfaceFlinger::handlePageFlip() mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->hasReadyFrame()) { frameQueued = true; - const nsecs_t expectedPresentTime = getExpectedPresentTime(); if (layer->shouldPresentNow(expectedPresentTime)) { mLayersWithQueuedFrames.push_back(layer); } else { @@ -3335,7 +3338,7 @@ bool SurfaceFlinger::handlePageFlip() Mutex::Autolock lock(mStateLock); for (auto& layer : mLayersWithQueuedFrames) { - if (layer->latchBuffer(visibleRegions, latchTime)) { + if (layer->latchBuffer(visibleRegions, latchTime, expectedPresentTime)) { mLayersPendingRefresh.push_back(layer); } layer->useSurfaceDamage(); @@ -3656,6 +3659,7 @@ bool SurfaceFlinger::flushTransactionQueues() { while (!transactionQueue.empty()) { const auto& transaction = transactionQueue.front(); if (!transactionIsReadyToBeApplied(transaction.desiredPresentTime, + true /* useCachedExpectedPresentTime */, transaction.states)) { setTransactionFlags(eTransactionFlushNeeded); break; @@ -3708,8 +3712,12 @@ bool SurfaceFlinger::containsAnyInvalidClientState(const Vector& } bool SurfaceFlinger::transactionIsReadyToBeApplied(int64_t desiredPresentTime, + bool useCachedExpectedPresentTime, const Vector& states) { - nsecs_t expectedPresentTime = getExpectedPresentTime(); + if (!useCachedExpectedPresentTime) + populateExpectedPresentTime(); + + const nsecs_t expectedPresentTime = mExpectedPresentTime.load(); // Do not present if the desiredPresentTime has not passed unless it is more than one second // in the future. We ignore timestamps more than 1 second in the future for stability reasons. if (desiredPresentTime >= 0 && desiredPresentTime >= expectedPresentTime && @@ -3764,8 +3772,10 @@ void SurfaceFlinger::setTransactionState(const Vector& states, itr = mTransactionQueues.find(applyToken); } } - if (itr != mTransactionQueues.end() || - !transactionIsReadyToBeApplied(desiredPresentTime, states)) { + + // Expected present time is computed and cached on invalidate, so it may be stale. + if (itr != mTransactionQueues.end() || !transactionIsReadyToBeApplied( + desiredPresentTime, false /* useCachedExpectedPresentTime */, states)) { mTransactionQueues[applyToken].emplace(states, displays, flags, desiredPresentTime, uncacheBuffer, listenerCallbacks, postTime, privileged); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 0e6eacf72b..099ba723ee 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -295,18 +295,13 @@ public: // main thread function to enable/disable h/w composer event void setPrimaryVsyncEnabledInternal(bool enabled); + void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled); // called on the main thread by MessageQueue when an internal message // is received // TODO: this should be made accessible only to MessageQueue void onMessageReceived(int32_t what); - // populates the expected present time for this frame. - // When we are in negative offsets, we perform a correction so that the - // predicted vsync for the *next* frame is used instead. - void populateExpectedPresentTime(); - nsecs_t getExpectedPresentTime() const { return mExpectedPresentTime; } - // for debugging only // TODO: this should be made accessible only to HWComposer const Vector>& getLayerSortedByZForHwcDisplay(DisplayId displayId); @@ -585,6 +580,7 @@ private: void commitOffscreenLayers(); bool containsAnyInvalidClientState(const Vector& states); bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, + bool useCachedExpectedPresentTime, const Vector& states); uint32_t setClientStateLocked(const ComposerState& composerState, int64_t desiredPresentTime, const std::vector& listenerCallbacks, @@ -816,6 +812,12 @@ private: bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock); + bool previousFrameMissed(); + + // Populates the expected present time for this frame. For negative offsets, performs a + // correction using the predicted vsync for the next frame instead. + void populateExpectedPresentTime(); + /* * Display identification */ @@ -844,9 +846,6 @@ private: return hwcDisplayId ? getHwComposer().toPhysicalDisplayId(*hwcDisplayId) : std::nullopt; } - bool previousFrameMissed(); - void setVsyncEnabledInHWC(DisplayId displayId, HWC2::Vsync enabled); - /* * Debugging & dumpsys */ @@ -1135,6 +1134,8 @@ private: scheduler::RefreshRateConfigs mRefreshRateConfigs; scheduler::RefreshRateStats mRefreshRateStats{mRefreshRateConfigs, *mTimeStats}; + std::atomic mExpectedPresentTime = 0; + // All configs are allowed if the set is empty. using DisplayConfigs = std::set; DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock); @@ -1188,8 +1189,6 @@ private: // Flags to capture the state of Vsync in HWC HWC2::Vsync mHWCVsyncState = HWC2::Vsync::Disable; HWC2::Vsync mHWCVsyncPendingState = HWC2::Vsync::Disable; - - nsecs_t mExpectedPresentTime; }; } // namespace android diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index e6211c488e..ce67a19c3b 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -502,7 +502,7 @@ struct BaseLayerProperties { EXPECT_CALL(*test->mRenderEngine, useNativeFenceSync()).WillRepeatedly(Return(true)); bool ignoredRecomputeVisibleRegions; - layer->latchBuffer(ignoredRecomputeVisibleRegions, 0); + layer->latchBuffer(ignoredRecomputeVisibleRegions, 0, 0); Mock::VerifyAndClear(test->mRenderEngine); } -- cgit v1.2.3-59-g8ed1b From 49a108cda1eda5ce10b7532bf56482d80ae90afa Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 12 Aug 2019 11:23:06 -0700 Subject: Latch and relase buffers for offscreen layers on main thread. The current code was calling fakeVsync, which was latching and releasing buffers on a binder thread when a new frame arrived. This was causing a race with the latchBuffer on the main thread. This change calls latchAndReleaseBuffer on the main thread for offscreen layers to ensure we don't block dequeueBuffer but also don't race the other latchBuffer call. Fixes: 139118508 Test: Race was only reproducible in monkey tests Change-Id: Ie7d87aa775c215de3fb2322b73849402596cc3fc --- services/surfaceflinger/BufferLayer.cpp | 9 +++++++++ services/surfaceflinger/BufferLayer.h | 7 +++++++ services/surfaceflinger/BufferQueueLayer.cpp | 16 +--------------- services/surfaceflinger/BufferQueueLayer.h | 2 -- services/surfaceflinger/Layer.h | 2 ++ services/surfaceflinger/SurfaceFlinger.cpp | 18 +++++++++--------- services/surfaceflinger/SurfaceFlinger.h | 1 - 7 files changed, 28 insertions(+), 27 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 13c748f24c..e9af9e292b 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -668,6 +668,15 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return FloatRect(0, 0, bufWidth, bufHeight); } +void BufferLayer::latchAndReleaseBuffer() { + mRefreshPending = false; + if (hasReadyFrame()) { + bool ignored = false; + latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); + } + releasePendingBuffer(systemTime()); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index 7a0f82b5c0..fb8d7d027f 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -103,6 +103,13 @@ public: // Returns the current scaling mode, unless mOverrideScalingMode // is set, in which case, it returns mOverrideScalingMode uint32_t getEffectiveScalingMode() const override; + + // Calls latchBuffer if the buffer has a frame queued and then releases the buffer. + // This is used if the buffer is just latched and releases to free up the buffer + // and will not be shown on screen. + // Should only be called on the main thread. + void latchAndReleaseBuffer() override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 12be00f116..5f494ff3d5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -412,14 +412,6 @@ void BufferQueueLayer::latchPerFrameState( // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- -void BufferQueueLayer::fakeVsync() { - mRefreshPending = false; - bool ignored = false; - latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); - usleep(16000); - releasePendingBuffer(systemTime()); -} - void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); // Add this buffer from our internal queue tracker @@ -456,13 +448,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { mFlinger->mInterceptor->saveBufferUpdate(this, item.mGraphicBuffer->getWidth(), item.mGraphicBuffer->getHeight(), item.mFrameNumber); - // If this layer is orphaned, then we run a fake vsync pulse so that - // dequeueBuffer doesn't block indefinitely. - if (isRemovedFromCurrentState()) { - fakeVsync(); - } else { - mFlinger->signalLayerUpdate(); - } + mFlinger->signalLayerUpdate(); mConsumer->onBufferAvailable(item); } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 231a531f58..392b706416 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -138,8 +138,6 @@ private: // thread-safe std::atomic mQueuedFrames{0}; std::atomic mSidebandStreamChanged{false}; - - void fakeVsync(); }; } // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 87a5896c6a..2a1564a440 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -544,6 +544,8 @@ public: virtual bool isBufferLatched() const { return false; } + virtual void latchAndReleaseBuffer() {} + /* * Remove relative z for the layer if its relative parent is not part of the * provided layer tree. diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 04e7bf5398..3375649aa2 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2887,14 +2887,6 @@ void SurfaceFlinger::updateCursorAsync() } } -void SurfaceFlinger::latchAndReleaseBuffer(const sp& layer) { - if (layer->hasReadyFrame()) { - bool ignored = false; - layer->latchBuffer(ignored, systemTime(), 0 /* expectedPresentTime */); - } - layer->releasePendingBuffer(systemTime()); -} - void SurfaceFlinger::commitTransaction() { if (!mLayersPendingRemoval.isEmpty()) { @@ -2905,7 +2897,7 @@ void SurfaceFlinger::commitTransaction() // Ensure any buffers set to display on any children are released. if (l->isRemovedFromCurrentState()) { - latchAndReleaseBuffer(l); + l->latchAndReleaseBuffer(); } // If the layer has been removed and has no parent, then it will not be reachable @@ -3163,6 +3155,14 @@ bool SurfaceFlinger::handlePageFlip() } }); + // The client can continue submitting buffers for offscreen layers, but they will not + // be shown on screen. Therefore, we need to latch and release buffers of offscreen + // layers to ensure dequeueBuffer doesn't block indefinitely. + for (Layer* offscreenLayer : mOffscreenLayers) { + offscreenLayer->traverseInZOrder(LayerVector::StateSet::Drawing, + [&](Layer* l) { l->latchAndReleaseBuffer(); }); + } + if (!mLayersWithQueuedFrames.empty()) { // mStateLock is needed for latchBuffer as LayerRejecter::reject() // writes to Layer current state. See also b/119481871 diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e199ad55f8..27a0f6bbaf 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -576,7 +576,6 @@ private: // Can only be called from the main thread or with mStateLock held uint32_t setTransactionFlags(uint32_t flags); uint32_t setTransactionFlags(uint32_t flags, Scheduler::TransactionStart transactionStart); - void latchAndReleaseBuffer(const sp& layer); void commitTransaction() REQUIRES(mStateLock); void commitOffscreenLayers(); bool transactionIsReadyToBeApplied(int64_t desiredPresentTime, -- cgit v1.2.3-59-g8ed1b From 2e1608ff49148a8d99c2e33897fa0e5c3ce532c2 Mon Sep 17 00:00:00 2001 From: Mikael Pessa Date: Fri, 19 Jul 2019 11:25:35 -0700 Subject: Add per-buffer perfetto trace points for SurfaceFlinger frame events In order to track how buffers move through the system, we add per-buffer perfetto trace points for SurfaceFlinger. The majority of these were already tracked through TimeStats, so the new tracing was built on top of TimeStats. Test: atest libsurfaceflinger_unittest Run trace with: { adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace <& displayId, if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); + mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + presentFence, TimeStats::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); + mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + actualPresentTime, + TimeStats::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 5f494ff3d5..6cad3c7d07 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -45,6 +45,14 @@ BufferQueueLayer::~BufferQueueLayer() { void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { mConsumer->setReleaseFence(releaseFence); + + // Prevent tracing the same release multiple times. + if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { + mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + TimeStats::FrameEvent::RELEASE_FENCE); + mPreviousReleasedFrameNumber = mPreviousFrameNumber; + } } void BufferQueueLayer::setTransformHint(uint32_t orientation) const { @@ -355,9 +363,15 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mQueuedFrames--; } + uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, mQueueItems[0].mFenceTime); + mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber, + mQueueItems[0].mFenceTime, + TimeStats::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); + mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + TimeStats::FrameEvent::LATCH); mQueueItems.removeAt(0); } @@ -373,6 +387,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t status_t BufferQueueLayer::updateActiveBuffer() { // update the active buffer + mPreviousBufferId = getCurrentBufferId(); mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; layerCompositionState.buffer = mActiveBuffer; @@ -413,6 +428,11 @@ void BufferQueueLayer::latchPerFrameState( // ----------------------------------------------------------------------- void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); + mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + systemTime(), TimeStats::FrameEvent::POST); + ATRACE_CALL(); // Add this buffer from our internal queue tracker { // Autolock scope diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 3bc625e462..bf3f917196 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -128,6 +128,9 @@ private: uint64_t mPreviousFrameNumber{0}; bool mUpdateTexImageFailed{false}; + uint64_t mPreviousBufferId = 0; + uint64_t mPreviousReleasedFrameNumber = 0; + // Local copy of the queued contents of the incoming BufferQueue mutable Mutex mQueueItemLock; Condition mQueueItemCondition; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index e0804ff50e..4a8261d99f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -87,6 +87,14 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { break; } } + + // Prevent tracing the same release multiple times. + if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { + mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + TimeStats::FrameEvent::RELEASE_FENCE); + mPreviousReleasedFrameNumber = mPreviousFrameNumber; + } } void BufferStateLayer::setTransformHint(uint32_t /*orientation*/) const { @@ -226,7 +234,11 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - mFlinger->mTimeStats->setPostTime(getSequence(), mFrameNumber, getName().c_str(), postTime); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); + mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); + mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + TimeStats::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -561,8 +573,13 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } } + const uint64_t bufferID = getCurrentBufferId(); mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); + mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + TimeStats::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); + mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + TimeStats::FrameEvent::LATCH); mCurrentStateModified = false; @@ -576,6 +593,7 @@ status_t BufferStateLayer::updateActiveBuffer() { return BAD_VALUE; } + mPreviousBufferId = getCurrentBufferId(); mActiveBuffer = s.buffer; mActiveBufferFence = s.acquireFence; auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; @@ -586,6 +604,7 @@ status_t BufferStateLayer::updateActiveBuffer() { status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { // TODO(marissaw): support frame history events + mPreviousFrameNumber = mCurrentFrameNumber; mCurrentFrameNumber = mFrameNumber; return NO_ERROR; } diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cc670087ac..c060ca8e76 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -156,6 +156,9 @@ private: mutable uint32_t mFrameNumber{0}; sp mPreviousReleaseFence; + uint64_t mPreviousBufferId = 0; + uint64_t mPreviousFrameNumber = 0; + uint64_t mPreviousReleasedFrameNumber = 0; mutable bool mCurrentStateModified = false; bool mReleasePreviousBuffer = false; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9107189d52..aa3970eb3a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -376,6 +376,14 @@ public: int32_t getSequence() const { return sequence; } + // For tracing. + // TODO: Replace with raw buffer id from buffer metadata when that becomes available. + // GraphicBuffer::getId() does not provide a reliable global identifier. Since the traces + // creates its tracks by buffer id and has no way of associating a buffer back to the process + // that created it, the current implementation is only sufficient for cases where a buffer is + // only used within a single layer. + uint64_t getCurrentBufferId() const { return mActiveBuffer ? mActiveBuffer->getId() : 0; } + // ----------------------------------------------------------------------- // Virtuals diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e8049239ba..6543089101 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -513,6 +513,8 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); + mTimeStats->initializeTracing(); + // wait patiently for the window manager death const String16 name("window"); mWindowManager = defaultServiceManager()->getService(name); diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp new file mode 100644 index 0000000000..9e1d5033b2 --- /dev/null +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -0,0 +1,15 @@ +cc_library_static { + name: "libtimestats", + defaults: ["surfaceflinger_defaults"], + srcs: [ + "TimeStats.cpp" + ], + export_include_dirs: ["."], + static_libs: [ + "libperfetto_client_experimental", + ], + shared_libs: [ + "libtimestats_proto", + "libui", + ], +} diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 3e3ab18e8f..b66e4cfe4f 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -30,10 +30,141 @@ #include #include +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource); + namespace android { namespace impl { +void TimeStats::initializeTracing() { + perfetto::TracingInitArgs args; + args.backends = perfetto::kSystemBackend; + perfetto::Tracing::Initialize(args); + registerTracingDataSource(); +} + +void TimeStats::registerTracingDataSource() { + perfetto::DataSourceDescriptor dsd; + dsd.set_name(kTimeStatsDataSource); + TimeStatsDataSource::Register(dsd); +} + +void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) { + TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) { + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + std::lock_guard lock(mTraceMutex); + mTraceTracker[layerID].layerName = layerName; + } + }); +} + +void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration) { + TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + duration](TimeStatsDataSource::TraceContext ctx) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + // Complete current trace. + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + }); +} + +void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime) { + TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + startTime](TimeStatsDataSource::TraceContext ctx) { + const nsecs_t signalTime = fence->getSignalTime(); + if (signalTime != Fence::SIGNAL_TIME_INVALID) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + if (signalTime != Fence::SIGNAL_TIME_PENDING) { + traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + } else { + mTraceTracker[layerID].pendingFences[bufferID].push_back( + {.frameNumber = frameNumber, + .type = type, + .fence = fence, + .startTime = startTime}); + } + } + }); +} + +void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID) { + if (mTraceTracker[layerID].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + for (size_t i = 0; i < pendingFences.size(); ++i) { + auto& pendingFence = pendingFences[i]; + + nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; + if (pendingFence.fence && pendingFence.fence->isValid()) { + signalTime = pendingFence.fence->getSignalTime(); + if (signalTime == Fence::SIGNAL_TIME_PENDING) { + continue; + } + } + + if (signalTime != Fence::SIGNAL_TIME_INVALID && + systemTime() - signalTime < kFenceSignallingDeadline) { + traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + pendingFence.startTime, signalTime); + } + + pendingFences.erase(pendingFences.begin() + i); + --i; + } + } +} + +void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(timestamp); + auto* event = packet->set_graphics_frame_event()->set_buffer_event(); + event->set_buffer_id(static_cast(bufferID)); + event->set_frame_number(frameNumber); + event->set_type(type); + + if (mTraceTracker.find(layerID) != mTraceTracker.end() && + !mTraceTracker[layerID].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerID].layerName; + event->set_layer_name(layerName.c_str(), layerName.size()); + } + + if (duration > 0) { + event->set_duration_ns(duration); + } +} + +void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, + FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime) { + nsecs_t timestamp = endTime; + nsecs_t duration = 0; + if (startTime > 0 && startTime < endTime) { + timestamp = startTime; + duration = endTime - startTime; + } + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); +} + void TimeStats::parseArgs(bool asProto, const Vector& args, std::string& result) { ATRACE_CALL(); @@ -76,6 +207,8 @@ std::string TimeStats::miniDump() { mTimeStatsTracker.size()); android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n", mTimeStats.stats.size()); + android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", + mTraceTracker.size()); return result; } @@ -407,14 +540,17 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, } void TimeStats::onDestroy(int32_t layerID) { - if (!mEnabled.load()) return; - ATRACE_CALL(); ALOGV("[%d]-onDestroy", layerID); + { + std::lock_guard lock(mMutex); + mTimeStatsTracker.erase(layerID); + } - std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - mTimeStatsTracker.erase(layerID); + { + std::lock_guard traceLock(mTraceMutex); + mTraceTracker.erase(layerID); + } } void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index eed711158a..470137a431 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -16,13 +16,12 @@ #pragma once +#include +#include +#include #include #include - -#include - #include - #include #include @@ -37,8 +36,32 @@ namespace android { class TimeStats { public: + using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; + virtual ~TimeStats() = default; + // Sets up the perfetto tracing backend and data source. + virtual void initializeTracing() = 0; + // Registers the data source with the perfetto backend. Called as part of initializeTracing() + // and should not be called manually outside of tests. Public to allow for substituting a + // perfetto::kInProcessBackend in tests. + virtual void registerTracingDataSource() = 0; + // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or + // traceFence() for each layer. + virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0; + // Creates a trace point at the timestamp provided. + virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0) = 0; + // Creates a trace point after the provided fence has been signalled. If a startTime is provided + // the trace will have be timestamped from startTime until fence signalling time. If no + // startTime is provided, a durationless trace point will be created timestamped at fence + // signalling time. If the fence hasn't signalled yet, the trace point will be created the next + // time after signalling a trace call for this buffer occurs. + virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0; + virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; virtual std::string miniDump() = 0; @@ -66,6 +89,13 @@ public: // Source of truth is RefrehRateStats. virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; virtual void setPresentFenceGlobal(const std::shared_ptr& presentFence) = 0; + + static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats"; + + // The maximum amount of time a fence has to signal before it is discarded. + // Used to avoid fence's from previous traces generating new trace points in later ones. + // Public for testing. + static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds }; namespace impl { @@ -87,6 +117,13 @@ class TimeStats : public android::TimeStats { std::shared_ptr presentFence; }; + struct PendingFence { + uint64_t frameNumber; + FrameEvent::BufferEventType type; + std::shared_ptr fence; + nsecs_t startTime; + }; + struct LayerRecord { std::string layerName; // This is the index in timeRecords, at which the timestamps for that @@ -98,6 +135,12 @@ class TimeStats : public android::TimeStats { std::deque timeRecords; }; + struct TraceRecord { + std::string layerName; + using BufferID = uint64_t; + std::unordered_map> pendingFences; + }; + struct PowerTime { int32_t powerMode = HWC_POWER_MODE_OFF; nsecs_t prevTime = 0; @@ -109,8 +152,23 @@ class TimeStats : public android::TimeStats { }; public: + class TimeStatsDataSource : public perfetto::DataSource { + virtual void OnSetup(const SetupArgs&) override{}; + virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); }; + virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); }; + }; + TimeStats() = default; + void initializeTracing() override; + void registerTracingDataSource() override; + void traceNewLayer(int32_t layerID, const std::string& layerName) override; + void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration = 0) override; + void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, FrameEvent::BufferEventType type, + nsecs_t startTime = 0) override; + void parseArgs(bool asProto, const Vector& args, std::string& result) override; bool isEnabled() override; std::string miniDump() override; @@ -142,6 +200,20 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: + // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates + // trace points for them. + void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID); + // Creates a trace point by translating a start time and an end time to a timestamp and + // duration. If startTime is later than end time it sets end time as the timestamp and the + // duration to 0. Used by traceFence(). + void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime); + void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0); + bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerID); void flushPowerTimeLocked(); @@ -160,6 +232,9 @@ private: PowerTime mPowerTime; GlobalRecord mGlobalRecord; + std::mutex mTraceMutex; + std::unordered_map mTraceTracker; + static const size_t MAX_NUM_LAYER_RECORDS = 200; static const size_t MAX_NUM_LAYER_STATS = 200; }; diff --git a/services/surfaceflinger/tests/fakehwc/Android.bp b/services/surfaceflinger/tests/fakehwc/Android.bp index 644cd7e698..57851bc850 100644 --- a/services/surfaceflinger/tests/fakehwc/Android.bp +++ b/services/surfaceflinger/tests/fakehwc/Android.bp @@ -34,7 +34,9 @@ cc_test { ], static_libs: [ "libgmock", + "libperfetto_client_experimental", "librenderengine", + "libtimestats", "libtrace_proto", ], header_libs: [ diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 4917bc2a51..0eedf9b7b1 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -36,7 +36,7 @@ cc_test { ":libsurfaceflinger_sources", "libsurfaceflinger_unittest_main.cpp", "CachingTest.cpp", - "CompositionTest.cpp", + "CompositionTest.cpp", "DispSyncSourceTest.cpp", "DisplayIdentificationTest.cpp", "DisplayTransactionTest.cpp", @@ -69,7 +69,13 @@ cc_test { "libgmock", "libcompositionengine", "libcompositionengine_mocks", + "libperfetto_client_experimental", "librenderengine_mocks", + "libtimestats", + "perfetto_trace_protos", + ], + shared_libs: [ + "libsurfaceflinger", ], header_libs: [ "libsurfaceflinger_headers", diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index f35758debf..f01e603f20 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -17,18 +17,17 @@ #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" +#include #include #include - #include +#include #include #include #include #include -#include "TimeStats/TimeStats.h" - #include "libsurfaceflinger_unittest_main.h" using namespace android::surfaceflinger; @@ -110,6 +109,15 @@ public: const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + // Need to initialize tracing in process for testing, and only once per test suite. + static bool wasInitialized = false; + if (!wasInitialized) { + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + wasInitialized = true; + } } ~TimeStatsTest() { @@ -118,6 +126,13 @@ public: ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } + void SetUp() override { + mTimeStats = std::make_unique(); + mTimeStats->registerTracingDataSource(); + } + + void TearDown() override { mTimeStats.reset(); } + std::string inputCommand(InputCommand cmd, bool useProto); void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts); @@ -132,8 +147,22 @@ public: } } + // Each tracing session can be used for a single block of Start -> Stop. + static std::unique_ptr getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(500); + cfg.add_buffers()->set_size_kb(1024); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name(TimeStats::kTimeStatsDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; + } + std::mt19937 mRandomEngine = std::mt19937(std::random_device()()); - std::unique_ptr mTimeStats = std::make_unique(); + std::unique_ptr mTimeStats; + FenceToFenceTimeMap fenceFactory; }; std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { @@ -210,6 +239,330 @@ int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) { return distr(mRandomEngine); } +TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) { + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + mTimeStats->traceNewLayer(layerID, layerName); + + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + mTimeStats->traceNewLayer(layerID, layerName); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); + tracingSession->StopBlocking(); +} + +TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) { + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const int32_t secondLayerID = 6; + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceNewLayer(secondLayerID, layerName); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n"); + tracingSession->StopBlocking(); + + mTimeStats->onDestroy(layerID); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); + mTimeStats->onDestroy(layerID); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); + mTimeStats->onDestroy(secondLayerID); + EXPECT_EQ(mTimeStats->miniDump(), + "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " + "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); +} + +TEST_F(TimeStatsTest, canTraceAfterAddingLayer) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 1; + const uint32_t bufferID = 2; + const uint64_t frameNumber = 3; + const nsecs_t timestamp = 4; + const nsecs_t duration = 5; + const auto type = TimeStats::FrameEvent::POST; + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 1); + + const auto& packet = trace.packet().Get(0); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + ASSERT_TRUE(buffer_event.has_duration_ns()); + EXPECT_EQ(buffer_event.duration_ns(), duration); + } +} + +TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + // Trace. + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + const nsecs_t timestamp = systemTime(); + fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); + // Create extra trace packet to trigger and finalize fence trace packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. + + const auto& packet = trace.packet().Get(1); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + EXPECT_FALSE(buffer_event.has_duration_ns()); + } +} + +TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 + 100000; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 + 100000; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), signalTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), signalTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); +} + +TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline; + + auto tracingSession = getTracingSessionForTest(); + auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); + // Create extra trace packet to trigger and finalize any previous fence packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); +} + +TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; + const nsecs_t duration = 1234; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mTimeStats->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 - duration; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 - duration; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), startTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event1.duration_ns(), duration); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), startTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event2.duration_ns(), duration); +} + TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); ASSERT_TRUE(mTimeStats->isEnabled()); diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index b1634a8da7..542c70a8fb 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -28,6 +28,14 @@ public: TimeStats(); ~TimeStats() override; + MOCK_METHOD0(initializeTracing, void()); + MOCK_METHOD0(registerTracingDataSource, void()); + MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); + MOCK_METHOD6(traceTimestamp, + void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD6(traceFence, + void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, + FrameEvent::BufferEventType, nsecs_t)); MOCK_METHOD3(parseArgs, void(bool, const Vector&, std::string&)); MOCK_METHOD0(isEnabled, bool()); MOCK_METHOD0(miniDump, std::string()); -- cgit v1.2.3-59-g8ed1b From 90092f4335b7360b149a57ee759df778e099ff87 Mon Sep 17 00:00:00 2001 From: Mikael Pessa Date: Mon, 26 Aug 2019 17:22:04 -0700 Subject: Refactor: Pull tracing out of TimeStats. The tracing in TimeStats ended up having no actual overlap with current TimeStats functionality. This CL pulls all tracing related code out into its own class. Test: atest libsurfaceflinger_unittest and manually inspected traces. Run trace with: { adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/trace <deleteTextureAsync(mTextureName); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } void BufferLayer::useSurfaceDamage() { @@ -314,17 +317,17 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, if (presentFence->isValid()) { mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); - mFlinger->mTimeStats->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, - presentFence, TimeStats::FrameEvent::PRESENT_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); - mFlinger->mTimeStats->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, - actualPresentTime, - TimeStats::FrameEvent::PRESENT_FENCE); + mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + actualPresentTime, + FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); } diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 6cad3c7d07..4da39e4d6f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -29,6 +29,7 @@ #include "LayerRejecter.h" #include "SurfaceInterceptor.h" +#include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" namespace android { @@ -48,9 +49,9 @@ void BufferQueueLayer::onLayerDisplayed(const sp& releaseFence) { // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, - std::make_shared(releaseFence), - TimeStats::FrameEvent::RELEASE_FENCE); + mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + FrameTracer::FrameEvent::RELEASE_FENCE); mPreviousReleasedFrameNumber = mPreviousFrameNumber; } } @@ -337,6 +338,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t mQueueItems.clear(); mQueuedFrames = 0; mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } // Once we have hit this state, the shadow queue may no longer @@ -366,12 +368,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, mQueueItems[0].mFenceTime); - mFlinger->mTimeStats->traceFence(layerID, bufferID, currentFrameNumber, - mQueueItems[0].mFenceTime, - TimeStats::FrameEvent::ACQUIRE_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber, + mQueueItems[0].mFenceTime, + FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); - mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, - TimeStats::FrameEvent::LATCH); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + FrameTracer::FrameEvent::LATCH); mQueueItems.removeAt(0); } @@ -429,9 +431,9 @@ void BufferQueueLayer::latchPerFrameState( void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { const int32_t layerID = getSequence(); - mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); - mFlinger->mTimeStats->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, - systemTime(), TimeStats::FrameEvent::POST); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + systemTime(), FrameTracer::FrameEvent::POST); ATRACE_CALL(); // Add this buffer from our internal queue tracker diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 4a8261d99f..e7d1b63b03 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -32,6 +32,7 @@ #include "BufferStateLayer.h" #include "ColorLayer.h" +#include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" namespace android { @@ -90,9 +91,9 @@ void BufferStateLayer::onLayerDisplayed(const sp& releaseFence) { // Prevent tracing the same release multiple times. if (mPreviousFrameNumber != mPreviousReleasedFrameNumber) { - mFlinger->mTimeStats->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, - std::make_shared(releaseFence), - TimeStats::FrameEvent::RELEASE_FENCE); + mFlinger->mFrameTracer->traceFence(getSequence(), mPreviousBufferId, mPreviousFrameNumber, + std::make_shared(releaseFence), + FrameTracer::FrameEvent::RELEASE_FENCE); mPreviousReleasedFrameNumber = mPreviousFrameNumber; } } @@ -236,9 +237,9 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi const int32_t layerID = getSequence(); mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); - mFlinger->mTimeStats->traceNewLayer(layerID, getName().c_str()); - mFlinger->mTimeStats->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, - TimeStats::FrameEvent::POST); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; if (mFlinger->mUseSmart90ForVideo) { @@ -569,17 +570,18 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse status_t err = bindTextureImage(); if (err != NO_ERROR) { mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); return BAD_VALUE; } } const uint64_t bufferID = getCurrentBufferId(); mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); - mFlinger->mTimeStats->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), - TimeStats::FrameEvent::ACQUIRE_FENCE); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); - mFlinger->mTimeStats->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, - TimeStats::FrameEvent::LATCH); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + FrameTracer::FrameEvent::LATCH); mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp new file mode 100644 index 0000000000..7cbb8d8b7c --- /dev/null +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -0,0 +1,173 @@ +/* + * Copyright 2019 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. + */ + +#undef LOG_TAG +#define LOG_TAG "FrameTracer" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "FrameTracer.h" + +#include + +#include + +PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::FrameTracer::FrameTracerDataSource); + +namespace android { + +void FrameTracer::initialize() { + perfetto::TracingInitArgs args; + args.backends = perfetto::kSystemBackend; + perfetto::Tracing::Initialize(args); + registerDataSource(); +} + +void FrameTracer::registerDataSource() { + perfetto::DataSourceDescriptor dsd; + dsd.set_name(kFrameTracerDataSource); + FrameTracerDataSource::Register(dsd); +} + +void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) { + FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) { + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + std::lock_guard lock(mTraceMutex); + mTraceTracker[layerID].layerName = layerName; + } + }); +} + +void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration) { + FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + duration](FrameTracerDataSource::TraceContext ctx) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + // Complete current trace. + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + }); +} + +void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, + FrameEvent::BufferEventType type, nsecs_t startTime) { + FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + startTime](FrameTracerDataSource::TraceContext ctx) { + const nsecs_t signalTime = fence->getSignalTime(); + if (signalTime != Fence::SIGNAL_TIME_INVALID) { + std::lock_guard lock(mTraceMutex); + if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + return; + } + + // Handle any pending fences for this buffer. + tracePendingFencesLocked(ctx, layerID, bufferID); + + if (signalTime != Fence::SIGNAL_TIME_PENDING) { + traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + } else { + mTraceTracker[layerID].pendingFences[bufferID].push_back( + {.frameNumber = frameNumber, + .type = type, + .fence = fence, + .startTime = startTime}); + } + } + }); +} + +void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, + int32_t layerID, uint64_t bufferID) { + if (mTraceTracker[layerID].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + for (size_t i = 0; i < pendingFences.size(); ++i) { + auto& pendingFence = pendingFences[i]; + + nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; + if (pendingFence.fence && pendingFence.fence->isValid()) { + signalTime = pendingFence.fence->getSignalTime(); + if (signalTime == Fence::SIGNAL_TIME_PENDING) { + continue; + } + } + + if (signalTime != Fence::SIGNAL_TIME_INVALID && + systemTime() - signalTime < kFenceSignallingDeadline) { + traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + pendingFence.startTime, signalTime); + } + + pendingFences.erase(pendingFences.begin() + i); + --i; + } + } +} + +void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration) { + auto packet = ctx.NewTracePacket(); + packet->set_timestamp(timestamp); + auto* event = packet->set_graphics_frame_event()->set_buffer_event(); + event->set_buffer_id(static_cast(bufferID)); + event->set_frame_number(frameNumber); + event->set_type(type); + + if (mTraceTracker.find(layerID) != mTraceTracker.end() && + !mTraceTracker[layerID].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerID].layerName; + event->set_layer_name(layerName.c_str(), layerName.size()); + } + + if (duration > 0) { + event->set_duration_ns(duration); + } +} + +void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, + FrameEvent::BufferEventType type, nsecs_t startTime, + nsecs_t endTime) { + nsecs_t timestamp = endTime; + nsecs_t duration = 0; + if (startTime > 0 && startTime < endTime) { + timestamp = startTime; + duration = endTime - startTime; + } + traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); +} + +void FrameTracer::onDestroy(int32_t layerID) { + std::lock_guard traceLock(mTraceMutex); + mTraceTracker.erase(layerID); +} + +std::string FrameTracer::miniDump() { + std::string result = "FrameTracer miniDump:\n"; + std::lock_guard lock(mTraceMutex); + android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", + mTraceTracker.size()); + return result; +} + +} // namespace android diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h new file mode 100644 index 0000000000..d34ad81fee --- /dev/null +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -0,0 +1,105 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include +#include +#include + +#include +#include + +namespace android { + +class FrameTracer { +public: + class FrameTracerDataSource : public perfetto::DataSource { + virtual void OnSetup(const SetupArgs&) override{}; + virtual void OnStart(const StartArgs&) override{}; + virtual void OnStop(const StopArgs&) override{}; + }; + + using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; + + ~FrameTracer() = default; + + // Sets up the perfetto tracing backend and data source. + void initialize(); + // Registers the data source with the perfetto backend. Called as part of initialize() + // and should not be called manually outside of tests. Public to allow for substituting a + // perfetto::kInProcessBackend in tests. + void registerDataSource(); + // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or + // traceFence() for each layer. + void traceNewLayer(int32_t layerID, const std::string& layerName); + // Creates a trace point at the timestamp provided. + void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + FrameEvent::BufferEventType type, nsecs_t duration = 0); + // Creates a trace point after the provided fence has been signalled. If a startTime is provided + // the trace will have be timestamped from startTime until fence signalling time. If no + // startTime is provided, a durationless trace point will be created timestamped at fence + // signalling time. If the fence hasn't signalled yet, the trace point will be created the next + // time after signalling a trace call for this buffer occurs. + void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + const std::shared_ptr& fence, FrameEvent::BufferEventType type, + nsecs_t startTime = 0); + + // Takes care of cleanup when a layer is destroyed. + void onDestroy(int32_t layerID); + + std::string miniDump(); + + static constexpr char kFrameTracerDataSource[] = "android.surfaceflinger.frame"; + + // The maximum amount of time a fence has to signal before it is discarded. + // Used to avoid fences from previous traces generating new trace points in later ones. + // Public for testing. + static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds + +private: + struct PendingFence { + uint64_t frameNumber; + FrameEvent::BufferEventType type; + std::shared_ptr fence; + nsecs_t startTime; + }; + + struct TraceRecord { + std::string layerName; + using BufferID = uint64_t; + std::unordered_map> pendingFences; + }; + + // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates + // trace points for them. + void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID); + // Creates a trace point by translating a start time and an end time to a timestamp and + // duration. If startTime is later than end time it sets end time as the timestamp and the + // duration to 0. Used by traceFence(). + void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, + nsecs_t startTime, nsecs_t endTime); + void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, + nsecs_t duration = 0); + + std::mutex mTraceMutex; + std::unordered_map mTraceTracker; +}; + +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..106d505faa 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -57,6 +57,7 @@ #include "Colorizer.h" #include "DisplayDevice.h" #include "DisplayHardware/HWComposer.h" +#include "FrameTracer/FrameTracer.h" #include "LayerProtoHelper.h" #include "LayerRejecter.h" #include "MonitoredProducer.h" @@ -1343,7 +1344,9 @@ void Layer::dumpFrameEvents(std::string& result) { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - mFlinger->mTimeStats->onDestroy(getSequence()); + const int32_t layerID = getSequence(); + mFlinger->mTimeStats->onDestroy(layerID); + mFlinger->mFrameTracer->onDestroy(layerID); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6543089101..e8902b3c62 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -98,6 +98,7 @@ #include "DisplayHardware/HWComposer.h" #include "DisplayHardware/VirtualDisplaySurface.h" #include "Effects/Daltonizer.h" +#include "FrameTracer/FrameTracer.h" #include "RegionSamplingThread.h" #include "Scheduler/DispSync.h" #include "Scheduler/DispSyncSource.h" @@ -257,6 +258,7 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) : mFactory(factory), mInterceptor(mFactory.createSurfaceInterceptor(this)), mTimeStats(mFactory.createTimeStats()), + mFrameTracer(std::make_unique()), mEventQueue(mFactory.createMessageQueue()), mCompositionEngine(mFactory.createCompositionEngine()), mPhaseOffsets(mFactory.createPhaseOffsets()) {} @@ -513,7 +515,7 @@ void SurfaceFlinger::bootFinished() const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); - mTimeStats->initializeTracing(); + mFrameTracer->initialize(); // wait patiently for the window manager death const String16 name("window"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8408ef5174..c7cc07e490 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -94,6 +94,7 @@ class MessageBase; class RefreshRateOverlay; class RegionSamplingThread; class TimeStats; +class FrameTracer; namespace compositionengine { class DisplaySurface; @@ -996,6 +997,7 @@ private: bool mTracingEnabled = false; bool mTracingEnabledChanged GUARDED_BY(mStateLock) = false; const std::shared_ptr mTimeStats; + const std::unique_ptr mFrameTracer; bool mUseHwcVirtualDisplays = false; std::atomic mFrameMissedCount = 0; std::atomic mHwcFrameMissedCount = 0; diff --git a/services/surfaceflinger/TimeStats/Android.bp b/services/surfaceflinger/TimeStats/Android.bp index 9e1d5033b2..2080a3847e 100644 --- a/services/surfaceflinger/TimeStats/Android.bp +++ b/services/surfaceflinger/TimeStats/Android.bp @@ -2,12 +2,9 @@ cc_library_static { name: "libtimestats", defaults: ["surfaceflinger_defaults"], srcs: [ - "TimeStats.cpp" + "TimeStats.cpp", ], export_include_dirs: ["."], - static_libs: [ - "libperfetto_client_experimental", - ], shared_libs: [ "libtimestats_proto", "libui", diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index b66e4cfe4f..b01fa81594 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -30,141 +30,10 @@ #include #include -PERFETTO_DEFINE_DATA_SOURCE_STATIC_MEMBERS(android::impl::TimeStats::TimeStatsDataSource); - namespace android { namespace impl { -void TimeStats::initializeTracing() { - perfetto::TracingInitArgs args; - args.backends = perfetto::kSystemBackend; - perfetto::Tracing::Initialize(args); - registerTracingDataSource(); -} - -void TimeStats::registerTracingDataSource() { - perfetto::DataSourceDescriptor dsd; - dsd.set_name(kTimeStatsDataSource); - TimeStatsDataSource::Register(dsd); -} - -void TimeStats::traceNewLayer(int32_t layerID, const std::string& layerName) { - TimeStatsDataSource::Trace([this, layerID, &layerName](TimeStatsDataSource::TraceContext) { - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - std::lock_guard lock(mTraceMutex); - mTraceTracker[layerID].layerName = layerName; - } - }); -} - -void TimeStats::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration) { - TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, - duration](TimeStatsDataSource::TraceContext ctx) { - std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - return; - } - - // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); - - // Complete current trace. - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); - }); -} - -void TimeStats::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, - FrameEvent::BufferEventType type, nsecs_t startTime) { - TimeStatsDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, - startTime](TimeStatsDataSource::TraceContext ctx) { - const nsecs_t signalTime = fence->getSignalTime(); - if (signalTime != Fence::SIGNAL_TIME_INVALID) { - std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { - return; - } - - // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); - - if (signalTime != Fence::SIGNAL_TIME_PENDING) { - traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); - } else { - mTraceTracker[layerID].pendingFences[bufferID].push_back( - {.frameNumber = frameNumber, - .type = type, - .fence = fence, - .startTime = startTime}); - } - } - }); -} - -void TimeStats::tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID) { - if (mTraceTracker[layerID].pendingFences.count(bufferID)) { - auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; - for (size_t i = 0; i < pendingFences.size(); ++i) { - auto& pendingFence = pendingFences[i]; - - nsecs_t signalTime = Fence::SIGNAL_TIME_INVALID; - if (pendingFence.fence && pendingFence.fence->isValid()) { - signalTime = pendingFence.fence->getSignalTime(); - if (signalTime == Fence::SIGNAL_TIME_PENDING) { - continue; - } - } - - if (signalTime != Fence::SIGNAL_TIME_INVALID && - systemTime() - signalTime < kFenceSignallingDeadline) { - traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, - pendingFence.startTime, signalTime); - } - - pendingFences.erase(pendingFences.begin() + i); - --i; - } - } -} - -void TimeStats::traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, - FrameEvent::BufferEventType type, nsecs_t duration) { - auto packet = ctx.NewTracePacket(); - packet->set_timestamp(timestamp); - auto* event = packet->set_graphics_frame_event()->set_buffer_event(); - event->set_buffer_id(static_cast(bufferID)); - event->set_frame_number(frameNumber); - event->set_type(type); - - if (mTraceTracker.find(layerID) != mTraceTracker.end() && - !mTraceTracker[layerID].layerName.empty()) { - const std::string& layerName = mTraceTracker[layerID].layerName; - event->set_layer_name(layerName.c_str(), layerName.size()); - } - - if (duration > 0) { - event->set_duration_ns(duration); - } -} - -void TimeStats::traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID, uint64_t frameNumber, - FrameEvent::BufferEventType type, nsecs_t startTime, - nsecs_t endTime) { - nsecs_t timestamp = endTime; - nsecs_t duration = 0; - if (startTime > 0 && startTime < endTime) { - timestamp = startTime; - duration = endTime - startTime; - } - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); -} - void TimeStats::parseArgs(bool asProto, const Vector& args, std::string& result) { ATRACE_CALL(); @@ -207,8 +76,6 @@ std::string TimeStats::miniDump() { mTimeStatsTracker.size()); android::base::StringAppendF(&result, "Number of layers in the stats pool is %zu\n", mTimeStats.stats.size()); - android::base::StringAppendF(&result, "Number of layers currently being traced is %zu\n", - mTraceTracker.size()); return result; } @@ -542,15 +409,8 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, void TimeStats::onDestroy(int32_t layerID) { ATRACE_CALL(); ALOGV("[%d]-onDestroy", layerID); - { - std::lock_guard lock(mMutex); - mTimeStatsTracker.erase(layerID); - } - - { - std::lock_guard traceLock(mTraceMutex); - mTraceTracker.erase(layerID); - } + std::lock_guard lock(mMutex); + mTimeStatsTracker.erase(layerID); } void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 470137a431..9ebc1adc90 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -17,8 +17,6 @@ #pragma once #include -#include -#include #include #include #include @@ -36,32 +34,8 @@ namespace android { class TimeStats { public: - using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; - virtual ~TimeStats() = default; - // Sets up the perfetto tracing backend and data source. - virtual void initializeTracing() = 0; - // Registers the data source with the perfetto backend. Called as part of initializeTracing() - // and should not be called manually outside of tests. Public to allow for substituting a - // perfetto::kInProcessBackend in tests. - virtual void registerTracingDataSource() = 0; - // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or - // traceFence() for each layer. - virtual void traceNewLayer(int32_t layerID, const std::string& layerName) = 0; - // Creates a trace point at the timestamp provided. - virtual void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration = 0) = 0; - // Creates a trace point after the provided fence has been signalled. If a startTime is provided - // the trace will have be timestamped from startTime until fence signalling time. If no - // startTime is provided, a durationless trace point will be created timestamped at fence - // signalling time. If the fence hasn't signalled yet, the trace point will be created the next - // time after signalling a trace call for this buffer occurs. - virtual void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, - FrameEvent::BufferEventType type, nsecs_t startTime = 0) = 0; - virtual void parseArgs(bool asProto, const Vector& args, std::string& result) = 0; virtual bool isEnabled() = 0; virtual std::string miniDump() = 0; @@ -89,13 +63,6 @@ public: // Source of truth is RefrehRateStats. virtual void recordRefreshRate(uint32_t fps, nsecs_t duration) = 0; virtual void setPresentFenceGlobal(const std::shared_ptr& presentFence) = 0; - - static constexpr char kTimeStatsDataSource[] = "android.surfaceflinger.timestats"; - - // The maximum amount of time a fence has to signal before it is discarded. - // Used to avoid fence's from previous traces generating new trace points in later ones. - // Public for testing. - static constexpr nsecs_t kFenceSignallingDeadline = 60'000'000'000; // 60 seconds }; namespace impl { @@ -117,13 +84,6 @@ class TimeStats : public android::TimeStats { std::shared_ptr presentFence; }; - struct PendingFence { - uint64_t frameNumber; - FrameEvent::BufferEventType type; - std::shared_ptr fence; - nsecs_t startTime; - }; - struct LayerRecord { std::string layerName; // This is the index in timeRecords, at which the timestamps for that @@ -135,12 +95,6 @@ class TimeStats : public android::TimeStats { std::deque timeRecords; }; - struct TraceRecord { - std::string layerName; - using BufferID = uint64_t; - std::unordered_map> pendingFences; - }; - struct PowerTime { int32_t powerMode = HWC_POWER_MODE_OFF; nsecs_t prevTime = 0; @@ -152,23 +106,8 @@ class TimeStats : public android::TimeStats { }; public: - class TimeStatsDataSource : public perfetto::DataSource { - virtual void OnSetup(const SetupArgs&) override{}; - virtual void OnStart(const StartArgs&) override { ALOGV("TimeStats trace started"); }; - virtual void OnStop(const StopArgs&) override { ALOGV("TimeStats trace stopped"); }; - }; - TimeStats() = default; - void initializeTracing() override; - void registerTracingDataSource() override; - void traceNewLayer(int32_t layerID, const std::string& layerName) override; - void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, - FrameEvent::BufferEventType type, nsecs_t duration = 0) override; - void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, - const std::shared_ptr& fence, FrameEvent::BufferEventType type, - nsecs_t startTime = 0) override; - void parseArgs(bool asProto, const Vector& args, std::string& result) override; bool isEnabled() override; std::string miniDump() override; @@ -200,20 +139,6 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: - // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates - // trace points for them. - void tracePendingFencesLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, - uint64_t bufferID); - // Creates a trace point by translating a start time and an end time to a timestamp and - // duration. If startTime is later than end time it sets end time as the timestamp and the - // duration to 0. Used by traceFence(). - void traceSpanLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, - uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, - nsecs_t endTime); - void traceLocked(TimeStatsDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, - uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, - nsecs_t duration = 0); - bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); void flushAvailableRecordsToStatsLocked(int32_t layerID); void flushPowerTimeLocked(); @@ -232,9 +157,6 @@ private: PowerTime mPowerTime; GlobalRecord mGlobalRecord; - std::mutex mTraceMutex; - std::unordered_map mTraceTracker; - static const size_t MAX_NUM_LAYER_RECORDS = 200; static const size_t MAX_NUM_LAYER_STATS = 200; }; diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 0eedf9b7b1..8d98af6298 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -51,6 +51,7 @@ cc_test { "RefreshRateStatsTest.cpp", "RegionSamplingTest.cpp", "TimeStatsTest.cpp", + "FrameTracerTest.cpp", "mock/DisplayHardware/MockComposer.cpp", "mock/DisplayHardware/MockDisplay.cpp", "mock/DisplayHardware/MockPowerAdvisor.cpp", @@ -63,6 +64,7 @@ cc_test { "mock/MockNativeWindowSurface.cpp", "mock/MockSurfaceInterceptor.cpp", "mock/MockTimeStats.cpp", + "mock/MockFrameTracer.cpp", "mock/system/window/MockNativeWindow.cpp", ], static_libs: [ diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp new file mode 100644 index 0000000000..b5af591e25 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -0,0 +1,396 @@ +/* + * Copyright 2019 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. + */ + +#undef LOG_TAG +#define LOG_TAG "LibSurfaceFlingerUnittests" + +#include +#include +#include +#include +#include + +#include "libsurfaceflinger_unittest_main.h" + +using namespace google::protobuf; + +namespace android { +namespace { + +class FrameTracerTest : public testing::Test { +public: + FrameTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); + + // Need to initialize tracing in process for testing, and only once per test suite. + static bool wasInitialized = false; + if (!wasInitialized) { + perfetto::TracingInitArgs args; + args.backends = perfetto::kInProcessBackend; + perfetto::Tracing::Initialize(args); + wasInitialized = true; + } + } + + ~FrameTracerTest() { + const ::testing::TestInfo* const test_info = + ::testing::UnitTest::GetInstance()->current_test_info(); + ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); + } + + void SetUp() override { + mFrameTracer = std::make_unique(); + mFrameTracer->registerDataSource(); + } + + void TearDown() override { mFrameTracer.reset(); } + + // Each tracing session can be used for a single block of Start -> Stop. + static std::unique_ptr getTracingSessionForTest() { + perfetto::TraceConfig cfg; + cfg.set_duration_ms(500); + cfg.add_buffers()->set_size_kb(1024); + auto* ds_cfg = cfg.add_data_sources()->mutable_config(); + ds_cfg->set_name(FrameTracer::kFrameTracerDataSource); + + auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); + tracingSession->Setup(cfg); + return tracingSession; + } + + std::unique_ptr mFrameTracer; + FenceToFenceTimeMap fenceFactory; +}; + +TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + mFrameTracer->traceNewLayer(layerID, layerName); + + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + mFrameTracer->traceNewLayer(layerID, layerName); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + tracingSession->StopBlocking(); +} + +TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) { + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); + + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const int32_t secondLayerID = 6; + + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(secondLayerID, layerName); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n"); + tracingSession->StopBlocking(); + + mFrameTracer->onDestroy(layerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + mFrameTracer->onDestroy(layerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); + mFrameTracer->onDestroy(secondLayerID); + EXPECT_EQ(mFrameTracer->miniDump(), + "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); +} + +TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 1; + const uint32_t bufferID = 2; + const uint64_t frameNumber = 3; + const nsecs_t timestamp = 4; + const nsecs_t duration = 5; + const auto type = FrameTracer::FrameEvent::POST; + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + // Create second trace packet to finalize the previous one. + mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 1); + + const auto& packet = trace.packet().Get(0); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + ASSERT_TRUE(buffer_event.has_duration_ns()); + EXPECT_EQ(buffer_event.duration_ns(), duration); + } +} + +TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + // Trace. + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); + } + + { + auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + auto tracingSession = getTracingSessionForTest(); + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + const nsecs_t timestamp = systemTime(); + fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. + + const auto& packet = trace.packet().Get(1); + ASSERT_TRUE(packet.has_timestamp()); + EXPECT_EQ(packet.timestamp(), timestamp); + ASSERT_TRUE(packet.has_graphics_frame_event()); + const auto& frame_event = packet.graphics_frame_event(); + ASSERT_TRUE(frame_event.has_buffer_event()); + const auto& buffer_event = frame_event.buffer_event(); + ASSERT_TRUE(buffer_event.has_buffer_id()); + EXPECT_EQ(buffer_event.buffer_id(), bufferID); + ASSERT_TRUE(buffer_event.has_frame_number()); + EXPECT_EQ(buffer_event.frame_number(), frameNumber); + ASSERT_TRUE(buffer_event.has_type()); + EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); + EXPECT_FALSE(buffer_event.has_duration_ns()); + } +} + +TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 + 100000; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 + 100000; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), signalTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), signalTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); +} + +TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + const nsecs_t signalTime = systemTime() - FrameTracer::kFenceSignallingDeadline; + + auto tracingSession = getTracingSessionForTest(); + auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); + // Create extra trace packet to trigger and finalize any previous fence packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + EXPECT_EQ(raw_trace.size(), 0); +} + +TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { + const std::string layerName = "co.layername#0"; + const int32_t layerID = 5; + const uint32_t bufferID = 4; + const uint64_t frameNumber = 3; + const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; + const nsecs_t duration = 1234; + + auto tracingSession = getTracingSessionForTest(); + + tracingSession->StartBlocking(); + // Clean up irrelevant traces. + tracingSession->ReadTraceBlocking(); + mFrameTracer->traceNewLayer(layerID, layerName); + + // traceFence called after fence signalled. + const nsecs_t signalTime1 = systemTime(); + const nsecs_t startTime1 = signalTime1 - duration; + auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + + // traceFence called before fence signalled. + const nsecs_t signalTime2 = systemTime(); + const nsecs_t startTime2 = signalTime2 - duration; + auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); + mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); + + // Create extra trace packet to trigger and finalize fence trace packets. + mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + tracingSession->StopBlocking(); + + std::vector raw_trace = tracingSession->ReadTraceBlocking(); + ASSERT_GT(raw_trace.size(), 0); + + perfetto::protos::Trace trace; + ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); + ASSERT_FALSE(trace.packet().empty()); + EXPECT_EQ(trace.packet().size(), 2); + + const auto& packet1 = trace.packet().Get(0); + ASSERT_TRUE(packet1.has_timestamp()); + EXPECT_EQ(packet1.timestamp(), startTime1); + ASSERT_TRUE(packet1.has_graphics_frame_event()); + ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event1.duration_ns(), duration); + + const auto& packet2 = trace.packet().Get(1); + ASSERT_TRUE(packet2.has_timestamp()); + EXPECT_EQ(packet2.timestamp(), startTime2); + ASSERT_TRUE(packet2.has_graphics_frame_event()); + ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); + ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); + const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); + EXPECT_EQ(buffer_event2.duration_ns(), duration); +} + +} // namespace +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index f01e603f20..ffacbfef16 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -20,8 +20,8 @@ #include #include #include + #include -#include #include #include @@ -109,15 +109,6 @@ public: const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - - // Need to initialize tracing in process for testing, and only once per test suite. - static bool wasInitialized = false; - if (!wasInitialized) { - perfetto::TracingInitArgs args; - args.backends = perfetto::kInProcessBackend; - perfetto::Tracing::Initialize(args); - wasInitialized = true; - } } ~TimeStatsTest() { @@ -126,13 +117,6 @@ public: ALOGD("**** Tearing down after %s.%s\n", test_info->test_case_name(), test_info->name()); } - void SetUp() override { - mTimeStats = std::make_unique(); - mTimeStats->registerTracingDataSource(); - } - - void TearDown() override { mTimeStats.reset(); } - std::string inputCommand(InputCommand cmd, bool useProto); void setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts); @@ -147,22 +131,8 @@ public: } } - // Each tracing session can be used for a single block of Start -> Stop. - static std::unique_ptr getTracingSessionForTest() { - perfetto::TraceConfig cfg; - cfg.set_duration_ms(500); - cfg.add_buffers()->set_size_kb(1024); - auto* ds_cfg = cfg.add_data_sources()->mutable_config(); - ds_cfg->set_name(TimeStats::kTimeStatsDataSource); - - auto tracingSession = perfetto::Tracing::NewTrace(perfetto::kInProcessBackend); - tracingSession->Setup(cfg); - return tracingSession; - } - std::mt19937 mRandomEngine = std::mt19937(std::random_device()()); - std::unique_ptr mTimeStats; - FenceToFenceTimeMap fenceFactory; + std::unique_ptr mTimeStats = std::make_unique(); }; std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { @@ -239,330 +209,6 @@ int32_t TimeStatsTest::genRandomInt32(int32_t begin, int32_t end) { return distr(mRandomEngine); } -TEST_F(TimeStatsTest, traceNewLayerStartsTrackingLayerWhenTracing) { - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - mTimeStats->traceNewLayer(layerID, layerName); - - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - mTimeStats->traceNewLayer(layerID, layerName); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - tracingSession->StopBlocking(); -} - -TEST_F(TimeStatsTest, onDestroyRemovesTheTrackedLayer) { - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); - - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const int32_t secondLayerID = 6; - - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceNewLayer(secondLayerID, layerName); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 2\n"); - tracingSession->StopBlocking(); - - mTimeStats->onDestroy(layerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - mTimeStats->onDestroy(layerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 1\n"); - mTimeStats->onDestroy(secondLayerID); - EXPECT_EQ(mTimeStats->miniDump(), - "TimeStats miniDump:\nNumber of layers currently being tracked is 0\nNumber of " - "layers in the stats pool is 0\nNumber of layers currently being traced is 0\n"); -} - -TEST_F(TimeStatsTest, canTraceAfterAddingLayer) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 1; - const uint32_t bufferID = 2; - const uint64_t frameNumber = 3; - const nsecs_t timestamp = 4; - const nsecs_t duration = 5; - const auto type = TimeStats::FrameEvent::POST; - - { - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - - mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); - // Create second trace packet to finalize the previous one. - mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); - } - - { - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); - // Create second trace packet to finalize the previous one. - mTimeStats->traceTimestamp(layerID, 0, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 1); - - const auto& packet = trace.packet().Get(0); - ASSERT_TRUE(packet.has_timestamp()); - EXPECT_EQ(packet.timestamp(), timestamp); - ASSERT_TRUE(packet.has_graphics_frame_event()); - const auto& frame_event = packet.graphics_frame_event(); - ASSERT_TRUE(frame_event.has_buffer_event()); - const auto& buffer_event = frame_event.buffer_event(); - ASSERT_TRUE(buffer_event.has_buffer_id()); - EXPECT_EQ(buffer_event.buffer_id(), bufferID); - ASSERT_TRUE(buffer_event.has_frame_number()); - EXPECT_EQ(buffer_event.frame_number(), frameNumber); - ASSERT_TRUE(buffer_event.has_type()); - EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); - ASSERT_TRUE(buffer_event.has_duration_ns()); - EXPECT_EQ(buffer_event.duration_ns(), duration); - } -} - -TEST_F(TimeStatsTest, traceFenceTriggersOnNextTraceAfterFenceFired) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - - { - auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, Fence::SIGNAL_TIME_PENDING); - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - // Trace. - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); - // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); - } - - { - auto fenceTime = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - auto tracingSession = getTracingSessionForTest(); - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fenceTime, type); - const nsecs_t timestamp = systemTime(); - fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); // Two packets because of the extra trace made above. - - const auto& packet = trace.packet().Get(1); - ASSERT_TRUE(packet.has_timestamp()); - EXPECT_EQ(packet.timestamp(), timestamp); - ASSERT_TRUE(packet.has_graphics_frame_event()); - const auto& frame_event = packet.graphics_frame_event(); - ASSERT_TRUE(frame_event.has_buffer_event()); - const auto& buffer_event = frame_event.buffer_event(); - ASSERT_TRUE(buffer_event.has_buffer_id()); - EXPECT_EQ(buffer_event.buffer_id(), bufferID); - ASSERT_TRUE(buffer_event.has_frame_number()); - EXPECT_EQ(buffer_event.frame_number(), frameNumber); - ASSERT_TRUE(buffer_event.has_type()); - EXPECT_EQ(buffer_event.type(), perfetto::protos::GraphicsFrameEvent_BufferEventType(type)); - EXPECT_FALSE(buffer_event.has_duration_ns()); - } -} - -TEST_F(TimeStatsTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - - // traceFence called after fence signalled. - const nsecs_t signalTime1 = systemTime(); - const nsecs_t startTime1 = signalTime1 + 100000; - auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); - - // traceFence called before fence signalled. - const nsecs_t signalTime2 = systemTime(); - const nsecs_t startTime2 = signalTime2 + 100000; - auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); - - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); - - const auto& packet1 = trace.packet().Get(0); - ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), signalTime1); - ASSERT_TRUE(packet1.has_graphics_frame_event()); - ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); - ASSERT_FALSE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); - - const auto& packet2 = trace.packet().Get(1); - ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), signalTime2); - ASSERT_TRUE(packet2.has_graphics_frame_event()); - ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); - ASSERT_FALSE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); -} - -TEST_F(TimeStatsTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - const nsecs_t signalTime = systemTime() - TimeStats::kFenceSignallingDeadline; - - auto tracingSession = getTracingSessionForTest(); - auto fence = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence, type); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); - // Create extra trace packet to trigger and finalize any previous fence packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - EXPECT_EQ(raw_trace.size(), 0); -} - -TEST_F(TimeStatsTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { - const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const uint32_t bufferID = 4; - const uint64_t frameNumber = 3; - const auto type = TimeStats::FrameEvent::ACQUIRE_FENCE; - const nsecs_t duration = 1234; - - auto tracingSession = getTracingSessionForTest(); - - tracingSession->StartBlocking(); - // Clean up irrelevant traces. - tracingSession->ReadTraceBlocking(); - mTimeStats->traceNewLayer(layerID, layerName); - - // traceFence called after fence signalled. - const nsecs_t signalTime1 = systemTime(); - const nsecs_t startTime1 = signalTime1 - duration; - auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); - - // traceFence called before fence signalled. - const nsecs_t signalTime2 = systemTime(); - const nsecs_t startTime2 = signalTime2 - duration; - auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mTimeStats->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); - fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); - - // Create extra trace packet to trigger and finalize fence trace packets. - mTimeStats->traceTimestamp(layerID, bufferID, 0, 0, TimeStats::FrameEvent::UNSPECIFIED); - tracingSession->StopBlocking(); - - std::vector raw_trace = tracingSession->ReadTraceBlocking(); - ASSERT_GT(raw_trace.size(), 0); - - perfetto::protos::Trace trace; - ASSERT_TRUE(trace.ParseFromArray(raw_trace.data(), int(raw_trace.size()))); - ASSERT_FALSE(trace.packet().empty()); - EXPECT_EQ(trace.packet().size(), 2); - - const auto& packet1 = trace.packet().Get(0); - ASSERT_TRUE(packet1.has_timestamp()); - EXPECT_EQ(packet1.timestamp(), startTime1); - ASSERT_TRUE(packet1.has_graphics_frame_event()); - ASSERT_TRUE(packet1.graphics_frame_event().has_buffer_event()); - ASSERT_TRUE(packet1.graphics_frame_event().buffer_event().has_duration_ns()); - const auto& buffer_event1 = packet1.graphics_frame_event().buffer_event(); - EXPECT_EQ(buffer_event1.duration_ns(), duration); - - const auto& packet2 = trace.packet().Get(1); - ASSERT_TRUE(packet2.has_timestamp()); - EXPECT_EQ(packet2.timestamp(), startTime2); - ASSERT_TRUE(packet2.has_graphics_frame_event()); - ASSERT_TRUE(packet2.graphics_frame_event().has_buffer_event()); - ASSERT_TRUE(packet2.graphics_frame_event().buffer_event().has_duration_ns()); - const auto& buffer_event2 = packet2.graphics_frame_event().buffer_event(); - EXPECT_EQ(buffer_event2.duration_ns(), duration); -} - TEST_F(TimeStatsTest, canEnableAndDisableTimeStats) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); ASSERT_TRUE(mTimeStats->isEnabled()); diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp new file mode 100644 index 0000000000..358dfdb856 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.cpp @@ -0,0 +1,27 @@ +/* + * Copyright 2019 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. + */ + +#include "mock/MockFrameTracer.h" + +namespace android { +namespace mock { + +// Explicit default instantiation is recommended. +FrameTracer::FrameTracer() = default; +FrameTracer::~FrameTracer() = default; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h new file mode 100644 index 0000000000..f768b8114d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockFrameTracer.h @@ -0,0 +1,43 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include + +#include "FrameTracer/FrameTracer.h" + +namespace android { +namespace mock { + +class FrameTracer : public android::FrameTracer { +public: + FrameTracer(); + ~FrameTracer(); + + MOCK_METHOD0(initialize, void()); + MOCK_METHOD0(registerDataSource, void()); + MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); + MOCK_METHOD6(traceTimestamp, + void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD6(traceFence, + void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, + FrameEvent::BufferEventType, nsecs_t)); + MOCK_METHOD0(miniDump, std::string()); +}; + +} // namespace mock +} // namespace android diff --git a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h index 542c70a8fb..b1634a8da7 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h +++ b/services/surfaceflinger/tests/unittests/mock/MockTimeStats.h @@ -28,14 +28,6 @@ public: TimeStats(); ~TimeStats() override; - MOCK_METHOD0(initializeTracing, void()); - MOCK_METHOD0(registerTracingDataSource, void()); - MOCK_METHOD2(traceNewLayer, void(int32_t, const std::string&)); - MOCK_METHOD6(traceTimestamp, - void(int32_t, uint64_t, uint64_t, nsecs_t, FrameEvent::BufferEventType, nsecs_t)); - MOCK_METHOD6(traceFence, - void(int32_t, uint64_t, uint64_t, const std::shared_ptr&, - FrameEvent::BufferEventType, nsecs_t)); MOCK_METHOD3(parseArgs, void(bool, const Vector&, std::string&)); MOCK_METHOD0(isEnabled, bool()); MOCK_METHOD0(miniDump, std::string()); -- cgit v1.2.3-59-g8ed1b From 214c89db99f280cd67ca14357c9ee11adce0acce Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 16:03:53 -0700 Subject: Remove setGeometryAppliesWithResize This function is no longer used so removing the API and any logic implemented for it. Test: go/wm-smoke Change-Id: I4ae2128cd38e818fcd16dafa4ce47c9411bd61c9 --- libs/gui/LayerState.cpp | 3 - libs/gui/SurfaceComposerClient.cpp | 13 --- libs/gui/include/gui/LayerState.h | 2 +- libs/gui/include/gui/SurfaceComposerClient.h | 6 - services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.h | 4 +- services/surfaceflinger/Layer.cpp | 39 ++----- services/surfaceflinger/Layer.h | 6 +- services/surfaceflinger/LayerRejecter.cpp | 28 ++--- services/surfaceflinger/LayerRejecter.h | 12 +- services/surfaceflinger/RefreshRateOverlay.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 7 +- services/surfaceflinger/tests/Transaction_test.cpp | 124 --------------------- .../tests/fakehwc/SFFakeHwc_test.cpp | 18 --- 14 files changed, 32 insertions(+), 234 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index be58b853d7..523ed1d2ce 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -291,9 +291,6 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eOverrideScalingModeChanged; overrideScalingMode = other.overrideScalingMode; } - if (other.what & eGeometryAppliesWithResize) { - what |= eGeometryAppliesWithResize; - } if (other.what & eReparentChildren) { what |= eReparentChildren; reparentHandle = other.reparentHandle; diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 5faf010d72..67dd726eba 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1187,19 +1187,6 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setOverr return *this; } -SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setGeometryAppliesWithResize( - const sp& sc) { - layer_state_t* s = getLayerState(sc); - if (!s) { - mStatus = BAD_INDEX; - return *this; - } - s->what |= layer_state_t::eGeometryAppliesWithResize; - - registerSurfaceControlForCallback(sc); - return *this; -} - #ifndef NO_INPUT SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setInputWindowInfo( const sp& sc, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index cbd1c8553b..2eb5492558 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -71,7 +71,7 @@ struct layer_state_t { eCropChanged_legacy = 0x00000100, eDeferTransaction_legacy = 0x00000200, eOverrideScalingModeChanged = 0x00000400, - eGeometryAppliesWithResize = 0x00000800, + // AVAILABLE 0x00000800, eReparentChildren = 0x00001000, eDetachChildren = 0x00002000, eRelativeLayerChanged = 0x00004000, diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index f303a03254..d65e679e24 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -446,12 +446,6 @@ public: Transaction& setOverrideScalingMode(const sp& sc, int32_t overrideScalingMode); - // If the size changes in this transaction, all geometry updates specified - // in this transaction will not complete until a buffer of the new size - // arrives. As some elements normally apply immediately, this enables - // freezing the total geometry of a surface until a resize is completed. - Transaction& setGeometryAppliesWithResize(const sp& sc); - #ifndef NO_INPUT Transaction& setInputWindowInfo(const sp& sc, const InputWindowInfo& info); Transaction& transferTouchFocus(const sp& fromToken, const sp& toToken); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 5f494ff3d5..85a00fbe0d 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -276,7 +276,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t const int32_t layerID = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, - getTransformToDisplayInverse(), mFreezeGeometryUpdates); + getTransformToDisplayInverse()); if (isRemovedFromCurrentState()) { expectedPresentTime = 0; diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index cc670087ac..f2a5dffe7c 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -82,13 +82,13 @@ public: // Override to ignore legacy layer state properties that are not used by BufferStateLayer bool setSize(uint32_t /*w*/, uint32_t /*h*/) override { return false; } - bool setPosition(float /*x*/, float /*y*/, bool /*immediate*/) override { return false; } + bool setPosition(float /*x*/, float /*y*/) override { return false; } bool setTransparentRegionHint(const Region& transparent) override; bool setMatrix(const layer_state_t::matrix22_t& /*matrix*/, bool /*allowNonRectPreservingTransforms*/) override { return false; } - bool setCrop_legacy(const Rect& /*crop*/, bool /*immediate*/) override { return false; } + bool setCrop_legacy(const Rect& /*crop*/) override { return false; } bool setOverrideScalingMode(int32_t /*overrideScalingMode*/) override { return false; } void deferTransactionUntil_legacy(const sp& /*barrierHandle*/, uint64_t /*frameNumber*/) override {} diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5121835cae..4c8a6bf465 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -770,11 +770,6 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { if (!(flags & eDontUpdateGeometryState)) { State& editCurrentState(getCurrentState()); - // If mFreezeGeometryUpdates is true we are in the setGeometryAppliesWithResize - // mode, which causes attributes which normally latch regardless of scaling mode, - // to be delayed. We copy the requested state to the active state making sure - // to respect these rules (again see Layer.h for a detailed discussion). - // // There is an awkward asymmetry in the handling of the crop states in the position // states, as can be seen below. Largely this arises from position and transform // being stored in the same data structure while having different latching rules. @@ -782,16 +777,8 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { // // Careful that "stateToCommit" and editCurrentState may not begin as equivalent due to // applyPendingStates in the presence of deferred transactions. - if (mFreezeGeometryUpdates) { - float tx = stateToCommit->active_legacy.transform.tx(); - float ty = stateToCommit->active_legacy.transform.ty(); - stateToCommit->active_legacy = stateToCommit->requested_legacy; - stateToCommit->active_legacy.transform.set(tx, ty); - editCurrentState.active_legacy = stateToCommit->active_legacy; - } else { - editCurrentState.active_legacy = editCurrentState.requested_legacy; - stateToCommit->active_legacy = stateToCommit->requested_legacy; - } + editCurrentState.active_legacy = editCurrentState.requested_legacy; + stateToCommit->active_legacy = stateToCommit->requested_legacy; } return flags; @@ -858,7 +845,7 @@ uint32_t Layer::setTransactionFlags(uint32_t flags) { return mTransactionFlags.fetch_or(flags); } -bool Layer::setPosition(float x, float y, bool immediate) { +bool Layer::setPosition(float x, float y) { if (mCurrentState.requested_legacy.transform.tx() == x && mCurrentState.requested_legacy.transform.ty() == y) return false; @@ -868,14 +855,11 @@ bool Layer::setPosition(float x, float y, bool immediate) { // we want to apply the position portion of the transform matrix immediately, // but still delay scaling when resizing a SCALING_MODE_FREEZE layer. mCurrentState.requested_legacy.transform.set(x, y); - if (immediate && !mFreezeGeometryUpdates) { - // Here we directly update the active state - // unlike other setters, because we store it within - // the transform, but use different latching rules. - // b/38182305 - mCurrentState.active_legacy.transform.set(x, y); - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; + // Here we directly update the active state + // unlike other setters, because we store it within + // the transform, but use different latching rules. + // b/38182305 + mCurrentState.active_legacy.transform.set(x, y); mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); @@ -1081,14 +1065,11 @@ bool Layer::setFlags(uint8_t flags, uint8_t mask) { return true; } -bool Layer::setCrop_legacy(const Rect& crop, bool immediate) { +bool Layer::setCrop_legacy(const Rect& crop) { if (mCurrentState.requestedCrop_legacy == crop) return false; mCurrentState.sequence++; mCurrentState.requestedCrop_legacy = crop; - if (immediate && !mFreezeGeometryUpdates) { - mCurrentState.crop_legacy = crop; - } - mFreezeGeometryUpdates = mFreezeGeometryUpdates || !immediate; + mCurrentState.crop_legacy = crop; mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 9107189d52..a2409e79d2 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -268,9 +268,9 @@ public: // setPosition operates in parent buffer space (pre parent-transform) or display // space for top-level layers. - virtual bool setPosition(float x, float y, bool immediate); + virtual bool setPosition(float x, float y); // Buffer space - virtual bool setCrop_legacy(const Rect& crop, bool immediate); + virtual bool setCrop_legacy(const Rect& crop); // TODO(b/38182121): Could we eliminate the various latching modes by // using the layer hierarchy? @@ -860,8 +860,6 @@ protected: // This layer can be a cursor on some displays. bool mPotentialCursor{false}; - bool mFreezeGeometryUpdates{false}; - // Child list about to be committed/used for editing. LayerVector mCurrentChildren{LayerVector::StateSet::Current}; // Child list used for rendering. diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 72abea8b2d..8a221837ac 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -23,22 +23,16 @@ namespace android { -LayerRejecter::LayerRejecter(Layer::State& front, - Layer::State& current, - bool& recomputeVisibleRegions, - bool stickySet, - const char* name, - int32_t overrideScalingMode, - bool transformToDisplayInverse, - bool& freezePositionUpdates) - : mFront(front), - mCurrent(current), - mRecomputeVisibleRegions(recomputeVisibleRegions), - mStickyTransformSet(stickySet), - mName(name), - mOverrideScalingMode(overrideScalingMode), - mTransformToDisplayInverse(transformToDisplayInverse), - mFreezeGeometryUpdates(freezePositionUpdates) {} +LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current, + bool& recomputeVisibleRegions, bool stickySet, const char* name, + int32_t overrideScalingMode, bool transformToDisplayInverse) + : mFront(front), + mCurrent(current), + mRecomputeVisibleRegions(recomputeVisibleRegions), + mStickyTransformSet(stickySet), + mName(name), + mOverrideScalingMode(overrideScalingMode), + mTransformToDisplayInverse(transformToDisplayInverse) {} bool LayerRejecter::reject(const sp& buf, const BufferItem& item) { if (buf == nullptr) { @@ -83,8 +77,6 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // recompute visible region mRecomputeVisibleRegions = true; - mFreezeGeometryUpdates = false; - if (mFront.crop_legacy != mFront.requestedCrop_legacy) { mFront.crop_legacy = mFront.requestedCrop_legacy; mCurrent.crop_legacy = mFront.requestedCrop_legacy; diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index 63d51de0ca..1bd0c26dc6 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -23,14 +23,9 @@ namespace android { class LayerRejecter : public BufferLayerConsumer::BufferRejecter { public: - LayerRejecter(Layer::State &front, - Layer::State ¤t, - bool &recomputeVisibleRegions, - bool stickySet, - const char *name, - int32_t overrideScalingMode, - bool transformToDisplayInverse, - bool &freezePositionUpdates); + LayerRejecter(Layer::State &front, Layer::State ¤t, bool &recomputeVisibleRegions, + bool stickySet, const char *name, int32_t overrideScalingMode, + bool transformToDisplayInverse); virtual bool reject(const sp &buf, const BufferItem &item); @@ -42,7 +37,6 @@ namespace android { const char *mName; int32_t mOverrideScalingMode; bool mTransformToDisplayInverse; - bool &mFreezeGeometryUpdates; }; } // namespace android diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 5b4bec96ea..976fedb58a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -39,7 +39,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); - mLayer->setCrop_legacy(Rect(50, 70, 200, 100), true); + mLayer->setCrop_legacy(Rect(50, 70, 200, 100)); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 7a8eb6b2da..c1a8f87d37 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3597,8 +3597,6 @@ uint32_t SurfaceFlinger::setClientStateLocked( uint32_t flags = 0; const uint64_t what = s.what; - bool geometryAppliesWithResize = - what & layer_state_t::eGeometryAppliesWithResize; // If we are deferring transaction, make sure to push the pending state, as otherwise the // pending state will also be deferred. @@ -3607,7 +3605,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::ePositionChanged) { - if (layer->setPosition(s.x, s.y, !geometryAppliesWithResize)) { + if (layer->setPosition(s.x, s.y)) { flags |= eTraversalNeeded; } } @@ -3698,8 +3696,7 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } if (what & layer_state_t::eCropChanged_legacy) { - if (layer->setCrop_legacy(s.crop_legacy, !geometryAppliesWithResize)) - flags |= eTraversalNeeded; + if (layer->setCrop_legacy(s.crop_legacy)) flags |= eTraversalNeeded; } if (what & layer_state_t::eCornerRadiusChanged) { if (layer->setCornerRadius(s.cornerRadius)) diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index b1fde22e0e..03c646b0bb 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -842,62 +842,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetPositionWithResize_BufferQueue) { } } -TEST_P(LayerRenderTypeTransactionTest, SetPositionWithNextResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // request setPosition to be applied with the next resize - Transaction().setPosition(layer, 5, 10).setGeometryAppliesWithResize(layer).apply(); - { - SCOPED_TRACE("new position pending"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setPosition(layer, 15, 20).apply(); - { - SCOPED_TRACE("pending new position modified"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setSize(layer, 64, 64).apply(); - { - SCOPED_TRACE("resize pending"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - // finally resize and latch the buffer - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("new position applied"); - getScreenCapture()->expectColor(Rect(15, 20, 79, 84), Color::RED); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetPositionWithNextResizeScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setPosition is not immediate even with SCALE_TO_WINDOW override - Transaction() - .setPosition(layer, 5, 10) - .setSize(layer, 64, 64) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("new position pending"); - getScreenCapture()->expectColor(Rect(0, 0, 64, 64), Color::RED); - } - - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 64, 64)); - { - SCOPED_TRACE("new position applied"); - getScreenCapture()->expectColor(Rect(5, 10, 69, 74), Color::RED); - } -} - TEST_P(LayerRenderTypeTransactionTest, SetSizeBasic_BufferQueue) { sp layer; ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); @@ -2310,74 +2254,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetCropWithResize_BufferQueue) { } } -TEST_P(LayerRenderTypeTransactionTest, SetCropWithNextResize_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // request setCrop_legacy to be applied with the next resize - Transaction() - .setCrop_legacy(layer, Rect(8, 8, 24, 24)) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("waiting for next resize"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setCrop_legacy(layer, Rect(4, 4, 12, 12)).apply(); - { - SCOPED_TRACE("pending crop modified"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - Transaction().setSize(layer, 16, 16).apply(); - { - SCOPED_TRACE("resize pending"); - getScreenCapture()->expectColor(Rect(0, 0, 32, 32), Color::RED); - } - - // finally resize - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - { - SCOPED_TRACE("new crop applied"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - -TEST_P(LayerRenderTypeTransactionTest, SetCropWithNextResizeScaleToWindow_BufferQueue) { - sp layer; - ASSERT_NO_FATAL_FAILURE(layer = createLayer("test", 32, 32)); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 32, 32)); - - // setCrop_legacy is not immediate even with SCALE_TO_WINDOW override - Transaction() - .setCrop_legacy(layer, Rect(4, 4, 12, 12)) - .setSize(layer, 16, 16) - .setOverrideScalingMode(layer, NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW) - .setGeometryAppliesWithResize(layer) - .apply(); - { - SCOPED_TRACE("new crop pending"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(0, 0, 16, 16), Color::RED); - shot->expectBorder(Rect(0, 0, 16, 16), Color::BLACK); - } - - // XXX crop is never latched without other geometry change (b/69315677) - Transaction().setPosition(layer, 1, 0).setGeometryAppliesWithResize(layer).apply(); - ASSERT_NO_FATAL_FAILURE(fillBufferQueueLayerColor(layer, Color::RED, 16, 16)); - Transaction().setPosition(layer, 0, 0).apply(); - { - SCOPED_TRACE("new crop applied"); - auto shot = getScreenCapture(); - shot->expectColor(Rect(4, 4, 12, 12), Color::RED); - shot->expectBorder(Rect(4, 4, 12, 12), Color::BLACK); - } -} - TEST_P(LayerRenderTypeTransactionTest, SetFrameBasic_BufferState) { sp layer; ASSERT_NO_FATAL_FAILURE( diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index a892a2abd0..093bcf576d 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -1331,16 +1331,6 @@ TEST_F(LatchingTest, SurfacePositionLatching) { restoreInitialState(); - // Now we repeat with setGeometryAppliesWithResize - // and verify the position DOESN'T latch. - { - TransactionScope ts(*sFakeComposer); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setSize(mFGSurfaceControl, 32, 32); - ts.setPosition(mFGSurfaceControl, 100, 100); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - completeFGResize(); auto referenceFrame2 = mBaseFrame; @@ -1365,14 +1355,6 @@ TEST_F(LatchingTest, CropLatching) { restoreInitialState(); - { - TransactionScope ts(*sFakeComposer); - ts.setSize(mFGSurfaceControl, 128, 128); - ts.setGeometryAppliesWithResize(mFGSurfaceControl); - ts.setCrop_legacy(mFGSurfaceControl, Rect(0, 0, 63, 63)); - } - EXPECT_TRUE(framesAreSame(mBaseFrame, sFakeComposer->getLatestFrame())); - completeFGResize(); auto referenceFrame2 = mBaseFrame; -- cgit v1.2.3-59-g8ed1b From 4244e0356083fba0a367b9cb5422cd24d567518a Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 11:27:49 -0700 Subject: Created bufferInfo to track buffer data in a single place (1/2) This is in preparation for layer mirroring since mirrored buffer layers should just copy the bufferInfo instead of the entire BufferQueue or parts of BufferState Test: go/wm-smoke Change-Id: Iba1be05c4b038f0b678150deed8e673bf1e7710b --- services/surfaceflinger/BufferLayer.cpp | 124 ++++++++++++++++---------- services/surfaceflinger/BufferLayer.h | 46 ++++++---- services/surfaceflinger/BufferQueueLayer.cpp | 65 ++++---------- services/surfaceflinger/BufferQueueLayer.h | 15 +--- services/surfaceflinger/BufferStateLayer.cpp | 126 ++++++++++----------------- services/surfaceflinger/BufferStateLayer.h | 20 ++--- services/surfaceflinger/ColorLayer.cpp | 9 +- services/surfaceflinger/ColorLayer.h | 2 +- services/surfaceflinger/Layer.cpp | 42 +++------ services/surfaceflinger/Layer.h | 12 +-- 10 files changed, 204 insertions(+), 257 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 90a02b3ad9..bca15e6903 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -81,7 +81,7 @@ void BufferLayer::useSurfaceDamage() { if (mFlinger->mForceFullDamage) { surfaceDamageRegion = Region::INVALID_REGION; } else { - surfaceDamageRegion = getDrawingSurfaceDamage(); + surfaceDamageRegion = mBufferInfo.mSurfaceDamage; } } @@ -187,7 +187,7 @@ std::optional BufferLayer::prepareClientComposition // Query the texture matrix given our current filtering mode. float textureMatrix[16]; setFilteringEnabled(useFiltering); - getDrawingTransformMatrix(textureMatrix); + memcpy(textureMatrix, mBufferInfo.mTransformMatrix, sizeof(mBufferInfo.mTransformMatrix)); if (getTransformToDisplayInverse()) { /* @@ -254,8 +254,8 @@ std::optional BufferLayer::prepareClientComposition bool BufferLayer::isHdrY410() const { // pixel format is HDR Y410 masquerading as RGBA_1010102 - return (mCurrentDataSpace == ui::Dataspace::BT2020_ITU_PQ && - getDrawingApi() == NATIVE_WINDOW_API_MEDIA && + return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && + mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } @@ -268,7 +268,7 @@ void BufferLayer::latchPerFrameState( compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; } else { // Normal buffer layers - compositionState.hdrMetadata = getDrawingHdrMetadata(); + compositionState.hdrMetadata = mBufferInfo.mHdrMetadata; compositionState.compositionType = mPotentialCursor ? Hwc2::IComposerClient::Composition::CURSOR : Hwc2::IComposerClient::Composition::DEVICE; @@ -300,13 +300,13 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } // Update mFrameTracker. - nsecs_t desiredPresentTime = getDesiredPresentTime(); + nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; mFrameTracker.setDesiredPresentTime(desiredPresentTime); const int32_t layerID = getSequence(); mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); - std::shared_ptr frameReadyFence = getCurrentFenceTime(); + std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { mFrameTracker.setFrameReadyFence(std::move(frameReadyFence)); } else { @@ -394,6 +394,9 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } + BufferInfo oldBufferInfo = mBufferInfo; + gatherBufferInfo(); + mRefreshPending = true; mFrameLatencyNeeded = true; if (oldBuffer == nullptr) { @@ -402,43 +405,10 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - ui::Dataspace dataSpace = getDrawingDataSpace(); - // translate legacy dataspaces to modern dataspaces - switch (dataSpace) { - case ui::Dataspace::SRGB: - dataSpace = ui::Dataspace::V0_SRGB; - break; - case ui::Dataspace::SRGB_LINEAR: - dataSpace = ui::Dataspace::V0_SRGB_LINEAR; - break; - case ui::Dataspace::JFIF: - dataSpace = ui::Dataspace::V0_JFIF; - break; - case ui::Dataspace::BT601_625: - dataSpace = ui::Dataspace::V0_BT601_625; - break; - case ui::Dataspace::BT601_525: - dataSpace = ui::Dataspace::V0_BT601_525; - break; - case ui::Dataspace::BT709: - dataSpace = ui::Dataspace::V0_BT709; - break; - default: - break; - } - mCurrentDataSpace = dataSpace; - - Rect crop(getDrawingCrop()); - const uint32_t transform(getDrawingTransform()); - const uint32_t scalingMode(getDrawingScalingMode()); - const bool transformToDisplayInverse(getTransformToDisplayInverse()); - if ((crop != mCurrentCrop) || (transform != mCurrentTransform) || - (scalingMode != mCurrentScalingMode) || - (transformToDisplayInverse != mTransformToDisplayInverse)) { - mCurrentCrop = crop; - mCurrentTransform = transform; - mCurrentScalingMode = scalingMode; - mTransformToDisplayInverse = transformToDisplayInverse; + if ((mBufferInfo.mCrop != oldBufferInfo.mCrop) || + (mBufferInfo.mTransform != oldBufferInfo.mTransform) || + (mBufferInfo.mScaleMode != oldBufferInfo.mScaleMode) || + (mBufferInfo.mTransformToDisplayInverse != oldBufferInfo.mTransformToDisplayInverse)) { recomputeVisibleRegions = true; } @@ -510,7 +480,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { return mOverrideScalingMode; } - return mCurrentScalingMode; + return mBufferInfo.mScaleMode; } bool BufferLayer::isProtected() const { @@ -626,7 +596,7 @@ Rect BufferLayer::getBufferSize(const State& s) const { uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. - if (mCurrentTransform & ui::Transform::ROT_90) { + if (mBufferInfo.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -662,7 +632,7 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const uint32_t bufHeight = mActiveBuffer->getHeight(); // Undo any transformations on the buffer and return the result. - if (mCurrentTransform & ui::Transform::ROT_90) { + if (mBufferInfo.mTransform & ui::Transform::ROT_90) { std::swap(bufWidth, bufHeight); } @@ -685,6 +655,66 @@ void BufferLayer::latchAndReleaseBuffer() { releasePendingBuffer(systemTime()); } +PixelFormat BufferLayer::getPixelFormat() const { + return mBufferInfo.mPixelFormat; +} + +bool BufferLayer::getTransformToDisplayInverse() const { + return mBufferInfo.mTransformToDisplayInverse; +} + +Rect BufferLayer::getBufferCrop() const { + // this is the crop rectangle that applies to the buffer + // itself (as opposed to the window) + if (!mBufferInfo.mCrop.isEmpty()) { + // if the buffer crop is defined, we use that + return mBufferInfo.mCrop; + } else if (mActiveBuffer != nullptr) { + // otherwise we use the whole buffer + return mActiveBuffer->getBounds(); + } else { + // if we don't have a buffer yet, we use an empty/invalid crop + return Rect(); + } +} + +uint32_t BufferLayer::getBufferTransform() const { + return mBufferInfo.mTransform; +} + +ui::Dataspace BufferLayer::getDataSpace() const { + return mBufferInfo.mDataspace; +} + +ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { + ui::Dataspace updatedDataspace = dataspace; + // translate legacy dataspaces to modern dataspaces + switch (dataspace) { + case ui::Dataspace::SRGB: + updatedDataspace = ui::Dataspace::V0_SRGB; + break; + case ui::Dataspace::SRGB_LINEAR: + updatedDataspace = ui::Dataspace::V0_SRGB_LINEAR; + break; + case ui::Dataspace::JFIF: + updatedDataspace = ui::Dataspace::V0_JFIF; + break; + case ui::Dataspace::BT601_625: + updatedDataspace = ui::Dataspace::V0_BT601_625; + break; + case ui::Dataspace::BT601_525: + updatedDataspace = ui::Dataspace::V0_BT601_525; + break; + case ui::Dataspace::BT709: + updatedDataspace = ui::Dataspace::V0_BT709; + break; + default: + break; + } + + return updatedDataspace; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index ee44cbe836..e8838e812c 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -106,6 +106,14 @@ public: // Should only be called on the main thread. void latchAndReleaseBuffer() override; + bool getTransformToDisplayInverse() const override; + + Rect getBufferCrop() const override; + + uint32_t getBufferTransform() const override; + + ui::Dataspace getDataSpace() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -115,18 +123,7 @@ private: virtual bool fenceHasSignaled() const = 0; virtual bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const = 0; - virtual nsecs_t getDesiredPresentTime() = 0; - virtual std::shared_ptr getCurrentFenceTime() const = 0; - - virtual void getDrawingTransformMatrix(float *matrix) = 0; - virtual uint32_t getDrawingTransform() const = 0; - virtual ui::Dataspace getDrawingDataSpace() const = 0; - virtual Rect getDrawingCrop() const = 0; - virtual uint32_t getDrawingScalingMode() const = 0; - virtual Region getDrawingSurfaceDamage() const = 0; - virtual const HdrMetadata& getDrawingHdrMetadata() const = 0; - virtual int getDrawingApi() const = 0; - virtual PixelFormat getPixelFormat() const = 0; + PixelFormat getPixelFormat() const; virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; @@ -148,6 +145,25 @@ private: virtual status_t updateFrameNumber(nsecs_t latchTime) = 0; protected: + struct BufferInfo { + nsecs_t mDesiredPresentTime; + std::shared_ptr mFenceTime; + sp mFence; + float mTransformMatrix[16]; + uint32_t mTransform{0}; + ui::Dataspace mDataspace; + Rect mCrop; + uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; + Region mSurfaceDamage; + HdrMetadata mHdrMetadata; + int mApi; + PixelFormat mPixelFormat; + bool mTransformToDisplayInverse{false}; + }; + + BufferInfo mBufferInfo; + virtual void gatherBufferInfo() = 0; + /* * compositionengine::LayerFE overrides */ @@ -171,16 +187,14 @@ protected: bool mRefreshPending{false}; + ui::Dataspace translateDataspace(ui::Dataspace dataspace); + private: // Returns true if this layer requires filtering bool needsFiltering(const sp& displayDevice) const override; uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; - uint32_t mCurrentScalingMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; - - bool mTransformToDisplayInverse{false}; - // main thread. bool mBufferLatched{false}; // TODO: Use mActiveBuffer? diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 4da39e4d6f..e9e8e6e9dc 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -70,10 +70,6 @@ std::vector BufferQueueLayer::getOccupancyHistory(boo return history; } -bool BufferQueueLayer::getTransformToDisplayInverse() const { - return mConsumer->getTransformToDisplayInverse(); -} - void BufferQueueLayer::releasePendingBuffer(nsecs_t dequeueReadyTime) { if (!mConsumer->releasePendingBuffer()) { return; @@ -155,55 +151,12 @@ bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mQueueItems[0].mTimestamp <= expectedPresentTime; } -nsecs_t BufferQueueLayer::getDesiredPresentTime() { - return mConsumer->getTimestamp(); -} - -std::shared_ptr BufferQueueLayer::getCurrentFenceTime() const { - return mConsumer->getCurrentFenceTime(); -} - -void BufferQueueLayer::getDrawingTransformMatrix(float *matrix) { - return mConsumer->getTransformMatrix(matrix); -} - // NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's // These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state // so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's // current buffer so the consumer functions start with "getCurrent". // // This results in the rather confusing functions below. -uint32_t BufferQueueLayer::getDrawingTransform() const { - return mConsumer->getCurrentTransform(); -} - -ui::Dataspace BufferQueueLayer::getDrawingDataSpace() const { - return mConsumer->getCurrentDataSpace(); -} - -Rect BufferQueueLayer::getDrawingCrop() const { - return mConsumer->getCurrentCrop(); -} - -uint32_t BufferQueueLayer::getDrawingScalingMode() const { - return mConsumer->getCurrentScalingMode(); -} - -Region BufferQueueLayer::getDrawingSurfaceDamage() const { - return mConsumer->getSurfaceDamage(); -} - -const HdrMetadata& BufferQueueLayer::getDrawingHdrMetadata() const { - return mConsumer->getCurrentHdrMetadata(); -} - -int BufferQueueLayer::getDrawingApi() const { - return mConsumer->getCurrentApi(); -} - -PixelFormat BufferQueueLayer::getPixelFormat() const { - return mFormat; -} uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); @@ -422,7 +375,7 @@ void BufferQueueLayer::latchPerFrameState( compositionState.buffer = mActiveBuffer; compositionState.bufferSlot = (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; - compositionState.acquireFence = mConsumer->getCurrentFence(); + compositionState.acquireFence = mBufferInfo.mFence; } // ----------------------------------------------------------------------- @@ -573,4 +526,20 @@ uint32_t BufferQueueLayer::getProducerStickyTransform() const { return static_cast(producerStickyTransform); } +void BufferQueueLayer::gatherBufferInfo() { + mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp(); + mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime(); + mBufferInfo.mFence = mConsumer->getCurrentFence(); + mConsumer->getTransformMatrix(mBufferInfo.mTransformMatrix); + mBufferInfo.mTransform = mConsumer->getCurrentTransform(); + mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace()); + mBufferInfo.mCrop = mConsumer->getCurrentCrop(); + mBufferInfo.mScaleMode = mConsumer->getCurrentScalingMode(); + mBufferInfo.mSurfaceDamage = mConsumer->getSurfaceDamage(); + mBufferInfo.mHdrMetadata = mConsumer->getCurrentHdrMetadata(); + mBufferInfo.mApi = mConsumer->getCurrentApi(); + mBufferInfo.mPixelFormat = mFormat; + mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); +} + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index bf3f917196..6cbafb31ce 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -46,7 +46,6 @@ public: std::vector getOccupancyHistory(bool forceFlush) override; - bool getTransformToDisplayInverse() const override; // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; @@ -66,18 +65,6 @@ public: bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: - nsecs_t getDesiredPresentTime() override; - std::shared_ptr getCurrentFenceTime() const override; - - void getDrawingTransformMatrix(float *matrix) override; - uint32_t getDrawingTransform() const override; - ui::Dataspace getDrawingDataSpace() const override; - Rect getDrawingCrop() const override; - uint32_t getDrawingScalingMode() const override; - Region getDrawingSurfaceDamage() const override; - const HdrMetadata& getDrawingHdrMetadata() const override; - int getDrawingApi() const override; - PixelFormat getPixelFormat() const override; uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; @@ -103,6 +90,8 @@ private: // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- protected: + void gatherBufferInfo() override; + void onFrameAvailable(const BufferItem& item) override; void onFrameReplaced(const BufferItem& item) override; void onSidebandStreamChanged() override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index e7d1b63b03..07a83b9d35 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -125,10 +125,6 @@ bool BufferStateLayer::willPresentCurrentTransaction() const { (mCurrentState.buffer != nullptr || mCurrentState.bgColorLayer != nullptr)); } -bool BufferStateLayer::getTransformToDisplayInverse() const { - return mCurrentState.transformToDisplayInverse; -} - void BufferStateLayer::pushPendingState() { if (!mCurrentState.modified) { return; @@ -400,75 +396,6 @@ bool BufferStateLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mCurrentState.desiredPresentTime <= expectedPresentTime; } -nsecs_t BufferStateLayer::getDesiredPresentTime() { - return getDrawingState().desiredPresentTime; -} - -std::shared_ptr BufferStateLayer::getCurrentFenceTime() const { - return std::make_shared(getDrawingState().acquireFence); -} - -void BufferStateLayer::getDrawingTransformMatrix(float *matrix) { - std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), matrix); -} - -uint32_t BufferStateLayer::getDrawingTransform() const { - return getDrawingState().transform; -} - -ui::Dataspace BufferStateLayer::getDrawingDataSpace() const { - return getDrawingState().dataspace; -} - -// Crop that applies to the buffer -Rect BufferStateLayer::getDrawingCrop() const { - const State& s(getDrawingState()); - - if (s.crop.isEmpty() && s.buffer) { - return s.buffer->getBounds(); - } else if (s.buffer) { - Rect crop = s.crop; - crop.left = std::max(crop.left, 0); - crop.top = std::max(crop.top, 0); - uint32_t bufferWidth = s.buffer->getWidth(); - uint32_t bufferHeight = s.buffer->getHeight(); - if (bufferHeight <= std::numeric_limits::max() && - bufferWidth <= std::numeric_limits::max()) { - crop.right = std::min(crop.right, static_cast(bufferWidth)); - crop.bottom = std::min(crop.bottom, static_cast(bufferHeight)); - } - if (!crop.isValid()) { - // Crop rect is out of bounds, return whole buffer - return s.buffer->getBounds(); - } - return crop; - } - return s.crop; -} - -uint32_t BufferStateLayer::getDrawingScalingMode() const { - return NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; -} - -Region BufferStateLayer::getDrawingSurfaceDamage() const { - return getDrawingState().surfaceDamageRegion; -} - -const HdrMetadata& BufferStateLayer::getDrawingHdrMetadata() const { - return getDrawingState().hdrMetadata; -} - -int BufferStateLayer::getDrawingApi() const { - return getDrawingState().api; -} - -PixelFormat BufferStateLayer::getPixelFormat() const { - if (!mActiveBuffer) { - return PIXEL_FORMAT_NONE; - } - return mActiveBuffer->format; -} - uint64_t BufferStateLayer::getFrameNumber(nsecs_t /*expectedPresentTime*/) const { return mFrameNumber; } @@ -506,8 +433,8 @@ bool BufferStateLayer::hasFrameUpdate() const { } void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mCurrentCrop, - mCurrentTransform, enabled); + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, enabled); } status_t BufferStateLayer::bindTextureImage() { @@ -576,8 +503,8 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse } const uint64_t bufferID = getCurrentBufferId(); - mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, getCurrentFenceTime()); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, getCurrentFenceTime(), + mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime); + mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, @@ -622,7 +549,7 @@ void BufferStateLayer::latchPerFrameState( compositionState.buffer = s.buffer; compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); - compositionState.acquireFence = s.acquireFence; + compositionState.acquireFence = mBufferInfo.mFence; mFrameNumber++; } @@ -707,4 +634,47 @@ void BufferStateLayer::HwcSlotGenerator::eraseBufferLocked(const client_cache_t& mFreeHwcCacheSlots.push(hwcCacheSlot); mCachedBuffers.erase(clientCacheId); } + +void BufferStateLayer::gatherBufferInfo() { + const State& s(getDrawingState()); + + mBufferInfo.mDesiredPresentTime = s.desiredPresentTime; + mBufferInfo.mFenceTime = std::make_shared(s.acquireFence); + mBufferInfo.mFence = s.acquireFence; + std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), + mBufferInfo.mTransformMatrix); + mBufferInfo.mTransform = s.transform; + mBufferInfo.mDataspace = translateDataspace(s.dataspace); + mBufferInfo.mCrop = computeCrop(s); + mBufferInfo.mScaleMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; + mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; + mBufferInfo.mHdrMetadata = s.hdrMetadata; + mBufferInfo.mApi = s.api; + mBufferInfo.mPixelFormat = !mActiveBuffer ? PIXEL_FORMAT_NONE : mActiveBuffer->format; + mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; +} + +Rect BufferStateLayer::computeCrop(const State& s) { + if (s.crop.isEmpty() && s.buffer) { + return s.buffer->getBounds(); + } else if (s.buffer) { + Rect crop = s.crop; + crop.left = std::max(crop.left, 0); + crop.top = std::max(crop.top, 0); + uint32_t bufferWidth = s.buffer->getWidth(); + uint32_t bufferHeight = s.buffer->getHeight(); + if (bufferHeight <= std::numeric_limits::max() && + bufferWidth <= std::numeric_limits::max()) { + crop.right = std::min(crop.right, static_cast(bufferWidth)); + crop.bottom = std::min(crop.bottom, static_cast(bufferHeight)); + } + if (!crop.isValid()) { + // Crop rect is out of bounds, return whole buffer + return s.buffer->getBounds(); + } + return crop; + } + return s.crop; +} + } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index c060ca8e76..086fd0a6ba 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -48,8 +48,6 @@ public: bool shouldPresentNow(nsecs_t expectedPresentTime) const override; - bool getTransformToDisplayInverse() const override; - uint32_t doTransactionResize(uint32_t flags, Layer::State* /*stateToCommit*/) override { return flags; } @@ -106,19 +104,10 @@ public: bool fenceHasSignaled() const override; bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; +protected: + void gatherBufferInfo() override; + private: - nsecs_t getDesiredPresentTime() override; - std::shared_ptr getCurrentFenceTime() const override; - - void getDrawingTransformMatrix(float *matrix) override; - uint32_t getDrawingTransform() const override; - ui::Dataspace getDrawingDataSpace() const override; - Rect getDrawingCrop() const override; - uint32_t getDrawingScalingMode() const override; - Region getDrawingSurfaceDamage() const override; - const HdrMetadata& getDrawingHdrMetadata() const override; - int getDrawingApi() const override; - PixelFormat getPixelFormat() const override; uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; @@ -140,6 +129,9 @@ private: void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + // Crop that applies to the buffer + Rect computeCrop(const State& s); + private: friend class SlotGenerationTest; void onFirstRef() override; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 2ad7591b86..49b18102c7 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -99,11 +99,6 @@ void ColorLayer::latchPerFrameState( compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; } -void ColorLayer::commitTransaction(const State& stateToCommit) { - Layer::commitTransaction(stateToCommit); - mCurrentDataSpace = mDrawingState.dataspace; -} - std::shared_ptr ColorLayer::getCompositionLayer() const { return mCompositionLayer; } @@ -112,6 +107,10 @@ bool ColorLayer::isOpaque(const Layer::State& s) const { return (s.flags & layer_state_t::eLayerOpaque) != 0; } +ui::Dataspace ColorLayer::getDataSpace() const { + return mDrawingState.dataspace; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 57c54c7e2c..16921df356 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -37,7 +37,7 @@ public: bool setDataspace(ui::Dataspace dataspace) override; - void commitTransaction(const State& stateToCommit) override; + ui::Dataspace getDataSpace() const override; bool isOpaque(const Layer::State& s) const override; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c916f74291..f1a5175424 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -78,7 +78,6 @@ Layer::Layer(const LayerCreationArgs& args) mName(args.name), mClientRef(args.client), mWindowType(args.metadata.getInt32(METADATA_WINDOW_TYPE, 0)) { - mCurrentCrop.makeInvalid(); uint32_t layerFlags = 0; if (args.flags & ISurfaceComposerClient::eHidden) layerFlags |= layer_state_t::eLayerHidden; @@ -259,23 +258,6 @@ sp Layer::getHandle() { // h/w composer set-up // --------------------------------------------------------------------------- -Rect Layer::getContentCrop() const { - // this is the crop rectangle that applies to the buffer - // itself (as opposed to the window) - Rect crop; - if (!mCurrentCrop.isEmpty()) { - // if the buffer crop is defined, we use that - crop = mCurrentCrop; - } else if (mActiveBuffer != nullptr) { - // otherwise we use the whole buffer - crop = mActiveBuffer->getBounds(); - } else { - // if we don't have a buffer yet, we use an empty/invalid crop - crop.makeInvalid(); - } - return crop; -} - static Rect reduce(const Rect& win, const Region& exclude) { if (CC_LIKELY(exclude.isEmpty())) { return win; @@ -335,7 +317,7 @@ ui::Transform Layer::getBufferScaleTransform() const { int bufferWidth = mActiveBuffer->getWidth(); int bufferHeight = mActiveBuffer->getHeight(); - if (mCurrentTransform & NATIVE_WINDOW_TRANSFORM_ROT_90) { + if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); } @@ -442,9 +424,9 @@ void Layer::latchGeometry(compositionengine::LayerFECompositionState& compositio compositionState.geomLayerTransform = getTransform(); compositionState.geomInverseLayerTransform = compositionState.geomLayerTransform.inverse(); compositionState.geomBufferSize = getBufferSize(drawingState); - compositionState.geomContentCrop = getContentCrop(); + compositionState.geomContentCrop = getBufferCrop(); compositionState.geomCrop = getCrop(drawingState); - compositionState.geomBufferTransform = mCurrentTransform; + compositionState.geomBufferTransform = getBufferTransform(); compositionState.geomBufferUsesDisplayInverseTransform = getTransformToDisplayInverse(); compositionState.geomActiveTransparentRegion = getActiveTransparentRegion(drawingState); compositionState.geomLayerBounds = mBounds; @@ -466,7 +448,7 @@ void Layer::latchPerFrameState(compositionengine::LayerFECompositionState& compo compositionState.geomVisibleRegion = visibleRegion; compositionState.isColorspaceAgnostic = isColorSpaceAgnostic(); - compositionState.dataspace = mCurrentDataSpace; + compositionState.dataspace = getDataSpace(); compositionState.colorTransform = getColorTransform(); compositionState.colorTransformIsIdentity = !hasColorTransform(); compositionState.surfaceDamage = surfaceDamageRegion; @@ -543,7 +525,7 @@ std::optional Layer::prepareClientComposition( layerSettings.geometry.roundedCornersCrop = roundedCornerState.cropRect; layerSettings.alpha = alpha; - layerSettings.sourceDataspace = mCurrentDataSpace; + layerSettings.sourceDataspace = getDataSpace(); return layerSettings; } @@ -726,7 +708,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), mCurrentTransform, getEffectiveScalingMode(), + this, getName().string(), getBufferTransform(), getEffectiveScalingMode(), stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, @@ -1232,7 +1214,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mColor = ds.color; info.mFlags = ds.flags; info.mPixelFormat = getPixelFormat(); - info.mDataSpace = static_cast(mCurrentDataSpace); + info.mDataSpace = static_cast(getDataSpace()); info.mMatrix[0][0] = ds.active_legacy.transform[0][0]; info.mMatrix[0][1] = ds.active_legacy.transform[0][1]; info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; @@ -1551,8 +1533,9 @@ bool Layer::hasColorTransform() const { bool Layer::isLegacyDataSpace() const { // return true when no higher bits are set - return !(mCurrentDataSpace & (ui::Dataspace::STANDARD_MASK | - ui::Dataspace::TRANSFER_MASK | ui::Dataspace::RANGE_MASK)); + return !(getDataSpace() & + (ui::Dataspace::STANDARD_MASK | ui::Dataspace::TRANSFER_MASK | + ui::Dataspace::RANGE_MASK)); } void Layer::setParent(const sp& layer) { @@ -1834,13 +1817,12 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); - LayerProtoHelper::writeToProto(ui::Transform(mCurrentTransform), + LayerProtoHelper::writeToProto(ui::Transform(getBufferTransform()), layerInfo->mutable_buffer_transform()); } layerInfo->set_invalidate(contentDirty); layerInfo->set_is_protected(isProtected()); - layerInfo->set_dataspace( - dataspaceDetails(static_cast(mCurrentDataSpace))); + layerInfo->set_dataspace(dataspaceDetails(static_cast(getDataSpace()))); layerInfo->set_queued_frames(getQueuedFrameCount()); layerInfo->set_refresh_pending(isBufferLatched()); layerInfo->set_curr_frame(mCurrentFrameNumber); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 23c1acd759..ea5b8447ad 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -330,7 +330,7 @@ public: virtual bool setBackgroundColor(const half3& color, float alpha, ui::Dataspace dataspace); virtual bool setColorSpaceAgnostic(const bool agnostic); - ui::Dataspace getDataSpace() const { return mCurrentDataSpace; } + virtual ui::Dataspace getDataSpace() const { return ui::Dataspace::UNKNOWN; } // Before color management is introduced, contents on Android have to be // desaturated in order to match what they appears like visually. @@ -587,7 +587,12 @@ public: * returns the rectangle that crops the content of the layer and scales it * to the layer's size. */ - Rect getContentCrop() const; + virtual Rect getBufferCrop() const { return Rect(); } + + /* + * Returns the transform applied to the buffer. + */ + virtual uint32_t getBufferTransform() const { return 0; } /* * Returns if a frame is ready @@ -846,9 +851,6 @@ protected: // composition, true otherwise. bool mIsActiveBufferUpdatedForGpu = true; - ui::Dataspace mCurrentDataSpace = ui::Dataspace::UNKNOWN; - Rect mCurrentCrop; - uint32_t mCurrentTransform{0}; // We encode unset as -1. int32_t mOverrideScalingMode{-1}; std::atomic mCurrentFrameNumber{0}; -- cgit v1.2.3-59-g8ed1b From d62d30645c41d703a241443de761ab9eaa0c99af Mon Sep 17 00:00:00 2001 From: chaviw Date: Wed, 4 Sep 2019 14:48:02 -0700 Subject: Moved info about activeBuffer into bufferInfo (2/2) This is in preparation for layer mirroring since mirrored buffer layers should just copy the bufferInfo instead of the entire BufferQueue or parts of BufferState Test: go/wm-smoke Change-Id: I48c34141151370d9905c312239883f8374b884b9 --- services/surfaceflinger/BufferLayer.cpp | 53 +++++++++++++++------------- services/surfaceflinger/BufferLayer.h | 8 +++-- services/surfaceflinger/BufferQueueLayer.cpp | 14 ++++---- services/surfaceflinger/BufferQueueLayer.h | 1 - services/surfaceflinger/BufferStateLayer.cpp | 19 +++++----- services/surfaceflinger/Layer.cpp | 16 ++++----- services/surfaceflinger/Layer.h | 7 ++-- 7 files changed, 62 insertions(+), 56 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index bca15e6903..6a3d60f50c 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -92,7 +92,7 @@ void BufferLayer::useEmptyDamage() { bool BufferLayer::isOpaque(const Layer::State& s) const { // if we don't have a buffer or sidebandStream yet, we're translucent regardless of the // layer's opaque flag. - if ((mSidebandStream == nullptr) && (mActiveBuffer == nullptr)) { + if ((mSidebandStream == nullptr) && (mBufferInfo.mBuffer == nullptr)) { return false; } @@ -103,7 +103,7 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { bool BufferLayer::isVisible() const { bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && - (mActiveBuffer != nullptr || mSidebandStream != nullptr); + (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); return visible; @@ -144,7 +144,7 @@ std::optional BufferLayer::prepareClientComposition return result; } - if (CC_UNLIKELY(mActiveBuffer == 0)) { + if (CC_UNLIKELY(mBufferInfo.mBuffer == 0)) { // the texture has not been created yet, this Layer has // in fact never been drawn into. This happens frequently with // SurfaceView because the WindowManager can't know when the client @@ -175,9 +175,9 @@ std::optional BufferLayer::prepareClientComposition const State& s(getDrawingState()); auto& layer = *result; if (!blackOutLayer) { - layer.source.buffer.buffer = mActiveBuffer; + layer.source.buffer.buffer = mBufferInfo.mBuffer; layer.source.buffer.isOpaque = isOpaque(s); - layer.source.buffer.fence = mActiveBufferFence; + layer.source.buffer.fence = mBufferInfo.mFence; layer.source.buffer.textureName = mTextureName; layer.source.buffer.usePremultipliedAlpha = getPremultipledAlpha(); layer.source.buffer.isY410BT2020 = isHdrY410(); @@ -256,7 +256,7 @@ bool BufferLayer::isHdrY410() const { // pixel format is HDR Y410 masquerading as RGBA_1010102 return (mBufferInfo.mDataspace == ui::Dataspace::BT2020_ITU_PQ && mBufferInfo.mApi == NATIVE_WINDOW_API_MEDIA && - mActiveBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); + mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } void BufferLayer::latchPerFrameState( @@ -276,7 +276,7 @@ void BufferLayer::latchPerFrameState( } bool BufferLayer::onPreComposition(nsecs_t refreshStartTime) { - if (mBufferLatched) { + if (mBufferInfo.mBuffer != nullptr) { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.addPreComposition(mCurrentFrameNumber, refreshStartTime); } @@ -370,7 +370,8 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, // Capture the old state of the layer for comparisons later const State& s(getDrawingState()); const bool oldOpacity = isOpaque(s); - sp oldBuffer = mActiveBuffer; + + BufferInfo oldBufferInfo = mBufferInfo; if (!allTransactionsSignaled(expectedPresentTime)) { mFlinger->setTransactionFlags(eTraversalNeeded); @@ -387,19 +388,16 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, return false; } - mBufferLatched = true; - err = updateFrameNumber(latchTime); if (err != NO_ERROR) { return false; } - BufferInfo oldBufferInfo = mBufferInfo; gatherBufferInfo(); mRefreshPending = true; mFrameLatencyNeeded = true; - if (oldBuffer == nullptr) { + if (oldBufferInfo.mBuffer == nullptr) { // the first time we receive a buffer, we need to trigger a // geometry invalidation. recomputeVisibleRegions = true; @@ -412,10 +410,11 @@ bool BufferLayer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime, recomputeVisibleRegions = true; } - if (oldBuffer != nullptr) { - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); - if (bufWidth != uint32_t(oldBuffer->width) || bufHeight != uint32_t(oldBuffer->height)) { + if (oldBufferInfo.mBuffer != nullptr) { + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); + if (bufWidth != uint32_t(oldBufferInfo.mBuffer->width) || + bufHeight != uint32_t(oldBufferInfo.mBuffer->height)) { recomputeVisibleRegions = true; } } @@ -484,7 +483,7 @@ uint32_t BufferLayer::getEffectiveScalingMode() const { } bool BufferLayer::isProtected() const { - const sp& buffer(mActiveBuffer); + const sp& buffer(mBufferInfo.mBuffer); return (buffer != 0) && (buffer->getUsage() & GRALLOC_USAGE_PROTECTED); } @@ -588,12 +587,12 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect(getActiveWidth(s), getActiveHeight(s)); } - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { return Rect::INVALID_RECT; } - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -624,12 +623,12 @@ FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const return FloatRect(0, 0, getActiveWidth(s), getActiveHeight(s)); } - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { return parentBounds; } - uint32_t bufWidth = mActiveBuffer->getWidth(); - uint32_t bufHeight = mActiveBuffer->getHeight(); + uint32_t bufWidth = mBufferInfo.mBuffer->getWidth(); + uint32_t bufHeight = mBufferInfo.mBuffer->getHeight(); // Undo any transformations on the buffer and return the result. if (mBufferInfo.mTransform & ui::Transform::ROT_90) { @@ -669,9 +668,9 @@ Rect BufferLayer::getBufferCrop() const { if (!mBufferInfo.mCrop.isEmpty()) { // if the buffer crop is defined, we use that return mBufferInfo.mCrop; - } else if (mActiveBuffer != nullptr) { + } else if (mBufferInfo.mBuffer != nullptr) { // otherwise we use the whole buffer - return mActiveBuffer->getBounds(); + return mBufferInfo.mBuffer->getBounds(); } else { // if we don't have a buffer yet, we use an empty/invalid crop return Rect(); @@ -715,6 +714,10 @@ ui::Dataspace BufferLayer::translateDataspace(ui::Dataspace dataspace) { return updatedDataspace; } +sp BufferLayer::getBuffer() const { + return mBufferInfo.mBuffer; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index e8838e812c..a685ea2305 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -114,6 +114,8 @@ public: ui::Dataspace getDataSpace() const override; + sp getBuffer() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -159,6 +161,9 @@ protected: int mApi; PixelFormat mPixelFormat; bool mTransformToDisplayInverse{false}; + + sp mBuffer; + int mBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; }; BufferInfo mBufferInfo; @@ -195,9 +200,6 @@ private: uint64_t getHeadFrameNumber(nsecs_t expectedPresentTime) const; - // main thread. - bool mBufferLatched{false}; // TODO: Use mActiveBuffer? - // BufferStateLayers can return Rect::INVALID_RECT if the layer does not have a display frame // and its parent layer is not bounded Rect getBufferSize(const State& s) const override; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e9e8e6e9dc..a4f7bc23a4 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -343,11 +343,12 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t status_t BufferQueueLayer::updateActiveBuffer() { // update the active buffer mPreviousBufferId = getCurrentBufferId(); - mActiveBuffer = mConsumer->getCurrentBuffer(&mActiveBufferSlot, &mActiveBufferFence); + mBufferInfo.mBuffer = + mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.buffer = mActiveBuffer; + layerCompositionState.buffer = mBufferInfo.mBuffer; - if (mActiveBuffer == nullptr) { + if (mBufferInfo.mBuffer == nullptr) { // this can only happen if the very first buffer was rejected. return BAD_VALUE; } @@ -372,9 +373,10 @@ void BufferQueueLayer::latchPerFrameState( return; } - compositionState.buffer = mActiveBuffer; - compositionState.bufferSlot = - (mActiveBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mActiveBufferSlot; + compositionState.buffer = mBufferInfo.mBuffer; + compositionState.bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) + ? 0 + : mBufferInfo.mBufferSlot; compositionState.acquireFence = mBufferInfo.mFence; } diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 6cbafb31ce..43eb3eaab8 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -127,7 +127,6 @@ private: std::atomic mLastFrameNumberReceived{0}; bool mAutoRefresh{false}; - int mActiveBufferSlot{BufferQueue::INVALID_BUFFER_SLOT}; // thread-safe std::atomic mQueuedFrames{0}; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 07a83b9d35..afbe22854f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -53,12 +53,12 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) } BufferStateLayer::~BufferStateLayer() { - if (mActiveBuffer != nullptr) { - // Ensure that mActiveBuffer is uncached from RenderEngine here, as + if (mBufferInfo.mBuffer != nullptr) { + // Ensure that mBuffer is uncached from RenderEngine here, as // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. auto& engine(mFlinger->getRenderEngine()); - engine.unbindExternalTextureBuffer(mActiveBuffer->getId()); + engine.unbindExternalTextureBuffer(mBufferInfo.mBuffer->getId()); } } @@ -433,8 +433,8 @@ bool BufferStateLayer::hasFrameUpdate() const { } void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mActiveBuffer, mBufferInfo.mCrop, - mBufferInfo.mTransform, enabled); + GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mBufferInfo.mBuffer, + mBufferInfo.mCrop, mBufferInfo.mTransform, enabled); } status_t BufferStateLayer::bindTextureImage() { @@ -523,10 +523,10 @@ status_t BufferStateLayer::updateActiveBuffer() { } mPreviousBufferId = getCurrentBufferId(); - mActiveBuffer = s.buffer; - mActiveBufferFence = s.acquireFence; + mBufferInfo.mBuffer = s.buffer; + mBufferInfo.mFence = s.acquireFence; auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; - layerCompositionState.buffer = mActiveBuffer; + layerCompositionState.buffer = mBufferInfo.mBuffer; return NO_ERROR; } @@ -650,7 +650,8 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mSurfaceDamage = s.surfaceDamageRegion; mBufferInfo.mHdrMetadata = s.hdrMetadata; mBufferInfo.mApi = s.api; - mBufferInfo.mPixelFormat = !mActiveBuffer ? PIXEL_FORMAT_NONE : mActiveBuffer->format; + mBufferInfo.mPixelFormat = + !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; } diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f1a5175424..d0b9187d56 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -302,7 +302,7 @@ ui::Transform Layer::getBufferScaleTransform() const { // If the layer is not using NATIVE_WINDOW_SCALING_MODE_FREEZE (e.g. // it isFixedSize) then there may be additional scaling not accounted // for in the layer transform. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return {}; } @@ -314,8 +314,8 @@ ui::Transform Layer::getBufferScaleTransform() const { return {}; } - int bufferWidth = mActiveBuffer->getWidth(); - int bufferHeight = mActiveBuffer->getHeight(); + int bufferWidth = getBuffer()->getWidth(); + int bufferHeight = getBuffer()->getHeight(); if (getBufferTransform() & NATIVE_WINDOW_TRANSFORM_ROT_90) { std::swap(bufferWidth, bufferHeight); @@ -332,7 +332,7 @@ ui::Transform Layer::getBufferScaleTransform() const { ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTransform) const { // We need to mirror this scaling to child surfaces or we will break the contract where WM can // treat child surfaces as pixels in the parent surface. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mEffectiveTransform; } return mEffectiveTransform * bufferScaleTransform; @@ -341,7 +341,7 @@ ui::Transform Layer::getTransformWithScale(const ui::Transform& bufferScaleTrans FloatRect Layer::getBoundsPreScaling(const ui::Transform& bufferScaleTransform) const { // We need the pre scaled layer bounds when computing child bounds to make sure the child is // cropped to its parent layer after any buffer transform scaling is applied. - if (!isFixedSize() || !mActiveBuffer) { + if (!isFixedSize() || getBuffer() == nullptr) { return mBounds; } return bufferScaleTransform.inverse().transform(mBounds); @@ -740,7 +740,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { const bool resizePending = ((stateToCommit->requested_legacy.w != stateToCommit->active_legacy.w) || (stateToCommit->requested_legacy.h != stateToCommit->active_legacy.h)) && - (mActiveBuffer != nullptr); + (getBuffer() != nullptr); if (!isFixedSize()) { if (resizePending && mSidebandStream == nullptr) { flags |= eDontUpdateGeometryState; @@ -1220,7 +1220,7 @@ LayerDebugInfo Layer::getLayerDebugInfo() const { info.mMatrix[1][0] = ds.active_legacy.transform[1][0]; info.mMatrix[1][1] = ds.active_legacy.transform[1][1]; { - sp buffer = mActiveBuffer; + sp buffer = getBuffer(); if (buffer != 0) { info.mActiveBufferWidth = buffer->getWidth(); info.mActiveBufferHeight = buffer->getHeight(); @@ -1813,7 +1813,7 @@ void Layer::writeToProtoDrawingState(LayerProto* layerInfo, uint32_t traceFlags) } } - auto buffer = mActiveBuffer; + auto buffer = getBuffer(); if (buffer != nullptr) { LayerProtoHelper::writeToProto(buffer, [&]() { return layerInfo->mutable_active_buffer(); }); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ea5b8447ad..d6cc27a801 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -382,7 +382,7 @@ public: // creates its tracks by buffer id and has no way of associating a buffer back to the process // that created it, the current implementation is only sufficient for cases where a buffer is // only used within a single layer. - uint64_t getCurrentBufferId() const { return mActiveBuffer ? mActiveBuffer->getId() : 0; } + uint64_t getCurrentBufferId() const { return getBuffer() ? getBuffer()->getId() : 0; } // ----------------------------------------------------------------------- // Virtuals @@ -594,6 +594,8 @@ public: */ virtual uint32_t getBufferTransform() const { return 0; } + virtual sp getBuffer() const { return nullptr; } + /* * Returns if a frame is ready */ @@ -844,9 +846,6 @@ protected: // main thread sp mSidebandStream; - // Active buffer fields - sp mActiveBuffer; - sp mActiveBufferFence; // False if the buffer and its contents have been previously used for GPU // composition, true otherwise. bool mIsActiveBufferUpdatedForGpu = true; -- cgit v1.2.3-59-g8ed1b From f83ce183aa13db5e66b5fd5e6bd09de5169373c5 Mon Sep 17 00:00:00 2001 From: chaviw Date: Thu, 12 Sep 2019 14:43:08 -0700 Subject: Corrected drawingTransformMatrix The transformMatrix needed to be calculated in prepareClientComposition so storing it in BufferInfo was incorrect. Instead, allow the transformMatrix to get calculated when prepareClientComposition but avoid using the consumer for BufferQueueLayer. Also combined getDrawingTransformMatrix and setFilteringEnabled since setFilteringEnabled was only used to update the transformMatrix before getting it. BufferQueueLayers no longer go through the consumer to get the transformMatrix and just directly calculate the matrix using the GLUtils class. Fixes: 140759442 Test: atest android.view.cts.ASurfaceControlTest Change-Id: I09179de275bd905960fb366e45e36fb9874bc0b3 --- services/surfaceflinger/BufferLayer.cpp | 9 +++++++-- services/surfaceflinger/BufferLayer.h | 9 +++++---- services/surfaceflinger/BufferQueueLayer.cpp | 12 ------------ services/surfaceflinger/BufferQueueLayer.h | 4 ---- services/surfaceflinger/BufferStateLayer.cpp | 14 +++----------- services/surfaceflinger/BufferStateLayer.h | 6 ------ 6 files changed, 15 insertions(+), 39 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 486b042873..b060b047af 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -187,8 +188,7 @@ std::optional BufferLayer::prepareClientComposition // Query the texture matrix given our current filtering mode. float textureMatrix[16]; - setFilteringEnabled(useFiltering); - memcpy(textureMatrix, mBufferInfo.mTransformMatrix, sizeof(mBufferInfo.mTransformMatrix)); + getDrawingTransformMatrix(useFiltering, textureMatrix); if (getTransformToDisplayInverse()) { /* @@ -719,6 +719,11 @@ sp BufferLayer::getBuffer() const { return mBufferInfo.mBuffer; } +void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]) { + GLConsumer::computeTransformMatrix(outMatrix, mBufferInfo.mBuffer, mBufferInfo.mCrop, + mBufferInfo.mTransform, filteringEnabled); +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index a685ea2305..f0a30e319a 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -127,6 +127,10 @@ private: PixelFormat getPixelFormat() const; + // Computes the transform matrix using the setFilteringEnabled to determine whether the + // transform matrix should be computed for use with bilinear filtering. + void getDrawingTransformMatrix(bool filteringEnabled, float outMatrix[16]); + virtual uint64_t getFrameNumber(nsecs_t expectedPresentTime) const = 0; virtual bool getAutoRefresh() const = 0; @@ -137,8 +141,6 @@ private: virtual bool hasFrameUpdate() const = 0; - virtual void setFilteringEnabled(bool enabled) = 0; - virtual status_t bindTextureImage() = 0; virtual status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) = 0; @@ -151,9 +153,8 @@ protected: nsecs_t mDesiredPresentTime; std::shared_ptr mFenceTime; sp mFence; - float mTransformMatrix[16]; uint32_t mTransform{0}; - ui::Dataspace mDataspace; + ui::Dataspace mDataspace{ui::Dataspace::UNKNOWN}; Rect mCrop; uint32_t mScaleMode{NATIVE_WINDOW_SCALING_MODE_FREEZE}; Region mSurfaceDamage; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index a9e364a00d..5f7975085a 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -151,13 +151,6 @@ bool BufferQueueLayer::framePresentTimeIsCurrent(nsecs_t expectedPresentTime) co return mQueueItems[0].mTimestamp <= expectedPresentTime; } -// NOTE: SurfaceFlinger's definitions of "Current" and "Drawing" do not neatly map to BufferQueue's -// These functions get the fields for the frame that is currently in SurfaceFlinger's Drawing state -// so the functions start with "getDrawing". The data is retrieved from the BufferQueueConsumer's -// current buffer so the consumer functions start with "getCurrent". -// -// This results in the rather confusing functions below. - uint64_t BufferQueueLayer::getFrameNumber(nsecs_t expectedPresentTime) const { Mutex::Autolock lock(mQueueItemLock); uint64_t frameNumber = mQueueItems[0].mFrameNumber; @@ -220,10 +213,6 @@ bool BufferQueueLayer::hasFrameUpdate() const { return mQueuedFrames > 0; } -void BufferQueueLayer::setFilteringEnabled(bool enabled) { - return mConsumer->setFilteringEnabled(enabled); -} - status_t BufferQueueLayer::bindTextureImage() { return mConsumer->bindTextureImage(); } @@ -532,7 +521,6 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mDesiredPresentTime = mConsumer->getTimestamp(); mBufferInfo.mFenceTime = mConsumer->getCurrentFenceTime(); mBufferInfo.mFence = mConsumer->getCurrentFence(); - mConsumer->getTransformMatrix(mBufferInfo.mTransformMatrix); mBufferInfo.mTransform = mConsumer->getCurrentTransform(); mBufferInfo.mDataspace = translateDataspace(mConsumer->getCurrentDataSpace()); mBufferInfo.mCrop = mConsumer->getCurrentCrop(); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 43eb3eaab8..9374741ddb 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -46,7 +46,6 @@ public: std::vector getOccupancyHistory(bool forceFlush) override; - // If a buffer was replaced this frame, release the former buffer void releasePendingBuffer(nsecs_t dequeueReadyTime) override; @@ -65,7 +64,6 @@ public: bool framePresentTimeIsCurrent(nsecs_t expectedPresentTime) const override; private: - uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; @@ -75,8 +73,6 @@ private: bool hasFrameUpdate() const override; - void setFilteringEnabled(bool enabled) override; - status_t bindTextureImage() override; status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) override; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index afbe22854f..509deaf996 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -432,11 +432,6 @@ bool BufferStateLayer::hasFrameUpdate() const { return mCurrentStateModified && (c.buffer != nullptr || c.bgColorLayer != nullptr); } -void BufferStateLayer::setFilteringEnabled(bool enabled) { - GLConsumer::computeTransformMatrix(mTransformMatrix.data(), mBufferInfo.mBuffer, - mBufferInfo.mCrop, mBufferInfo.mTransform, enabled); -} - status_t BufferStateLayer::bindTextureImage() { const State& s(getDrawingState()); auto& engine(mFlinger->getRenderEngine()); @@ -545,10 +540,8 @@ void BufferStateLayer::latchPerFrameState( return; } - const State& s(getDrawingState()); - - compositionState.buffer = s.buffer; - compositionState.bufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); + compositionState.buffer = mBufferInfo.mBuffer; + compositionState.bufferSlot = mBufferInfo.mBufferSlot; compositionState.acquireFence = mBufferInfo.mFence; mFrameNumber++; @@ -641,8 +634,6 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mDesiredPresentTime = s.desiredPresentTime; mBufferInfo.mFenceTime = std::make_shared(s.acquireFence); mBufferInfo.mFence = s.acquireFence; - std::copy(std::begin(mTransformMatrix), std::end(mTransformMatrix), - mBufferInfo.mTransformMatrix); mBufferInfo.mTransform = s.transform; mBufferInfo.mDataspace = translateDataspace(s.dataspace); mBufferInfo.mCrop = computeCrop(s); @@ -653,6 +644,7 @@ void BufferStateLayer::gatherBufferInfo() { mBufferInfo.mPixelFormat = !mBufferInfo.mBuffer ? PIXEL_FORMAT_NONE : mBufferInfo.mBuffer->format; mBufferInfo.mTransformToDisplayInverse = s.transformToDisplayInverse; + mBufferInfo.mBufferSlot = mHwcSlotGenerator->getHwcCacheSlot(s.clientCacheId); } Rect BufferStateLayer::computeCrop(const State& s) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 0b27d640ce..52063fcc58 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -19,7 +19,6 @@ #include "BufferLayer.h" #include "Layer.h" -#include #include #include #include @@ -108,7 +107,6 @@ protected: void gatherBufferInfo() override; private: - uint64_t getFrameNumber(nsecs_t expectedPresentTime) const override; bool getAutoRefresh() const override; @@ -118,8 +116,6 @@ private: bool hasFrameUpdate() const override; - void setFilteringEnabled(bool enabled) override; - status_t bindTextureImage() override; status_t updateTexImage(bool& recomputeVisibleRegions, nsecs_t latchTime, nsecs_t expectedPresentTime) override; @@ -141,8 +137,6 @@ private: std::unique_ptr mTextureImage; - std::array mTransformMatrix{IDENTITY_MATRIX}; - std::atomic mSidebandStreamChanged{false}; mutable uint32_t mFrameNumber{0}; -- cgit v1.2.3-59-g8ed1b From 9755fb755c062b406ff5a9310ef6b23b9f1ce5a2 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Tue, 26 Mar 2019 14:44:40 -0700 Subject: CE: Layers only have FE layer state Remove the concept of having a compositionengine::Layer having internal state since it was only used to internally store a copy of the LayerFECompositionState. Instead switch the Layer interface so only the FE state can be obtained. Any internal state will from now on be private. Doing this also allows the LayerFECompostionState to be easily extended by extended versions of CompositionEngine. Test: atest libsurfaceflinger_unittest libcompositionengine_test Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Test: go/wm-smoke Bug: 121291683 Change-Id: I689e8714aca46320c87e0cb5ef18fdde93eb7499 --- services/surfaceflinger/BufferLayer.cpp | 2 - services/surfaceflinger/BufferQueueLayer.cpp | 12 +- services/surfaceflinger/BufferStateLayer.cpp | 12 +- services/surfaceflinger/ColorLayer.cpp | 4 - .../surfaceflinger/CompositionEngine/Android.bp | 2 +- .../include/compositionengine/Layer.h | 16 +-- .../compositionengine/LayerFECompositionState.h | 3 + .../include/compositionengine/impl/Layer.h | 9 +- .../compositionengine/impl/LayerCompositionState.h | 42 ------- .../include/compositionengine/mock/Layer.h | 6 +- .../CompositionEngine/src/CompositionEngine.cpp | 4 +- .../surfaceflinger/CompositionEngine/src/Layer.cpp | 12 +- .../src/LayerCompositionState.cpp | 91 -------------- .../src/LayerFECompositionState.cpp | 85 +++++++++++++ .../CompositionEngine/src/Output.cpp | 19 ++- .../CompositionEngine/src/OutputLayer.cpp | 16 +-- .../CompositionEngine/tests/OutputLayerTest.cpp | 132 ++++++++++----------- .../CompositionEngine/tests/OutputTest.cpp | 76 ++++++------ services/surfaceflinger/Layer.cpp | 1 - services/surfaceflinger/SurfaceFlinger.cpp | 3 - .../tests/unittests/TestableSurfaceFlinger.h | 4 +- 21 files changed, 243 insertions(+), 308 deletions(-) delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h delete mode 100644 services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp create mode 100644 services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b060b047af..fba235d397 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -22,12 +22,10 @@ #include "BufferLayer.h" #include -#include #include #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index f2e861d1ce..fcabedf63e 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -17,15 +17,13 @@ #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS -#include +#include "BufferQueueLayer.h" + #include -#include -#include -#include +#include #include #include -#include "BufferQueueLayer.h" #include "LayerRejecter.h" #include "SurfaceInterceptor.h" @@ -197,7 +195,7 @@ bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) { // mSidebandStreamChanged was changed to false mSidebandStream = mConsumer->getSidebandStream(); - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.sidebandStream = mSidebandStream; if (layerCompositionState.sidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); @@ -335,7 +333,7 @@ status_t BufferQueueLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.buffer = mBufferInfo.mBuffer; if (mBufferInfo.mBuffer == nullptr) { diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 509deaf996..ad05bc8671 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -19,18 +19,16 @@ #define LOG_TAG "BufferStateLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS +#include "BufferStateLayer.h" + #include -#include #include -#include -#include -#include +#include #include #include #include -#include "BufferStateLayer.h" #include "ColorLayer.h" #include "FrameTracer/FrameTracer.h" #include "TimeStats/TimeStats.h" @@ -415,7 +413,7 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { // mSidebandStreamChanged was true LOG_ALWAYS_FATAL_IF(!getCompositionLayer()); mSidebandStream = s.sidebandStream; - getCompositionLayer()->editState().frontEnd.sidebandStream = mSidebandStream; + getCompositionLayer()->editFEState().sidebandStream = mSidebandStream; if (mSidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); @@ -520,7 +518,7 @@ status_t BufferStateLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = s.buffer; mBufferInfo.mFence = s.acquireFence; - auto& layerCompositionState = getCompositionLayer()->editState().frontEnd; + auto& layerCompositionState = getCompositionLayer()->editFEState(); layerCompositionState.buffer = mBufferInfo.mBuffer; return NO_ERROR; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 49b18102c7..99805d9da2 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -25,13 +25,9 @@ #include #include -#include #include #include #include -#include -#include -#include #include #include #include diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index e49b65ff07..fcb94fde95 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -47,7 +47,7 @@ cc_library { "src/DumpHelpers.cpp", "src/HwcBufferCache.cpp", "src/Layer.cpp", - "src/LayerCompositionState.cpp", + "src/LayerFECompositionState.cpp", "src/Output.cpp", "src/OutputCompositionState.cpp", "src/OutputLayer.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h index 451608b2ae..1259c524b2 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h @@ -26,9 +26,7 @@ namespace android::compositionengine { class Display; class LayerFE; -namespace impl { -struct LayerCompositionState; -} // namespace impl +struct LayerFECompositionState; /** * A layer contains the output-independent composition state for a front-end @@ -42,17 +40,13 @@ public: // front-end layer no longer exists. virtual sp getLayerFE() const = 0; - using CompositionState = impl::LayerCompositionState; - - // Gets the raw composition state data for the layer + // Gets the raw front-end composition state data for the layer // TODO(lpique): Make this protected once it is only internally called. - virtual const CompositionState& getState() const = 0; + virtual const LayerFECompositionState& getFEState() const = 0; - // Allows mutable access to the raw composition state data for the layer. - // This is meant to be used by the various functions that are part of the - // composition process. + // Allows mutable access to the raw front-end composition state // TODO(lpique): Make this protected once it is only internally called. - virtual CompositionState& editState() = 0; + virtual LayerFECompositionState& editFEState() = 0; // Debugging virtual void dump(std::string& result) const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 530f49a600..2ba781d924 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -147,6 +147,9 @@ struct LayerFECompositionState { // The output-independent frame for the cursor Rect cursorFrame; + + // Debugging + void dump(std::string& out) const; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h index 3e56b21b18..d441c9c1b6 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h @@ -19,7 +19,7 @@ #include #include -#include +#include #include #include @@ -41,8 +41,8 @@ public: sp getLayerFE() const override; - const LayerCompositionState& getState() const override; - LayerCompositionState& editState() override; + const LayerFECompositionState& getFEState() const override; + LayerFECompositionState& editFEState() override; void dump(std::string& result) const override; @@ -50,7 +50,8 @@ private: const compositionengine::CompositionEngine& mCompositionEngine; const wp mLayerFE; - LayerCompositionState mState; + // State obtained from calls to LayerFE::getCompositionState + LayerFECompositionState mFrontEndState; }; std::shared_ptr createLayer(const compositionengine::CompositionEngine&, diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h deleted file mode 100644 index 726c850780..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/LayerCompositionState.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include -#include - -#include -#include -#include - -namespace android { - -namespace compositionengine::impl { - -struct LayerCompositionState { - /* - * State set by LayerFE::getCompositionState - */ - - LayerFECompositionState frontEnd; - - // Debugging - void dump(std::string& result) const; -}; - -} // namespace compositionengine::impl -} // namespace android diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h index cce3b97bbd..4f03cb46ae 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h @@ -18,7 +18,7 @@ #include #include -#include +#include #include namespace android::compositionengine::mock { @@ -30,8 +30,8 @@ public: MOCK_CONST_METHOD0(getLayerFE, sp()); - MOCK_CONST_METHOD0(getState, const CompositionState&()); - MOCK_METHOD0(editState, CompositionState&()); + MOCK_CONST_METHOD0(getFEState, const LayerFECompositionState&()); + MOCK_METHOD0(editFEState, LayerFECompositionState&()); MOCK_CONST_METHOD1(dump, void(std::string&)); }; diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 713266ff85..8391458e99 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -103,8 +103,8 @@ void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) { for (auto& layer : output->getOutputLayersOrderedByZ()) { if (layer->isHardwareCursor()) { // Latch the cursor composition state from each front-end layer. - layer->getLayerFE().latchCursorCompositionState( - layer->getLayer().editState().frontEnd); + layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState()); + layer->writeCursorPositionToHWC(); } } diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp index 96e9731768..8a1cbe409b 100644 --- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp @@ -43,19 +43,21 @@ sp Layer::getLayerFE() const { return mLayerFE.promote(); } -const LayerCompositionState& Layer::getState() const { - return mState; +const compositionengine::LayerFECompositionState& Layer::getFEState() const { + return mFrontEndState; } -LayerCompositionState& Layer::editState() { - return mState; +compositionengine::LayerFECompositionState& Layer::editFEState() { + return mFrontEndState; } void Layer::dump(std::string& out) const { auto layerFE = getLayerFE(); android::base::StringAppendF(&out, "* compositionengine::Layer %p (%s)\n", this, layerFE ? layerFE->getDebugName() : ""); - mState.dump(out); + + out.append(" frontend:\n"); + mFrontEndState.dump(out); } } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp deleted file mode 100644 index c5debf6e77..0000000000 --- a/services/surfaceflinger/CompositionEngine/src/LayerCompositionState.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#include -#include -#include - -namespace android::compositionengine::impl { - -namespace { - -using android::compositionengine::impl::dumpVal; - -void dumpVal(std::string& out, const char* name, half4 value) { - using android::base::StringAppendF; - StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), - static_cast(value.g), static_cast(value.b)); -} - -void dumpFrontEnd(std::string& out, const LayerFECompositionState& state) { - out.append(" "); - dumpVal(out, "isSecure", state.isSecure); - dumpVal(out, "geomUsesSourceCrop", state.geomUsesSourceCrop); - dumpVal(out, "geomBufferUsesDisplayInverseTransform", - state.geomBufferUsesDisplayInverseTransform); - dumpVal(out, "geomLayerTransform", state.geomLayerTransform); - - out.append("\n "); - dumpVal(out, "geomBufferSize", state.geomBufferSize); - dumpVal(out, "geomContentCrop", state.geomContentCrop); - dumpVal(out, "geomCrop", state.geomCrop); - dumpVal(out, "geomBufferTransform", state.geomBufferTransform); - - out.append("\n "); - dumpVal(out, "transparentRegionHint", state.transparentRegionHint); - - out.append(" "); - dumpVal(out, "geomLayerBounds", state.geomLayerBounds); - - out.append("\n "); - dumpVal(out, "blend", toString(state.blendMode), state.blendMode); - dumpVal(out, "alpha", state.alpha); - - out.append("\n "); - dumpVal(out, "type", state.type); - dumpVal(out, "appId", state.appId); - - dumpVal(out, "composition type", toString(state.compositionType), state.compositionType); - - out.append("\n buffer: "); - dumpVal(out, "bufferSlot", state.bufferSlot); - dumpVal(out, "buffer", state.buffer.get()); - - out.append("\n "); - dumpVal(out, "sideband stream", state.sidebandStream.get()); - - out.append("\n "); - dumpVal(out, "color", state.color); - - out.append("\n "); - dumpVal(out, "isOpaque", state.isOpaque); - dumpVal(out, "hasProtectedContent", state.hasProtectedContent); - dumpVal(out, "isColorspaceAgnostic", state.isColorspaceAgnostic); - dumpVal(out, "dataspace", toString(state.dataspace), state.dataspace); - dumpVal(out, "hdr metadata types", state.hdrMetadata.validTypes); - dumpVal(out, "colorTransform", state.colorTransform); - - out.append("\n"); -} - -} // namespace - -void LayerCompositionState::dump(std::string& out) const { - out.append(" frontend:\n"); - dumpFrontEnd(out, frontEnd); -} - -} // namespace android::compositionengine::impl diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp new file mode 100644 index 0000000000..1ca03dca5f --- /dev/null +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -0,0 +1,85 @@ +/* + * Copyright 2019 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. + */ + +#include +#include +#include + +namespace android::compositionengine { + +namespace { + +using android::compositionengine::impl::dumpVal; + +void dumpVal(std::string& out, const char* name, half4 value) { + using android::base::StringAppendF; + StringAppendF(&out, "%s=[%f %f %f] ", name, static_cast(value.r), + static_cast(value.g), static_cast(value.b)); +} + +} // namespace + +void LayerFECompositionState::dump(std::string& out) const { + out.append(" "); + dumpVal(out, "isSecure", isSecure); + dumpVal(out, "geomUsesSourceCrop", geomUsesSourceCrop); + dumpVal(out, "geomBufferUsesDisplayInverseTransform", geomBufferUsesDisplayInverseTransform); + dumpVal(out, "geomLayerTransform", geomLayerTransform); + + out.append("\n "); + dumpVal(out, "geomBufferSize", geomBufferSize); + dumpVal(out, "geomContentCrop", geomContentCrop); + dumpVal(out, "geomCrop", geomCrop); + dumpVal(out, "geomBufferTransform", geomBufferTransform); + + out.append("\n "); + dumpVal(out, "transparentRegionHint", transparentRegionHint); + + out.append(" "); + dumpVal(out, "geomLayerBounds", geomLayerBounds); + + out.append("\n "); + dumpVal(out, "blend", toString(blendMode), blendMode); + dumpVal(out, "alpha", alpha); + + out.append("\n "); + dumpVal(out, "type", type); + dumpVal(out, "appId", appId); + + dumpVal(out, "composition type", toString(compositionType), compositionType); + + out.append("\n buffer: "); + dumpVal(out, "slot", bufferSlot); + dumpVal(out, "buffer", buffer.get()); + + out.append("\n "); + dumpVal(out, "sideband stream", sidebandStream.get()); + + out.append("\n "); + dumpVal(out, "color", color); + + out.append("\n "); + dumpVal(out, "isOpaque", isOpaque); + dumpVal(out, "hasProtectedContent", hasProtectedContent); + dumpVal(out, "isColorspaceAgnostic", isColorspaceAgnostic); + dumpVal(out, "dataspace", toString(dataspace), dataspace); + dumpVal(out, "hdr metadata types", hdrMetadata.validTypes); + dumpVal(out, "colorTransform", colorTransform); + + out.append("\n"); +} + +} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 83df628f25..02ebc1fc4f 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -22,8 +22,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -249,7 +249,7 @@ bool Output::belongsInOutput(const compositionengine::Layer* layer) const { return false; } - const auto& layerFEState = layer->getState().frontEnd; + const auto& layerFEState = layer->getFEState(); return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly); } @@ -400,12 +400,12 @@ std::unique_ptr Output::getOutputLayerIfVisible( // appear on multiple outputs. if (!coverage.latchedLayers.count(layerFE)) { coverage.latchedLayers.insert(layerFE); - layerFE->latchCompositionState(layer->editState().frontEnd, + layerFE->latchCompositionState(layer->editFEState(), compositionengine::LayerFE::StateSubset::BasicGeometry); } // Obtain a read-only reference to the front-end layer state - const auto& layerFEState = layer->getState().frontEnd; + const auto& layerFEState = layer->getFEState(); // Only consider the layers on the given layer stack if (!belongsInOutput(layer.get())) { @@ -572,7 +572,7 @@ void Output::setReleasedLayers(const compositionengine::CompositionRefreshArgs&) void Output::updateLayerStateFromFE(const CompositionRefreshArgs& args) const { for (auto& layer : mOutputLayersOrderedByZ) { - layer->getLayerFE().latchCompositionState(layer->getLayer().editState().frontEnd, + layer->getLayerFE().latchCompositionState(layer->getLayer().editFEState(), args.updatingGeometryThisFrame ? LayerFE::StateSubset::GeometryAndContent : LayerFE::StateSubset::Content); @@ -615,7 +615,7 @@ ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, *outHdrDataSpace = ui::Dataspace::UNKNOWN; for (const auto& layer : mOutputLayersOrderedByZ) { - switch (layer->getLayer().getState().frontEnd.dataspace) { + switch (layer->getLayer().getFEState().dataspace) { case ui::Dataspace::V0_SCRGB: case ui::Dataspace::V0_SCRGB_LINEAR: case ui::Dataspace::BT2020: @@ -631,8 +631,7 @@ ui::Dataspace Output::getBestDataspace(ui::Dataspace* outHdrDataSpace, case ui::Dataspace::BT2020_ITU_PQ: bestDataSpace = ui::Dataspace::DISPLAY_P3; *outHdrDataSpace = ui::Dataspace::BT2020_PQ; - *outIsHdrClientComposition = - layer->getLayer().getState().frontEnd.forceClientComposition; + *outIsHdrClientComposition = layer->getLayer().getFEState().forceClientComposition; break; case ui::Dataspace::BT2020_HLG: case ui::Dataspace::BT2020_ITU_HLG: @@ -838,7 +837,7 @@ std::optional Output::composeSurfaces(const Region& debugRegion bool needsProtected = std::any_of(mOutputLayersOrderedByZ.begin(), mOutputLayersOrderedByZ.end(), [](auto& layer) { - return layer->getLayer().getState().frontEnd.hasProtectedContent; + return layer->getLayer().getFEState().hasProtectedContent; }); if (needsProtected != renderEngine.isProtected()) { renderEngine.useProtectedContext(needsProtected); @@ -892,7 +891,7 @@ std::vector Output::generateClientCompositionReques for (auto& layer : mOutputLayersOrderedByZ) { const auto& layerState = layer->getState(); - const auto& layerFEState = layer->getLayer().getState().frontEnd; + const auto& layerFEState = layer->getLayer().getFEState(); auto& layerFE = layer->getLayerFE(); const Region clip(viewportRegion.intersect(layerState.visibleRegion)); diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 4eb256f94c..2e45953e5f 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -18,8 +18,8 @@ #include #include #include +#include #include -#include #include #include #include @@ -86,7 +86,7 @@ OutputLayerCompositionState& OutputLayer::editState() { } Rect OutputLayer::calculateInitialCrop() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); // apply the projection's clipping to the window crop in // layerstack space, and convert-back to layer space. @@ -119,7 +119,7 @@ Rect OutputLayer::calculateInitialCrop() const { } FloatRect OutputLayer::calculateOutputSourceCrop() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); if (!layerState.geomUsesSourceCrop) { @@ -196,7 +196,7 @@ FloatRect OutputLayer::calculateOutputSourceCrop() const { } Rect OutputLayer::calculateOutputDisplayFrame() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); // apply the layer's transform, followed by the display's global transform @@ -243,7 +243,7 @@ Rect OutputLayer::calculateOutputDisplayFrame() const { } uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { - const auto& layerState = mLayer->getState().frontEnd; + const auto& layerState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); /* @@ -283,7 +283,7 @@ uint32_t OutputLayer::calculateOutputRelativeBufferTransform() const { } // namespace impl void OutputLayer::updateCompositionState(bool includeGeometry) { - const auto& layerFEState = mLayer->getState().frontEnd; + const auto& layerFEState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); const auto& profile = *mOutput.getDisplayColorProfile(); @@ -327,7 +327,7 @@ void OutputLayer::writeStateToHWC(bool includeGeometry) { return; } - const auto& outputIndependentState = mLayer->getState().frontEnd; + const auto& outputIndependentState = mLayer->getFEState(); auto requestedCompositionType = outputIndependentState.compositionType; if (includeGeometry) { @@ -544,7 +544,7 @@ void OutputLayer::writeCursorPositionToHWC() const { return; } - const auto& layerFEState = mLayer->getState().frontEnd; + const auto& layerFEState = mLayer->getFEState(); const auto& outputState = mOutput.getState(); Rect frame = layerFEState.cursorFrame; diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index b73c47ba17..88cedfa7ea 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -59,7 +59,7 @@ struct OutputLayerTest : public testing::Test { EXPECT_CALL(*mLayerFE, getDebugName()).WillRepeatedly(Return("Test LayerFE")); EXPECT_CALL(mOutput, getName()).WillRepeatedly(ReturnRef(kOutputName)); - EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); } @@ -70,7 +70,7 @@ struct OutputLayerTest : public testing::Test { new StrictMock()}; impl::OutputLayer mOutputLayer{mOutput, mLayer, mLayerFE}; - impl::LayerCompositionState mLayerState; + LayerFECompositionState mLayerFEState; impl::OutputCompositionState mOutputState; }; @@ -112,27 +112,26 @@ struct OutputLayerSourceCropTest : public OutputLayerTest { OutputLayerSourceCropTest() { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.geomUsesSourceCrop = true; - mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.transparentRegionHint = Region{}; - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; - mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomBufferTransform = TR_IDENT; + mLayerFEState.geomUsesSourceCrop = true; + mLayerFEState.geomContentCrop = Rect{0, 0, 1920, 1080}; + mLayerFEState.transparentRegionHint = Region{}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerFEState.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerFEState.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomBufferTransform = TR_IDENT; mOutputState.viewport = Rect{0, 0, 1920, 1080}; } FloatRect calculateOutputSourceCrop() { - mLayerState.frontEnd.geomInverseLayerTransform = - mLayerState.frontEnd.geomLayerTransform.inverse(); + mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse(); return mOutputLayer.calculateOutputSourceCrop(); } }; TEST_F(OutputLayerSourceCropTest, computesEmptyIfSourceCropNotUsed) { - mLayerState.frontEnd.geomUsesSourceCrop = false; + mLayerFEState.geomUsesSourceCrop = false; const FloatRect expected{}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -144,15 +143,15 @@ TEST_F(OutputLayerSourceCropTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewport) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; const FloatRect expected{0.f, 0.f, 1920.f, 1080.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); } TEST_F(OutputLayerSourceCropTest, handlesBoundsOutsideViewportRotated) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; - mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + mLayerFEState.geomLayerBounds = FloatRect{-2000.f, -2000.f, 2000.f, 2000.f}; + mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); const FloatRect expected{0.f, 0.f, 1080.f, 1080.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -190,8 +189,8 @@ TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformed for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomBufferUsesDisplayInverseTransform = entry.bufferInvDisplay; + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(entry.expected)) << "entry " << i; @@ -199,7 +198,7 @@ TEST_F(OutputLayerSourceCropTest, calculateOutputSourceCropWorksWithATransformed } TEST_F(OutputLayerSourceCropTest, geomContentCropAffectsCrop) { - mLayerState.frontEnd.geomContentCrop = Rect{0, 0, 960, 540}; + mLayerFEState.geomContentCrop = Rect{0, 0, 960, 540}; const FloatRect expected{0.f, 0.f, 960.f, 540.f}; EXPECT_THAT(calculateOutputSourceCrop(), FloatRectEq(expected)); @@ -221,20 +220,19 @@ struct OutputLayerDisplayFrameTest : public OutputLayerTest { // Set reasonable default values for a simple case. Each test will // set one specific value to something different. - mLayerState.frontEnd.transparentRegionHint = Region{}; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{TR_IDENT}; - mLayerState.frontEnd.geomBufferSize = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; - mLayerState.frontEnd.geomCrop = Rect{0, 0, 1920, 1080}; - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; + mLayerFEState.transparentRegionHint = Region{}; + mLayerFEState.geomLayerTransform = ui::Transform{TR_IDENT}; + mLayerFEState.geomBufferSize = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomBufferUsesDisplayInverseTransform = false; + mLayerFEState.geomCrop = Rect{0, 0, 1920, 1080}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 1920.f, 1080.f}; mOutputState.viewport = Rect{0, 0, 1920, 1080}; mOutputState.transform = ui::Transform{TR_IDENT}; } Rect calculateOutputDisplayFrame() { - mLayerState.frontEnd.geomInverseLayerTransform = - mLayerState.frontEnd.geomLayerTransform.inverse(); + mLayerFEState.geomInverseLayerTransform = mLayerFEState.geomLayerTransform.inverse(); return mOutputLayer.calculateOutputDisplayFrame(); } @@ -246,32 +244,32 @@ TEST_F(OutputLayerDisplayFrameTest, correctForSimpleDefaultCase) { } TEST_F(OutputLayerDisplayFrameTest, fullActiveTransparentRegionReturnsEmptyFrame) { - mLayerState.frontEnd.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; + mLayerFEState.transparentRegionHint = Region{Rect{0, 0, 1920, 1080}}; const Rect expected{0, 0, 0, 0}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrame) { - mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; + mLayerFEState.geomCrop = Rect{100, 200, 300, 500}; const Rect expected{100, 200, 300, 500}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, cropAffectsDisplayFrameRotated) { - mLayerState.frontEnd.geomCrop = Rect{100, 200, 300, 500}; - mLayerState.frontEnd.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); + mLayerFEState.geomCrop = Rect{100, 200, 300, 500}; + mLayerFEState.geomLayerTransform.set(HAL_TRANSFORM_ROT_90, 1920, 1080); const Rect expected{1420, 100, 1720, 300}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, emptyGeomCropIsNotUsedToComputeFrame) { - mLayerState.frontEnd.geomCrop = Rect{}; + mLayerFEState.geomCrop = Rect{}; const Rect expected{0, 0, 1920, 1080}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } TEST_F(OutputLayerDisplayFrameTest, geomLayerBoundsAffectsFrame) { - mLayerState.frontEnd.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; + mLayerFEState.geomLayerBounds = FloatRect{0.f, 0.f, 960.f, 540.f}; const Rect expected{0, 0, 960, 540}; EXPECT_THAT(calculateOutputDisplayFrame(), RectEq(expected)); } @@ -293,7 +291,7 @@ TEST_F(OutputLayerDisplayFrameTest, outputTransformAffectsDisplayFrame) { */ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = false; + mLayerFEState.geomBufferUsesDisplayInverseTransform = false; struct Entry { uint32_t layer; @@ -340,8 +338,8 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomLayerTransform.set(entry.layer, 1920, 1080); - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomLayerTransform.set(entry.layer, 1920, 1080); + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); @@ -351,7 +349,7 @@ TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestsNeeded) { TEST_F(OutputLayerTest, calculateOutputRelativeBufferTransformTestWithOfBufferUsesDisplayInverseTransform) { - mLayerState.frontEnd.geomBufferUsesDisplayInverseTransform = true; + mLayerFEState.geomBufferUsesDisplayInverseTransform = true; struct Entry { uint32_t layer; @@ -398,8 +396,8 @@ TEST_F(OutputLayerTest, for (size_t i = 0; i < testData.size(); i++) { const auto& entry = testData[i]; - mLayerState.frontEnd.geomLayerTransform = ui::Transform{entry.layer}; - mLayerState.frontEnd.geomBufferTransform = entry.buffer; + mLayerFEState.geomLayerTransform = ui::Transform{entry.layer}; + mLayerFEState.geomBufferTransform = entry.buffer; mOutputState.orientation = entry.display; auto actual = mOutputLayer.calculateOutputRelativeBufferTransform(); @@ -425,7 +423,7 @@ struct OutputLayerPartialMockForUpdateCompositionState : public impl::OutputLaye struct OutputLayerUpdateCompositionStateTest : public OutputLayerTest { public: OutputLayerUpdateCompositionStateTest() { - EXPECT_CALL(*mLayer, getState()).WillRepeatedly(ReturnRef(mLayerState)); + EXPECT_CALL(*mLayer, getFEState()).WillRepeatedly(ReturnRef(mLayerFEState)); EXPECT_CALL(mOutput, getState()).WillRepeatedly(ReturnRef(mOutputState)); EXPECT_CALL(mOutput, getDisplayColorProfile()) .WillRepeatedly(Return(&mDisplayColorProfile)); @@ -458,7 +456,7 @@ public: }; TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = true; setupGeometryChildCallValues(); @@ -472,7 +470,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsStateNormally) { TEST_F(OutputLayerUpdateCompositionStateTest, alsoSetsForceCompositionIfSecureLayerOnNonsecureOutput) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = false; setupGeometryChildCallValues(); @@ -486,7 +484,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, TEST_F(OutputLayerUpdateCompositionStateTest, alsoSetsForceCompositionIfUnsupportedBufferTransform) { - mLayerState.frontEnd.isSecure = true; + mLayerFEState.isSecure = true; mOutputState.isSecure = true; mBufferTransform = ui::Transform::ROT_INVALID; @@ -501,12 +499,12 @@ TEST_F(OutputLayerUpdateCompositionStateTest, } TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly) { - mLayerState.frontEnd.dataspace = ui::Dataspace::DISPLAY_P3; + mLayerFEState.dataspace = ui::Dataspace::DISPLAY_P3; mOutputState.targetDataspace = ui::Dataspace::V0_SCRGB; // If the layer is not colorspace agnostic, the output layer dataspace // should use the layers requested colorspace. - mLayerState.frontEnd.isColorspaceAgnostic = false; + mLayerFEState.isColorspaceAgnostic = false; mOutputLayer.updateCompositionState(false); @@ -514,7 +512,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, setsOutputLayerColorspaceCorrectly // If the layer is colorspace agnostic, the output layer dataspace // should use the colorspace chosen for the whole output. - mLayerState.frontEnd.isColorspaceAgnostic = true; + mLayerFEState.isColorspaceAgnostic = true; mOutputLayer.updateCompositionState(false); @@ -528,7 +526,7 @@ TEST_F(OutputLayerUpdateCompositionStateTest, doesNotRecomputeGeometryIfNotReque } TEST_F(OutputLayerUpdateCompositionStateTest, clientCompositionForcedFromFrontEndFlagAtAnyTime) { - mLayerState.frontEnd.forceClientComposition = true; + mLayerFEState.forceClientComposition = true; mOutputLayer.updateCompositionState(false); @@ -583,18 +581,18 @@ struct OutputLayerWriteStateToHWCTest : public OutputLayerTest { outputLayerState.outputSpaceVisibleRegion = kOutputSpaceVisibleRegion; outputLayerState.dataspace = kDataspace; - mLayerState.frontEnd.blendMode = kBlendMode; - mLayerState.frontEnd.alpha = kAlpha; - mLayerState.frontEnd.type = kType; - mLayerState.frontEnd.appId = kAppId; - mLayerState.frontEnd.colorTransform = kColorTransform; - mLayerState.frontEnd.color = kColor; - mLayerState.frontEnd.surfaceDamage = kSurfaceDamage; - mLayerState.frontEnd.hdrMetadata = kHdrMetadata; - mLayerState.frontEnd.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); - mLayerState.frontEnd.buffer = kBuffer; - mLayerState.frontEnd.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; - mLayerState.frontEnd.acquireFence = kFence; + mLayerFEState.blendMode = kBlendMode; + mLayerFEState.alpha = kAlpha; + mLayerFEState.type = kType; + mLayerFEState.appId = kAppId; + mLayerFEState.colorTransform = kColorTransform; + mLayerFEState.color = kColor; + mLayerFEState.surfaceDamage = kSurfaceDamage; + mLayerFEState.hdrMetadata = kHdrMetadata; + mLayerFEState.sidebandStream = NativeHandle::create(kSidebandStreamHandle, false); + mLayerFEState.buffer = kBuffer; + mLayerFEState.bufferSlot = BufferQueue::INVALID_BUFFER_SLOT; + mLayerFEState.acquireFence = kFence; EXPECT_CALL(mOutput, getDisplayColorProfile()) .WillRepeatedly(Return(&mDisplayColorProfile)); @@ -698,7 +696,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetAllState) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -708,7 +706,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSolidColor) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; expectPerFrameCommonCalls(); expectSetSidebandHandleCall(); @@ -718,7 +716,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForSideband) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::CURSOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::CURSOR; expectPerFrameCommonCalls(); expectSetHdrMetadataAndBufferCalls(); @@ -728,7 +726,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForCursor) { } TEST_F(OutputLayerWriteStateToHWCTest, canSetPerFrameStateForDevice) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::DEVICE; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::DEVICE; expectPerFrameCommonCalls(); expectSetHdrMetadataAndBufferCalls(); @@ -741,7 +739,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { (*mOutputLayer.editState().hwc).hwcCompositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -751,7 +749,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsNotSetIfUnchanged) { } TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransformNotSupported) { - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(SimulateUnsupported::ColorTransform); expectSetColorCall(); @@ -763,7 +761,7 @@ TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfColorTransf TEST_F(OutputLayerWriteStateToHWCTest, compositionTypeIsSetToClientIfClientCompositionForced) { mOutputLayer.editState().forceClientComposition = true; - mLayerState.frontEnd.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + mLayerFEState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; expectPerFrameCommonCalls(); expectSetColorCall(); @@ -787,7 +785,7 @@ struct OutputLayerWriteCursorPositionToHWCTest : public OutputLayerTest { auto& outputLayerState = mOutputLayer.editState(); outputLayerState.hwc = impl::OutputLayerCompositionState::Hwc(mHwcLayer); - mLayerState.frontEnd.cursorFrame = kDefaultCursorFrame; + mLayerFEState.cursorFrame = kDefaultCursorFrame; mOutputState.viewport = kDefaultDisplayViewport; mOutputState.transform = ui::Transform{kDefaultTransform}; @@ -812,7 +810,7 @@ TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCWritesSt } TEST_F(OutputLayerWriteCursorPositionToHWCTest, writeCursorPositionToHWCIntersectedWithViewport) { - mLayerState.frontEnd.cursorFrame = Rect{3000, 3000, 3016, 3016}; + mLayerFEState.cursorFrame = Rect{3000, 3000, 3016, 3016}; EXPECT_CALL(*mHwcLayer, setCursorPosition(1920, 1080)).WillOnce(Return(kDefaultError)); diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index a0b8017264..70c343bba6 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -16,7 +16,7 @@ #include -#include +#include #include #include #include @@ -378,9 +378,9 @@ TEST_F(OutputTest, belongsInOutputFiltersAsExpected) { TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { StrictMock layer; - impl::LayerCompositionState layerState; + LayerFECompositionState layerFEState; - EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(layerState)); + EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); const uint32_t layerStack1 = 123u; const uint32_t layerStack2 = 456u; @@ -392,29 +392,29 @@ TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { EXPECT_FALSE(mOutput.belongsInOutput(nullptr)); // A layer with no layerStack does not belong to it, internal-only or not. - layerState.frontEnd.layerStackId = std::nullopt; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = std::nullopt; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = std::nullopt; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = std::nullopt; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); // Any layer with layerStack1 belongs to it, internal-only or not. - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = false; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = true; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); // If the output accepts layerStack1 but not internal-only layers... @@ -424,20 +424,20 @@ TEST_F(OutputTest, belongsInOutputFiltersLayersAsExpected) { EXPECT_FALSE(mOutput.belongsInOutput(nullptr)); // Only non-internal layers with layerStack1 belong to it. - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = false; EXPECT_TRUE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack1; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack1; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = true; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = true; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); - layerState.frontEnd.layerStackId = layerStack2; - layerState.frontEnd.internalOnly = false; + layerFEState.layerStackId = layerStack2; + layerFEState.internalOnly = false; EXPECT_FALSE(mOutput.belongsInOutput(&layer)); } @@ -732,8 +732,8 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) leftOutputLayerState.clearClientTarget = false; leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; - impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.isOpaque = true; + LayerFECompositionState leftLayerFEState; + leftLayerFEState.isOpaque = true; const half3 leftLayerColor{1.f, 0.f, 0.f}; renderengine::LayerSettings leftLayerRESettings; @@ -743,8 +743,8 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) rightOutputLayerState.clearClientTarget = false; rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; - impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.isOpaque = true; + LayerFECompositionState rightLayerFEState; + rightLayerFEState.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; renderengine::LayerSettings rightLayerRESettings; @@ -755,7 +755,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE)); EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(leftLayer, getState()).WillRepeatedly(ReturnRef(leftLayerState)); + EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(leftLayerFE, prepareClientComposition(_)).WillOnce(Return(leftLayerRESettings)); EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); @@ -763,7 +763,7 @@ TEST_F(GenerateClientCompositionRequestsTest, worksForLandscapeModeSplitScreen) EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE)); EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(rightLayer, getState()).WillRepeatedly(ReturnRef(rightLayerState)); + EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); Output::OutputLayers outputLayers; @@ -806,15 +806,15 @@ TEST_F(GenerateClientCompositionRequestsTest, ignoresLayersThatDoNotIntersectWit outputLayerState.clearClientTarget = false; outputLayerState.visibleRegion = Region{Rect{3000, 0, 4000, 1000}}; - impl::LayerCompositionState layerState; - layerState.frontEnd.isOpaque = true; + LayerFECompositionState layerFEState; + layerFEState.isOpaque = true; EXPECT_CALL(*outputLayer, getState()).WillRepeatedly(ReturnRef(outputLayerState)); EXPECT_CALL(*outputLayer, getLayer()).WillRepeatedly(ReturnRef(layer)); EXPECT_CALL(*outputLayer, getLayerFE()).WillRepeatedly(ReturnRef(layerFE)); EXPECT_CALL(*outputLayer, requiresClientComposition()).WillRepeatedly(Return(true)); EXPECT_CALL(*outputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(layer, getState()).WillRepeatedly(ReturnRef(layerState)); + EXPECT_CALL(layer, getFEState()).WillRepeatedly(ReturnRef(layerFEState)); EXPECT_CALL(layerFE, prepareClientComposition(_)).Times(0); Output::OutputLayers outputLayers; @@ -861,15 +861,15 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { leftOutputLayerState.clearClientTarget = true; leftOutputLayerState.visibleRegion = Region{Rect{0, 0, 1000, 1000}}; - impl::LayerCompositionState leftLayerState; - leftLayerState.frontEnd.isOpaque = true; + LayerFECompositionState leftLayerFEState; + leftLayerFEState.isOpaque = true; impl::OutputLayerCompositionState rightOutputLayerState; rightOutputLayerState.clearClientTarget = true; rightOutputLayerState.visibleRegion = Region{Rect{1000, 0, 2000, 1000}}; - impl::LayerCompositionState rightLayerState; - rightLayerState.frontEnd.isOpaque = true; + LayerFECompositionState rightLayerFEState; + rightLayerFEState.isOpaque = true; const half3 rightLayerColor{0.f, 1.f, 0.f}; renderengine::LayerSettings rightLayerRESettings; @@ -881,14 +881,14 @@ TEST_F(GenerateClientCompositionRequestsTest, clearsDeviceLayesAfterFirst) { EXPECT_CALL(*leftOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(leftLayerFE)); EXPECT_CALL(*leftOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(*leftOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(leftLayer, getState()).WillRepeatedly(ReturnRef(leftLayerState)); + EXPECT_CALL(leftLayer, getFEState()).WillRepeatedly(ReturnRef(leftLayerFEState)); EXPECT_CALL(*rightOutputLayer, getState()).WillRepeatedly(ReturnRef(rightOutputLayerState)); EXPECT_CALL(*rightOutputLayer, getLayer()).WillRepeatedly(ReturnRef(rightLayer)); EXPECT_CALL(*rightOutputLayer, getLayerFE()).WillRepeatedly(ReturnRef(rightLayerFE)); EXPECT_CALL(*rightOutputLayer, requiresClientComposition()).WillRepeatedly(Return(false)); EXPECT_CALL(*rightOutputLayer, needsFiltering()).WillRepeatedly(Return(false)); - EXPECT_CALL(rightLayer, getState()).WillRepeatedly(ReturnRef(rightLayerState)); + EXPECT_CALL(rightLayer, getFEState()).WillRepeatedly(ReturnRef(rightLayerFEState)); EXPECT_CALL(rightLayerFE, prepareClientComposition(_)).WillOnce(Return(rightLayerRESettings)); Output::OutputLayers outputLayers; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index bed33a71d0..7b708bccae 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -27,7 +27,6 @@ #include #include #include -#include #include #include #include diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index cc12608e87..15550799bf 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -41,12 +41,9 @@ #include #include #include -#include #include #include -#include #include -#include #include #include #include diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index d0d391b679..b77f82a7f8 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -18,9 +18,9 @@ #include #include +#include #include #include -#include #include #include "BufferQueueLayer.h" @@ -235,7 +235,7 @@ public: void setLayerSidebandStream(sp layer, sp sidebandStream) { layer->mDrawingState.sidebandStream = sidebandStream; layer->mSidebandStream = sidebandStream; - layer->getCompositionLayer()->editState().frontEnd.sidebandStream = sidebandStream; + layer->getCompositionLayer()->editFEState().sidebandStream = sidebandStream; } void setLayerCompositionType(sp layer, HWC2::Composition type) { -- cgit v1.2.3-59-g8ed1b From b4c6e5850f16d045abcb4e3308b7556749a61be0 Mon Sep 17 00:00:00 2001 From: chaviw Date: Fri, 16 Aug 2019 14:35:07 -0700 Subject: [Mirror Layers] Added clone function to layers (1/4) Added a cloning function to each layer in preparation for mirroring Test: Nothing to test yet since no calls Bug: 131622422 Change-Id: Iba0692b75c4d99841de48f40ed55b3dbccf2b9b9 --- services/surfaceflinger/BufferLayer.cpp | 19 +++++++++++++-- services/surfaceflinger/BufferLayer.h | 1 + services/surfaceflinger/BufferQueueLayer.cpp | 20 ++++++++++------ services/surfaceflinger/BufferQueueLayer.h | 2 ++ services/surfaceflinger/BufferStateLayer.cpp | 27 ++++++++++++++-------- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 8 +++++++ services/surfaceflinger/ColorLayer.h | 2 ++ services/surfaceflinger/ContainerLayer.cpp | 7 ++++++ services/surfaceflinger/ContainerLayer.h | 3 +++ services/surfaceflinger/Layer.cpp | 9 ++++++++ services/surfaceflinger/Layer.h | 15 ++++++++++++ services/surfaceflinger/SurfaceFlinger.cpp | 21 +++++++++++++---- .../tests/unittests/CompositionTest.cpp | 13 +++++++---- 14 files changed, 121 insertions(+), 28 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index fba235d397..d189846dd5 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -58,7 +58,7 @@ namespace android { BufferLayer::BufferLayer(const LayerCreationArgs& args) : Layer(args), - mTextureName(args.flinger->getNewTexture()), + mTextureName(args.textureName), mCompositionLayer{mFlinger->getCompositionEngine().createLayer( compositionengine::LayerCreationArgs{this})} { ALOGV("Creating Layer %s", args.name.string()); @@ -70,7 +70,13 @@ BufferLayer::BufferLayer(const LayerCreationArgs& args) } BufferLayer::~BufferLayer() { - mFlinger->deleteTextureAsync(mTextureName); + if (!isClone()) { + // The original layer and the clone layer share the same texture. Therefore, only one of + // the layers, in this case the original layer, needs to handle the deletion. The original + // layer and the clone should be removed at the same time so there shouldn't be any issue + // with the clone layer trying to use the deleted texture. + mFlinger->deleteTextureAsync(mTextureName); + } const int32_t layerID = getSequence(); mFlinger->mTimeStats->onDestroy(layerID); mFlinger->mFrameTracer->onDestroy(layerID); @@ -722,6 +728,15 @@ void BufferLayer::getDrawingTransformMatrix(bool filteringEnabled, float outMatr mBufferInfo.mTransform, filteringEnabled); } +void BufferLayer::setInitialValuesForClone(const sp& clonedFrom) { + Layer::setInitialValuesForClone(clonedFrom); + + sp bufferClonedFrom = static_cast(clonedFrom.get()); + mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha; + mPotentialCursor = bufferClonedFrom->mPotentialCursor; + mProtectedByApp = bufferClonedFrom->mProtectedByApp; +} + } // namespace android #if defined(__gl_h_) diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index f0a30e319a..b2c06183a6 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -194,6 +194,7 @@ protected: bool mRefreshPending{false}; ui::Dataspace translateDataspace(ui::Dataspace dataspace); + void setInitialValuesForClone(const sp& clonedFrom); private: // Returns true if this layer requires filtering diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index fcabedf63e..eb13f658d9 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -461,12 +461,7 @@ void BufferQueueLayer::onFirstRef() { sp consumer; BufferQueue::createBufferQueue(&producer, &consumer, true); mProducer = new MonitoredProducer(producer, mFlinger, this); - { - // Grab the SF state lock during this since it's the only safe way to access RenderEngine - Mutex::Autolock lock(mFlinger->mStateLock); - mConsumer = - new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); - } + mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); @@ -476,7 +471,7 @@ void BufferQueueLayer::onFirstRef() { mProducer->setMaxDequeuedBufferCount(2); } - if (const auto display = mFlinger->getDefaultDisplayDevice()) { + if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) { updateTransformHint(display); } } @@ -531,4 +526,15 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); } +sp BufferQueueLayer::createClone() { + const String8 name = mName + " (Mirror)"; + LayerCreationArgs args = + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + args.textureName = mTextureName; + sp layer = new BufferQueueLayer(args); + layer->setInitialValuesForClone(this); + + return layer; +} + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 9374741ddb..36dff156e1 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -31,6 +31,7 @@ namespace android { */ class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { public: + // Only call while mStateLock is held explicit BufferQueueLayer(const LayerCreationArgs&); ~BufferQueueLayer() override; @@ -81,6 +82,7 @@ private: status_t updateFrameNumber(nsecs_t latchTime) override; void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + sp createClone() override; // ----------------------------------------------------------------------- // Interface implementation for BufferLayerConsumer::ContentsChangedListener diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index ad05bc8671..30fdbe14e8 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -48,10 +48,17 @@ BufferStateLayer::BufferStateLayer(const LayerCreationArgs& args) : BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) { mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW; mCurrentState.dataspace = ui::Dataspace::V0_SRGB; + if (const auto display = args.displayDevice) { + updateTransformHint(display); + } } BufferStateLayer::~BufferStateLayer() { - if (mBufferInfo.mBuffer != nullptr) { + // The original layer and the clone layer share the same texture and buffer. Therefore, only + // one of the layers, in this case the original layer, needs to handle the deletion. The + // original layer and the clone should be removed at the same time so there shouldn't be any + // issue with the clone layer trying to use the texture. + if (mBufferInfo.mBuffer != nullptr && !isClone()) { // Ensure that mBuffer is uncached from RenderEngine here, as // RenderEngine may have been using the buffer as an external texture // after the client uncached the buffer. @@ -545,14 +552,6 @@ void BufferStateLayer::latchPerFrameState( mFrameNumber++; } -void BufferStateLayer::onFirstRef() { - BufferLayer::onFirstRef(); - - if (const auto display = mFlinger->getDefaultDisplayDevice()) { - updateTransformHint(display); - } -} - void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) { std::lock_guard lock(mMutex); if (!clientCacheId.isValid()) { @@ -668,4 +667,14 @@ Rect BufferStateLayer::computeCrop(const State& s) { return s.crop; } +sp BufferStateLayer::createClone() { + const String8 name = mName + " (Mirror)"; + LayerCreationArgs args = + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + args.textureName = mTextureName; + sp layer = new BufferStateLayer(args); + layer->mHwcSlotGenerator = mHwcSlotGenerator; + layer->setInitialValuesForClone(this); + return layer; +} } // namespace android diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 52063fcc58..e951ccf97a 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -124,13 +124,13 @@ private: status_t updateFrameNumber(nsecs_t latchTime) override; void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + sp createClone() override; // Crop that applies to the buffer Rect computeCrop(const State& s); private: friend class SlotGenerationTest; - void onFirstRef() override; bool willPresentCurrentTransaction() const; static const std::array IDENTITY_MATRIX; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 99805d9da2..5b620543ac 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -107,6 +107,14 @@ ui::Dataspace ColorLayer::getDataSpace() const { return mDrawingState.dataspace; } +sp ColorLayer::createClone() { + String8 name = mName + " (Mirror)"; + sp layer = new ColorLayer( + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + layer->setInitialValuesForClone(this); + return layer; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 16921df356..634a80003a 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -50,6 +50,8 @@ protected: compositionengine::LayerFE::ClientCompositionTargetSettings&) override; std::shared_ptr mCompositionLayer; + + sp createClone() override; }; } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index 4a1130365a..cb50d9ff6d 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -30,4 +30,11 @@ bool ContainerLayer::isVisible() const { return false; } +sp ContainerLayer::createClone() { + String8 name = mName + " (Mirror)"; + sp layer = new ContainerLayer( + LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + layer->setInitialValuesForClone(this); + return layer; +} } // namespace android diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h index c3624f6d7d..b48d471bde 100644 --- a/services/surfaceflinger/ContainerLayer.h +++ b/services/surfaceflinger/ContainerLayer.h @@ -32,6 +32,9 @@ public: bool isVisible() const override; bool isCreatedFromMainThread() const override { return true; } + +protected: + sp createClone() override; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index ba948cfdbc..52a09b35d1 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -2015,6 +2015,15 @@ Region Layer::debugGetVisibleRegionOnDefaultDisplay() const { return outputLayer->getState().visibleRegion; } +void Layer::setInitialValuesForClone(const sp& clonedFrom) { + // copy drawing state from cloned layer + mDrawingState = clonedFrom->mDrawingState; + mClonedFrom = clonedFrom; + + // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple + // InputWindows per client token yet. + mDrawingState.inputInfo.token = nullptr; +} // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 8771ccd08e..96970ace89 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -91,6 +91,8 @@ struct LayerCreationArgs { LayerMetadata metadata; pid_t callingPid; uid_t callingUid; + sp displayDevice; + uint32_t textureName; }; class Layer : public compositionengine::LayerFE { @@ -465,6 +467,13 @@ public: virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; } virtual bool needsFiltering(const sp&) const { return false; } +protected: + virtual sp createClone() = 0; + sp getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; } + + bool isClone() { return getClonedFrom() != nullptr; } + virtual void setInitialValuesForClone(const sp& clonedFrom); + public: /* * compositionengine::LayerFE overrides @@ -912,6 +921,12 @@ private: // to help debugging. pid_t mCallingPid; uid_t mCallingUid; + + // The current layer is a clone of mClonedFrom. This means that this layer will update it's + // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers, + // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children, + // and relatives, this layer will update as well. + wp mClonedFrom; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 41afb5da55..e3cf84aa1a 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3532,8 +3532,18 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const break; } - sp layer = getFactory().createBufferQueueLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + sp layer; + LayerCreationArgs args = + LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + args.textureName = getNewTexture(); + { + // Grab the SF state lock during this since it's the only safe way to access + // RenderEngine when creating a BufferLayerConsumer + // TODO: Check if this lock is still needed here + Mutex::Autolock lock(mStateLock); + layer = getFactory().createBufferQueueLayer(args); + } + status_t err = layer->setDefaultBufferProperties(w, h, format); if (err == NO_ERROR) { *handle = layer->getHandle(); @@ -3549,8 +3559,11 @@ status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { - sp layer = getFactory().createBufferStateLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + LayerCreationArgs args = + LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + args.displayDevice = getDefaultDisplayDevice(); + args.textureName = getNewTexture(); + sp layer = getFactory().createBufferStateLayer(args); *handle = layer->getHandle(); *outLayer = layer; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 20dfed65e2..f29e2ddd33 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -883,11 +883,14 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { - return new BufferQueueLayer( - LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, - LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS, LayerMetadata())); + sp client; + String8 name("test-layer"); + LayerCreationArgs args = + LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name, + LayerProperties::WIDTH, LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS, LayerMetadata()); + args.textureName = test->mFlinger.mutableTexturePool().back(); + return new BufferQueueLayer(args); }); LayerProperties::setupLayerState(test, layer); -- cgit v1.2.3-59-g8ed1b From 1c3a5eb0a4adb44adce52ea4a7b2005d18dc86e6 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 3 Oct 2019 13:07:08 -0700 Subject: SF: Switch Layer::createClone to using the factory Using the factory ensures the intended actual types are used for the clone. Test: atest libsurfaceflinger_unittest Test: go/wm_smoke Bug: None Change-Id: I64138724aed2d8c61dc5d59bba247d132291da0c --- services/surfaceflinger/BufferQueueLayer.cpp | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 2 +- services/surfaceflinger/ColorLayer.cpp | 2 +- services/surfaceflinger/ContainerLayer.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index eb13f658d9..d80a70e4c6 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -531,7 +531,7 @@ sp BufferQueueLayer::createClone() { LayerCreationArgs args = LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; - sp layer = new BufferQueueLayer(args); + sp layer = mFlinger->getFactory().createBufferQueueLayer(args); layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index fa4539ab91..75fc0e9c06 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -673,7 +673,7 @@ sp BufferStateLayer::createClone() { LayerCreationArgs args = LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; - sp layer = new BufferStateLayer(args); + sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->mHwcSlotGenerator = mHwcSlotGenerator; layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 5b620543ac..172d44556a 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -109,7 +109,7 @@ ui::Dataspace ColorLayer::getDataSpace() const { sp ColorLayer::createClone() { String8 name = mName + " (Mirror)"; - sp layer = new ColorLayer( + sp layer = mFlinger->getFactory().createColorLayer( LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); layer->setInitialValuesForClone(this); return layer; diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index cb50d9ff6d..e58e6f425e 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -32,7 +32,7 @@ bool ContainerLayer::isVisible() const { sp ContainerLayer::createClone() { String8 name = mName + " (Mirror)"; - sp layer = new ContainerLayer( + sp layer = mFlinger->getFactory().createContainerLayer( LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); layer->setInitialValuesForClone(this); return layer; -- cgit v1.2.3-59-g8ed1b From 87a07e42dd60a748cbf82be7e82b07b0326ea469 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Thu, 10 Oct 2019 20:38:02 -0700 Subject: SF: Use std::string for layer names Bug: 130554049 Test: Build Change-Id: Id083a85fcb838da4138c39a55b12cf10ff0cdddb --- services/surfaceflinger/BufferLayer.cpp | 2 +- services/surfaceflinger/BufferQueueLayer.cpp | 16 ++-- services/surfaceflinger/BufferStateLayer.cpp | 8 +- services/surfaceflinger/ColorLayer.cpp | 8 +- services/surfaceflinger/ContainerLayer.cpp | 5 +- services/surfaceflinger/EventLog/EventLog.cpp | 27 +++--- services/surfaceflinger/EventLog/EventLog.h | 38 +++------ services/surfaceflinger/FrameTracker.cpp | 5 +- services/surfaceflinger/FrameTracker.h | 21 ++--- services/surfaceflinger/Layer.cpp | 45 +++++----- services/surfaceflinger/Layer.h | 11 ++- services/surfaceflinger/LayerRejecter.cpp | 7 +- services/surfaceflinger/LayerRejecter.h | 37 ++++---- services/surfaceflinger/RegionSamplingThread.cpp | 2 +- services/surfaceflinger/SurfaceFlinger.cpp | 98 +++++++++++----------- services/surfaceflinger/SurfaceFlinger.h | 14 ++-- services/surfaceflinger/SurfaceInterceptor.cpp | 6 +- services/surfaceflinger/SurfaceInterceptor.h | 1 - .../tests/unittests/CompositionTest.cpp | 10 +-- 19 files changed, 159 insertions(+), 202 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index b500ad3eee..603a9f7f70 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -61,7 +61,7 @@ BufferLayer::BufferLayer(const LayerCreationArgs& args) mTextureName(args.textureName), mCompositionLayer{mFlinger->getCompositionEngine().createLayer( compositionengine::LayerCreationArgs{this})} { - ALOGV("Creating Layer %s", args.name.string()); + ALOGV("Creating Layer %s", getDebugName()); mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d80a70e4c6..cd0d87cb82 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -62,7 +62,7 @@ std::vector BufferQueueLayer::getOccupancyHistory(boo std::vector history; status_t result = mConsumer->getOccupancyHistory(forceFlush, &history); if (result != NO_ERROR) { - ALOGW("[%s] Failed to obtain occupancy history (%d)", mName.string(), result); + ALOGW("[%s] Failed to obtain occupancy history (%d)", getDebugName(), result); return {}; } return history; @@ -110,7 +110,7 @@ bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { ALOGW_IF(!isPlausible, "[%s] Timestamp %" PRId64 " seems implausible " "relative to expectedPresent %" PRId64, - mName.string(), addedTime, expectedPresentTime); + getDebugName(), addedTime, expectedPresentTime); const bool isDue = addedTime < expectedPresentTime; return isDue || !isPlausible; @@ -225,7 +225,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t bool queuedBuffer = false; const int32_t layerID = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, - getProducerStickyTransform() != 0, mName.string(), mOverrideScalingMode, + getProducerStickyTransform() != 0, mName, mOverrideScalingMode, getTransformToDisplayInverse()); if (isRemovedFromCurrentState()) { @@ -398,7 +398,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); + ALOGE("[%s] Timed out waiting on callback", getDebugName()); } } @@ -426,7 +426,7 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { while (item.mFrameNumber != mLastFrameNumberReceived + 1) { status_t result = mQueueItemCondition.waitRelative(mQueueItemLock, ms2ns(500)); if (result != NO_ERROR) { - ALOGE("[%s] Timed out waiting on callback", mName.string()); + ALOGE("[%s] Timed out waiting on callback", getDebugName()); } } @@ -464,7 +464,7 @@ void BufferQueueLayer::onFirstRef() { mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); - mConsumer->setName(mName); + mConsumer->setName(String8(mName.data(), mName.size())); // BufferQueueCore::mMaxDequeuedBufferCount is default to 1 if (!mFlinger->isLayerTripleBufferingDisabled()) { @@ -527,9 +527,7 @@ void BufferQueueLayer::gatherBufferInfo() { } sp BufferQueueLayer::createClone() { - const String8 name = mName + " (Mirror)"; - LayerCreationArgs args = - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferQueueLayer(args); layer->setInitialValuesForClone(this); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 75fc0e9c06..6fe89c41b5 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -136,7 +136,7 @@ void BufferStateLayer::pushPendingState() { return; } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool BufferStateLayer::applyPendingStates(Layer::State* stateToCommit) { @@ -479,7 +479,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse (s.active.w != bufferWidth || s.active.h != bufferHeight)) { ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", - mName.string(), bufferWidth, bufferHeight, s.active.w, s.active.h); + getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); return BAD_VALUE; } @@ -669,9 +669,7 @@ Rect BufferStateLayer::computeCrop(const State& s) { } sp BufferStateLayer::createClone() { - const String8 name = mName + " (Mirror)"; - LayerCreationArgs args = - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()); + LayerCreationArgs args(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, LayerMetadata()); args.textureName = mTextureName; sp layer = mFlinger->getFactory().createBufferStateLayer(args); layer->mHwcSlotGenerator = mHwcSlotGenerator; diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 172d44556a..8bfa569eeb 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -108,13 +108,11 @@ ui::Dataspace ColorLayer::getDataSpace() const { } sp ColorLayer::createClone() { - String8 name = mName + " (Mirror)"; sp layer = mFlinger->getFactory().createColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, + LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } -// --------------------------------------------------------------------------- - -}; // namespace android +} // namespace android diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index e58e6f425e..ab664be5e2 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -31,10 +31,11 @@ bool ContainerLayer::isVisible() const { } sp ContainerLayer::createClone() { - String8 name = mName + " (Mirror)"; sp layer = mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, mName + " (Mirror)", 0, 0, 0, + LayerMetadata())); layer->setInitialValuesForClone(this); return layer; } + } // namespace android diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp index 365a0bd868..a532fc130f 100644 --- a/services/surfaceflinger/EventLog/EventLog.cpp +++ b/services/surfaceflinger/EventLog/EventLog.cpp @@ -17,13 +17,10 @@ #include #include #include -#include #include "EventLog.h" -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) @@ -31,11 +28,11 @@ ANDROID_SINGLETON_STATIC_INSTANCE(EventLog) EventLog::EventLog() { } -void EventLog::doLogFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations) { +void EventLog::doLogFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations) { EventLog::TagBuffer buffer(LOGTAG_SF_FRAME_DUR); buffer.startList(1 + numDurations); - buffer.writeString8(window); + buffer.writeString(name); for (size_t i = 0; i < numDurations; i++) { buffer.writeInt32(durations[i]); } @@ -43,10 +40,9 @@ void EventLog::doLogFrameDurations(const String8& window, buffer.log(); } -void EventLog::logFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations) { - EventLog::getInstance().doLogFrameDurations(window, durations, - numDurations); +void EventLog::logFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations) { + EventLog::getInstance().doLogFrameDurations(name, durations, numDurations); } // --------------------------------------------------------------------------- @@ -113,9 +109,9 @@ void EventLog::TagBuffer::writeInt64(int64_t value) { mPos += needed; } -void EventLog::TagBuffer::writeString8(const String8& value) { +void EventLog::TagBuffer::writeString(const std::string_view& value) { if (mOverflow) return; - const int32_t stringLen = value.length(); + const size_t stringLen = value.length(); const size_t needed = 1 + sizeof(int32_t) + stringLen; if (mPos + needed > STORAGE_MAX_SIZE) { mOverflow = true; @@ -123,11 +119,8 @@ void EventLog::TagBuffer::writeString8(const String8& value) { } mStorage[mPos + 0] = EVENT_TYPE_STRING; memcpy(&mStorage[mPos + 1], &stringLen, sizeof(int32_t)); - memcpy(&mStorage[mPos + 5], value.string(), stringLen); + memcpy(&mStorage[mPos + 5], value.data(), stringLen); mPos += needed; } -// --------------------------------------------------------------------------- -}// namespace android - -// --------------------------------------------------------------------------- +} // namespace android diff --git a/services/surfaceflinger/EventLog/EventLog.h b/services/surfaceflinger/EventLog/EventLog.h index efc5d70cd3..ee3587ef8a 100644 --- a/services/surfaceflinger/EventLog/EventLog.h +++ b/services/surfaceflinger/EventLog/EventLog.h @@ -14,24 +14,21 @@ * limitations under the License. */ -#include +#pragma once + #include #include -#ifndef ANDROID_SF_EVENTLOG_H -#define ANDROID_SF_EVENTLOG_H +#include +#include -// --------------------------------------------------------------------------- namespace android { -// --------------------------------------------------------------------------- - -class String8; class EventLog : public Singleton { public: - static void logFrameDurations(const String8& window, - const int32_t* durations, size_t numDurations); + static void logFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations); protected: EventLog(); @@ -54,18 +51,13 @@ private: public: explicit TagBuffer(int32_t tag); - // starts list of items void startList(int8_t count); - // terminates the list void endList(); - // write a 32-bit integer - void writeInt32(int32_t value); - // write a 64-bit integer - void writeInt64(int64_t value); - // write a C string - void writeString8(const String8& value); - // outputs the the buffer to the log + void writeInt32(int32_t); + void writeInt64(int64_t); + void writeString(const std::string_view&); + void log(); }; @@ -74,12 +66,8 @@ private: EventLog& operator =(const EventLog&); enum { LOGTAG_SF_FRAME_DUR = 60100 }; - void doLogFrameDurations(const String8& window, const int32_t* durations, - size_t numDurations); + void doLogFrameDurations(const std::string_view& name, const int32_t* durations, + size_t numDurations); }; -// --------------------------------------------------------------------------- -}// namespace android -// --------------------------------------------------------------------------- - -#endif /* ANDROID_SF_EVENTLOG_H */ +} // namespace android diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index f4cc49b851..a6e511e76e 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -21,7 +21,6 @@ #include #include -#include #include @@ -139,7 +138,7 @@ void FrameTracker::getStats(FrameStats* outStats) const { } } -void FrameTracker::logAndResetStats(const String8& name) { +void FrameTracker::logAndResetStats(const std::string_view& name) { Mutex::Autolock lock(mMutex); logStatsLocked(name); resetFrameCountersLocked(); @@ -217,7 +216,7 @@ void FrameTracker::resetFrameCountersLocked() { } } -void FrameTracker::logStatsLocked(const String8& name) const { +void FrameTracker::logStatsLocked(const std::string_view& name) const { for (int i = 0; i < NUM_FRAME_BUCKETS; i++) { if (mNumFrames[i] > 0) { EventLog::logFrameDurations(name, mNumFrames, NUM_FRAME_BUCKETS); diff --git a/services/surfaceflinger/FrameTracker.h b/services/surfaceflinger/FrameTracker.h index 555dcc1d1f..35382be1c0 100644 --- a/services/surfaceflinger/FrameTracker.h +++ b/services/surfaceflinger/FrameTracker.h @@ -14,20 +14,17 @@ * limitations under the License. */ -#ifndef ANDROID_FRAMETRACKER_H -#define ANDROID_FRAMETRACKER_H +#pragma once #include - -#include - #include -#include #include +#include -namespace android { +#include +#include -class String8; +namespace android { // FrameTracker tracks information about the most recently rendered frames. It // uses a circular buffer of frame records, and is *NOT* thread-safe - @@ -87,7 +84,7 @@ public: // logAndResetStats dumps the current statistics to the binary event log // and then resets the accumulated statistics to their initial values. - void logAndResetStats(const String8& name); + void logAndResetStats(const std::string_view& name); // dumpStats dump appends the current frame display time history to the result string. void dumpStats(std::string& result) const; @@ -123,7 +120,7 @@ private: void resetFrameCountersLocked(); // logStatsLocked dumps the current statistics to the binary event log. - void logStatsLocked(const String8& name) const; + void logStatsLocked(const std::string_view& name) const; // isFrameValidLocked returns true if the data for the given frame index is // valid and has all arrived (i.e. there are no oustanding fences). @@ -160,6 +157,4 @@ private: mutable Mutex mMutex; }; -} - -#endif // ANDROID_FRAMETRACKER_H +} // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 6a45625c89..0c700a779f 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -83,8 +83,6 @@ Layer::Layer(const LayerCreationArgs& args) if (args.flags & ISurfaceComposerClient::eOpaque) layerFlags |= layer_state_t::eLayerOpaque; if (args.flags & ISurfaceComposerClient::eSecure) layerFlags |= layer_state_t::eLayerSecure; - mTransactionName = String8("TX - ") + mName; - mCurrentState.active_legacy.w = args.w; mCurrentState.active_legacy.h = args.h; mCurrentState.flags = layerFlags; @@ -137,11 +135,11 @@ Layer::~Layer() { } LayerCreationArgs::LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, - const String8& name, uint32_t w, uint32_t h, uint32_t flags, + std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata) : flinger(flinger), client(client), - name(name), + name(std::move(name)), w(w), h(h), flags(flags), @@ -235,10 +233,6 @@ void Layer::addToCurrentState() { // set-up // --------------------------------------------------------------------------- -const String8& Layer::getName() const { - return mName; -} - bool Layer::getPremultipledAlpha() const { return mPremultipliedAlpha; } @@ -523,7 +517,7 @@ void Layer::latchCompositionState(compositionengine::LayerFECompositionState& co } const char* Layer::getDebugName() const { - return mName.string(); + return mName.c_str(); } // --------------------------------------------------------------------------- @@ -614,7 +608,7 @@ void Layer::pushPendingState() { if (mCurrentState.barrierLayer_legacy != nullptr && !isRemovedFromCurrentState()) { sp barrierLayer = mCurrentState.barrierLayer_legacy.promote(); if (barrierLayer == nullptr) { - ALOGE("[%s] Unable to promote barrier Layer.", mName.string()); + ALOGE("[%s] Unable to promote barrier Layer.", getDebugName()); // If we can't promote the layer we are intended to wait on, // then it is expired or otherwise invalid. Allow this transaction // to be applied as per normal (no synchronization). @@ -638,7 +632,7 @@ void Layer::pushPendingState() { mFlinger->setTransactionFlags(eTraversalNeeded); } mPendingStates.push_back(mCurrentState); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } void Layer::popPendingState(State* stateToCommit) { @@ -646,7 +640,7 @@ void Layer::popPendingState(State* stateToCommit) { *stateToCommit = mPendingStates[0]; mPendingStates.removeAt(0); - ATRACE_INT(mTransactionName.string(), mPendingStates.size()); + ATRACE_INT(mTransactionName.c_str(), mPendingStates.size()); } bool Layer::applyPendingStates(State* stateToCommit) { @@ -657,7 +651,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { // If we don't have a sync point for this, apply it anyway. It // will be visually wrong, but it should keep us from getting // into too much trouble. - ALOGE("[%s] No local sync point found", mName.string()); + ALOGE("[%s] No local sync point found", getDebugName()); popPendingState(stateToCommit); stateUpdateAvailable = true; continue; @@ -665,7 +659,7 @@ bool Layer::applyPendingStates(State* stateToCommit) { if (mRemoteSyncPoints.front()->getFrameNumber() != mPendingStates[0].frameNumber_legacy) { - ALOGE("[%s] Unexpected sync point frame number found", mName.string()); + ALOGE("[%s] Unexpected sync point frame number found", getDebugName()); // Signal our end of the sync point and then dispose of it mRemoteSyncPoints.front()->setTransactionApplied(); @@ -717,7 +711,7 @@ uint32_t Layer::doTransactionResize(uint32_t flags, State* stateToCommit) { " requested={ wh={%4u,%4u} }}\n" " drawing={ active ={ wh={%4u,%4u} crop={%4d,%4d,%4d,%4d} (%4d,%4d) }\n" " requested={ wh={%4u,%4u} }}\n", - this, getName().string(), getBufferTransform(), getEffectiveScalingMode(), + this, getName().c_str(), getBufferTransform(), getEffectiveScalingMode(), stateToCommit->active_legacy.w, stateToCommit->active_legacy.h, stateToCommit->crop_legacy.left, stateToCommit->crop_legacy.top, stateToCommit->crop_legacy.right, stateToCommit->crop_legacy.bottom, @@ -999,9 +993,10 @@ bool Layer::setBackgroundColor(const half3& color, float alpha, ui::Dataspace da if (!mCurrentState.bgColorLayer && alpha != 0) { // create background color layer if one does not yet exist uint32_t flags = ISurfaceComposerClient::eFXSurfaceColor; - const String8& name = mName + "BackgroundColorLayer"; + std::string name = mName + "BackgroundColorLayer"; mCurrentState.bgColorLayer = mFlinger->getFactory().createColorLayer( - LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, flags, LayerMetadata())); + LayerCreationArgs(mFlinger.get(), nullptr, std::move(name), 0, 0, flags, + LayerMetadata())); // add to child list addChild(mCurrentState.bgColorLayer); @@ -1196,11 +1191,13 @@ void Layer::updateTransformHint(const sp& display) const { // TODO(marissaw): add new layer state info to layer debugging LayerDebugInfo Layer::getLayerDebugInfo() const { + using namespace std::string_literals; + LayerDebugInfo info; const State& ds = getDrawingState(); info.mName = getName(); sp parent = getParent(); - info.mParentName = (parent == nullptr ? std::string("none") : parent->getName().string()); + info.mParentName = parent ? parent->getName() : "none"s; info.mType = getType(); info.mTransparentRegion = ds.activeTransparentRegion_legacy; @@ -1267,12 +1264,12 @@ void Layer::miniDump(std::string& result, const sp& displayDevice std::string name; if (mName.length() > 77) { std::string shortened; - shortened.append(mName.string(), 36); + shortened.append(mName, 0, 36); shortened.append("[...]"); - shortened.append(mName.string() + (mName.length() - 36), 36); - name = shortened; + shortened.append(mName, mName.length() - 36); + name = std::move(shortened); } else { - name = std::string(mName.string(), mName.size()); + name = mName; } StringAppendF(&result, " %s\n", name.c_str()); @@ -1319,14 +1316,14 @@ void Layer::getFrameStats(FrameStats* outStats) const { } void Layer::dumpFrameEvents(std::string& result) { - StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().string(), getType(), this); + StringAppendF(&result, "- Layer %s (%s, %p)\n", getName().c_str(), getType(), this); Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.checkFencesForCompletion(); mFrameEventHistory.dump(result); } void Layer::dumpCallingUidPid(std::string& result) const { - StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().string(), getType(), + StringAppendF(&result, "Layer %s (%s) pid:%d uid:%d\n", getName().c_str(), getType(), mCallingPid, mCallingUid); } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3023cf5df3..ad81920dc9 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -34,7 +34,6 @@ #include #include #include -#include #include #include @@ -79,12 +78,12 @@ class SurfaceInterceptor; // --------------------------------------------------------------------------- struct LayerCreationArgs { - LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, const String8& name, + LayerCreationArgs(SurfaceFlinger* flinger, const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata); SurfaceFlinger* flinger; const sp& client; - const String8& name; + std::string name; uint32_t w; uint32_t h; uint32_t flags; @@ -804,7 +803,7 @@ public: // Creates a new handle each time, so we only expect // this to be called once. sp getHandle(); - const String8& getName() const; + const std::string& getName() const { return mName; } virtual void notifyAvailableFrames(nsecs_t /*expectedPresentTime*/) {} virtual PixelFormat getPixelFormat() const { return PIXEL_FORMAT_NONE; } bool getPremultipledAlpha() const; @@ -820,8 +819,8 @@ protected: bool usingRelativeZ(LayerVector::StateSet stateSet) const; bool mPremultipliedAlpha{true}; - String8 mName; - String8 mTransactionName; // A cached version of "TX - " + mName for systraces + const std::string mName; + const std::string mTransactionName{"TX - " + mName}; bool mPrimaryDisplayOnly = false; diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 8a221837ac..1a60f1ed08 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -24,7 +24,7 @@ namespace android { LayerRejecter::LayerRejecter(Layer::State& front, Layer::State& current, - bool& recomputeVisibleRegions, bool stickySet, const char* name, + bool& recomputeVisibleRegions, bool stickySet, const std::string& name, int32_t overrideScalingMode, bool transformToDisplayInverse) : mFront(front), mCurrent(current), @@ -90,7 +90,7 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) "(%4d,%4d) " "}\n" " requested_legacy={ wh={%4u,%4u} }}\n", - mName, bufWidth, bufHeight, item.mTransform, item.mScalingMode, + mName.c_str(), bufWidth, bufHeight, item.mTransform, item.mScalingMode, mFront.active_legacy.w, mFront.active_legacy.h, mFront.crop_legacy.left, mFront.crop_legacy.top, mFront.crop_legacy.right, mFront.crop_legacy.bottom, mFront.crop_legacy.getWidth(), mFront.crop_legacy.getHeight(), @@ -102,7 +102,8 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) // reject this buffer ALOGE("[%s] rejecting buffer: " "bufWidth=%d, bufHeight=%d, front.active_legacy.{w=%d, h=%d}", - mName, bufWidth, bufHeight, mFront.active_legacy.w, mFront.active_legacy.h); + mName.c_str(), bufWidth, bufHeight, mFront.active_legacy.w, + mFront.active_legacy.h); return true; } } diff --git a/services/surfaceflinger/LayerRejecter.h b/services/surfaceflinger/LayerRejecter.h index 1bd0c26dc6..fb5c750571 100644 --- a/services/surfaceflinger/LayerRejecter.h +++ b/services/surfaceflinger/LayerRejecter.h @@ -14,30 +14,29 @@ * limitations under the License. */ -#ifndef ANDROID_LAYER_REJECTER_H -#define ANDROID_LAYER_REJECTER_H +#pragma once #include "Layer.h" #include "BufferLayerConsumer.h" namespace android { - class LayerRejecter : public BufferLayerConsumer::BufferRejecter { - public: - LayerRejecter(Layer::State &front, Layer::State ¤t, bool &recomputeVisibleRegions, - bool stickySet, const char *name, int32_t overrideScalingMode, - bool transformToDisplayInverse); - virtual bool reject(const sp &buf, const BufferItem &item); +class LayerRejecter : public BufferLayerConsumer::BufferRejecter { +public: + LayerRejecter(Layer::State& front, Layer::State& current, bool& recomputeVisibleRegions, + bool stickySet, const std::string& name, int32_t overrideScalingMode, + bool transformToDisplayInverse); - private: - Layer::State &mFront; - Layer::State &mCurrent; - bool &mRecomputeVisibleRegions; - bool mStickyTransformSet; - const char *mName; - int32_t mOverrideScalingMode; - bool mTransformToDisplayInverse; - }; -} // namespace android + virtual bool reject(const sp&, const BufferItem&); -#endif // ANDROID_LAYER_REJECTER_H +private: + Layer::State& mFront; + Layer::State& mCurrent; + bool& mRecomputeVisibleRegions; + const bool mStickyTransformSet; + const std::string& mName; + const int32_t mOverrideScalingMode; + const bool mTransformToDisplayInverse; +}; + +} // namespace android diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 1c1367c916..30027decfb 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -436,7 +436,7 @@ void RegionSamplingThread::captureSample() { } if (!intersectsAnyArea) return; - ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getName().string(), bounds.left, + ALOGV("Traversing [%s] [%d, %d, %d, %d]", layer->getDebugName(), bounds.left, bounds.top, bounds.right, bounds.bottom); visitor(layer); }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 54e20659a7..0e33f10ab6 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -122,6 +122,8 @@ namespace android { +using namespace std::string_literals; + using namespace android::hardware::configstore; using namespace android::hardware::configstore::V1_0; using namespace android::sysprop; @@ -1911,8 +1913,7 @@ void SurfaceFlinger::postComposition() layer->onPostComposition(displayDevice->getId(), glCompositionDoneFenceTime, presentFenceTime, compositorTiming); if (frameLatched) { - recordBufferingStats(layer->getName().string(), - layer->getOccupancyHistory(false)); + recordBufferingStats(layer->getName(), layer->getOccupancyHistory(false)); } }); @@ -2574,7 +2575,7 @@ void SurfaceFlinger::commitTransactionLocked() { if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from for (const auto& l : mLayersPendingRemoval) { - recordBufferingStats(l->getName().string(), l->getOccupancyHistory(true)); + recordBufferingStats(l->getName(), l->getOccupancyHistory(true)); // Ensure any buffers set to display on any children are released. if (l->isRemovedFromCurrentState()) { @@ -3244,11 +3245,12 @@ uint32_t SurfaceFlinger::setClientStateLocked( // everything else inherits layer stack from its parent. if (layer->hasParent()) { ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", - layer->getName().string()); + layer->getDebugName()); } else if (idx < 0) { ALOGE("Attempt to set layer stack on layer without parent (%s) that " - "that also does not appear in the top level layer list. Something" - " has gone wrong.", layer->getName().string()); + "that also does not appear in the top level layer list. Something" + " has gone wrong.", + layer->getDebugName()); } else if (layer->setLayerStack(s.layerStack)) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); @@ -3406,7 +3408,7 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp sp mirrorLayer; sp mirrorFrom; - String8 uniqueName = getUniqueLayerName(String8("MirrorRoot")); + std::string uniqueName = getUniqueLayerName("MirrorRoot"); { Mutex::Autolock _l(mStateLock); @@ -3415,8 +3417,8 @@ status_t SurfaceFlinger::mirrorLayer(const sp& client, const sp return NAME_NOT_FOUND; } - status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(), - outHandle, &mirrorLayer); + status_t result = createContainerLayer(client, std::move(uniqueName), -1, -1, 0, + LayerMetadata(), outHandle, &mirrorLayer); if (result != NO_ERROR) { return result; } @@ -3447,7 +3449,7 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie sp layer; - String8 uniqueName = getUniqueLayerName(name); + std::string uniqueName = getUniqueLayerName(name.string()); bool primaryDisplayOnly = false; @@ -3463,13 +3465,13 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie switch (flags & ISurfaceComposerClient::eFXSurfaceMask) { case ISurfaceComposerClient::eFXSurfaceBufferQueue: - result = createBufferQueueLayer(client, uniqueName, w, h, flags, std::move(metadata), - format, handle, gbp, &layer); + result = createBufferQueueLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), format, handle, gbp, &layer); break; case ISurfaceComposerClient::eFXSurfaceBufferState: - result = createBufferStateLayer(client, uniqueName, w, h, flags, std::move(metadata), - handle, &layer); + result = createBufferStateLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceColor: // check if buffer size is set for color layer. @@ -3479,8 +3481,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return BAD_VALUE; } - result = createColorLayer(client, uniqueName, w, h, flags, std::move(metadata), handle, - &layer); + result = createColorLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; case ISurfaceComposerClient::eFXSurfaceContainer: // check if buffer size is set for container layer. @@ -3489,8 +3491,8 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie int(w), int(h)); return BAD_VALUE; } - result = createContainerLayer(client, uniqueName, w, h, flags, std::move(metadata), - handle, &layer); + result = createContainerLayer(client, std::move(uniqueName), w, h, flags, + std::move(metadata), handle, &layer); break; default: result = BAD_VALUE; @@ -3517,35 +3519,32 @@ status_t SurfaceFlinger::createLayer(const String8& name, const sp& clie return result; } -String8 SurfaceFlinger::getUniqueLayerName(const String8& name) -{ - bool matchFound = true; - uint32_t dupeCounter = 0; +std::string SurfaceFlinger::getUniqueLayerName(const char* name) { + unsigned dupeCounter = 0; // Tack on our counter whether there is a hit or not, so everyone gets a tag - String8 uniqueName = name + "#" + String8(std::to_string(dupeCounter).c_str()); + std::string uniqueName = base::StringPrintf("%s#%u", name, dupeCounter); // Grab the state lock since we're accessing mCurrentState Mutex::Autolock lock(mStateLock); // Loop over layers until we're sure there is no matching name + bool matchFound = true; while (matchFound) { matchFound = false; mCurrentState.traverseInZOrder([&](Layer* layer) { if (layer->getName() == uniqueName) { matchFound = true; - uniqueName = name + "#" + String8(std::to_string(++dupeCounter).c_str()); + uniqueName = base::StringPrintf("%s#%u", name, ++dupeCounter); } }); } - ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name.c_str(), - uniqueName.c_str()); - + ALOGV_IF(dupeCounter > 0, "duplicate layer name: changing %s to %s", name, uniqueName.c_str()); return uniqueName; } -status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, PixelFormat& format, sp* handle, @@ -3563,8 +3562,7 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const } sp layer; - LayerCreationArgs args = - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.textureName = getNewTexture(); { // Grab the SF state lock during this since it's the only safe way to access @@ -3585,12 +3583,11 @@ status_t SurfaceFlinger::createBufferQueueLayer(const sp& client, const return err; } -status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createBufferStateLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { - LayerCreationArgs args = - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)); + LayerCreationArgs args(this, client, std::move(name), w, h, flags, std::move(metadata)); args.displayDevice = getDefaultDisplayDevice(); args.textureName = getNewTexture(); sp layer = getFactory().createBufferStateLayer(args); @@ -3600,26 +3597,25 @@ status_t SurfaceFlinger::createBufferStateLayer(const sp& client, const return NO_ERROR; } -status_t SurfaceFlinger::createColorLayer(const sp& client, const String8& name, uint32_t w, +status_t SurfaceFlinger::createColorLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { *outLayer = getFactory().createColorLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + {this, client, std::move(name), w, h, flags, std::move(metadata)}); *handle = (*outLayer)->getHandle(); return NO_ERROR; } -status_t SurfaceFlinger::createContainerLayer(const sp& client, const String8& name, +status_t SurfaceFlinger::createContainerLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* handle, sp* outLayer) { *outLayer = getFactory().createContainerLayer( - LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata))); + {this, client, std::move(name), w, h, flags, std::move(metadata)}); *handle = (*outLayer)->getHandle(); return NO_ERROR; } - void SurfaceFlinger::markLayerPendingRemovalLocked(const sp& layer) { mLayersPendingRemoval.add(layer); mLayersRemoved = true; @@ -3828,8 +3824,6 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, strerror(-err), err); } - using namespace std::string_literals; - static const std::unordered_map dumpers = { {"--display-id"s, dumper(&SurfaceFlinger::dumpDisplayIdentificationData)}, {"--dispsync"s, @@ -3885,7 +3879,7 @@ status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) { void SurfaceFlinger::listLayersLocked(std::string& result) const { mCurrentState.traverseInZOrder( - [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getName().string()); }); + [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getDebugName()); }); } void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const { @@ -3894,7 +3888,7 @@ void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) if (args.size() > 1) { const auto name = String8(args[1]); mCurrentState.traverseInZOrder([&](Layer* layer) { - if (name == layer->getName()) { + if (layer->getName() == name.string()) { layer->dumpFrameStats(result); } }); @@ -3904,8 +3898,11 @@ void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) } void SurfaceFlinger::clearStatsLocked(const DumpArgs& args, std::string&) { + const bool clearAll = args.size() < 2; + const auto name = clearAll ? String8() : String8(args[1]); + mCurrentState.traverseInZOrder([&](Layer* layer) { - if (args.size() < 2 || String8(args[1]) == layer->getName()) { + if (clearAll || layer->getName() == name.string()) { layer->clearFrameStats(); } }); @@ -3924,7 +3921,7 @@ void SurfaceFlinger::logFrameStats() { layer->logFrameStats(); }); - mAnimFrameTracker.logAndResetStats(String8("")); + mAnimFrameTracker.logAndResetStats(""); } void SurfaceFlinger::appendSfConfigString(std::string& result) const { @@ -3982,8 +3979,8 @@ void SurfaceFlinger::dumpStaticScreenStats(std::string& result) const { bucketTimeSec, percent); } -void SurfaceFlinger::recordBufferingStats(const char* layerName, - std::vector&& history) { +void SurfaceFlinger::recordBufferingStats(const std::string& layerName, + std::vector&& history) { Mutex::Autolock lock(getBE().mBufferingStatsMutex); auto& stats = getBE().mBufferingStats[layerName]; for (const auto& segment : history) { @@ -5031,13 +5028,14 @@ status_t SurfaceFlinger::captureLayers( drawLayers(); } else { Rect bounds = getBounds(); + uint32_t w = static_cast(bounds.getWidth()); + uint32_t h = static_cast(bounds.getHeight()); // In the "childrenOnly" case we reparent the children to a screenshot // layer which has no properties set and which does not draw. sp screenshotParentLayer = - mFlinger->getFactory().createContainerLayer( - LayerCreationArgs(mFlinger, nullptr, String8("Screenshot Parent"), - bounds.getWidth(), bounds.getHeight(), 0, - LayerMetadata())); + mFlinger->getFactory().createContainerLayer({mFlinger, nullptr, + "Screenshot Parent"s, w, h, 0, + LayerMetadata()}); ReparentForDrawing reparent(mLayer, screenshotParentLayer, sourceCrop); drawLayers(); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 9f3a914366..b719245caa 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -607,27 +607,27 @@ private: sp* handle, sp* gbp, const sp& parentHandle, const sp& parentLayer = nullptr); - status_t createBufferQueueLayer(const sp& client, const String8& name, uint32_t w, + status_t createBufferQueueLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, PixelFormat& format, sp* outHandle, sp* outGbp, sp* outLayer); - status_t createBufferStateLayer(const sp& client, const String8& name, uint32_t w, + status_t createBufferStateLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); - status_t createColorLayer(const sp& client, const String8& name, uint32_t w, uint32_t h, + status_t createColorLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); - status_t createContainerLayer(const sp& client, const String8& name, uint32_t w, + status_t createContainerLayer(const sp& client, std::string name, uint32_t w, uint32_t h, uint32_t flags, LayerMetadata metadata, sp* outHandle, sp* outLayer); status_t mirrorLayer(const sp& client, const sp& mirrorFromHandle, sp* outHandle); - String8 getUniqueLayerName(const String8& name); + std::string getUniqueLayerName(const char* name); // called when all clients have released all their references to // this layer meaning it is entirely safe to destroy all @@ -866,8 +866,8 @@ private: // Not const because each Layer needs to query Fences and cache timestamps. void dumpFrameEventsLocked(std::string& result); - void recordBufferingStats(const char* layerName, - std::vector&& history); + void recordBufferingStats(const std::string& layerName, + std::vector&& history); void dumpBufferingStats(std::string& result) const; void dumpDisplayIdentificationData(std::string& result) const; void dumpRawDisplayIdentificationData(const DumpArgs&, std::string& result) const; diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index a02d14cc4d..7e6c472d7f 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -165,10 +165,6 @@ const sp SurfaceInterceptor::getLayer(const wp& weak return layer; } -const std::string SurfaceInterceptor::getLayerName(const sp& layer) const { - return layer->getName().string(); -} - int32_t SurfaceInterceptor::getLayerId(const sp& layer) const { return layer->sequence; } @@ -490,7 +486,7 @@ void SurfaceInterceptor::addSurfaceCreationLocked(Increment* increment, { SurfaceCreation* creation(increment->mutable_surface_creation()); creation->set_id(getLayerId(layer)); - creation->set_name(getLayerName(layer)); + creation->set_name(layer->getName()); creation->set_w(layer->mCurrentState.active_legacy.w); creation->set_h(layer->mCurrentState.active_legacy.h); } diff --git a/services/surfaceflinger/SurfaceInterceptor.h b/services/surfaceflinger/SurfaceInterceptor.h index 6858c4d5a6..72b734b8fd 100644 --- a/services/surfaceflinger/SurfaceInterceptor.h +++ b/services/surfaceflinger/SurfaceInterceptor.h @@ -123,7 +123,6 @@ private: status_t writeProtoFileLocked(); const sp getLayer(const wp& weakHandle) const; - const std::string getLayerName(const sp& layer) const; int32_t getLayerId(const sp& layer) const; int32_t getLayerIdFromWeakRef(const wp& layer) const; int32_t getLayerIdFromHandle(const sp& weakHandle) const; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 8aff096d5e..60da70fd25 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -839,7 +839,7 @@ struct ColorLayerVariant : public BaseLayerVariant { static FlingerLayerType createLayer(CompositionTest* test) { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { return new ColorLayer(LayerCreationArgs(test->mFlinger.mFlinger.get(), sp(), - String8("test-layer"), LayerProperties::WIDTH, + "test-layer", LayerProperties::WIDTH, LayerProperties::HEIGHT, LayerProperties::LAYER_FLAGS, LayerMetadata())); }); @@ -879,11 +879,9 @@ struct BufferLayerVariant : public BaseLayerVariant { FlingerLayerType layer = Base::template createLayerWithFactory(test, [test]() { sp client; - String8 name("test-layer"); - LayerCreationArgs args = - LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name, - LayerProperties::WIDTH, LayerProperties::HEIGHT, - LayerProperties::LAYER_FLAGS, LayerMetadata()); + LayerCreationArgs args(test->mFlinger.mFlinger.get(), client, "test-layer", + LayerProperties::WIDTH, LayerProperties::HEIGHT, + LayerProperties::LAYER_FLAGS, LayerMetadata()); args.textureName = test->mFlinger.mutableTexturePool().back(); return new BufferQueueLayer(args); }); -- cgit v1.2.3-59-g8ed1b From e300b31e0a60df6026925b958c6de5d13672bba8 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Thu, 3 Oct 2019 13:03:45 -0700 Subject: SF: Switch BufferQueueLayer to using the factory during init Test: atest libsurfaceflinger_unittest Test: go/wm_smoke Bug: None Change-Id: I63afc8020894ca2d56789db693ecaeb145ea6e6d --- services/surfaceflinger/BufferQueueLayer.cpp | 8 +++--- .../SurfaceFlingerDefaultFactory.cpp | 14 ++++++++++ .../surfaceflinger/SurfaceFlingerDefaultFactory.h | 6 +++++ services/surfaceflinger/SurfaceFlingerFactory.h | 9 +++++++ .../tests/unittests/TestableSurfaceFlinger.h | 30 ++++++++++++---------- 5 files changed, 50 insertions(+), 17 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d80a70e4c6..781c67512f 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -459,9 +459,11 @@ void BufferQueueLayer::onFirstRef() { // Creates a custom BufferQueue for SurfaceFlingerConsumer to use sp producer; sp consumer; - BufferQueue::createBufferQueue(&producer, &consumer, true); - mProducer = new MonitoredProducer(producer, mFlinger, this); - mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); + mFlinger->getFactory().createBufferQueue(&producer, &consumer, true); + mProducer = mFlinger->getFactory().createMonitoredProducer(producer, mFlinger, this); + mConsumer = + mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(), + mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); mConsumer->setContentsChangedListener(this); mConsumer->setName(mName); diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index f0457e3e8a..4f439da344 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -17,12 +17,14 @@ #include #include +#include "BufferLayerConsumer.h" #include "BufferQueueLayer.h" #include "BufferStateLayer.h" #include "ColorLayer.h" #include "ContainerLayer.h" #include "DisplayDevice.h" #include "Layer.h" +#include "MonitoredProducer.h" #include "NativeWindowSurface.h" #include "StartPropertySetThread.h" #include "SurfaceFlingerDefaultFactory.h" @@ -92,6 +94,18 @@ void DefaultFactory::createBufferQueue(sp* outProducer, BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); } +sp DefaultFactory::createMonitoredProducer( + const sp& producer, const sp& flinger, + const wp& layer) { + return new MonitoredProducer(producer, flinger, layer); +} + +sp DefaultFactory::createBufferLayerConsumer( + const sp& consumer, renderengine::RenderEngine& renderEngine, + uint32_t textureName, Layer* layer) { + return new BufferLayerConsumer(consumer, renderEngine, textureName, layer); +} + std::unique_ptr DefaultFactory::createNativeWindowSurface( const sp& producer) { return surfaceflinger::impl::createNativeWindowSurface(producer); diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h index 89e0679c83..42bb177195 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.h +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.h @@ -42,6 +42,12 @@ public: void createBufferQueue(sp* outProducer, sp* outConsumer, bool consumerIsSurfaceFlinger) override; + sp createMonitoredProducer(const sp&, + const sp&, + const wp&) override; + sp createBufferLayerConsumer(const sp&, + renderengine::RenderEngine&, uint32_t tex, + Layer*) override; std::unique_ptr createNativeWindowSurface( const sp&) override; std::unique_ptr createCompositionEngine() override; diff --git a/services/surfaceflinger/SurfaceFlingerFactory.h b/services/surfaceflinger/SurfaceFlingerFactory.h index 3fd4de8170..20784d2707 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.h +++ b/services/surfaceflinger/SurfaceFlingerFactory.h @@ -30,6 +30,7 @@ typedef int32_t PixelFormat; class BufferQueueLayer; class BufferStateLayer; +class BufferLayerConsumer; class ColorLayer; class ContainerLayer; class DisplayDevice; @@ -39,6 +40,7 @@ class GraphicBuffer; class HWComposer; class IGraphicBufferConsumer; class IGraphicBufferProducer; +class Layer; class MessageQueue; class Scheduler; class StartPropertySetThread; @@ -85,6 +87,13 @@ public: virtual void createBufferQueue(sp* outProducer, sp* outConsumer, bool consumerIsSurfaceFlinger) = 0; + virtual sp createMonitoredProducer(const sp&, + const sp&, + const wp&) = 0; + virtual sp createBufferLayerConsumer(const sp&, + renderengine::RenderEngine&, + uint32_t tex, Layer*) = 0; + virtual std::unique_ptr createNativeWindowSurface( const sp&) = 0; diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index b85c1b622e..c7664fb9ac 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -62,23 +62,19 @@ public: ~Factory() = default; std::unique_ptr createDispSync(const char*, bool) override { - // TODO: Use test-fixture controlled factory return nullptr; } std::unique_ptr createEventControlThread( std::function) override { - // TODO: Use test-fixture controlled factory return nullptr; } std::unique_ptr createHWComposer(const std::string&) override { - // TODO: Use test-fixture controlled factory return nullptr; } std::unique_ptr createMessageQueue() override { - // TODO: Use test-fixture controlled factory return std::make_unique(); } @@ -88,39 +84,49 @@ public: std::unique_ptr createScheduler(std::function, const scheduler::RefreshRateConfigs&) override { - // TODO: Use test-fixture controlled factory return nullptr; } std::unique_ptr createSurfaceInterceptor(SurfaceFlinger* flinger) override { - // TODO: Use test-fixture controlled factory return std::make_unique(flinger); } sp createStartPropertySetThread(bool timestampPropertyValue) override { - // TODO: Use test-fixture controlled factory return new StartPropertySetThread(timestampPropertyValue); } sp createDisplayDevice(DisplayDeviceCreationArgs&& creationArgs) override { - // TODO: Use test-fixture controlled factory return new DisplayDevice(std::move(creationArgs)); } sp createGraphicBuffer(uint32_t width, uint32_t height, PixelFormat format, uint32_t layerCount, uint64_t usage, std::string requestorName) override { - // TODO: Use test-fixture controlled factory return new GraphicBuffer(width, height, format, layerCount, usage, requestorName); } void createBufferQueue(sp* outProducer, sp* outConsumer, bool consumerIsSurfaceFlinger) override { - if (!mCreateBufferQueue) return; + if (!mCreateBufferQueue) { + BufferQueue::createBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); + return; + } mCreateBufferQueue(outProducer, outConsumer, consumerIsSurfaceFlinger); } + sp createMonitoredProducer(const sp& producer, + const sp& flinger, + const wp& layer) override { + return new MonitoredProducer(producer, flinger, layer); + } + + sp createBufferLayerConsumer(const sp& consumer, + renderengine::RenderEngine& renderEngine, + uint32_t textureName, Layer* layer) override { + return new BufferLayerConsumer(consumer, renderEngine, textureName, layer); + } + std::unique_ptr createNativeWindowSurface( const sp& producer) override { if (!mCreateNativeWindowSurface) return nullptr; @@ -132,22 +138,18 @@ public: } sp createBufferQueueLayer(const LayerCreationArgs&) override { - // TODO: Use test-fixture controlled factory return nullptr; } sp createBufferStateLayer(const LayerCreationArgs&) override { - // TODO: Use test-fixture controlled factory return nullptr; } sp createColorLayer(const LayerCreationArgs&) override { - // TODO: Use test-fixture controlled factory return nullptr; } sp createContainerLayer(const LayerCreationArgs&) override { - // TODO: Use test-fixture controlled factory return nullptr; } -- cgit v1.2.3-59-g8ed1b From 2e43438757b21add0fd12feaa4a41926aab13c1a Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Wed, 9 Oct 2019 11:43:01 -0700 Subject: Add tracing for dequeueBuffer, detachBuffer and cancelBuffer The FrameTracer prototype currently doesn't have some of the events traced. This change adds the plumbing required to emit dequeueBuffer, detachBuffer and cancelBuffer. Only the dequeueBuffer is made to emit the event in this CL while enabling detach and cancel to have a place if emitting is required. Test: Build and trace with GAPID and FrameTracer perfetto changes. Bug: 142502670 Change-Id: I2ba90b32d7b309a7c8145f75387c8e6f8f6bd0fb --- libs/gui/BufferQueue.cpp | 21 +++++++++++ libs/gui/BufferQueueProducer.cpp | 13 ++++++- libs/gui/ConsumerBase.cpp | 42 ++++++++++++++++++++++ libs/gui/IConsumerListener.cpp | 26 +++++++++++++- libs/gui/include/gui/BufferQueue.h | 3 ++ libs/gui/include/gui/ConsumerBase.h | 6 ++++ libs/gui/include/gui/IConsumerListener.h | 11 ++++++ services/surfaceflinger/BufferQueueLayer.cpp | 8 ++++- services/surfaceflinger/BufferQueueLayer.h | 1 + .../surfaceflinger/FrameTracer/FrameTracer.cpp | 4 ++- services/surfaceflinger/FrameTracer/FrameTracer.h | 2 ++ 11 files changed, 133 insertions(+), 4 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/gui/BufferQueue.cpp b/libs/gui/BufferQueue.cpp index 5fb3f0b80f..c1d92a2a7f 100644 --- a/libs/gui/BufferQueue.cpp +++ b/libs/gui/BufferQueue.cpp @@ -43,6 +43,27 @@ void BufferQueue::ProxyConsumerListener::onDisconnect() { } } +void BufferQueue::ProxyConsumerListener::onFrameDequeued(const uint64_t bufferId) { + sp listener(mConsumerListener.promote()); + if (listener != nullptr) { + listener->onFrameDequeued(bufferId); + } +} + +void BufferQueue::ProxyConsumerListener::onFrameCancelled(const uint64_t bufferId) { + sp listener(mConsumerListener.promote()); + if (listener != nullptr) { + listener->onFrameCancelled(bufferId); + } +} + +void BufferQueue::ProxyConsumerListener::onFrameDetached(const uint64_t bufferId) { + sp listener(mConsumerListener.promote()); + if (listener != nullptr) { + listener->onFrameDetached(bufferId); + } +} + void BufferQueue::ProxyConsumerListener::onFrameAvailable( const BufferItem& item) { sp listener(mConsumerListener.promote()); diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index 56746749b9..09c74deee4 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -580,6 +580,11 @@ status_t BufferQueueProducer::dequeueBuffer(int* outSlot, sp* ou } addAndGetFrameTimestamps(nullptr, outTimestamps); + { // Autolock scope + std::lock_guard lock(mCore->mMutex); + mCore->mConsumerListener->onFrameDequeued(mSlots[*outSlot].mGraphicBuffer->getId()); + } + return returnFlags; } @@ -621,13 +626,16 @@ status_t BufferQueueProducer::detachBuffer(int slot) { return BAD_VALUE; } + listener = mCore->mConsumerListener; + if (listener != nullptr) { + listener->onFrameDetached(mSlots[slot].mGraphicBuffer->getId()); + } mSlots[slot].mBufferState.detachProducer(); mCore->mActiveBuffers.erase(slot); mCore->mFreeSlots.insert(slot); mCore->clearBufferSlotLocked(slot); mCore->mDequeueCondition.notify_all(); VALIDATE_CONSISTENCY(); - listener = mCore->mConsumerListener; } if (listener != nullptr) { @@ -1083,6 +1091,9 @@ status_t BufferQueueProducer::cancelBuffer(int slot, const sp& fence) { mCore->mFreeBuffers.push_back(slot); } + if (mCore->mConsumerListener != nullptr) { + mCore->mConsumerListener->onFrameCancelled(mSlots[slot].mGraphicBuffer->getId()); + } mSlots[slot].mFence = fence; mCore->mDequeueCondition.notify_all(); VALIDATE_CONSISTENCY(); diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index abd9921fa9..9f91d9d3aa 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -101,6 +101,48 @@ void ConsumerBase::freeBufferLocked(int slotIndex) { mSlots[slotIndex].mFrameNumber = 0; } +void ConsumerBase::onFrameDequeued(const uint64_t bufferId) { + CB_LOGV("onFrameDequeued"); + + sp listener; + { + Mutex::Autolock lock(mFrameAvailableMutex); + listener = mFrameAvailableListener.promote(); + } + + if (listener != nullptr) { + listener->onFrameDequeued(bufferId); + } +} + +void ConsumerBase::onFrameCancelled(const uint64_t bufferId) { + CB_LOGV("onFrameCancelled"); + + sp listener; + { + Mutex::Autolock lock(mFrameAvailableMutex); + listener = mFrameAvailableListener.promote(); + } + + if (listener != nullptr) { + listener->onFrameCancelled(bufferId); + } +} + +void ConsumerBase::onFrameDetached(const uint64_t bufferId) { + CB_LOGV("onFrameDetached"); + + sp listener; + { + Mutex::Autolock lock(mFrameAvailableMutex); + listener = mFrameAvailableListener.promote(); + } + + if (listener != nullptr) { + listener->onFrameDetached(bufferId); + } +} + void ConsumerBase::onFrameAvailable(const BufferItem& item) { CB_LOGV("onFrameAvailable"); diff --git a/libs/gui/IConsumerListener.cpp b/libs/gui/IConsumerListener.cpp index 85ac304ab8..48cb4b9db8 100644 --- a/libs/gui/IConsumerListener.cpp +++ b/libs/gui/IConsumerListener.cpp @@ -28,7 +28,10 @@ enum class Tag : uint32_t { ON_FRAME_REPLACED, ON_BUFFERS_RELEASED, ON_SIDEBAND_STREAM_CHANGED, - LAST = ON_SIDEBAND_STREAM_CHANGED, + ON_FRAME_DEQUEUED, + ON_FRAME_CANCELLED, + ON_FRAME_DETACHED, + LAST = ON_FRAME_DETACHED, }; } // Anonymous namespace @@ -44,6 +47,21 @@ public: callRemoteAsync(Tag::ON_DISCONNECT); } + void onFrameDequeued(const uint64_t bufferId) override { + callRemoteAsync(Tag::ON_FRAME_DEQUEUED, + bufferId); + } + + void onFrameDetached(const uint64_t bufferId) override { + callRemoteAsync(Tag::ON_FRAME_DETACHED, + bufferId); + } + + void onFrameCancelled(const uint64_t bufferId) override { + callRemoteAsync(Tag::ON_FRAME_CANCELLED, + bufferId); + } + void onFrameAvailable(const BufferItem& item) override { callRemoteAsync(Tag::ON_FRAME_AVAILABLE, item); @@ -93,6 +111,12 @@ status_t BnConsumerListener::onTransact(uint32_t code, const Parcel& data, Parce return callLocalAsync(data, reply, &IConsumerListener::onBuffersReleased); case Tag::ON_SIDEBAND_STREAM_CHANGED: return callLocalAsync(data, reply, &IConsumerListener::onSidebandStreamChanged); + case Tag::ON_FRAME_DEQUEUED: + return callLocalAsync(data, reply, &IConsumerListener::onFrameDequeued); + case Tag::ON_FRAME_CANCELLED: + return callLocalAsync(data, reply, &IConsumerListener::onFrameCancelled); + case Tag::ON_FRAME_DETACHED: + return callLocalAsync(data, reply, &IConsumerListener::onFrameDetached); } } diff --git a/libs/gui/include/gui/BufferQueue.h b/libs/gui/include/gui/BufferQueue.h index da952744f3..91f80d2f17 100644 --- a/libs/gui/include/gui/BufferQueue.h +++ b/libs/gui/include/gui/BufferQueue.h @@ -63,6 +63,9 @@ public: void onFrameReplaced(const BufferItem& item) override; void onBuffersReleased() override; void onSidebandStreamChanged() override; + void onFrameDequeued(const uint64_t bufferId) override; + void onFrameCancelled(const uint64_t bufferId) override; + void onFrameDetached(const uint64_t bufferID) override; void addAndGetFrameTimestamps( const NewFrameEventsEntry* newTimestamps, FrameEventHistoryDelta* outDelta) override; diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h index 366ced380b..8ff0cd0f6e 100644 --- a/libs/gui/include/gui/ConsumerBase.h +++ b/libs/gui/include/gui/ConsumerBase.h @@ -45,6 +45,9 @@ public: // See IConsumerListener::onFrame{Available,Replaced} virtual void onFrameAvailable(const BufferItem& item) = 0; virtual void onFrameReplaced(const BufferItem& /* item */) {} + virtual void onFrameDequeued(const uint64_t){}; + virtual void onFrameCancelled(const uint64_t){}; + virtual void onFrameDetached(const uint64_t){}; }; ~ConsumerBase() override; @@ -141,6 +144,9 @@ protected: // classes if they want the notification. virtual void onFrameAvailable(const BufferItem& item) override; virtual void onFrameReplaced(const BufferItem& item) override; + virtual void onFrameDequeued(const uint64_t bufferId) override; + virtual void onFrameCancelled(const uint64_t bufferId) override; + virtual void onFrameDetached(const uint64_t bufferId) override; virtual void onBuffersReleased() override; virtual void onSidebandStreamChanged() override; diff --git a/libs/gui/include/gui/IConsumerListener.h b/libs/gui/include/gui/IConsumerListener.h index c0828820e3..046f6e10d0 100644 --- a/libs/gui/include/gui/IConsumerListener.h +++ b/libs/gui/include/gui/IConsumerListener.h @@ -43,6 +43,17 @@ public: // onDisconnect is called when a producer disconnects from the BufferQueue. virtual void onDisconnect() {} /* Asynchronous */ + // onFrameDequeued is called when a call to the BufferQueueProducer::dequeueBuffer successfully + // returns a slot from the BufferQueue. + virtual void onFrameDequeued(const uint64_t) {} + + // onFrameCancelled is called when the client calls cancelBuffer, thereby releasing the slot + // back to the BufferQueue. + virtual void onFrameCancelled(const uint64_t) {} + + // onFrameDetached is called after a successful detachBuffer() call while in asynchronous mode. + virtual void onFrameDetached(const uint64_t) {} + // onFrameAvailable is called from queueBuffer each time an additional frame becomes available // for consumption. This means that frames that are queued while in asynchronous mode only // trigger the callback if no previous frames are pending. Frames queued while in synchronous diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d80a70e4c6..b0d8287522 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -372,11 +372,17 @@ void BufferQueueLayer::latchPerFrameState( // Interface implementation for BufferLayerConsumer::ContentsChangedListener // ----------------------------------------------------------------------- +void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) { + const int32_t layerID = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + systemTime(), FrameTracer::FrameEvent::DEQUEUE, 3000); +} + void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { const int32_t layerID = getSequence(); mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, - systemTime(), FrameTracer::FrameEvent::POST); + systemTime(), FrameTracer::FrameEvent::QUEUE); ATRACE_CALL(); // Add this buffer from our internal queue tracker diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index f3e8a19a7d..95e0b106d4 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -93,6 +93,7 @@ protected: void onFrameAvailable(const BufferItem& item) override; void onFrameReplaced(const BufferItem& item) override; void onSidebandStreamChanged() override; + void onFrameDequeued(const uint64_t bufferId) override; // ----------------------------------------------------------------------- public: diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp index 006dbfe67e..3a0408edbd 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.cpp +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -133,7 +133,9 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t packet->set_timestamp(timestamp); auto* event = packet->set_graphics_frame_event()->set_buffer_event(); event->set_buffer_id(static_cast(bufferID)); - event->set_frame_number(frameNumber); + if (frameNumber != UNSPECIFIED_FRAME_NUMBER) { + event->set_frame_number(frameNumber); + } event->set_type(type); if (mTraceTracker.find(layerID) != mTraceTracker.end() && diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h index d4dfab94eb..e91a7503cd 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.h +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -33,6 +33,8 @@ public: virtual void OnStop(const StopArgs&) override{}; }; + static const uint64_t UNSPECIFIED_FRAME_NUMBER = std::numeric_limits::max(); + using FrameEvent = perfetto::protos::pbzero::GraphicsFrameEvent; ~FrameTracer() = default; -- cgit v1.2.3-59-g8ed1b From f7a09ed2b7f85378e3043b1ce21617fc0a2bde12 Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Mon, 7 Oct 2019 13:54:18 -0700 Subject: SF: Optimize layer history in scheduler Register layers with LayerHistory by storing a weak pointer rather than allocating a LayerHandle. Query layer visibility when needed instead of synchronizing it to LayerInfo whenever Layer::isVisible is called. Store active/inactive layers in contiguous memory instead of two hash maps for cache efficiency, and minimal allocation and run time of operations like clearing history. Remove redundant ref-counting, locking, and frequency- period conversion in LayerInfo. Avoid sleeping in unit tests. This is also prework for per-display layer history. Bug: 130554049 Bug: 134772048 Test: go/wm-smoke with debug.sf.layer_history_trace Test: C2/F2 test cases from spreadsheet Test: LayerHistoryTest with new test cases Change-Id: Ibfcfe46cd76ebd93b916d4a0c737a19e837d4ff1 --- services/surfaceflinger/BufferLayer.cpp | 5 +- services/surfaceflinger/BufferQueueLayer.cpp | 4 +- services/surfaceflinger/BufferStateLayer.cpp | 4 +- services/surfaceflinger/Layer.cpp | 3 +- services/surfaceflinger/Layer.h | 5 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 217 +++++++-------- services/surfaceflinger/Scheduler/LayerHistory.h | 100 +++---- services/surfaceflinger/Scheduler/LayerInfo.cpp | 35 +-- services/surfaceflinger/Scheduler/LayerInfo.h | 170 +++++------- services/surfaceflinger/Scheduler/Scheduler.cpp | 47 ++-- services/surfaceflinger/Scheduler/Scheduler.h | 16 +- services/surfaceflinger/Scheduler/SchedulerUtils.h | 16 -- services/surfaceflinger/SurfaceFlinger.cpp | 10 + services/surfaceflinger/SurfaceFlinger.h | 7 +- .../tests/unittests/LayerHistoryTest.cpp | 291 ++++++++++++++------- .../tests/unittests/TestableScheduler.h | 1 + .../tests/unittests/TestableSurfaceFlinger.h | 6 +- .../tests/unittests/mock/MockLayer.h | 35 +++ 18 files changed, 502 insertions(+), 470 deletions(-) create mode 100644 services/surfaceflinger/tests/unittests/mock/MockLayer.h (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 603a9f7f70..a25709ceee 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -107,11 +107,8 @@ bool BufferLayer::isOpaque(const Layer::State& s) const { } bool BufferLayer::isVisible() const { - bool visible = !(isHiddenByPolicy()) && getAlpha() > 0.0f && + return !isHiddenByPolicy() && getAlpha() > 0.0f && (mBufferInfo.mBuffer != nullptr || mSidebandStream != nullptr); - mFlinger->mScheduler->setLayerVisibility(mSchedulerLayerHandle, visible); - - return visible; } bool BufferLayer::isFixedSize() const { diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 8cc1831d0f..c24cdaa617 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -389,8 +389,8 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { { // Autolock scope if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, - item.mHdrMetadata.validTypes != 0); + mFlinger->mScheduler->recordLayerHistory(this, presentTime, + item.mHdrMetadata.validTypes != 0); } Mutex::Autolock lock(mQueueItemLock); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 85d2253bf5..5768edd744 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -249,8 +249,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi if (mFlinger->mUseSmart90ForVideo) { const nsecs_t presentTime = (desiredPresentTime == -1) ? 0 : desiredPresentTime; - mFlinger->mScheduler->addLayerPresentTimeAndHDR(mSchedulerLayerHandle, presentTime, - mCurrentState.hdrMetadata.validTypes != 0); + mFlinger->mScheduler->recordLayerHistory(this, presentTime, + mCurrentState.hdrMetadata.validTypes != 0); } return true; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 37caab2b3f..e19b79b7c5 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -118,10 +118,9 @@ Layer::Layer(const LayerCreationArgs& args) mFrameEventHistory.initializeCompositorTiming(compositorTiming); mFrameTracker.setDisplayRefreshPeriod(compositorTiming.interval); - mSchedulerLayerHandle = mFlinger->mScheduler->registerLayer(mName.c_str(), mWindowType); mCallingPid = args.callingPid; mCallingUid = args.callingUid; - mFlinger->onLayerCreated(); + mFlinger->onLayerCreated(this); } Layer::~Layer() { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ad81920dc9..fdac98f317 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -221,6 +221,8 @@ public: explicit Layer(const LayerCreationArgs& args); virtual ~Layer(); + int getWindowType() const { return mWindowType; } + void setPrimaryDisplayOnly() { mPrimaryDisplayOnly = true; } bool getPrimaryDisplayOnly() const { return mPrimaryDisplayOnly; } @@ -886,9 +888,6 @@ protected: // Window types from WindowManager.LayoutParams const int mWindowType; - // This is populated if the layer is registered with Scheduler for tracking purposes. - std::unique_ptr mSchedulerLayerHandle; - private: /** * Returns an unsorted vector of all layers that are part of this tree. diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 5473db6974..8b717289c6 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -14,183 +14,150 @@ * limitations under the License. */ +#undef LOG_TAG +#define LOG_TAG "LayerHistory" #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "LayerHistory.h" -#include -#include -#include -#include -#include -#include - #include #include #include #include +#include +#include +#include +#include + +#include "../Layer.h" +#include "LayerInfo.h" #include "SchedulerUtils.h" -namespace android { -namespace scheduler { +namespace android::scheduler { -std::atomic LayerHistory::sNextId = 0; +namespace { -LayerHistory::LayerHistory() { +bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { + return layer.isVisible() && (info.isHDR() || info.getLastUpdatedTime() >= threshold); +} + +bool traceEnabled() { char value[PROPERTY_VALUE_MAX]; property_get("debug.sf.layer_history_trace", value, "0"); - mTraceEnabled = static_cast(atoi(value)); + return atoi(value); } -LayerHistory::~LayerHistory() = default; +void trace(const wp& weak, int fps) { + const auto layer = weak.promote(); + if (!layer) return; + + const auto& name = layer->getName(); + const auto tag = "LFPS " + name; + ATRACE_INT(tag.c_str(), fps); + ALOGD("%s: %s @ %d Hz", __FUNCTION__, name.c_str(), fps); +} -std::unique_ptr LayerHistory::createLayer(const std::string name, - float minRefreshRate, - float maxRefreshRate) { - const int64_t id = sNextId++; +} // namespace +LayerHistory::LayerHistory() : mTraceEnabled(traceEnabled()) {} +LayerHistory::~LayerHistory() = default; + +void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate) { + auto info = std::make_unique(lowRefreshRate, highRefreshRate); std::lock_guard lock(mLock); - mInactiveLayerInfos.emplace(id, - std::make_shared(name, minRefreshRate, maxRefreshRate)); - return std::make_unique(*this, id); + mLayerInfos.emplace_back(layer, std::move(info)); } -void LayerHistory::destroyLayer(const int64_t id) { +void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t now) { std::lock_guard lock(mLock); - auto it = mActiveLayerInfos.find(id); - if (it != mActiveLayerInfos.end()) { - mActiveLayerInfos.erase(it); - } - it = mInactiveLayerInfos.find(id); - if (it != mInactiveLayerInfos.end()) { - mInactiveLayerInfos.erase(it); - } -} + const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), + [layer](const auto& pair) { return pair.first == layer; }); + LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer); -void LayerHistory::insert(const std::unique_ptr& layerHandle, nsecs_t presentTime, - bool isHdr) { - std::shared_ptr layerInfo; - { - std::lock_guard lock(mLock); - auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mInactiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - mInactiveLayerInfos.erase(layerInfoIterator); - mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); - } else { - layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mActiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - } else { - ALOGW("Inserting information about layer that is not registered: %" PRId64, - layerHandle->mId); - return; - } - } - } - layerInfo->setLastPresentTime(presentTime); - layerInfo->setHDRContent(isHdr); -} + const auto& info = it->second; + info->setLastPresentTime(presentTime, now); + info->setIsHDR(isHDR); -void LayerHistory::setVisibility(const std::unique_ptr& layerHandle, bool visible) { - std::shared_ptr layerInfo; - { - std::lock_guard lock(mLock); - auto layerInfoIterator = mInactiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mInactiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - if (visible) { - mInactiveLayerInfos.erase(layerInfoIterator); - mActiveLayerInfos.insert({layerHandle->mId, layerInfo}); - } - } else { - layerInfoIterator = mActiveLayerInfos.find(layerHandle->mId); - if (layerInfoIterator != mActiveLayerInfos.end()) { - layerInfo = layerInfoIterator->second; - } else { - ALOGW("Inserting information about layer that is not registered: %" PRId64, - layerHandle->mId); - return; - } - } + // Activate layer if inactive. + if (const auto end = activeLayers().end(); it >= end) { + std::iter_swap(it, end); + mActiveLayersEnd++; } - layerInfo->setVisibility(visible); } -std::pair LayerHistory::getDesiredRefreshRateAndHDR() { +LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { + float maxRefreshRate = 0; bool isHDR = false; - float newRefreshRate = 0.f; + std::lock_guard lock(mLock); - removeIrrelevantLayers(); + partitionLayers(now); - // Iterate through all layers that have been recently updated, and find the max refresh rate. - for (const auto& [layerId, layerInfo] : mActiveLayerInfos) { - const bool recent = layerInfo->isRecentlyActive(); + // Find the maximum refresh rate among recently active layers. + for (const auto& [layer, info] : activeLayers()) { + const bool recent = info->isRecentlyActive(now); if (recent || CC_UNLIKELY(mTraceEnabled)) { - const float refreshRate = layerInfo->getDesiredRefreshRate(); - if (recent && refreshRate > newRefreshRate) { - newRefreshRate = refreshRate; + const float refreshRate = info->getRefreshRate(now); + if (recent && refreshRate > maxRefreshRate) { + maxRefreshRate = refreshRate; } if (CC_UNLIKELY(mTraceEnabled)) { - std::string name = "LFPS " + layerInfo->getName(); - const float rate = std::round(refreshRate); - ATRACE_INT(name.c_str(), rate); - ALOGD("%s: %f", name.c_str(), rate); + trace(layer, std::round(refreshRate)); } } - isHDR |= layerInfo->getHDRContent(); + isHDR |= info->isHDR(); } if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("LayerHistory DesiredRefreshRate: %.2f", newRefreshRate); + ALOGD("%s: maxRefreshRate=%.2f, isHDR=%d", __FUNCTION__, maxRefreshRate, isHDR); } - return {newRefreshRate, isHDR}; + return {maxRefreshRate, isHDR}; } -void LayerHistory::removeIrrelevantLayers() { - const int64_t obsoleteEpsilon = systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); - // Iterator pointing to first element in map - auto it = mActiveLayerInfos.begin(); - while (it != mActiveLayerInfos.end()) { - // If last updated was before the obsolete time, remove it. - // Keep HDR layer around as long as they are visible. - if (!it->second->isVisible() || - (!it->second->getHDRContent() && it->second->getLastUpdatedTime() < obsoleteEpsilon)) { - // erase() function returns the iterator of the next - // to last deleted element. - if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("Layer %s obsolete", it->second->getName().c_str()); - // Make sure to update systrace to indicate that the layer was erased. - std::string layerName = "LFPS " + it->second->getName(); - ATRACE_INT(layerName.c_str(), 0); - } - auto id = it->first; - auto layerInfo = it->second; - layerInfo->clearHistory(); - mInactiveLayerInfos.insert({id, layerInfo}); - it = mActiveLayerInfos.erase(it); +void LayerHistory::partitionLayers(nsecs_t now) { + const nsecs_t threshold = getActiveLayerThreshold(now); + + // Collect expired and inactive layers after active layers. + size_t i = 0; + while (i < mActiveLayersEnd) { + auto& [weak, info] = mLayerInfos[i]; + if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) { + i++; + continue; + } + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(weak, 0); + } + + info->clearHistory(); + std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]); + } + + // Collect expired layers after inactive layers. + size_t end = mLayerInfos.size(); + while (i < end) { + if (mLayerInfos[i].first.promote()) { + i++; } else { - ++it; + std::swap(mLayerInfos[i], mLayerInfos[--end]); } } + + mLayerInfos.erase(mLayerInfos.begin() + end, mLayerInfos.end()); } -void LayerHistory::clearHistory() { +void LayerHistory::clear() { std::lock_guard lock(mLock); - auto it = mActiveLayerInfos.begin(); - while (it != mActiveLayerInfos.end()) { - auto id = it->first; - auto layerInfo = it->second; - layerInfo->clearHistory(); - mInactiveLayerInfos.insert({id, layerInfo}); - it = mActiveLayerInfos.erase(it); + for (const auto& [layer, info] : activeLayers()) { + info->clearHistory(); } + + mActiveLayersEnd = 0; } -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 5598cc1cf5..15ac8caccb 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -16,76 +16,78 @@ #pragma once -#include -#include -#include -#include -#include -#include - +#include +#include #include -#include "LayerInfo.h" -#include "SchedulerUtils.h" +#include +#include +#include +#include namespace android { + +class Layer; + namespace scheduler { -/* - * This class represents information about layers that are considered current. We keep an - * unordered map between layer name and LayerInfo. - */ +class LayerInfo; + +// Records per-layer history of scheduling-related information (primarily present time), +// heuristically categorizes layers as active or inactive, and summarizes stats about +// active layers (primarily maximum refresh rate). See go/content-fps-detection-in-scheduler. class LayerHistory { public: - // Handle for each layer we keep track of. - class LayerHandle { - public: - LayerHandle(LayerHistory& lh, int64_t id) : mId(id), mLayerHistory(lh) {} - ~LayerHandle() { mLayerHistory.destroyLayer(mId); } + LayerHistory(); + ~LayerHistory(); - const int64_t mId; + // Layers are unregistered when the weak reference expires. + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate); - private: - LayerHistory& mLayerHistory; + // Marks the layer as active, and records the given state to its history. + void record(Layer*, nsecs_t presentTime, bool isHDR, nsecs_t now); + + struct Summary { + float maxRefreshRate; // Maximum refresh rate among recently active layers. + bool isHDR; // True if any recently active layer has HDR content. }; - LayerHistory(); - ~LayerHistory(); + // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. + Summary summarize(nsecs_t now); - // When the layer is first created, register it. - std::unique_ptr createLayer(const std::string name, float minRefreshRate, - float maxRefreshRate); + void clear(); - // Method for inserting layers and their requested present time into the unordered map. - void insert(const std::unique_ptr& layerHandle, nsecs_t presentTime, bool isHdr); - // Method for setting layer visibility - void setVisibility(const std::unique_ptr& layerHandle, bool visible); +private: + friend class LayerHistoryTest; - // Returns the desired refresh rate, which is a max refresh rate of all the current - // layers. See go/content-fps-detection-in-scheduler for more information. - std::pair getDesiredRefreshRateAndHDR(); + using LayerPair = std::pair, std::unique_ptr>; + using LayerInfos = std::vector; - // Clears all layer history. - void clearHistory(); + struct ActiveLayers { + LayerInfos& infos; + const size_t index; - // Removes the handle and the object from the map. - void destroyLayer(const int64_t id); + auto begin() { return infos.begin(); } + auto end() { return begin() + index; } + }; -private: - // Removes the layers that have been idle for a given amount of time from mLayerInfos. - void removeIrrelevantLayers() REQUIRES(mLock); + ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; } + + // Iterates over layers in a single pass, swapping pairs such that active layers precede + // inactive layers, and inactive layers precede expired layers. Removes expired layers by + // truncating after inactive layers. + void partitionLayers(nsecs_t now) REQUIRES(mLock); - // Information about currently active layers. - std::mutex mLock; - std::unordered_map> mActiveLayerInfos GUARDED_BY(mLock); - std::unordered_map> mInactiveLayerInfos GUARDED_BY(mLock); + mutable std::mutex mLock; - // Each layer has it's own ID. This variable keeps track of the count. - static std::atomic sNextId; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active + // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. + LayerInfos mLayerInfos GUARDED_BY(mLock); + size_t mActiveLayersEnd GUARDED_BY(mLock) = 0; - // Flag whether to log layer FPS in systrace - bool mTraceEnabled = false; + // Whether to emit systrace output and debug logs. + const bool mTraceEnabled; }; } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index 723d71ff39..f3b0d56302 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -16,27 +16,17 @@ #include "LayerInfo.h" -#include -#include -#include -#include +#include +#include -namespace android { -namespace scheduler { +namespace android::scheduler { -LayerInfo::LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate) - : mName(name), - mMinRefreshDuration(1e9f / maxRefreshRate), - mLowActivityRefreshDuration(1e9f / minRefreshRate), - mRefreshRateHistory(mMinRefreshDuration) {} - -LayerInfo::~LayerInfo() = default; - -void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { - std::lock_guard lock(mLock); +LayerInfo::LayerInfo(float lowRefreshRate, float highRefreshRate) + : mLowRefreshRate(lowRefreshRate), mHighRefreshRate(highRefreshRate) {} +void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { // Buffers can come with a present time far in the future. That keeps them relevant. - mLastUpdatedTime = std::max(lastPresentTime, systemTime()); + mLastUpdatedTime = std::max(lastPresentTime, now); mPresentTimeHistory.insertPresentTime(mLastUpdatedTime); if (mLastPresentTime == 0) { @@ -45,14 +35,13 @@ void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime) { return; } - const nsecs_t timeDiff = lastPresentTime - mLastPresentTime; + const nsecs_t period = lastPresentTime - mLastPresentTime; mLastPresentTime = lastPresentTime; // Ignore time diff that are too high - those are stale values - if (timeDiff > OBSOLETE_TIME_EPSILON_NS.count()) return; - const nsecs_t refreshDuration = std::max(timeDiff, mMinRefreshDuration); - const int fps = 1e9f / refreshDuration; + if (period > MAX_ACTIVE_LAYER_PERIOD_NS.count()) return; + + const float fps = std::min(1e9f / period, mHighRefreshRate); mRefreshRateHistory.insertRefreshRate(fps); } -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index 17afddac28..b86709fc9c 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -16,27 +16,37 @@ #pragma once -#include -#include -#include -#include -#include -#include - -#include - -#include #include +#include +#include + #include "SchedulerUtils.h" namespace android { + +class Layer; + namespace scheduler { -/* - * This class represents information about individial layers. - */ +using namespace std::chrono_literals; + +// Maximum period between presents for a layer to be considered active. +constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms; + +// Earliest present time for a layer to be considered active. +constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) { + return now - MAX_ACTIVE_LAYER_PERIOD_NS.count(); +} + +// Stores history of present times and refresh rates for a layer. class LayerInfo { + // Layer is considered frequent if the earliest value in the window of most recent present times + // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in + // favor of a low refresh rate. + static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3; + static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 250ms; + /** * Struct that keeps the information about the refresh rate for last * HISTORY_SIZE frames. This is used to better determine the refresh rate @@ -44,9 +54,9 @@ class LayerInfo { */ class RefreshRateHistory { public: - explicit RefreshRateHistory(nsecs_t minRefreshDuration) - : mMinRefreshDuration(minRefreshDuration) {} - void insertRefreshRate(int refreshRate) { + explicit RefreshRateHistory(float highRefreshRate) : mHighRefreshRate(highRefreshRate) {} + + void insertRefreshRate(float refreshRate) { mElements.push_back(refreshRate); if (mElements.size() > HISTORY_SIZE) { mElements.pop_front(); @@ -54,19 +64,16 @@ class LayerInfo { } float getRefreshRateAvg() const { - if (mElements.empty()) { - return 1e9f / mMinRefreshDuration; - } - - return scheduler::calculate_mean(mElements); + return mElements.empty() ? mHighRefreshRate : calculate_mean(mElements); } void clearHistory() { mElements.clear(); } private: - std::deque mElements; + const float mHighRefreshRate; + static constexpr size_t HISTORY_SIZE = 30; - const nsecs_t mMinRefreshDuration; + std::deque mElements; }; /** @@ -76,6 +83,8 @@ class LayerInfo { */ class PresentTimeHistory { public: + static constexpr size_t HISTORY_SIZE = 90; + void insertPresentTime(nsecs_t presentTime) { mElements.push_back(presentTime); if (mElements.size() > HISTORY_SIZE) { @@ -83,60 +92,45 @@ class LayerInfo { } } - // Checks whether the present time that was inserted HISTORY_SIZE ago is within a - // certain threshold: TIME_EPSILON_NS. - bool isRelevant() const { + // Returns whether the earliest present time is within the active threshold. + bool isRecentlyActive(nsecs_t now) const { if (mElements.size() < 2) { return false; } // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates - if (mElements.size() != HISTORY_SIZE && - mElements.at(mElements.size() - 1) - mElements.at(0) < HISTORY_TIME.count()) { + if (mElements.size() < HISTORY_SIZE && + mElements.back() - mElements.front() < HISTORY_TIME.count()) { return false; } - // The last update should not be older than OBSOLETE_TIME_EPSILON_NS nanoseconds. - const int64_t obsoleteEpsilon = - systemTime() - scheduler::OBSOLETE_TIME_EPSILON_NS.count(); - if (mElements.at(mElements.size() - 1) < obsoleteEpsilon) { - return false; - } - - return true; + return mElements.back() >= getActiveLayerThreshold(now); } - bool isLowActivityLayer() const { - // We want to make sure that we received more than two frames from the layer - // in order to check low activity. - if (mElements.size() < scheduler::LOW_ACTIVITY_BUFFERS + 1) { + bool isFrequent(nsecs_t now) const { + // Assume layer is infrequent if too few present times have been recorded. + if (mElements.size() < FREQUENT_LAYER_WINDOW_SIZE) { return false; } - const int64_t obsoleteEpsilon = - systemTime() - scheduler::LOW_ACTIVITY_EPSILON_NS.count(); - // Check the frame before last to determine whether there is low activity. - // If that frame is older than LOW_ACTIVITY_EPSILON_NS, the layer is sending - // infrequent updates. - if (mElements.at(mElements.size() - (scheduler::LOW_ACTIVITY_BUFFERS + 1)) < - obsoleteEpsilon) { - return true; - } - - return false; + // Layer is frequent if the earliest value in the window of most recent present times is + // within threshold. + const auto it = mElements.end() - FREQUENT_LAYER_WINDOW_SIZE; + const nsecs_t threshold = now - MAX_FREQUENT_LAYER_PERIOD_NS.count(); + return *it >= threshold; } void clearHistory() { mElements.clear(); } private: std::deque mElements; - static constexpr size_t HISTORY_SIZE = 90; static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s; }; + friend class LayerHistoryTest; + public: - LayerInfo(const std::string name, float minRefreshRate, float maxRefreshRate); - ~LayerInfo(); + LayerInfo(float lowRefreshRate, float highRefreshRate); LayerInfo(const LayerInfo&) = delete; LayerInfo& operator=(const LayerInfo&) = delete; @@ -144,71 +138,37 @@ public: // Records the last requested oresent time. It also stores information about when // the layer was last updated. If the present time is farther in the future than the // updated time, the updated time is the present time. - void setLastPresentTime(nsecs_t lastPresentTime); + void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); - void setHDRContent(bool isHdr) { - std::lock_guard lock(mLock); - mIsHDR = isHdr; - } + bool isHDR() const { return mIsHDR; } + void setIsHDR(bool isHDR) { mIsHDR = isHDR; } - void setVisibility(bool visible) { - std::lock_guard lock(mLock); - mIsVisible = visible; - } + bool isRecentlyActive(nsecs_t now) const { return mPresentTimeHistory.isRecentlyActive(now); } + bool isFrequent(nsecs_t now) const { return mPresentTimeHistory.isFrequent(now); } - // Checks the present time history to see whether the layer is relevant. - bool isRecentlyActive() const { - std::lock_guard lock(mLock); - return mPresentTimeHistory.isRelevant(); - } - - // Calculate the average refresh rate. - float getDesiredRefreshRate() const { - std::lock_guard lock(mLock); - - if (mPresentTimeHistory.isLowActivityLayer()) { - return 1e9f / mLowActivityRefreshDuration; - } - return mRefreshRateHistory.getRefreshRateAvg(); - } - - bool getHDRContent() { - std::lock_guard lock(mLock); - return mIsHDR; - } - - bool isVisible() { - std::lock_guard lock(mLock); - return mIsVisible; + float getRefreshRate(nsecs_t now) const { + return isFrequent(now) ? mRefreshRateHistory.getRefreshRateAvg() : mLowRefreshRate; } // Return the last updated time. If the present time is farther in the future than the // updated time, the updated time is the present time. - nsecs_t getLastUpdatedTime() { - std::lock_guard lock(mLock); - return mLastUpdatedTime; - } - - std::string getName() const { return mName; } + nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; } void clearHistory() { - std::lock_guard lock(mLock); mRefreshRateHistory.clearHistory(); mPresentTimeHistory.clearHistory(); } private: - const std::string mName; - const nsecs_t mMinRefreshDuration; - const nsecs_t mLowActivityRefreshDuration; - mutable std::mutex mLock; - nsecs_t mLastUpdatedTime GUARDED_BY(mLock) = 0; - nsecs_t mLastPresentTime GUARDED_BY(mLock) = 0; - RefreshRateHistory mRefreshRateHistory GUARDED_BY(mLock); - PresentTimeHistory mPresentTimeHistory GUARDED_BY(mLock); - bool mIsHDR GUARDED_BY(mLock) = false; - bool mIsVisible GUARDED_BY(mLock) = false; + const float mLowRefreshRate; + const float mHighRefreshRate; + + nsecs_t mLastUpdatedTime = 0; + nsecs_t mLastPresentTime = 0; + RefreshRateHistory mRefreshRateHistory{mHighRefreshRate}; + PresentTimeHistory mPresentTimeHistory; + bool mIsHDR = false; }; } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index d60e101fb4..71b35001b6 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -20,13 +20,6 @@ #include "Scheduler.h" -#include -#include -#include -#include -#include -#include - #include #include #include @@ -37,6 +30,14 @@ #include #include +#include +#include +#include +#include +#include +#include + +#include "../Layer.h" #include "DispSync.h" #include "DispSyncSource.h" #include "EventControlThread.h" @@ -325,37 +326,27 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { return mPrimaryDispSync->expectedPresentTime(); } -std::unique_ptr Scheduler::registerLayer( - std::string const& name, int windowType) { +void Scheduler::registerLayer(Layer* layer) { uint32_t defaultFps, performanceFps; if (mRefreshRateConfigs.refreshRateSwitchingSupported()) { defaultFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; - performanceFps = - mRefreshRateConfigs - .getRefreshRateFromType((windowType == InputWindowInfo::TYPE_WALLPAPER) - ? RefreshRateType::DEFAULT - : RefreshRateType::PERFORMANCE) - .fps; + const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? RefreshRateType::DEFAULT + : RefreshRateType::PERFORMANCE; + performanceFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; } else { defaultFps = mRefreshRateConfigs.getCurrentRefreshRate().second.fps; performanceFps = defaultFps; } - return mLayerHistory.createLayer(name, defaultFps, performanceFps); -} - -void Scheduler::addLayerPresentTimeAndHDR( - const std::unique_ptr& layerHandle, - nsecs_t presentTime, bool isHDR) { - mLayerHistory.insert(layerHandle, presentTime, isHDR); + mLayerHistory.registerLayer(layer, defaultFps, performanceFps); } -void Scheduler::setLayerVisibility( - const std::unique_ptr& layerHandle, bool visible) { - mLayerHistory.setVisibility(layerHandle, visible); +void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, bool isHDR) { + mLayerHistory.record(layer, presentTime, isHDR, systemTime()); } void Scheduler::updateFpsBasedOnContent() { - auto [refreshRate, isHDR] = mLayerHistory.getDesiredRefreshRateAndHDR(); + auto [refreshRate, isHDR] = mLayerHistory.summarize(systemTime()); const uint32_t refreshRateRound = std::round(refreshRate); RefreshRateType newRefreshRateType; { @@ -402,7 +393,7 @@ void Scheduler::notifyTouchEvent() { // Touch event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clearHistory(); + mLayerHistory.clear(); } void Scheduler::setDisplayPowerState(bool normal) { @@ -417,7 +408,7 @@ void Scheduler::setDisplayPowerState(bool normal) { // Display Power event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clearHistory(); + mLayerHistory.clear(); } void Scheduler::kernelIdleTimerCallback(TimerState state) { diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index a5971fed23..c98347522e 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -100,17 +100,11 @@ public: void addPresentFence(const std::shared_ptr&); void setIgnorePresentFences(bool ignore); nsecs_t getDispSyncExpectedPresentTime(); - // Registers the layer in the scheduler, and returns the handle for future references. - std::unique_ptr registerLayer(std::string const& name, - int windowType); - - // Stores present time for a layer. - void addLayerPresentTimeAndHDR( - const std::unique_ptr& layerHandle, - nsecs_t presentTime, bool isHDR); - // Stores visibility for a layer. - void setLayerVisibility( - const std::unique_ptr& layerHandle, bool visible); + + // Layers are registered on creation, and unregistered when the weak reference expires. + void registerLayer(Layer*); + void recordLayerHistory(Layer*, nsecs_t presentTime, bool isHDR); + // Updates FPS based on the most content presented. void updateFpsBasedOnContent(); diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.h b/services/surfaceflinger/Scheduler/SchedulerUtils.h index 3b7567ce8b..d301b9977b 100644 --- a/services/surfaceflinger/Scheduler/SchedulerUtils.h +++ b/services/surfaceflinger/Scheduler/SchedulerUtils.h @@ -16,7 +16,6 @@ #pragma once -#include #include #include #include @@ -38,21 +37,6 @@ inline bool operator==(ConnectionHandle lhs, ConnectionHandle rhs) { return lhs.id == rhs.id; } -using namespace std::chrono_literals; - -// This number is used when we try to determine how long do we keep layer information around -// before we remove it. It is also used to determine how long the layer stays relevant. -// This time period captures infrequent updates when playing YouTube video with static image, -// or waiting idle in messaging app, when cursor is blinking. -static constexpr std::chrono::nanoseconds OBSOLETE_TIME_EPSILON_NS = 1200ms; - -// Layer is considered low activity if the LOW_ACTIVITY_BUFFERS buffers come more than -// LOW_ACTIVITY_EPSILON_NS apart. -// This is helping SF to vote for lower refresh rates when there is not activity -// in screen. -static constexpr int LOW_ACTIVITY_BUFFERS = 2; -static constexpr std::chrono::nanoseconds LOW_ACTIVITY_EPSILON_NS = 250ms; - // Calculates the statistical mean (average) in the data structure (array, vector). The // function does not modify the contents of the array. template diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 057669b376..1acb2da051 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -5505,6 +5505,16 @@ sp SurfaceFlinger::fromHandle(const sp& handle) { return nullptr; } +void SurfaceFlinger::onLayerCreated(Layer* layer) { + mNumLayers++; + mScheduler->registerLayer(layer); +} + +void SurfaceFlinger::onLayerDestroyed(Layer* layer) { + mNumLayers--; + mOffscreenLayers.erase(layer); +} + void SurfaceFlinger::bufferErased(const client_cache_t& clientCacheId) { getRenderEngine().unbindExternalTextureBuffer(clientCacheId.id); } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index b719245caa..abb8b821ba 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -310,11 +310,8 @@ public: bool authenticateSurfaceTextureLocked( const sp& bufferProducer) const; - inline void onLayerCreated() { mNumLayers++; } - inline void onLayerDestroyed(Layer* layer) { - mNumLayers--; - mOffscreenLayers.erase(layer); - } + void onLayerCreated(Layer*); + void onLayerDestroyed(Layer*); TransactionCompletedThread& getTransactionCompletedThread() { return mTransactionCompletedThread; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 8e7440c2e3..9a962bcc0c 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -1,140 +1,243 @@ #undef LOG_TAG -#define LOG_TAG "LayerHistoryUnittests" +#define LOG_TAG "LayerHistoryTest" #include #include - #include -#include -#include - #include "Scheduler/LayerHistory.h" +#include "Scheduler/LayerInfo.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockLayer.h" using testing::_; using testing::Return; -namespace android { -namespace scheduler { +namespace android::scheduler { class LayerHistoryTest : public testing::Test { -public: - LayerHistoryTest(); - ~LayerHistoryTest() override; - protected: - std::unique_ptr mLayerHistory; + static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfo::PresentTimeHistory::HISTORY_SIZE; + static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfo::MAX_FREQUENT_LAYER_PERIOD_NS; - static constexpr float MIN_REFRESH_RATE = 30.f; - static constexpr float MAX_REFRESH_RATE = 90.f; - static constexpr auto RELEVANT_FRAME_THRESHOLD = 90u; - static constexpr uint64_t THIRTY_FPS_INTERVAL = 33'333'333; + static constexpr float LO_FPS = 30.f; + static constexpr nsecs_t LO_FPS_PERIOD = 33'333'333; - void forceRelevancy(const std::unique_ptr& testLayer) { - mLayerHistory->setVisibility(testLayer, true); - for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); - } - }; -}; + static constexpr float HI_FPS = 90.f; + static constexpr nsecs_t HI_FPS_PERIOD = 11'111'111; -LayerHistoryTest::LayerHistoryTest() { - mLayerHistory = std::make_unique(); -} -LayerHistoryTest::~LayerHistoryTest() {} + LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } + + LayerHistory& history() { return mScheduler->mutableLayerHistory(); } + const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } + + size_t layerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mLayerInfos.size(); } + size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } + + size_t frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mLayerInfos; + return std::count_if(infos.begin(), infos.begin() + history().mActiveLayersEnd, + [now](const auto& pair) { return pair.second->isFrequent(now); }); + } + + auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } + + RefreshRateConfigs mConfigs{true, + {RefreshRateConfigs::InputConfig{0, LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{1, HI_FPS_PERIOD}}, + 0}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; + TestableSurfaceFlinger mFlinger; + + const nsecs_t mTime = systemTime(); +}; namespace { + TEST_F(LayerHistoryTest, oneLayer) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); - for (auto i = 0u; i < RELEVANT_FRAME_THRESHOLD; i++) { - EXPECT_FLOAT_EQ(0.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + const auto layer = createLayer(); + constexpr bool isHDR = false; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + // 0 FPS is returned if no layers are active. + EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(0, activeLayerCount()); + + // 0 FPS is returned if active layers have insufficient history. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + history().record(layer.get(), 0, isHDR, mTime); + EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); } - // Add a few more. This time we should get MAX refresh rate as the layer - // becomes relevant - static constexpr auto A_FEW = 10; - for (auto i = 0u; i < A_FEW; i++) { - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + // High FPS is returned once enough history has been recorded. + for (int i = 0; i < 10; i++) { + history().record(layer.get(), 0, isHDR, mTime); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); } } TEST_F(LayerHistoryTest, oneHDRLayer) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestHDRLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); + const auto layer = createLayer(); + constexpr bool isHDR = true; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + history().record(layer.get(), 0, isHDR, mTime); + auto summary = history().summarize(mTime); + EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); + EXPECT_TRUE(summary.isHDR); + EXPECT_EQ(1, activeLayerCount()); - mLayerHistory->insert(testLayer, 0, true /*isHDR*/); - EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - EXPECT_EQ(true, mLayerHistory->getDesiredRefreshRateAndHDR().second); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - mLayerHistory->setVisibility(testLayer, false); - EXPECT_FLOAT_EQ(0.0f, mLayerHistory->getDesiredRefreshRateAndHDR().first); - EXPECT_EQ(false, mLayerHistory->getDesiredRefreshRateAndHDR().second); + summary = history().summarize(mTime); + EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); + EXPECT_FALSE(summary.isHDR); + EXPECT_EQ(0, activeLayerCount()); } TEST_F(LayerHistoryTest, explicitTimestamp) { - std::unique_ptr test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(test30FpsLayer, true); - - nsecs_t startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + const auto layer = createLayer(); + constexpr bool isHDR = false; + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, isHDR, time); + time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); } TEST_F(LayerHistoryTest, multipleLayers) { - std::unique_ptr testLayer = - mLayerHistory->createLayer("TestLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer, true); - std::unique_ptr test30FpsLayer = - mLayerHistory->createLayer("30FpsLayer", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(test30FpsLayer, true); - std::unique_ptr testLayer2 = - mLayerHistory->createLayer("TestLayer2", MIN_REFRESH_RATE, MAX_REFRESH_RATE); - mLayerHistory->setVisibility(testLayer2, true); - - nsecs_t startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(testLayer, 0, false /*isHDR*/); + auto layer1 = createLayer(); + auto layer2 = createLayer(); + auto layer3 = createLayer(); + constexpr bool isHDR = false; + + EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); + + nsecs_t time = mTime; + + EXPECT_EQ(3, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer1 is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer1.get(), time, isHDR, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - startTime = systemTime(); - for (int i = 0; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer2 is frequent and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - for (int i = 10; i < RELEVANT_FRAME_THRESHOLD; i++) { - mLayerHistory->insert(test30FpsLayer, startTime + (i * THIRTY_FPS_INTERVAL), - false /*isHDR*/); + // layer1 is still active but infrequent. + history().record(layer1.get(), time, isHDR, time); + + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer1 is no longer active. + // layer2 is frequent and has low refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // This frame is only around for 9 occurrences, so it doesn't throw - // anything off. - for (int i = 0; i < 9; i++) { - mLayerHistory->insert(testLayer2, 0, false /*isHDR*/); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 has high refresh rate but not enough history. + constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + if (i % RATIO == 0) { + history().record(layer2.get(), time, isHDR, time); + } + + history().record(layer3.get(), time, isHDR, time); + time += HI_FPS_PERIOD; + } + + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer3 becomes recently active. + history().record(layer3.get(), time, isHDR, time); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer1 expires. + layer1.clear(); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(2, layerCount()); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 becomes inactive. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, isHDR, time); + time += LO_FPS_PERIOD; + } + + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 expires. + layer2.clear(); + EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer3 becomes active and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer3.get(), time, isHDR, time); + time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(MAX_REFRESH_RATE, mLayerHistory->getDesiredRefreshRateAndHDR().first); - // After 1200 ms frames become obsolete. - std::this_thread::sleep_for(std::chrono::milliseconds(1500)); - - mLayerHistory->insert(test30FpsLayer, - startTime + (RELEVANT_FRAME_THRESHOLD * THIRTY_FPS_INTERVAL), - false /*isHDR*/); - EXPECT_FLOAT_EQ(30.f, mLayerHistory->getDesiredRefreshRateAndHDR().first); + + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer3 expires. + layer3.clear(); + EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + EXPECT_EQ(0, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); } } // namespace -} // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index ae7246780a..ae6aa899af 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -48,6 +48,7 @@ public: auto& mutableEventControlThread() { return mEventControlThread; } auto& mutablePrimaryDispSync() { return mPrimaryDispSync; } auto& mutableHWVsyncAvailable() { return mHWVsyncAvailable; } + auto& mutableLayerHistory() { return mLayerHistory; } ~TestableScheduler() { // All these pointer and container clears help ensure that GMock does diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index c7664fb9ac..94fc5f7273 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -22,6 +22,7 @@ #include #include #include +#include #include "BufferQueueLayer.h" #include "BufferStateLayer.h" @@ -173,6 +174,7 @@ public: class TestableSurfaceFlinger { public: + SurfaceFlinger* flinger() { return mFlinger.get(); } TestableScheduler* scheduler() { return mScheduler; } // Extend this as needed for accessing SurfaceFlinger private (and public) @@ -207,13 +209,15 @@ public: mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); + resetScheduler(mScheduler); - mFlinger->mScheduler.reset(mScheduler); mFlinger->mVSyncModulator.emplace(*mScheduler, mFlinger->mAppConnectionHandle, mFlinger->mSfConnectionHandle, mFlinger->mPhaseOffsets->getCurrentOffsets()); } + void resetScheduler(Scheduler* scheduler) { mFlinger->mScheduler.reset(scheduler); } + using CreateBufferQueueFunction = surfaceflinger::test::Factory::CreateBufferQueueFunction; void setCreateBufferQueueFunction(CreateBufferQueueFunction f) { mFactory.mCreateBufferQueue = f; diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h new file mode 100644 index 0000000000..f375e23700 --- /dev/null +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -0,0 +1,35 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include + +#include "Layer.h" + +namespace android::mock { + +class MockLayer : public Layer { +public: + explicit MockLayer(SurfaceFlinger* flinger) + : Layer(LayerCreationArgs(flinger, nullptr, "TestLayer", 800, 600, 0, {})) {} + + MOCK_CONST_METHOD0(getType, const char*()); + MOCK_CONST_METHOD0(isVisible, bool()); + MOCK_METHOD0(createClone, sp()); +}; + +} // namespace android::mock -- cgit v1.2.3-59-g8ed1b From 7dbf76d53626e356b17f21852fe305eaeb162cbe Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Fri, 25 Oct 2019 18:17:11 -0700 Subject: Add implementation for onFrameDetached and onFrameCancelled With the detach and cancel events added to the proto, the onFrameDetached and onFrameCancelled functions need to be implemented and start emitting the respective events. Test: Run GAPID, open youtube and play a video. Bug: 142502670 Change-Id: I25a90e75a83dc4e55a5676697050689dabc56fa1 --- services/surfaceflinger/BufferQueueLayer.cpp | 17 +++++++++++++++-- services/surfaceflinger/BufferQueueLayer.h | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index c24cdaa617..dc61e498df 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -374,13 +374,26 @@ void BufferQueueLayer::latchPerFrameState( void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) { const int32_t layerID = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, - systemTime(), FrameTracer::FrameEvent::DEQUEUE, 3000); + systemTime(), FrameTracer::FrameEvent::DEQUEUE); } -void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { +void BufferQueueLayer::onFrameDetached(const uint64_t bufferId) { const int32_t layerID = getSequence(); mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + systemTime(), FrameTracer::FrameEvent::DETACH); +} + +void BufferQueueLayer::onFrameCancelled(const uint64_t bufferId) { + const int32_t layerID = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + systemTime(), FrameTracer::FrameEvent::CANCEL); +} + +void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { + const int32_t layerID = getSequence(); mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, systemTime(), FrameTracer::FrameEvent::QUEUE); diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 95e0b106d4..1b1fccd392 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -94,6 +94,8 @@ protected: void onFrameReplaced(const BufferItem& item) override; void onSidebandStreamChanged() override; void onFrameDequeued(const uint64_t bufferId) override; + void onFrameDetached(const uint64_t bufferId) override; + void onFrameCancelled(const uint64_t bufferId) override; // ----------------------------------------------------------------------- public: -- cgit v1.2.3-59-g8ed1b From 49cea519fa5095f18e7c376c281c617bb976825a Mon Sep 17 00:00:00 2001 From: Dominik Laskowski Date: Tue, 12 Nov 2019 14:13:23 -0800 Subject: SF: Fully disable content detection if opted out Layer history was created but not recorded/traversed on devices without refresh rate switching. ag/9549429 destroys stale history on traversal, so the LayerInfo records were leaked. Bug: 144363590 Test: Layer history is not created on crosshatch Change-Id: I45ebc7c4f8447b2bc2bfb1af01325d562b4afed1 --- services/surfaceflinger/BufferQueueLayer.cpp | 8 +-- services/surfaceflinger/BufferStateLayer.cpp | 7 +-- services/surfaceflinger/Scheduler/LayerHistory.h | 2 + services/surfaceflinger/Scheduler/LayerInfo.cpp | 2 + services/surfaceflinger/Scheduler/OneShotTimer.cpp | 9 ++- services/surfaceflinger/Scheduler/OneShotTimer.h | 4 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 67 +++++++++++++--------- services/surfaceflinger/Scheduler/Scheduler.h | 8 +-- services/surfaceflinger/SurfaceFlinger.cpp | 17 +----- services/surfaceflinger/SurfaceFlinger.h | 1 - .../tests/unittests/CompositionTest.cpp | 7 +++ .../tests/unittests/LayerHistoryTest.cpp | 6 +- .../tests/unittests/TestableScheduler.h | 13 ++++- 13 files changed, 84 insertions(+), 67 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc61e498df..6896da7218 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -400,11 +400,9 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { ATRACE_CALL(); // Add this buffer from our internal queue tracker { // Autolock scope - if (mFlinger->mUseSmart90ForVideo) { - const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - mFlinger->mScheduler->recordLayerHistory(this, presentTime, - item.mHdrMetadata.validTypes != 0); - } + const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; + const bool isHDR = item.mHdrMetadata.validTypes != 0; + mFlinger->mScheduler->recordLayerHistory(this, presentTime, isHDR); Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5768edd744..33cd0dc41c 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -247,11 +247,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; - if (mFlinger->mUseSmart90ForVideo) { - const nsecs_t presentTime = (desiredPresentTime == -1) ? 0 : desiredPresentTime; - mFlinger->mScheduler->recordLayerHistory(this, presentTime, - mCurrentState.hdrMetadata.validTypes != 0); - } + const bool isHDR = mCurrentState.hdrMetadata.validTypes != 0; + mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, isHDR); return true; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index 15ac8caccb..bd9aca1aed 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -28,6 +28,7 @@ namespace android { class Layer; +class TestableScheduler; namespace scheduler { @@ -59,6 +60,7 @@ public: private: friend class LayerHistoryTest; + friend TestableScheduler; using LayerPair = std::pair, std::unique_ptr>; using LayerInfos = std::vector; diff --git a/services/surfaceflinger/Scheduler/LayerInfo.cpp b/services/surfaceflinger/Scheduler/LayerInfo.cpp index f3b0d56302..6d9dd43d9a 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.cpp +++ b/services/surfaceflinger/Scheduler/LayerInfo.cpp @@ -25,6 +25,8 @@ LayerInfo::LayerInfo(float lowRefreshRate, float highRefreshRate) : mLowRefreshRate(lowRefreshRate), mHighRefreshRate(highRefreshRate) {} void LayerInfo::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { + lastPresentTime = std::max(lastPresentTime, static_cast(0)); + // Buffers can come with a present time far in the future. That keeps them relevant. mLastUpdatedTime = std::max(lastPresentTime, now); mPresentTimeHistory.insertPresentTime(mLastUpdatedTime); diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.cpp b/services/surfaceflinger/Scheduler/OneShotTimer.cpp index 4870a3bbdd..a90d05e17c 100644 --- a/services/surfaceflinger/Scheduler/OneShotTimer.cpp +++ b/services/surfaceflinger/Scheduler/OneShotTimer.cpp @@ -17,6 +17,7 @@ #include "OneShotTimer.h" #include +#include #include namespace android { @@ -98,7 +99,7 @@ void OneShotTimer::loop() { mTimeoutCallback(); } } -} // namespace scheduler +} void OneShotTimer::reset() { { @@ -108,5 +109,11 @@ void OneShotTimer::reset() { mCondition.notify_all(); } +std::string OneShotTimer::dump() const { + std::ostringstream stream; + stream << mInterval.count() << " ms"; + return stream.str(); +} + } // namespace scheduler } // namespace android diff --git a/services/surfaceflinger/Scheduler/OneShotTimer.h b/services/surfaceflinger/Scheduler/OneShotTimer.h index 921631e009..b005754c1a 100644 --- a/services/surfaceflinger/Scheduler/OneShotTimer.h +++ b/services/surfaceflinger/Scheduler/OneShotTimer.h @@ -39,8 +39,6 @@ public: const TimeoutCallback& timeoutCallback); ~OneShotTimer(); - const Interval& interval() const { return mInterval; } - // Initializes and turns on the idle timer. void start(); // Stops the idle timer and any held resources. @@ -48,6 +46,8 @@ public: // Resets the wakeup time and fires the reset callback. void reset(); + std::string dump() const; + private: // Enum to track in what state is the timer. enum class TimerState { diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 71b35001b6..55fd6032f2 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -20,6 +20,7 @@ #include "Scheduler.h" +#include #include #include #include @@ -66,9 +67,11 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, mRefreshRateConfigs(refreshRateConfig) { using namespace sysprop; - char value[PROPERTY_VALUE_MAX]; - property_get("debug.sf.set_idle_timer_ms", value, "0"); - const int setIdleTimerMs = atoi(value); + if (property_get_bool("debug.sf.use_smart_90_for_video", 0) || use_smart_90_for_video(false)) { + mLayerHistory.emplace(); + } + + const int setIdleTimerMs = property_get_int32("debug.sf.set_idle_timer_ms", 0); if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) { const auto callback = mSupportKernelTimer ? &Scheduler::kernelIdleTimerCallback @@ -327,26 +330,28 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { } void Scheduler::registerLayer(Layer* layer) { - uint32_t defaultFps, performanceFps; - if (mRefreshRateConfigs.refreshRateSwitchingSupported()) { - defaultFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; - const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER - ? RefreshRateType::DEFAULT - : RefreshRateType::PERFORMANCE; - performanceFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; - } else { - defaultFps = mRefreshRateConfigs.getCurrentRefreshRate().second.fps; - performanceFps = defaultFps; - } - mLayerHistory.registerLayer(layer, defaultFps, performanceFps); + if (!mLayerHistory) return; + + const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? RefreshRateType::DEFAULT + : RefreshRateType::PERFORMANCE; + + const auto lowFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; + const auto highFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; + + mLayerHistory->registerLayer(layer, lowFps, highFps); } void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, bool isHDR) { - mLayerHistory.record(layer, presentTime, isHDR, systemTime()); + if (mLayerHistory) { + mLayerHistory->record(layer, presentTime, isHDR, systemTime()); + } } -void Scheduler::updateFpsBasedOnContent() { - auto [refreshRate, isHDR] = mLayerHistory.summarize(systemTime()); +void Scheduler::chooseRefreshRateForContent() { + if (!mLayerHistory) return; + + auto [refreshRate, isHDR] = mLayerHistory->summarize(systemTime()); const uint32_t refreshRateRound = std::round(refreshRate); RefreshRateType newRefreshRateType; { @@ -393,7 +398,9 @@ void Scheduler::notifyTouchEvent() { // Touch event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clear(); + if (mLayerHistory) { + mLayerHistory->clear(); + } } void Scheduler::setDisplayPowerState(bool normal) { @@ -408,7 +415,9 @@ void Scheduler::setDisplayPowerState(bool normal) { // Display Power event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection - mLayerHistory.clear(); + if (mLayerHistory) { + mLayerHistory->clear(); + } } void Scheduler::kernelIdleTimerCallback(TimerState state) { @@ -446,15 +455,17 @@ void Scheduler::displayPowerTimerCallback(TimerState state) { } void Scheduler::dump(std::string& result) const { - std::ostringstream stream; - if (mIdleTimer) { - stream << "+ Idle timer interval: " << mIdleTimer->interval().count() << " ms\n"; - } - if (mTouchTimer) { - stream << "+ Touch timer interval: " << mTouchTimer->interval().count() << " ms\n"; - } + using base::StringAppendF; + const char* const states[] = {"off", "on"}; + + const bool supported = mRefreshRateConfigs.refreshRateSwitchingSupported(); + StringAppendF(&result, "+ Refresh rate switching: %s\n", states[supported]); + StringAppendF(&result, "+ Content detection: %s\n", states[mLayerHistory.has_value()]); - result.append(stream.str()); + StringAppendF(&result, "+ Idle timer: %s\n", + mIdleTimer ? mIdleTimer->dump().c_str() : states[0]); + StringAppendF(&result, "+ Touch timer: %s\n\n", + mTouchTimer ? mTouchTimer->dump().c_str() : states[0]); } template diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index c98347522e..346896c44f 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -105,8 +105,8 @@ public: void registerLayer(Layer*); void recordLayerHistory(Layer*, nsecs_t presentTime, bool isHDR); - // Updates FPS based on the most content presented. - void updateFpsBasedOnContent(); + // Detects content using layer history, and selects a matching refresh rate. + void chooseRefreshRateForContent(); // Called by Scheduler to change refresh rate. void setChangeRefreshRateCallback(ChangeRefreshRateCallback&&); @@ -184,8 +184,8 @@ private: std::unique_ptr mPrimaryDispSync; std::unique_ptr mEventControlThread; - // Historical information about individual layers. Used for predicting the refresh rate. - scheduler::LayerHistory mLayerHistory; + // Used to choose refresh rate if content detection is enabled. + std::optional mLayerHistory; // Whether to use idle timer callbacks that support the kernel timer. const bool mSupportKernelTimer; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 96c17a10d9..a17896bad7 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -356,14 +356,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI auto listSize = property_get_int32("debug.sf.max_igbp_list_size", int32_t(defaultListSize)); mMaxGraphicBufferProducerListSize = (listSize > 0) ? size_t(listSize) : defaultListSize; - mUseSmart90ForVideo = use_smart_90_for_video(false); - property_get("debug.sf.use_smart_90_for_video", value, "0"); - - int int_value = atoi(value); - if (int_value) { - mUseSmart90ForVideo = true; - } - property_get("debug.sf.luma_sampling", value, "1"); mLumaSampling = atoi(value); @@ -1643,11 +1635,7 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { mGpuFrameMissedCount++; } - if (mUseSmart90ForVideo) { - // This call is made each time SF wakes up and creates a new frame. It is part - // of video detection feature. - mScheduler->updateFpsBasedOnContent(); - } + mScheduler->chooseRefreshRateForContent(); if (performSetActiveConfig()) { break; @@ -3943,9 +3931,6 @@ void SurfaceFlinger::appendSfConfigString(std::string& result) const { void SurfaceFlinger::dumpVSync(std::string& result) const { mScheduler->dump(result); - StringAppendF(&result, "+ Refresh rate switching: %s\n", - mRefreshRateConfigs->refreshRateSwitchingSupported() ? "on" : "off"); - StringAppendF(&result, "+ Smart video mode: %s\n\n", mUseSmart90ForVideo ? "on" : "off"); mRefreshRateStats->dump(result); result.append("\n"); diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index e7ad295b2d..805da06ea4 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -1093,7 +1093,6 @@ private: /* ------------------------------------------------------------------------ * Scheduler */ - bool mUseSmart90ForVideo = false; std::unique_ptr mScheduler; scheduler::ConnectionHandle mAppConnectionHandle; scheduler::ConnectionHandle mSfConnectionHandle; diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index 60da70fd25..89c5d8a779 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -793,6 +793,9 @@ struct BaseLayerVariant { sp layer = factory(); + // Layer should be registered with scheduler. + EXPECT_EQ(1, test->mFlinger.scheduler()->layerHistorySize()); + Mock::VerifyAndClear(test->mComposer); Mock::VerifyAndClear(test->mRenderEngine); Mock::VerifyAndClear(test->mMessageQueue); @@ -828,6 +831,10 @@ struct BaseLayerVariant { test->mDisplay->getCompositionDisplay()->clearOutputLayers(); test->mFlinger.mutableDrawingState().layersSortedByZ.clear(); + + // Layer should be unregistered with scheduler. + test->mFlinger.onMessageReceived(MessageQueue::INVALIDATE); + EXPECT_EQ(0, test->mFlinger.scheduler()->layerHistorySize()); } }; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index 9a962bcc0c..e93d31e7f2 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -29,10 +29,10 @@ protected: LayerHistoryTest() { mFlinger.resetScheduler(mScheduler); } - LayerHistory& history() { return mScheduler->mutableLayerHistory(); } - const LayerHistory& history() const { return mScheduler->mutableLayerHistory(); } + LayerHistory& history() { return *mScheduler->mutableLayerHistory(); } + const LayerHistory& history() const { return *mScheduler->mutableLayerHistory(); } - size_t layerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mLayerInfos.size(); } + size_t layerCount() const { return mScheduler->layerHistorySize(); } size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } size_t frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index ae6aa899af..40c00c426f 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -21,6 +21,7 @@ #include "Scheduler/DispSync.h" #include "Scheduler/EventThread.h" +#include "Scheduler/LayerHistory.h" #include "Scheduler/Scheduler.h" namespace android { @@ -28,18 +29,26 @@ namespace android { class TestableScheduler : public Scheduler { public: explicit TestableScheduler(const scheduler::RefreshRateConfigs& configs) - : Scheduler([](bool) {}, configs) {} + : Scheduler([](bool) {}, configs) { + mLayerHistory.emplace(); + } TestableScheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, const scheduler::RefreshRateConfigs& configs) - : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs) {} + : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs) { + mLayerHistory.emplace(); + } // Used to inject mock event thread. ConnectionHandle createConnection(std::unique_ptr eventThread) { return Scheduler::createConnection(std::move(eventThread)); } + size_t layerHistorySize() const NO_THREAD_SAFETY_ANALYSIS { + return mLayerHistory->mLayerInfos.size(); + } + /* ------------------------------------------------------------------------ * Read-write access to private data to set up preconditions and assert * post-conditions. -- cgit v1.2.3-59-g8ed1b From 1a88c40d5623b61bd66338f5df0e8857d249fa79 Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 18 Nov 2019 10:43:58 -0800 Subject: TimeStats & FrameTracer: refactor layerID to layerId Test: build, flash and boot Test: atest libsurfaceflinger_unittest Change-Id: I297dce08dbaf625b56e1e6d47cffead1de440ab7 --- services/surfaceflinger/BufferLayer.cpp | 18 ++-- services/surfaceflinger/BufferQueueLayer.cpp | 38 +++---- services/surfaceflinger/BufferStateLayer.cpp | 24 ++--- .../surfaceflinger/FrameTracer/FrameTracer.cpp | 54 +++++----- services/surfaceflinger/FrameTracer/FrameTracer.h | 14 +-- services/surfaceflinger/Layer.cpp | 6 +- services/surfaceflinger/TimeStats/TimeStats.cpp | 110 ++++++++++----------- services/surfaceflinger/TimeStats/TimeStats.h | 42 ++++---- .../tests/unittests/FrameTracerTest.cpp | 74 +++++++------- .../tests/unittests/TimeStatsTest.cpp | 14 +-- 10 files changed, 197 insertions(+), 197 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index a25709ceee..31462569e2 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -77,9 +77,9 @@ BufferLayer::~BufferLayer() { // with the clone layer trying to use the deleted texture. mFlinger->deleteTextureAsync(mTextureName); } - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void BufferLayer::useSurfaceDamage() { @@ -305,8 +305,8 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, nsecs_t desiredPresentTime = mBufferInfo.mDesiredPresentTime; mFrameTracker.setDesiredPresentTime(desiredPresentTime); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->setDesiredTime(layerID, mCurrentFrameNumber, desiredPresentTime); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->setDesiredTime(layerId, mCurrentFrameNumber, desiredPresentTime); std::shared_ptr frameReadyFence = mBufferInfo.mFenceTime; if (frameReadyFence->isValid()) { @@ -318,16 +318,16 @@ bool BufferLayer::onPostComposition(const std::optional& displayId, } if (presentFence->isValid()) { - mFlinger->mTimeStats->setPresentFence(layerID, mCurrentFrameNumber, presentFence); - mFlinger->mFrameTracer->traceFence(layerID, getCurrentBufferId(), mCurrentFrameNumber, + mFlinger->mTimeStats->setPresentFence(layerId, mCurrentFrameNumber, presentFence); + mFlinger->mFrameTracer->traceFence(layerId, getCurrentBufferId(), mCurrentFrameNumber, presentFence, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentFence(std::shared_ptr(presentFence)); } else if (displayId && mFlinger->getHwComposer().isConnected(*displayId)) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t actualPresentTime = mFlinger->getHwComposer().getRefreshTimestamp(*displayId); - mFlinger->mTimeStats->setPresentTime(layerID, mCurrentFrameNumber, actualPresentTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, getCurrentBufferId(), mCurrentFrameNumber, + mFlinger->mTimeStats->setPresentTime(layerId, mCurrentFrameNumber, actualPresentTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, getCurrentBufferId(), mCurrentFrameNumber, actualPresentTime, FrameTracer::FrameEvent::PRESENT_FENCE); mFrameTracker.setActualPresentTime(actualPresentTime); diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index dc61e498df..37096f8024 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -223,7 +223,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // BufferItem's that weren't actually queued. This can happen in shared // buffer mode. bool queuedBuffer = false; - const int32_t layerID = getSequence(); + const int32_t layerId = getSequence(); LayerRejecter r(mDrawingState, getCurrentState(), recomputeVisibleRegions, getProducerStickyTransform() != 0, mName, mOverrideScalingMode, getTransformToDisplayInverse()); @@ -264,7 +264,7 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t if (queuedBuffer) { Mutex::Autolock lock(mQueueItemLock); mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } @@ -278,8 +278,8 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t Mutex::Autolock lock(mQueueItemLock); mQueueItems.clear(); mQueuedFrames = 0; - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } // Once we have hit this state, the shadow queue may no longer @@ -301,19 +301,19 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t // updateTexImage while (mQueueItems[0].mFrameNumber != currentFrameNumber) { mConsumer->mergeSurfaceDamage(mQueueItems[0].mSurfaceDamage); - mFlinger->mTimeStats->removeTimeRecord(layerID, mQueueItems[0].mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mQueueItems[0].mFrameNumber); mQueueItems.removeAt(0); mQueuedFrames--; } uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); - mFlinger->mTimeStats->setAcquireFence(layerID, currentFrameNumber, + mFlinger->mTimeStats->setAcquireFence(layerId, currentFrameNumber, mQueueItems[0].mFenceTime); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, currentFrameNumber, + mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber, mQueueItems[0].mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); - mFlinger->mTimeStats->setLatchTime(layerID, currentFrameNumber, latchTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, currentFrameNumber, latchTime, + mFlinger->mTimeStats->setLatchTime(layerId, currentFrameNumber, latchTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, currentFrameNumber, latchTime, FrameTracer::FrameEvent::LATCH); mQueueItems.removeAt(0); @@ -373,28 +373,28 @@ void BufferQueueLayer::latchPerFrameState( // ----------------------------------------------------------------------- void BufferQueueLayer::onFrameDequeued(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::DEQUEUE); } void BufferQueueLayer::onFrameDetached(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::DETACH); } void BufferQueueLayer::onFrameCancelled(const uint64_t bufferId) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferId, FrameTracer::UNSPECIFIED_FRAME_NUMBER, systemTime(), FrameTracer::FrameEvent::CANCEL); } void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { - const int32_t layerID = getSequence(); - mFlinger->mFrameTracer->traceTimestamp(layerID, item.mGraphicBuffer->getId(), item.mFrameNumber, + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber, systemTime(), FrameTracer::FrameEvent::QUEUE); ATRACE_CALL(); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 5768edd744..2f3906b348 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -240,10 +240,10 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi mCurrentState.modified = true; setTransactionFlags(eTransactionNeeded); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->setPostTime(layerID, mFrameNumber, getName().c_str(), postTime); - mFlinger->mFrameTracer->traceNewLayer(layerID, getName().c_str()); - mFlinger->mFrameTracer->traceTimestamp(layerID, buffer->getId(), mFrameNumber, postTime, + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->setPostTime(layerId, mFrameNumber, getName().c_str(), postTime); + mFlinger->mFrameTracer->traceNewLayer(layerId, getName().c_str()); + mFlinger->mFrameTracer->traceTimestamp(layerId, buffer->getId(), mFrameNumber, postTime, FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; @@ -461,7 +461,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse return NO_ERROR; } - const int32_t layerID = getSequence(); + const int32_t layerId = getSequence(); // Reject if the layer is invalid uint32_t bufferWidth = s.buffer->width; @@ -483,7 +483,7 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse ALOGE("[%s] rejecting buffer: " "bufferWidth=%d, bufferHeight=%d, front.active.{w=%d, h=%d}", getDebugName(), bufferWidth, bufferHeight, s.active.w, s.active.h); - mFlinger->mTimeStats->removeTimeRecord(layerID, mFrameNumber); + mFlinger->mTimeStats->removeTimeRecord(layerId, mFrameNumber); return BAD_VALUE; } @@ -500,18 +500,18 @@ status_t BufferStateLayer::updateTexImage(bool& /*recomputeVisibleRegions*/, nse // a GL-composited layer) not at all. status_t err = bindTextureImage(); if (err != NO_ERROR) { - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); return BAD_VALUE; } } const uint64_t bufferID = getCurrentBufferId(); - mFlinger->mTimeStats->setAcquireFence(layerID, mFrameNumber, mBufferInfo.mFenceTime); - mFlinger->mFrameTracer->traceFence(layerID, bufferID, mFrameNumber, mBufferInfo.mFenceTime, + mFlinger->mTimeStats->setAcquireFence(layerId, mFrameNumber, mBufferInfo.mFenceTime); + mFlinger->mFrameTracer->traceFence(layerId, bufferID, mFrameNumber, mBufferInfo.mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); - mFlinger->mTimeStats->setLatchTime(layerID, mFrameNumber, latchTime); - mFlinger->mFrameTracer->traceTimestamp(layerID, bufferID, mFrameNumber, latchTime, + mFlinger->mTimeStats->setLatchTime(layerId, mFrameNumber, latchTime); + mFlinger->mFrameTracer->traceTimestamp(layerId, bufferID, mFrameNumber, latchTime, FrameTracer::FrameEvent::LATCH); mCurrentStateModified = false; diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp index 3a0408edbd..6f918438bc 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.cpp +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -44,52 +44,52 @@ void FrameTracer::registerDataSource() { FrameTracerDataSource::Register(dsd); } -void FrameTracer::traceNewLayer(int32_t layerID, const std::string& layerName) { - FrameTracerDataSource::Trace([this, layerID, &layerName](FrameTracerDataSource::TraceContext) { - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { +void FrameTracer::traceNewLayer(int32_t layerId, const std::string& layerName) { + FrameTracerDataSource::Trace([this, layerId, &layerName](FrameTracerDataSource::TraceContext) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { std::lock_guard lock(mTraceMutex); - mTraceTracker[layerID].layerName = layerName; + mTraceTracker[layerId].layerName = layerName; } }); } -void FrameTracer::traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, +void FrameTracer::traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration) { - FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, timestamp, type, + FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, timestamp, type, duration](FrameTracerDataSource::TraceContext ctx) { std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { return; } // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); + tracePendingFencesLocked(ctx, layerId, bufferID); // Complete current trace. - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration); }); } -void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, +void FrameTracer::traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, const std::shared_ptr& fence, FrameEvent::BufferEventType type, nsecs_t startTime) { - FrameTracerDataSource::Trace([this, layerID, bufferID, frameNumber, &fence, type, + FrameTracerDataSource::Trace([this, layerId, bufferID, frameNumber, &fence, type, startTime](FrameTracerDataSource::TraceContext ctx) { const nsecs_t signalTime = fence->getSignalTime(); if (signalTime != Fence::SIGNAL_TIME_INVALID) { std::lock_guard lock(mTraceMutex); - if (mTraceTracker.find(layerID) == mTraceTracker.end()) { + if (mTraceTracker.find(layerId) == mTraceTracker.end()) { return; } // Handle any pending fences for this buffer. - tracePendingFencesLocked(ctx, layerID, bufferID); + tracePendingFencesLocked(ctx, layerId, bufferID); if (signalTime != Fence::SIGNAL_TIME_PENDING) { - traceSpanLocked(ctx, layerID, bufferID, frameNumber, type, startTime, signalTime); + traceSpanLocked(ctx, layerId, bufferID, frameNumber, type, startTime, signalTime); } else { - mTraceTracker[layerID].pendingFences[bufferID].push_back( + mTraceTracker[layerId].pendingFences[bufferID].push_back( {.frameNumber = frameNumber, .type = type, .fence = fence, @@ -100,9 +100,9 @@ void FrameTracer::traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameN } void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, - int32_t layerID, uint64_t bufferID) { - if (mTraceTracker[layerID].pendingFences.count(bufferID)) { - auto& pendingFences = mTraceTracker[layerID].pendingFences[bufferID]; + int32_t layerId, uint64_t bufferID) { + if (mTraceTracker[layerId].pendingFences.count(bufferID)) { + auto& pendingFences = mTraceTracker[layerId].pendingFences[bufferID]; for (size_t i = 0; i < pendingFences.size(); ++i) { auto& pendingFence = pendingFences[i]; @@ -116,7 +116,7 @@ void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& if (signalTime != Fence::SIGNAL_TIME_INVALID && systemTime() - signalTime < kFenceSignallingDeadline) { - traceSpanLocked(ctx, layerID, bufferID, pendingFence.frameNumber, pendingFence.type, + traceSpanLocked(ctx, layerId, bufferID, pendingFence.frameNumber, pendingFence.type, pendingFence.startTime, signalTime); } @@ -126,7 +126,7 @@ void FrameTracer::tracePendingFencesLocked(FrameTracerDataSource::TraceContext& } } -void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, +void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration) { auto packet = ctx.NewTracePacket(); @@ -138,9 +138,9 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t } event->set_type(type); - if (mTraceTracker.find(layerID) != mTraceTracker.end() && - !mTraceTracker[layerID].layerName.empty()) { - const std::string& layerName = mTraceTracker[layerID].layerName; + if (mTraceTracker.find(layerId) != mTraceTracker.end() && + !mTraceTracker[layerId].layerName.empty()) { + const std::string& layerName = mTraceTracker[layerId].layerName; event->set_layer_name(layerName.c_str(), layerName.size()); } @@ -149,7 +149,7 @@ void FrameTracer::traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t } } -void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, +void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, nsecs_t endTime) { @@ -159,12 +159,12 @@ void FrameTracer::traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int3 timestamp = startTime; duration = endTime - startTime; } - traceLocked(ctx, layerID, bufferID, frameNumber, timestamp, type, duration); + traceLocked(ctx, layerId, bufferID, frameNumber, timestamp, type, duration); } -void FrameTracer::onDestroy(int32_t layerID) { +void FrameTracer::onDestroy(int32_t layerId) { std::lock_guard traceLock(mTraceMutex); - mTraceTracker.erase(layerID); + mTraceTracker.erase(layerId); } std::string FrameTracer::miniDump() { diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.h b/services/surfaceflinger/FrameTracer/FrameTracer.h index e91a7503cd..ef5df90fea 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.h +++ b/services/surfaceflinger/FrameTracer/FrameTracer.h @@ -47,21 +47,21 @@ public: void registerDataSource(); // Starts tracking a new layer for tracing. Needs to be called once before traceTimestamp() or // traceFence() for each layer. - void traceNewLayer(int32_t layerID, const std::string& layerName); + void traceNewLayer(int32_t layerId, const std::string& layerName); // Creates a trace point at the timestamp provided. - void traceTimestamp(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, + void traceTimestamp(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration = 0); // Creates a trace point after the provided fence has been signalled. If a startTime is provided // the trace will have be timestamped from startTime until fence signalling time. If no // startTime is provided, a durationless trace point will be created timestamped at fence // signalling time. If the fence hasn't signalled yet, the trace point will be created the next // time after signalling a trace call for this buffer occurs. - void traceFence(int32_t layerID, uint64_t bufferID, uint64_t frameNumber, + void traceFence(int32_t layerId, uint64_t bufferID, uint64_t frameNumber, const std::shared_ptr& fence, FrameEvent::BufferEventType type, nsecs_t startTime = 0); // Takes care of cleanup when a layer is destroyed. - void onDestroy(int32_t layerID); + void onDestroy(int32_t layerId); std::string miniDump(); @@ -88,15 +88,15 @@ private: // Checks if any pending fences for a layer and buffer have signalled and, if they have, creates // trace points for them. - void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + void tracePendingFencesLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID); // Creates a trace point by translating a start time and an end time to a timestamp and // duration. If startTime is later than end time it sets end time as the timestamp and the // duration to 0. Used by traceFence(). - void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, + void traceSpanLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, FrameEvent::BufferEventType type, nsecs_t startTime, nsecs_t endTime); - void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerID, uint64_t bufferID, + void traceLocked(FrameTracerDataSource::TraceContext& ctx, int32_t layerId, uint64_t bufferID, uint64_t frameNumber, nsecs_t timestamp, FrameEvent::BufferEventType type, nsecs_t duration = 0); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index d5a9ae1b3b..3757fc7c00 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1356,9 +1356,9 @@ void Layer::dumpCallingUidPid(std::string& result) const { void Layer::onDisconnect() { Mutex::Autolock lock(mFrameEventHistoryMutex); mFrameEventHistory.onDisconnect(); - const int32_t layerID = getSequence(); - mFlinger->mTimeStats->onDestroy(layerID); - mFlinger->mFrameTracer->onDestroy(layerID); + const int32_t layerId = getSequence(); + mFlinger->mTimeStats->onDestroy(layerId); + mFlinger->mFrameTracer->onDestroy(layerId); } void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index 3e47ec6856..611afce604 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -113,9 +113,9 @@ void TimeStats::incrementClientCompositionFrames() { mTimeStats.clientCompositionFrames++; } -bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { +bool TimeStats::recordReadyLocked(int32_t layerId, TimeRecord* timeRecord) { if (!timeRecord->ready) { - ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerID, + ALOGV("[%d]-[%" PRIu64 "]-presentFence is still not received", layerId, timeRecord->frameTime.frameNumber); return false; } @@ -128,7 +128,7 @@ bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { timeRecord->frameTime.acquireTime = timeRecord->acquireFence->getSignalTime(); timeRecord->acquireFence = nullptr; } else { - ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerID, + ALOGV("[%d]-[%" PRIu64 "]-acquireFence signal time is invalid", layerId, timeRecord->frameTime.frameNumber); } } @@ -141,7 +141,7 @@ bool TimeStats::recordReadyLocked(int32_t layerID, TimeRecord* timeRecord) { timeRecord->frameTime.presentTime = timeRecord->presentFence->getSignalTime(); timeRecord->presentFence = nullptr; } else { - ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerID, + ALOGV("[%d]-[%" PRIu64 "]-presentFence signal time invalid", layerId, timeRecord->frameTime.frameNumber); } } @@ -155,15 +155,15 @@ static int32_t msBetween(nsecs_t start, nsecs_t end) { return static_cast(delta); } -void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { +void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerId) { ATRACE_CALL(); - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; TimeRecord& prevTimeRecord = layerRecord.prevTimeRecord; std::deque& timeRecords = layerRecord.timeRecords; while (!timeRecords.empty()) { - if (!recordReadyLocked(layerID, &timeRecords[0])) break; - ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerID, + if (!recordReadyLocked(layerId, &timeRecords[0])) break; + ALOGV("[%d]-[%" PRIu64 "]-presentFenceTime[%" PRId64 "]", layerId, timeRecords[0].frameTime.frameNumber, timeRecords[0].frameTime.presentTime); if (prevTimeRecord.ready) { @@ -178,37 +178,37 @@ void TimeStats::flushAvailableRecordsToStatsLocked(int32_t layerID) { const int32_t postToAcquireMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.acquireTime); - ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-post2acquire[%d]", layerId, timeRecords[0].frameTime.frameNumber, postToAcquireMs); timeStatsLayer.deltas["post2acquire"].insert(postToAcquireMs); const int32_t postToPresentMs = msBetween(timeRecords[0].frameTime.postTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-post2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, postToPresentMs); timeStatsLayer.deltas["post2present"].insert(postToPresentMs); const int32_t acquireToPresentMs = msBetween(timeRecords[0].frameTime.acquireTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-acquire2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, acquireToPresentMs); timeStatsLayer.deltas["acquire2present"].insert(acquireToPresentMs); const int32_t latchToPresentMs = msBetween(timeRecords[0].frameTime.latchTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-latch2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, latchToPresentMs); timeStatsLayer.deltas["latch2present"].insert(latchToPresentMs); const int32_t desiredToPresentMs = msBetween(timeRecords[0].frameTime.desiredTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-desired2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, desiredToPresentMs); timeStatsLayer.deltas["desired2present"].insert(desiredToPresentMs); const int32_t presentToPresentMs = msBetween(prevTimeRecord.frameTime.presentTime, timeRecords[0].frameTime.presentTime); - ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerID, + ALOGV("[%d]-[%" PRIu64 "]-present2present[%d]", layerId, timeRecords[0].frameTime.frameNumber, presentToPresentMs); timeStatsLayer.deltas["present2present"].insert(presentToPresentMs); } @@ -227,28 +227,28 @@ static bool layerNameIsValid(const std::string& layerName) { layerName.compare(0, kMinLenLayerName, kPopupWindowPrefix) != 0; } -void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, +void TimeStats::setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerID, frameNumber, layerName.c_str(), + ALOGV("[%d]-[%" PRIu64 "]-[%s]-PostTime[%" PRId64 "]", layerId, frameNumber, layerName.c_str(), postTime); std::lock_guard lock(mMutex); if (!mTimeStats.stats.count(layerName) && mTimeStats.stats.size() >= MAX_NUM_LAYER_STATS) { return; } - if (!mTimeStatsTracker.count(layerID) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS && + if (!mTimeStatsTracker.count(layerId) && mTimeStatsTracker.size() < MAX_NUM_LAYER_RECORDS && layerNameIsValid(layerName)) { - mTimeStatsTracker[layerID].layerName = layerName; + mTimeStatsTracker[layerId].layerName = layerName; } - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.timeRecords.size() == MAX_NUM_TIME_RECORDS) { ALOGE("[%d]-[%s]-timeRecords is at its maximum size[%zu]. Ignore this when unittesting.", - layerID, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); - mTimeStatsTracker.erase(layerID); + layerId, layerRecord.layerName.c_str(), MAX_NUM_TIME_RECORDS); + mTimeStatsTracker.erase(layerId); return; } // For most media content, the acquireFence is invalid because the buffer is @@ -270,15 +270,15 @@ void TimeStats::setPostTime(int32_t layerID, uint64_t frameNumber, const std::st layerRecord.waitData = layerRecord.timeRecords.size() - 1; } -void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) { +void TimeStats::setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerID, frameNumber, latchTime); + ALOGV("[%d]-[%" PRIu64 "]-LatchTime[%" PRId64 "]", layerId, frameNumber, latchTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -288,15 +288,15 @@ void TimeStats::setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latc } } -void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) { +void TimeStats::setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerID, frameNumber, desiredTime); + ALOGV("[%d]-[%" PRIu64 "]-DesiredTime[%" PRId64 "]", layerId, frameNumber, desiredTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -306,15 +306,15 @@ void TimeStats::setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t de } } -void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) { +void TimeStats::setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerID, frameNumber, acquireTime); + ALOGV("[%d]-[%" PRIu64 "]-AcquireTime[%" PRId64 "]", layerId, frameNumber, acquireTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -324,17 +324,17 @@ void TimeStats::setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t ac } } -void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, +void TimeStats::setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerID, frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-AcquireFenceTime[%" PRId64 "]", layerId, frameNumber, acquireFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -344,15 +344,15 @@ void TimeStats::setAcquireFence(int32_t layerID, uint64_t frameNumber, } } -void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) { +void TimeStats::setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerID, frameNumber, presentTime); + ALOGV("[%d]-[%" PRIu64 "]-PresentTime[%" PRId64 "]", layerId, frameNumber, presentTime); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -363,20 +363,20 @@ void TimeStats::setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t pr layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerID); + flushAvailableRecordsToStatsLocked(layerId); } -void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, +void TimeStats::setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerID, frameNumber, + ALOGV("[%d]-[%" PRIu64 "]-PresentFenceTime[%" PRId64 "]", layerId, frameNumber, presentFence->getSignalTime()); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; if (layerRecord.waitData < 0 || layerRecord.waitData >= static_cast(layerRecord.timeRecords.size())) return; @@ -387,25 +387,25 @@ void TimeStats::setPresentFence(int32_t layerID, uint64_t frameNumber, layerRecord.waitData++; } - flushAvailableRecordsToStatsLocked(layerID); + flushAvailableRecordsToStatsLocked(layerId); } -void TimeStats::onDestroy(int32_t layerID) { +void TimeStats::onDestroy(int32_t layerId) { ATRACE_CALL(); - ALOGV("[%d]-onDestroy", layerID); + ALOGV("[%d]-onDestroy", layerId); std::lock_guard lock(mMutex); - mTimeStatsTracker.erase(layerID); + mTimeStatsTracker.erase(layerId); } -void TimeStats::removeTimeRecord(int32_t layerID, uint64_t frameNumber) { +void TimeStats::removeTimeRecord(int32_t layerId, uint64_t frameNumber) { if (!mEnabled.load()) return; ATRACE_CALL(); - ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerID, frameNumber); + ALOGV("[%d]-[%" PRIu64 "]-removeTimeRecord", layerId, frameNumber); std::lock_guard lock(mMutex); - if (!mTimeStatsTracker.count(layerID)) return; - LayerRecord& layerRecord = mTimeStatsTracker[layerID]; + if (!mTimeStatsTracker.count(layerId)) return; + LayerRecord& layerRecord = mTimeStatsTracker[layerId]; size_t removeAt = 0; for (const TimeRecord& record : layerRecord.timeRecords) { if (record.frameTime.frameNumber == frameNumber) break; diff --git a/services/surfaceflinger/TimeStats/TimeStats.h b/services/surfaceflinger/TimeStats/TimeStats.h index 1313132920..6e71f5a14e 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.h +++ b/services/surfaceflinger/TimeStats/TimeStats.h @@ -44,20 +44,20 @@ public: virtual void incrementMissedFrames() = 0; virtual void incrementClientCompositionFrames() = 0; - virtual void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + virtual void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) = 0; - virtual void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) = 0; - virtual void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) = 0; - virtual void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) = 0; - virtual void setAcquireFence(int32_t layerID, uint64_t frameNumber, + virtual void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) = 0; + virtual void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) = 0; + virtual void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) = 0; + virtual void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) = 0; - virtual void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) = 0; - virtual void setPresentFence(int32_t layerID, uint64_t frameNumber, + virtual void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) = 0; + virtual void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) = 0; // Clean up the layer record - virtual void onDestroy(int32_t layerID) = 0; + virtual void onDestroy(int32_t layerId) = 0; // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - virtual void removeTimeRecord(int32_t layerID, uint64_t frameNumber) = 0; + virtual void removeTimeRecord(int32_t layerId, uint64_t frameNumber) = 0; virtual void setPowerMode(int32_t powerMode) = 0; // Source of truth is RefrehRateStats. @@ -116,20 +116,20 @@ public: void incrementMissedFrames() override; void incrementClientCompositionFrames() override; - void setPostTime(int32_t layerID, uint64_t frameNumber, const std::string& layerName, + void setPostTime(int32_t layerId, uint64_t frameNumber, const std::string& layerName, nsecs_t postTime) override; - void setLatchTime(int32_t layerID, uint64_t frameNumber, nsecs_t latchTime) override; - void setDesiredTime(int32_t layerID, uint64_t frameNumber, nsecs_t desiredTime) override; - void setAcquireTime(int32_t layerID, uint64_t frameNumber, nsecs_t acquireTime) override; - void setAcquireFence(int32_t layerID, uint64_t frameNumber, + void setLatchTime(int32_t layerId, uint64_t frameNumber, nsecs_t latchTime) override; + void setDesiredTime(int32_t layerId, uint64_t frameNumber, nsecs_t desiredTime) override; + void setAcquireTime(int32_t layerId, uint64_t frameNumber, nsecs_t acquireTime) override; + void setAcquireFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& acquireFence) override; - void setPresentTime(int32_t layerID, uint64_t frameNumber, nsecs_t presentTime) override; - void setPresentFence(int32_t layerID, uint64_t frameNumber, + void setPresentTime(int32_t layerId, uint64_t frameNumber, nsecs_t presentTime) override; + void setPresentFence(int32_t layerId, uint64_t frameNumber, const std::shared_ptr& presentFence) override; // Clean up the layer record - void onDestroy(int32_t layerID) override; + void onDestroy(int32_t layerId) override; // If SF skips or rejects a buffer, remove the corresponding TimeRecord. - void removeTimeRecord(int32_t layerID, uint64_t frameNumber) override; + void removeTimeRecord(int32_t layerId, uint64_t frameNumber) override; void setPowerMode(int32_t powerMode) override; // Source of truth is RefrehRateStats. @@ -139,8 +139,8 @@ public: static const size_t MAX_NUM_TIME_RECORDS = 64; private: - bool recordReadyLocked(int32_t layerID, TimeRecord* timeRecord); - void flushAvailableRecordsToStatsLocked(int32_t layerID); + bool recordReadyLocked(int32_t layerId, TimeRecord* timeRecord); + void flushAvailableRecordsToStatsLocked(int32_t layerId); void flushPowerTimeLocked(); void flushAvailableGlobalRecordsToStatsLocked(); @@ -152,7 +152,7 @@ private: std::atomic mEnabled = false; std::mutex mMutex; TimeStatsHelper::TimeStatsGlobal mTimeStats; - // Hashmap for LayerRecord with layerID as the hash key + // Hashmap for LayerRecord with layerId as the hash key std::unordered_map mTimeStatsTracker; PowerTime mPowerTime; GlobalRecord mGlobalRecord; diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp index b5af591e25..c334bcf85d 100644 --- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -82,8 +82,8 @@ TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - mFrameTracer->traceNewLayer(layerID, layerName); + const int32_t layerId = 5; + mFrameTracer->traceNewLayer(layerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); @@ -92,7 +92,7 @@ TEST_F(FrameTracerTest, traceNewLayerStartsTrackingLayerWhenTracing) { tracingSession->StartBlocking(); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); tracingSession->StopBlocking(); @@ -103,31 +103,31 @@ TEST_F(FrameTracerTest, onDestroyRemovesTheTrackedLayer) { "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; - const int32_t secondLayerID = 6; + const int32_t layerId = 5; + const int32_t secondlayerId = 6; auto tracingSession = getTracingSessionForTest(); tracingSession->StartBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceNewLayer(secondLayerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceNewLayer(secondlayerId, layerName); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 2\n"); tracingSession->StopBlocking(); - mFrameTracer->onDestroy(layerID); + mFrameTracer->onDestroy(layerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); - mFrameTracer->onDestroy(layerID); + mFrameTracer->onDestroy(layerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 1\n"); - mFrameTracer->onDestroy(secondLayerID); + mFrameTracer->onDestroy(secondlayerId); EXPECT_EQ(mFrameTracer->miniDump(), "FrameTracer miniDump:\nNumber of layers currently being traced is 0\n"); } TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 1; + const int32_t layerId = 1; const uint32_t bufferID = 2; const uint64_t frameNumber = 3; const nsecs_t timestamp = 4; @@ -141,9 +141,9 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration); // Create second trace packet to finalize the previous one. - mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -157,10 +157,10 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceTimestamp(layerID, bufferID, frameNumber, timestamp, type, duration); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceTimestamp(layerId, bufferID, frameNumber, timestamp, type, duration); // Create second trace packet to finalize the previous one. - mFrameTracer->traceTimestamp(layerID, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, 0, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -191,7 +191,7 @@ TEST_F(FrameTracerTest, canTraceAfterAddingLayer) { TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -204,10 +204,10 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); // Trace. - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type); // Create extra trace packet to (hopefully not) trigger and finalize the fence packet. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); EXPECT_EQ(raw_trace.size(), 0); @@ -219,12 +219,12 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fenceTime, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fenceTime, type); const nsecs_t timestamp = systemTime(); fenceFactory.signalAllForTest(Fence::NO_FENCE, timestamp); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -254,7 +254,7 @@ TEST_F(FrameTracerTest, traceFenceTriggersOnNextTraceAfterFenceFired) { TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDuration) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -264,24 +264,24 @@ TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDurat tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); // traceFence called after fence signalled. const nsecs_t signalTime1 = systemTime(); const nsecs_t startTime1 = signalTime1 + 100000; auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence1, type, startTime1); // traceFence called before fence signalled. const nsecs_t signalTime2 = systemTime(); const nsecs_t startTime2 = signalTime2 + 100000; auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence2, type, startTime2); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -309,7 +309,7 @@ TEST_F(FrameTracerTest, traceFenceWithStartTimeAfterSignalTime_ShouldHaveNoDurat TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -321,11 +321,11 @@ TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence, type); + mFrameTracer->traceNewLayer(layerId, layerName); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence, type); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime); // Create extra trace packet to trigger and finalize any previous fence packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); @@ -334,7 +334,7 @@ TEST_F(FrameTracerTest, traceFenceOlderThanDeadline_ShouldBeIgnored) { TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) { const std::string layerName = "co.layername#0"; - const int32_t layerID = 5; + const int32_t layerId = 5; const uint32_t bufferID = 4; const uint64_t frameNumber = 3; const auto type = FrameTracer::FrameEvent::ACQUIRE_FENCE; @@ -345,24 +345,24 @@ TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) tracingSession->StartBlocking(); // Clean up irrelevant traces. tracingSession->ReadTraceBlocking(); - mFrameTracer->traceNewLayer(layerID, layerName); + mFrameTracer->traceNewLayer(layerId, layerName); // traceFence called after fence signalled. const nsecs_t signalTime1 = systemTime(); const nsecs_t startTime1 = signalTime1 - duration; auto fence1 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime1); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence1, type, startTime1); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence1, type, startTime1); // traceFence called before fence signalled. const nsecs_t signalTime2 = systemTime(); const nsecs_t startTime2 = signalTime2 - duration; auto fence2 = fenceFactory.createFenceTimeForTest(Fence::NO_FENCE); - mFrameTracer->traceFence(layerID, bufferID, frameNumber, fence2, type, startTime2); + mFrameTracer->traceFence(layerId, bufferID, frameNumber, fence2, type, startTime2); fenceFactory.signalAllForTest(Fence::NO_FENCE, signalTime2); // Create extra trace packet to trigger and finalize fence trace packets. - mFrameTracer->traceTimestamp(layerID, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); + mFrameTracer->traceTimestamp(layerId, bufferID, 0, 0, FrameTracer::FrameEvent::UNSPECIFIED); tracingSession->StopBlocking(); std::vector raw_trace = tracingSession->ReadTraceBlocking(); diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 4eb9ec3672..7b60fa2ea6 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -170,8 +170,8 @@ std::string TimeStatsTest::inputCommand(InputCommand cmd, bool useProto) { return result; } -static std::string genLayerName(int32_t layerID) { - return (layerID < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerID); +static std::string genLayerName(int32_t layerId) { + return (layerId < 0 ? "PopupWindow:b54fcd1#0" : "com.dummy#") + std::to_string(layerId); } void TimeStatsTest::setTimeStamp(TimeStamp type, int32_t id, uint64_t frameNumber, nsecs_t ts) { @@ -560,22 +560,22 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { EXPECT_TRUE(inputCommand(InputCommand::ENABLE, FMT_STRING).empty()); for (size_t i = 0; i < 10000000; ++i) { - const int32_t layerID = genRandomInt32(-1, 10); + const int32_t layerId = genRandomInt32(-1, 10); const int32_t frameNumber = genRandomInt32(1, 10); switch (genRandomInt32(0, 100)) { case 0: ALOGV("removeTimeRecord"); - ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerID, frameNumber)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->removeTimeRecord(layerId, frameNumber)); continue; case 1: ALOGV("onDestroy"); - ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerID)); + ASSERT_NO_FATAL_FAILURE(mTimeStats->onDestroy(layerId)); continue; } TimeStamp type = static_cast(genRandomInt32(TIME_STAMP_BEGIN, TIME_STAMP_END)); const int32_t ts = genRandomInt32(1, 1000000000); - ALOGV("type[%d], layerID[%d], frameNumber[%d], ts[%d]", type, layerID, frameNumber, ts); - setTimeStamp(type, layerID, frameNumber, ts); + ALOGV("type[%d], layerId[%d], frameNumber[%d], ts[%d]", type, layerId, frameNumber, ts); + setTimeStamp(type, layerId, frameNumber, ts); } } -- cgit v1.2.3-59-g8ed1b From 487340f03dd621406c0e293200d22a1c06a8c4df Mon Sep 17 00:00:00 2001 From: Yiwei Zhang Date: Mon, 18 Nov 2019 17:42:12 -0800 Subject: TimeStats: make sure acquire fence is captured Previously, if setAcquireFence happens earlier than setPostTime, the acquire fence is not recorded in TimeStats which ends up with acquire time being the same with post time. This issue is almost eliminated after a previous refactoring of the order of recording TimeStats and EGL throttling logic. Since acquire fence is already available at post time, this change just captures that by then to avoid any chance of missing the acquire fence. Bug: 140266250 Test: atest libsurfaceflinger_unittest:TimeStatsTest Change-Id: I90a5ab609afc7054c618273c3af79c9d12d85730 --- services/surfaceflinger/BufferQueueLayer.cpp | 2 -- services/surfaceflinger/Layer.cpp | 2 ++ 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 9580ad5515..d51d34b3c5 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -307,8 +307,6 @@ status_t BufferQueueLayer::updateTexImage(bool& recomputeVisibleRegions, nsecs_t } uint64_t bufferID = mQueueItems[0].mGraphicBuffer->getId(); - mFlinger->mTimeStats->setAcquireFence(layerId, currentFrameNumber, - mQueueItems[0].mFenceTime); mFlinger->mFrameTracer->traceFence(layerId, bufferID, currentFrameNumber, mQueueItems[0].mFenceTime, FrameTracer::FrameEvent::ACQUIRE_FENCE); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5a19d8aa51..ce9aab5c7a 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1370,6 +1370,8 @@ void Layer::addAndGetFrameTimestamps(const NewFrameEventsEntry* newTimestamps, if (newTimestamps) { mFlinger->mTimeStats->setPostTime(getSequence(), newTimestamps->frameNumber, getName().c_str(), newTimestamps->postedTime); + mFlinger->mTimeStats->setAcquireFence(getSequence(), newTimestamps->frameNumber, + newTimestamps->acquireFence); } Mutex::Autolock lock(mFrameEventHistoryMutex); -- cgit v1.2.3-59-g8ed1b From 2d9a429a10a69bf57503f4f706856f079675dd14 Mon Sep 17 00:00:00 2001 From: chaviw Date: Mon, 2 Dec 2019 16:00:24 -0800 Subject: Avoid promoting weak reference of Layer on Binder thread. BufferQueueLayer registers itself to ConsumerBase so it can receive callbacks about incoming frames. When doing this, ConsumerBase holds a weak reference to BufferQueueLayer. This would normally be fine except ConsumerBase promotes the weak pointer on a Binder thread. This leads to a race where the layer is ready to get destroyed in SurfaceFlinger, but ConsumerBase promotes the layer. The layer will get destroyed after the function finishes, but now it gets destroyed off the main thread. When this happens, a lot of unexpected behavior occurs since the layer destructor expects the call to only happen on the main thread and therefore, doesn't hold any locks. Instead of giving ConsumerBase a weak reference to the layer, we can give it a reference to a listener. This listener can be managed by BufferQueueLayer and will only hold a raw reference to the Layer. ConsumerBase can promote the listener, but it will not be holding a strong reference to the Layer, allowing the layer to get destroyed on the main thread. We hold a lock when accessing the raw reference to ensure it's not being destroyed. The raw reference is nulled when the layer is getting destroyed to ensure no more calls are made to the layer after it's destroyed. Fixes: 143735125 Fixes: 143200062 Test: go/wm-smoke Change-Id: I47122b0e4c6d73f23a64027fd3622b2d7fd28871 --- services/surfaceflinger/BufferQueueLayer.cpp | 58 +++++++++++++++++++++++++++- services/surfaceflinger/BufferQueueLayer.h | 41 +++++++++++++++----- 2 files changed, 88 insertions(+), 11 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d51d34b3c5..543b0c458b 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -35,6 +35,7 @@ namespace android { BufferQueueLayer::BufferQueueLayer(const LayerCreationArgs& args) : BufferLayer(args) {} BufferQueueLayer::~BufferQueueLayer() { + mContentsChangedListener->abandon(); mConsumer->abandon(); } @@ -480,7 +481,9 @@ void BufferQueueLayer::onFirstRef() { mFlinger->getFactory().createBufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this); mConsumer->setConsumerUsageBits(getEffectiveUsage(0)); - mConsumer->setContentsChangedListener(this); + + mContentsChangedListener = new ContentsChangedListener(this); + mConsumer->setContentsChangedListener(mContentsChangedListener); mConsumer->setName(String8(mName.data(), mName.size())); // BufferQueueCore::mMaxDequeuedBufferCount is default to 1 @@ -552,4 +555,57 @@ sp BufferQueueLayer::createClone() { return layer; } +// ----------------------------------------------------------------------- +// Interface implementation for BufferLayerConsumer::ContentsChangedListener +// ----------------------------------------------------------------------- + +void BufferQueueLayer::ContentsChangedListener::onFrameAvailable(const BufferItem& item) { + Mutex::Autolock lock(mMutex); + if (mBufferQueueLayer != nullptr) { + mBufferQueueLayer->onFrameAvailable(item); + } +} + +void BufferQueueLayer::ContentsChangedListener::onFrameReplaced(const BufferItem& item) { + Mutex::Autolock lock(mMutex); + if (mBufferQueueLayer != nullptr) { + mBufferQueueLayer->onFrameReplaced(item); + } +} + +void BufferQueueLayer::ContentsChangedListener::onSidebandStreamChanged() { + Mutex::Autolock lock(mMutex); + if (mBufferQueueLayer != nullptr) { + mBufferQueueLayer->onSidebandStreamChanged(); + } +} + +void BufferQueueLayer::ContentsChangedListener::onFrameDequeued(const uint64_t bufferId) { + Mutex::Autolock lock(mMutex); + if (mBufferQueueLayer != nullptr) { + mBufferQueueLayer->onFrameDequeued(bufferId); + } +} + +void BufferQueueLayer::ContentsChangedListener::onFrameDetached(const uint64_t bufferId) { + Mutex::Autolock lock(mMutex); + if (mBufferQueueLayer != nullptr) { + mBufferQueueLayer->onFrameDetached(bufferId); + } +} + +void BufferQueueLayer::ContentsChangedListener::onFrameCancelled(const uint64_t bufferId) { + Mutex::Autolock lock(mMutex); + if (mBufferQueueLayer != nullptr) { + mBufferQueueLayer->onFrameCancelled(bufferId); + } +} + +void BufferQueueLayer::ContentsChangedListener::abandon() { + Mutex::Autolock lock(mMutex); + mBufferQueueLayer = nullptr; +} + +// ----------------------------------------------------------------------- + } // namespace android diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 1b1fccd392..b0405561bb 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -29,7 +29,7 @@ namespace android { * This also implements onFrameAvailable(), which notifies SurfaceFlinger * that new data has arrived. */ -class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener { +class BufferQueueLayer : public BufferLayer { public: // Only call while mStateLock is held explicit BufferQueueLayer(const LayerCreationArgs&); @@ -84,18 +84,37 @@ private: void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; sp createClone() override; - // ----------------------------------------------------------------------- - // Interface implementation for BufferLayerConsumer::ContentsChangedListener - // ----------------------------------------------------------------------- + void onFrameAvailable(const BufferItem& item); + void onFrameReplaced(const BufferItem& item); + void onSidebandStreamChanged(); + void onFrameDequeued(const uint64_t bufferId); + void onFrameDetached(const uint64_t bufferId); + void onFrameCancelled(const uint64_t bufferId); + protected: void gatherBufferInfo() override; - void onFrameAvailable(const BufferItem& item) override; - void onFrameReplaced(const BufferItem& item) override; - void onSidebandStreamChanged() override; - void onFrameDequeued(const uint64_t bufferId) override; - void onFrameDetached(const uint64_t bufferId) override; - void onFrameCancelled(const uint64_t bufferId) override; + // ----------------------------------------------------------------------- + // Interface implementation for BufferLayerConsumer::ContentsChangedListener + // ----------------------------------------------------------------------- + class ContentsChangedListener : public BufferLayerConsumer::ContentsChangedListener { + public: + ContentsChangedListener(BufferQueueLayer* bufferQueueLayer) + : mBufferQueueLayer(bufferQueueLayer) {} + void abandon(); + + protected: + void onFrameAvailable(const BufferItem& item) override; + void onFrameReplaced(const BufferItem& item) override; + void onSidebandStreamChanged() override; + void onFrameDequeued(const uint64_t bufferId) override; + void onFrameDetached(const uint64_t bufferId) override; + void onFrameCancelled(const uint64_t bufferId) override; + + private: + BufferQueueLayer* mBufferQueueLayer = nullptr; + Mutex mMutex; + }; // ----------------------------------------------------------------------- public: @@ -130,6 +149,8 @@ private: // thread-safe std::atomic mQueuedFrames{0}; std::atomic mSidebandStreamChanged{false}; + + sp mContentsChangedListener; }; } // namespace android -- cgit v1.2.3-59-g8ed1b From 2139f73d98f3f0d31f0f90bcca7f4537c66e5e70 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Wed, 13 Nov 2019 18:56:40 -0800 Subject: SurfaceFlinger: use config groups Composer 2.4 adds a new attribute for configs groups. This change groups configs according to their group and store them in RefreshRateConfigs. Test: rev up composer to 2.4 and test refresh rate switching Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test Bug: 141329414 Fixes: 139751853 Change-Id: Ic0bcd3da4bf6b73efa11a60c2594948ce030362f --- services/surfaceflinger/BufferQueueLayer.cpp | 3 +- services/surfaceflinger/BufferStateLayer.cpp | 3 +- services/surfaceflinger/DisplayDevice.cpp | 6 +- services/surfaceflinger/DisplayDevice.h | 7 +- services/surfaceflinger/RefreshRateOverlay.cpp | 6 +- services/surfaceflinger/RefreshRateOverlay.h | 4 +- services/surfaceflinger/Scheduler/EventThread.cpp | 8 +- services/surfaceflinger/Scheduler/EventThread.h | 5 +- services/surfaceflinger/Scheduler/HwcStrongTypes.h | 27 +++ services/surfaceflinger/Scheduler/LayerHistory.cpp | 11 +- services/surfaceflinger/Scheduler/LayerHistory.h | 3 +- services/surfaceflinger/Scheduler/LayerInfo.h | 4 - services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 30 +-- services/surfaceflinger/Scheduler/PhaseOffsets.h | 20 +- .../Scheduler/RefreshRateConfigs.cpp | 208 ++++++++++++--------- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 134 +++++++++---- .../surfaceflinger/Scheduler/RefreshRateStats.h | 29 ++- services/surfaceflinger/Scheduler/Scheduler.cpp | 121 +++++------- services/surfaceflinger/Scheduler/Scheduler.h | 34 ++-- services/surfaceflinger/Scheduler/StrongTyping.h | 20 +- services/surfaceflinger/Scheduler/VSyncDispatch.h | 2 +- .../Scheduler/VSyncDispatchTimerQueue.h | 3 +- .../surfaceflinger/Scheduler/VSyncModulator.cpp | 11 +- services/surfaceflinger/Scheduler/VSyncModulator.h | 3 - services/surfaceflinger/SurfaceFlinger.cpp | 160 +++++++++------- services/surfaceflinger/SurfaceFlinger.h | 21 ++- .../tests/unittests/DisplayTransactionTest.cpp | 2 +- .../tests/unittests/EventThreadTest.cpp | 10 +- .../tests/unittests/FakePhaseOffsets.h | 10 +- .../tests/unittests/LayerHistoryTest.cpp | 44 ++--- .../tests/unittests/RefreshRateConfigsTest.cpp | 195 +++++++++++++++---- .../tests/unittests/RefreshRateStatsTest.cpp | 29 +-- .../tests/unittests/SchedulerTest.cpp | 9 +- .../tests/unittests/StrongTypingTest.cpp | 14 +- .../tests/unittests/TestableSurfaceFlinger.h | 25 +-- .../tests/unittests/mock/MockEventThread.h | 2 +- 36 files changed, 735 insertions(+), 488 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/HwcStrongTypes.h (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index d51d34b3c5..8957e90034 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -399,8 +399,7 @@ void BufferQueueLayer::onFrameAvailable(const BufferItem& item) { // Add this buffer from our internal queue tracker { // Autolock scope const nsecs_t presentTime = item.mIsAutoTimestamp ? 0 : item.mTimestamp; - const bool isHDR = item.mHdrMetadata.validTypes != 0; - mFlinger->mScheduler->recordLayerHistory(this, presentTime, isHDR); + mFlinger->mScheduler->recordLayerHistory(this, presentTime); Mutex::Autolock lock(mQueueItemLock); // Reset the frame number tracker when we receive the first buffer after diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index d68fe8e3a5..1e471e53ff 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -247,8 +247,7 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; - const bool isHDR = mCurrentState.hdrMetadata.validTypes != 0; - mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime, isHDR); + mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime); return true; } diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index 89123df46c..84ec597d2f 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -132,11 +132,11 @@ bool DisplayDevice::isPoweredOn() const { } // ---------------------------------------------------------------------------- -void DisplayDevice::setActiveConfig(int mode) { +void DisplayDevice::setActiveConfig(HwcConfigIndexType mode) { mActiveConfig = mode; } -int DisplayDevice::getActiveConfig() const { +HwcConfigIndexType DisplayDevice::getActiveConfig() const { return mActiveConfig; } @@ -285,7 +285,7 @@ void DisplayDevice::dump(std::string& result) const { result.append(" "); StringAppendF(&result, "powerMode=%d, ", mPowerMode); - StringAppendF(&result, "activeConfig=%d, ", mActiveConfig); + StringAppendF(&result, "activeConfig=%d, ", mActiveConfig.value()); getCompositionDisplay()->dump(result); } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index ce4e1e6b09..2d0875b0c5 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -43,6 +43,7 @@ #include "DisplayHardware/DisplayIdentification.h" #include "DisplayHardware/PowerAdvisor.h" #include "RenderArea.h" +#include "Scheduler/HwcStrongTypes.h" namespace android { @@ -141,8 +142,8 @@ public: /* ------------------------------------------------------------------------ * Display active config management. */ - int getActiveConfig() const; - void setActiveConfig(int mode); + HwcConfigIndexType getActiveConfig() const; + void setActiveConfig(HwcConfigIndexType mode); // release HWC resources (if any) for removable displays void disconnect(); @@ -186,7 +187,7 @@ private: // Current power mode int mPowerMode; // Current active config - int mActiveConfig; + HwcConfigIndexType mActiveConfig; // TODO(b/74619554): Remove special cases for primary display. const bool mIsPrimary; diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 976fedb58a..38a80a798a 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -20,8 +20,6 @@ namespace android { -using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; - RefreshRateOverlay::RefreshRateOverlay(SurfaceFlinger& flinger) : mFlinger(flinger), mClient(new Client(&mFlinger)) { createLayer(); @@ -51,8 +49,8 @@ bool RefreshRateOverlay::createLayer() { return true; } -void RefreshRateOverlay::changeRefreshRate(RefreshRateType type) { - const half3& color = (type == RefreshRateType::PERFORMANCE) ? GREEN : RED; +void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { + const half3& color = (refreshRate.fps > 65.0f) ? GREEN : RED; mLayer->setColor(color); mFlinger.mTransactionFlags.fetch_or(eTransactionMask); } diff --git a/services/surfaceflinger/RefreshRateOverlay.h b/services/surfaceflinger/RefreshRateOverlay.h index ce29bc3243..414bc47ac9 100644 --- a/services/surfaceflinger/RefreshRateOverlay.h +++ b/services/surfaceflinger/RefreshRateOverlay.h @@ -19,13 +19,13 @@ namespace android { -using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; +using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; class RefreshRateOverlay { public: RefreshRateOverlay(SurfaceFlinger& flinger); - void changeRefreshRate(RefreshRateType type); + void changeRefreshRate(const RefreshRate& refreshRate); private: bool createLayer(); diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 8d9adc8525..ff800c3dbf 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -36,6 +36,7 @@ #include #include "EventThread.h" +#include "HwcStrongTypes.h" using namespace std::chrono_literals; @@ -101,10 +102,11 @@ DisplayEventReceiver::Event makeVSync(PhysicalDisplayId displayId, nsecs_t times return event; } -DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, int32_t configId) { +DisplayEventReceiver::Event makeConfigChanged(PhysicalDisplayId displayId, + HwcConfigIndexType configId) { DisplayEventReceiver::Event event; event.header = {DisplayEventReceiver::DISPLAY_EVENT_CONFIG_CHANGED, displayId, systemTime()}; - event.config.configId = configId; + event.config.configId = configId.value(); return event; } @@ -290,7 +292,7 @@ void EventThread::onHotplugReceived(PhysicalDisplayId displayId, bool connected) mCondition.notify_all(); } -void EventThread::onConfigChanged(PhysicalDisplayId displayId, int32_t configId) { +void EventThread::onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) { std::lock_guard lock(mMutex); mPendingEvents.push_back(makeConfigChanged(displayId, configId)); diff --git a/services/surfaceflinger/Scheduler/EventThread.h b/services/surfaceflinger/Scheduler/EventThread.h index a029586088..a42546c7df 100644 --- a/services/surfaceflinger/Scheduler/EventThread.h +++ b/services/surfaceflinger/Scheduler/EventThread.h @@ -33,6 +33,7 @@ #include #include +#include "HwcStrongTypes.h" // --------------------------------------------------------------------------- namespace android { @@ -109,7 +110,7 @@ public: virtual void onHotplugReceived(PhysicalDisplayId displayId, bool connected) = 0; // called when SF changes the active config and apps needs to be notified about the change - virtual void onConfigChanged(PhysicalDisplayId displayId, int32_t configId) = 0; + virtual void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) = 0; virtual void dump(std::string& result) const = 0; @@ -146,7 +147,7 @@ public: void onHotplugReceived(PhysicalDisplayId displayId, bool connected) override; - void onConfigChanged(PhysicalDisplayId displayId, int32_t configId) override; + void onConfigChanged(PhysicalDisplayId displayId, HwcConfigIndexType configId) override; void dump(std::string& result) const override; diff --git a/services/surfaceflinger/Scheduler/HwcStrongTypes.h b/services/surfaceflinger/Scheduler/HwcStrongTypes.h new file mode 100644 index 0000000000..cfbbdfe4fd --- /dev/null +++ b/services/surfaceflinger/Scheduler/HwcStrongTypes.h @@ -0,0 +1,27 @@ +/* + * Copyright 2019 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. + */ + +#pragma once + +#include "StrongTyping.h" + +namespace android { + +// Strong types for the different indexes as they are referring to a different base. +using HwcConfigIndexType = StrongTyping; +using HwcConfigGroupType = StrongTyping; + +} // namespace android \ No newline at end of file diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index 8b717289c6..146ec1bce0 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -39,7 +39,7 @@ namespace android::scheduler { namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { - return layer.isVisible() && (info.isHDR() || info.getLastUpdatedTime() >= threshold); + return layer.isVisible() && info.getLastUpdatedTime() >= threshold; } bool traceEnabled() { @@ -69,7 +69,7 @@ void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highR mLayerInfos.emplace_back(layer, std::move(info)); } -void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t now) { +void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now) { std::lock_guard lock(mLock); const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), @@ -78,7 +78,6 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t const auto& info = it->second; info->setLastPresentTime(presentTime, now); - info->setIsHDR(isHDR); // Activate layer if inactive. if (const auto end = activeLayers().end(); it >= end) { @@ -89,7 +88,6 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, bool isHDR, nsecs_t LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { float maxRefreshRate = 0; - bool isHDR = false; std::lock_guard lock(mLock); @@ -108,13 +106,12 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { trace(layer, std::round(refreshRate)); } } - isHDR |= info->isHDR(); } if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("%s: maxRefreshRate=%.2f, isHDR=%d", __FUNCTION__, maxRefreshRate, isHDR); + ALOGD("%s: maxRefreshRate=%.2f", __FUNCTION__, maxRefreshRate); } - return {maxRefreshRate, isHDR}; + return {maxRefreshRate}; } void LayerHistory::partitionLayers(nsecs_t now) { diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index bd9aca1aed..745c4c16ee 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -46,11 +46,10 @@ public: void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate); // Marks the layer as active, and records the given state to its history. - void record(Layer*, nsecs_t presentTime, bool isHDR, nsecs_t now); + void record(Layer*, nsecs_t presentTime, nsecs_t now); struct Summary { float maxRefreshRate; // Maximum refresh rate among recently active layers. - bool isHDR; // True if any recently active layer has HDR content. }; // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. diff --git a/services/surfaceflinger/Scheduler/LayerInfo.h b/services/surfaceflinger/Scheduler/LayerInfo.h index b86709fc9c..cb81ca2840 100644 --- a/services/surfaceflinger/Scheduler/LayerInfo.h +++ b/services/surfaceflinger/Scheduler/LayerInfo.h @@ -140,9 +140,6 @@ public: // updated time, the updated time is the present time. void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); - bool isHDR() const { return mIsHDR; } - void setIsHDR(bool isHDR) { mIsHDR = isHDR; } - bool isRecentlyActive(nsecs_t now) const { return mPresentTimeHistory.isRecentlyActive(now); } bool isFrequent(nsecs_t now) const { return mPresentTimeHistory.isFrequent(now); } @@ -167,7 +164,6 @@ private: nsecs_t mLastPresentTime = 0; RefreshRateHistory mRefreshRateHistory{mHighRefreshRate}; PresentTimeHistory mPresentTimeHistory; - bool mIsHDR = false; }; } // namespace scheduler diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 6be88f89f9..12832a690a 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -48,16 +48,18 @@ PhaseOffsets::PhaseOffsets() { getProperty("debug.sf.phase_offset_threshold_for_next_vsync_ns") .value_or(std::numeric_limits::max()); - const Offsets defaultOffsets = getDefaultOffsets(thresholdForNextVsync); - const Offsets highFpsOffsets = getHighFpsOffsets(thresholdForNextVsync); - - mOffsets.insert({RefreshRateType::DEFAULT, defaultOffsets}); - mOffsets.insert({RefreshRateType::PERFORMANCE, highFpsOffsets}); + mDefaultOffsets = getDefaultOffsets(thresholdForNextVsync); + mHighFpsOffsets = getHighFpsOffsets(thresholdForNextVsync); } -PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate( - RefreshRateType refreshRateType) const { - return mOffsets.at(refreshRateType); +PhaseOffsets::Offsets PhaseOffsets::getOffsetsForRefreshRate(float fps) const { + // TODO(145561086): Once offsets are common for all refresh rates we can remove the magic + // number for refresh rate + if (fps > 65.0f) { + return mHighFpsOffsets; + } else { + return mDefaultOffsets; + } } void PhaseOffsets::dump(std::string& result) const { @@ -80,13 +82,13 @@ PhaseOffsets::Offsets PhaseOffsets::getDefaultOffsets(nsecs_t thresholdForNextVs const auto earlyAppOffsetNs = getProperty("debug.sf.early_app_phase_offset_ns"); const auto earlyGlAppOffsetNs = getProperty("debug.sf.early_gl_app_phase_offset_ns"); - return {{RefreshRateType::DEFAULT, earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs), + return {{earlySfOffsetNs.value_or(sfVsyncPhaseOffsetNs), earlyAppOffsetNs.value_or(vsyncPhaseOffsetNs)}, - {RefreshRateType::DEFAULT, earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs), + {earlyGlSfOffsetNs.value_or(sfVsyncPhaseOffsetNs), earlyGlAppOffsetNs.value_or(vsyncPhaseOffsetNs)}, - {RefreshRateType::DEFAULT, sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}, + {sfVsyncPhaseOffsetNs, vsyncPhaseOffsetNs}, thresholdForNextVsync}; } @@ -104,13 +106,13 @@ PhaseOffsets::Offsets PhaseOffsets::getHighFpsOffsets(nsecs_t thresholdForNextVs const auto highFpsEarlyGlAppOffsetNs = getProperty("debug.sf.high_fps_early_gl_app_phase_offset_ns"); - return {{RefreshRateType::PERFORMANCE, highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs), + return {{highFpsEarlySfOffsetNs.value_or(highFpsLateSfOffsetNs), highFpsEarlyAppOffsetNs.value_or(highFpsLateAppOffsetNs)}, - {RefreshRateType::PERFORMANCE, highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs), + {highFpsEarlyGlSfOffsetNs.value_or(highFpsLateSfOffsetNs), highFpsEarlyGlAppOffsetNs.value_or(highFpsLateAppOffsetNs)}, - {RefreshRateType::PERFORMANCE, highFpsLateSfOffsetNs, highFpsLateAppOffsetNs}, + {highFpsLateSfOffsetNs, highFpsLateAppOffsetNs}, thresholdForNextVsync}; } diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.h b/services/surfaceflinger/Scheduler/PhaseOffsets.h index 2c52432448..7747f0cfcc 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.h +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.h @@ -32,7 +32,6 @@ namespace android::scheduler { class PhaseOffsets { public: using Offsets = VSyncModulator::OffsetsConfig; - using RefreshRateType = RefreshRateConfigs::RefreshRateType; virtual ~PhaseOffsets(); @@ -43,9 +42,9 @@ public: } virtual Offsets getCurrentOffsets() const = 0; - virtual Offsets getOffsetsForRefreshRate(RefreshRateType) const = 0; + virtual Offsets getOffsetsForRefreshRate(float fps) const = 0; - virtual void setRefreshRateType(RefreshRateType) = 0; + virtual void setRefreshRateFps(float fps) = 0; virtual void dump(std::string& result) const = 0; }; @@ -57,18 +56,14 @@ public: PhaseOffsets(); // Returns early, early GL, and late offsets for Apps and SF for a given refresh rate. - Offsets getOffsetsForRefreshRate(RefreshRateType) const override; + Offsets getOffsetsForRefreshRate(float fps) const override; // Returns early, early GL, and late offsets for Apps and SF. - Offsets getCurrentOffsets() const override { - return getOffsetsForRefreshRate(mRefreshRateType); - } + Offsets getCurrentOffsets() const override { return getOffsetsForRefreshRate(mRefreshRateFps); } // This function should be called when the device is switching between different // refresh rates, to properly update the offsets. - void setRefreshRateType(RefreshRateType refreshRateType) override { - mRefreshRateType = refreshRateType; - } + void setRefreshRateFps(float fps) override { mRefreshRateFps = fps; } // Returns current offsets in human friendly format. void dump(std::string& result) const override; @@ -77,9 +72,10 @@ private: static Offsets getDefaultOffsets(nsecs_t thresholdForNextVsync); static Offsets getHighFpsOffsets(nsecs_t thresholdForNextVsync); - std::atomic mRefreshRateType = RefreshRateType::DEFAULT; + std::atomic mRefreshRateFps = 0; - std::unordered_map mOffsets; + Offsets mDefaultOffsets; + Offsets mHighFpsOffsets; }; } // namespace impl diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 7dc98cce94..23fb96a38b 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -13,135 +13,169 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// #define LOG_NDEBUG 0 #include "RefreshRateConfigs.h" namespace android::scheduler { + +using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; using RefreshRate = RefreshRateConfigs::RefreshRate; -using RefreshRateType = RefreshRateConfigs::RefreshRateType; // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access // from multiple threads. This can only be called if refreshRateSwitching() returns true. // TODO(b/122916473): Get this information from configs prepared by vendors, instead of // baking them in. -const std::map& RefreshRateConfigs::getRefreshRateMap() const { - LOG_ALWAYS_FATAL_IF(!mRefreshRateSwitchingSupported); - return mRefreshRateMap; -} - -const RefreshRate& RefreshRateConfigs::getRefreshRateFromType(RefreshRateType type) const { - if (!mRefreshRateSwitchingSupported) { - return getCurrentRefreshRate().second; - } else { - auto refreshRate = mRefreshRateMap.find(type); - LOG_ALWAYS_FATAL_IF(refreshRate == mRefreshRateMap.end()); - return refreshRate->second; - } -} - -std::pair RefreshRateConfigs::getCurrentRefreshRate() const { - int currentConfig = mCurrentConfig; - if (mRefreshRateSwitchingSupported) { - for (const auto& [type, refresh] : mRefreshRateMap) { - if (refresh.configId == currentConfig) { - return {type, refresh}; +const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(float contentFramerate) const { + std::lock_guard lock(mLock); + // Find the appropriate refresh rate with minimal error + auto iter = min_element(mAvailableRefreshRates.cbegin(), mAvailableRefreshRates.cend(), + [contentFramerate](const auto& lhs, const auto& rhs) -> bool { + return std::abs(lhs->fps - contentFramerate) < + std::abs(rhs->fps - contentFramerate); + }); + + // Some content aligns better on higher refresh rate. For example for 45fps we should choose + // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't + // align well with both + const RefreshRate* bestSoFar = *iter; + constexpr float MARGIN = 0.05f; + float ratio = (*iter)->fps / contentFramerate; + if (std::abs(std::round(ratio) - ratio) > MARGIN) { + while (iter != mAvailableRefreshRates.cend()) { + ratio = (*iter)->fps / contentFramerate; + + if (std::abs(std::round(ratio) - ratio) <= MARGIN) { + bestSoFar = *iter; + break; } + ++iter; } - LOG_ALWAYS_FATAL(); } - return {RefreshRateType::DEFAULT, mRefreshRates[currentConfig]}; + + return *bestSoFar; } -const RefreshRate& RefreshRateConfigs::getRefreshRateFromConfigId(int configId) const { - LOG_ALWAYS_FATAL_IF(configId >= mRefreshRates.size()); - return mRefreshRates[configId]; +const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { + return mRefreshRates; } -RefreshRateType RefreshRateConfigs::getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const { - if (!mRefreshRateSwitchingSupported) return RefreshRateType::DEFAULT; +const RefreshRate& RefreshRateConfigs::getMinRefreshRateByPolicy() const { + std::lock_guard lock(mLock); + if (!mRefreshRateSwitching) { + return *mCurrentRefreshRate; + } else { + return *mAvailableRefreshRates.front(); + } +} - for (const auto& [type, refreshRate] : mRefreshRateMap) { - if (refreshRate.hwcId == hwcId) { - return type; - } +const RefreshRate& RefreshRateConfigs::getMaxRefreshRateByPolicy() const { + std::lock_guard lock(mLock); + if (!mRefreshRateSwitching) { + return *mCurrentRefreshRate; + } else { + return *mAvailableRefreshRates.back(); } +} - return RefreshRateType::DEFAULT; +const RefreshRate& RefreshRateConfigs::getCurrentRefreshRate() const { + std::lock_guard lock(mLock); + return *mCurrentRefreshRate; } -void RefreshRateConfigs::setCurrentConfig(int config) { - LOG_ALWAYS_FATAL_IF(config >= mRefreshRates.size()); - mCurrentConfig = config; +void RefreshRateConfigs::setCurrentConfigId(HwcConfigIndexType configId) { + std::lock_guard lock(mLock); + mCurrentRefreshRate = &mRefreshRates.at(configId); } RefreshRateConfigs::RefreshRateConfigs(bool refreshRateSwitching, - const std::vector& configs, int currentConfig) { - init(refreshRateSwitching, configs, currentConfig); + const std::vector& configs, + HwcConfigIndexType currentHwcConfig) + : mRefreshRateSwitching(refreshRateSwitching) { + init(configs, currentHwcConfig); } RefreshRateConfigs::RefreshRateConfigs( bool refreshRateSwitching, const std::vector>& configs, - int currentConfig) { + HwcConfigIndexType currentConfigId) + : mRefreshRateSwitching(refreshRateSwitching) { std::vector inputConfigs; - for (const auto& config : configs) { - inputConfigs.push_back({config->getId(), config->getVsyncPeriod()}); + for (auto configId = HwcConfigIndexType(0); configId < HwcConfigIndexType(configs.size()); + ++configId) { + auto configGroup = HwcConfigGroupType(configs[configId.value()]->getConfigGroup()); + inputConfigs.push_back( + {configId, configGroup, configs[configId.value()]->getVsyncPeriod()}); } - init(refreshRateSwitching, inputConfigs, currentConfig); + init(inputConfigs, currentConfigId); } -void RefreshRateConfigs::init(bool refreshRateSwitching, const std::vector& configs, - int currentConfig) { - mRefreshRateSwitchingSupported = refreshRateSwitching; - LOG_ALWAYS_FATAL_IF(configs.empty()); - LOG_ALWAYS_FATAL_IF(currentConfig >= configs.size()); - mCurrentConfig = currentConfig; - - auto buildRefreshRate = [&](int configId) -> RefreshRate { - const nsecs_t vsyncPeriod = configs[configId].vsyncPeriod; - const float fps = 1e9 / vsyncPeriod; - return {configId, base::StringPrintf("%2.ffps", fps), static_cast(fps), - vsyncPeriod, configs[configId].hwcId}; - }; +void RefreshRateConfigs::setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate, + float maxRefreshRate) { + std::lock_guard lock(mLock); + mCurrentGroupId = mRefreshRates.at(defaultConfigId).configGroup; + mMinRefreshRateFps = minRefreshRate; + mMaxRefreshRateFps = maxRefreshRate; + constructAvailableRefreshRates(); +} - for (int i = 0; i < configs.size(); ++i) { - mRefreshRates.push_back(buildRefreshRate(i)); +void RefreshRateConfigs::getSortedRefreshRateList( + const std::function& shouldAddRefreshRate, + std::vector* outRefreshRates) { + outRefreshRates->clear(); + outRefreshRates->reserve(mRefreshRates.size()); + for (const auto& [type, refreshRate] : mRefreshRates) { + if (shouldAddRefreshRate(refreshRate)) { + ALOGV("getSortedRefreshRateList: config %d added to list policy", + refreshRate.configId.value()); + outRefreshRates->push_back(&refreshRate); + } } - if (!mRefreshRateSwitchingSupported) return; + std::sort(outRefreshRates->begin(), outRefreshRates->end(), + [](const auto refreshRate1, const auto refreshRate2) { + return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; + }); +} - auto findDefaultAndPerfConfigs = [&]() -> std::optional> { - if (configs.size() < 2) { - return {}; - } +void RefreshRateConfigs::constructAvailableRefreshRates() { + // Filter configs based on current policy and sort based on vsync period + ALOGV("constructRefreshRateMap: group %d min %.2f max %.2f", mCurrentGroupId.value(), + mMinRefreshRateFps, mMaxRefreshRateFps); + getSortedRefreshRateList( + [this](const RefreshRate& refreshRate) REQUIRES(mLock) { + return refreshRate.configGroup == mCurrentGroupId && + refreshRate.fps >= mMinRefreshRateFps && + refreshRate.fps <= mMaxRefreshRateFps; + }, + &mAvailableRefreshRates); +} - std::vector sortedRefreshRates; - for (const auto& refreshRate : mRefreshRates) { - sortedRefreshRates.push_back(&refreshRate); - } - std::sort(sortedRefreshRates.begin(), sortedRefreshRates.end(), - [](const RefreshRate* refreshRate1, const RefreshRate* refreshRate2) { - return refreshRate1->vsyncPeriod > refreshRate2->vsyncPeriod; - }); - - // When the configs are ordered by the resync rate, we assume that - // the first one is DEFAULT and the second one is PERFORMANCE, - // i.e. the higher rate. - if (sortedRefreshRates[0]->vsyncPeriod == 0 || sortedRefreshRates[1]->vsyncPeriod == 0) { - return {}; - } +// NO_THREAD_SAFETY_ANALYSIS since this is called from the constructor +void RefreshRateConfigs::init(const std::vector& configs, + HwcConfigIndexType currentHwcConfig) NO_THREAD_SAFETY_ANALYSIS { + LOG_ALWAYS_FATAL_IF(configs.empty()); + LOG_ALWAYS_FATAL_IF(currentHwcConfig.value() >= configs.size()); - return std::pair(sortedRefreshRates[0]->configId, - sortedRefreshRates[1]->configId); + auto buildRefreshRate = [&](InputConfig config) -> RefreshRate { + const float fps = 1e9f / config.vsyncPeriod; + return RefreshRate(config.configId, config.vsyncPeriod, config.configGroup, + base::StringPrintf("%2.ffps", fps), fps); }; - auto defaultAndPerfConfigs = findDefaultAndPerfConfigs(); - if (!defaultAndPerfConfigs) { - mRefreshRateSwitchingSupported = false; - return; + for (const auto& config : configs) { + mRefreshRates.emplace(config.configId, buildRefreshRate(config)); + if (config.configId == currentHwcConfig) { + mCurrentRefreshRate = &mRefreshRates.at(config.configId); + mCurrentGroupId = config.configGroup; + } } - mRefreshRateMap[RefreshRateType::DEFAULT] = mRefreshRates[defaultAndPerfConfigs->first]; - mRefreshRateMap[RefreshRateType::PERFORMANCE] = mRefreshRates[defaultAndPerfConfigs->second]; + std::vector sortedConfigs; + getSortedRefreshRateList([](const RefreshRate&) { return true; }, &sortedConfigs); + mMinSupportedRefreshRate = sortedConfigs.front(); + mMaxSupportedRefreshRate = sortedConfigs.back(); + constructAvailableRefreshRates(); } -} // namespace android::scheduler \ No newline at end of file +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 90bba24332..fb14dc7a9a 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -23,7 +23,9 @@ #include #include "DisplayHardware/HWComposer.h" +#include "HwcStrongTypes.h" #include "Scheduler/SchedulerUtils.h" +#include "Scheduler/StrongTyping.h" namespace android::scheduler { @@ -41,71 +43,123 @@ inline RefreshRateConfigEvent operator|(RefreshRateConfigEvent lhs, RefreshRateC */ class RefreshRateConfigs { public: - // Enum to indicate which vsync rate to run at. Default is the old 60Hz, and performance - // is the new 90Hz. Eventually we want to have a way for vendors to map these in the configs. - enum class RefreshRateType { DEFAULT, PERFORMANCE }; - struct RefreshRate { + RefreshRate(HwcConfigIndexType configId, nsecs_t vsyncPeriod, + HwcConfigGroupType configGroup, std::string name, float fps) + : configId(configId), + vsyncPeriod(vsyncPeriod), + configGroup(configGroup), + name(std::move(name)), + fps(fps) {} // This config ID corresponds to the position of the config in the vector that is stored // on the device. - int configId; - // Human readable name of the refresh rate. - std::string name; - // Refresh rate in frames per second, rounded to the nearest integer. - uint32_t fps = 0; + const HwcConfigIndexType configId; // Vsync period in nanoseconds. - nsecs_t vsyncPeriod; - // Hwc config Id (returned from HWC2::Display::Config::getId()) - hwc2_config_t hwcId; + const nsecs_t vsyncPeriod; + // This configGroup for the config. + const HwcConfigGroupType configGroup; + // Human readable name of the refresh rate. + const std::string name; + // Refresh rate in frames per second + const float fps = 0; + + bool operator!=(const RefreshRate& other) const { + return configId != other.configId || vsyncPeriod != other.vsyncPeriod || + configGroup != other.configGroup; + } + + bool operator==(const RefreshRate& other) const { return !(*this != other); } }; + using AllRefreshRatesMapType = std::unordered_map; + + // Sets the current policy to choose refresh rates. + void setPolicy(HwcConfigIndexType defaultConfigId, float minRefreshRate, float maxRefreshRate) + EXCLUDES(mLock); + // Returns true if this device is doing refresh rate switching. This won't change at runtime. - bool refreshRateSwitchingSupported() const { return mRefreshRateSwitchingSupported; } + bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; } + + // Returns all available refresh rates according to the current policy. + const RefreshRate& getRefreshRateForContent(float contentFramerate) const EXCLUDES(mLock); + + // Returns all the refresh rates supported by the device. This won't change at runtime. + const AllRefreshRatesMapType& getAllRefreshRates() const EXCLUDES(mLock); - // Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access - // from multiple threads. This can only be called if refreshRateSwitching() returns true. - // TODO(b/122916473): Get this information from configs prepared by vendors, instead of - // baking them in. - const std::map& getRefreshRateMap() const; + // Returns the lowest refresh rate supported by the device. This won't change at runtime. + const RefreshRate& getMinRefreshRate() const { return *mMinSupportedRefreshRate; } - const RefreshRate& getRefreshRateFromType(RefreshRateType type) const; + // Returns the lowest refresh rate according to the current policy. May change in runtime. + const RefreshRate& getMinRefreshRateByPolicy() const EXCLUDES(mLock); - std::pair getCurrentRefreshRate() const; + // Returns the highest refresh rate supported by the device. This won't change at runtime. + const RefreshRate& getMaxRefreshRate() const { return *mMaxSupportedRefreshRate; } - const RefreshRate& getRefreshRateFromConfigId(int configId) const; + // Returns the highest refresh rate according to the current policy. May change in runtime. + const RefreshRate& getMaxRefreshRateByPolicy() const EXCLUDES(mLock); - RefreshRateType getRefreshRateTypeFromHwcConfigId(hwc2_config_t hwcId) const; + // Returns the current refresh rate + const RefreshRate& getCurrentRefreshRate() const EXCLUDES(mLock); - void setCurrentConfig(int config); + // Returns the refresh rate that corresponds to a HwcConfigIndexType. This won't change at + // runtime. + const RefreshRate& getRefreshRateFromConfigId(HwcConfigIndexType configId) const { + return mRefreshRates.at(configId); + }; + + // Stores the current configId the device operates at + void setCurrentConfigId(HwcConfigIndexType configId) EXCLUDES(mLock); struct InputConfig { - hwc2_config_t hwcId = 0; + HwcConfigIndexType configId = HwcConfigIndexType(0); + HwcConfigGroupType configGroup = HwcConfigGroupType(0); nsecs_t vsyncPeriod = 0; }; RefreshRateConfigs(bool refreshRateSwitching, const std::vector& configs, - int currentConfig); - + HwcConfigIndexType currentHwcConfig); RefreshRateConfigs(bool refreshRateSwitching, const std::vector>& configs, - int currentConfig); + HwcConfigIndexType currentConfigId); private: - void init(bool refreshRateSwitching, const std::vector& configs, - int currentConfig); - // Whether this device is doing refresh rate switching or not. This must not change after this - // object is initialized. - bool mRefreshRateSwitchingSupported; + void init(const std::vector& configs, HwcConfigIndexType currentHwcConfig); + + void constructAvailableRefreshRates() REQUIRES(mLock); + + void getSortedRefreshRateList( + const std::function& shouldAddRefreshRate, + std::vector* outRefreshRates); + // The list of refresh rates, indexed by display config ID. This must not change after this // object is initialized. - std::vector mRefreshRates; - // The mapping of refresh rate type to RefreshRate. This must not change after this object is - // initialized. - std::map mRefreshRateMap; - // The ID of the current config. This will change at runtime. This is set by SurfaceFlinger on - // the main thread, and read by the Scheduler (and other objects) on other threads, so it's - // atomic. - std::atomic mCurrentConfig; + AllRefreshRatesMapType mRefreshRates; + + // The list of refresh rates which are available in the current policy, ordered by vsyncPeriod + // (the first element is the lowest refresh rate) + std::vector mAvailableRefreshRates GUARDED_BY(mLock); + + // The current config. This will change at runtime. This is set by SurfaceFlinger on + // the main thread, and read by the Scheduler (and other objects) on other threads. + const RefreshRate* mCurrentRefreshRate GUARDED_BY(mLock); + + // The current config group. This will change at runtime. This is set by SurfaceFlinger on + // the main thread, and read by the Scheduler (and other objects) on other threads. + HwcConfigGroupType mCurrentGroupId GUARDED_BY(mLock); + + // The min and max FPS allowed by the policy. This will change at runtime and set by + // SurfaceFlinger on the main thread. + float mMinRefreshRateFps GUARDED_BY(mLock) = 0; + float mMaxRefreshRateFps GUARDED_BY(mLock) = std::numeric_limits::max(); + + // The min and max refresh rates supported by the device. + // This will not change at runtime. + const RefreshRate* mMinSupportedRefreshRate; + const RefreshRate* mMaxSupportedRefreshRate; + + const bool mRefreshRateSwitching; + + mutable std::mutex mLock; }; } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index 8afc93e8db..a384dbe29b 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -25,8 +25,7 @@ #include "android-base/stringprintf.h" #include "utils/Timers.h" -namespace android { -namespace scheduler { +namespace android::scheduler { /** * Class to encapsulate statistics about refresh rates that the display is using. When the power @@ -42,10 +41,10 @@ class RefreshRateStats { public: RefreshRateStats(const RefreshRateConfigs& refreshRateConfigs, TimeStats& timeStats, - int currentConfigMode, int currentPowerMode) + HwcConfigIndexType currentConfigId, int currentPowerMode) : mRefreshRateConfigs(refreshRateConfigs), mTimeStats(timeStats), - mCurrentConfigMode(currentConfigMode), + mCurrentConfigMode(currentConfigId), mCurrentPowerMode(currentPowerMode) {} // Sets power mode. @@ -59,12 +58,12 @@ public: // Sets config mode. If the mode has changed, it records how much time was spent in the previous // mode. - void setConfigMode(int mode) { - if (mCurrentConfigMode == mode) { + void setConfigMode(HwcConfigIndexType configId) { + if (mCurrentConfigMode == configId) { return; } flushTime(); - mCurrentConfigMode = mode; + mCurrentConfigMode = configId; } // Returns a map between human readable refresh rate and number of seconds the device spent in @@ -78,11 +77,11 @@ public: std::unordered_map totalTime; // Multiple configs may map to the same name, e.g. "60fps". Add the // times for such configs together. - for (const auto& [config, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] = 0; + for (const auto& [configId, time] : mConfigModesTotalTime) { + totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] = 0; } - for (const auto& [config, time] : mConfigModesTotalTime) { - totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(config).name] += time; + for (const auto& [configId, time] : mConfigModesTotalTime) { + totalTime[mRefreshRateConfigs.getRefreshRateFromConfigId(configId).name] += time; } totalTime["ScreenOff"] = mScreenOffTime; return totalTime; @@ -139,14 +138,14 @@ private: // Aggregate refresh rate statistics for telemetry. TimeStats& mTimeStats; - int mCurrentConfigMode; + HwcConfigIndexType mCurrentConfigMode; int32_t mCurrentPowerMode; - std::unordered_map mConfigModesTotalTime; + std::unordered_map + mConfigModesTotalTime; int64_t mScreenOffTime = 0; nsecs_t mPreviousRecordedTime = systemTime(); }; -} // namespace scheduler -} // namespace android +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 55fd6032f2..1d50fe1dd4 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -182,7 +182,7 @@ void Scheduler::onScreenReleased(ConnectionHandle handle) { } void Scheduler::onConfigChanged(ConnectionHandle handle, PhysicalDisplayId displayId, - int32_t configId) { + HwcConfigIndexType configId) { RETURN_IF_INVALID_HANDLE(handle); mConnections[handle].thread->onConfigChanged(displayId, configId); } @@ -280,8 +280,7 @@ void Scheduler::resync() { const nsecs_t last = mLastResyncTime.exchange(now); if (now - last > kIgnoreDelay) { - resyncToHardwareVsync(false, - mRefreshRateConfigs.getCurrentRefreshRate().second.vsyncPeriod); + resyncToHardwareVsync(false, mRefreshRateConfigs.getCurrentRefreshRate().vsyncPeriod); } } @@ -332,53 +331,49 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - const auto type = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER - ? RefreshRateType::DEFAULT - : RefreshRateType::PERFORMANCE; - - const auto lowFps = mRefreshRateConfigs.getRefreshRateFromType(RefreshRateType::DEFAULT).fps; - const auto highFps = mRefreshRateConfigs.getRefreshRateFromType(type).fps; + const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; + const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? lowFps + : mRefreshRateConfigs.getMaxRefreshRate().fps; mLayerHistory->registerLayer(layer, lowFps, highFps); } -void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime, bool isHDR) { +void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) { if (mLayerHistory) { - mLayerHistory->record(layer, presentTime, isHDR, systemTime()); + mLayerHistory->record(layer, presentTime, systemTime()); } } void Scheduler::chooseRefreshRateForContent() { if (!mLayerHistory) return; - auto [refreshRate, isHDR] = mLayerHistory->summarize(systemTime()); + auto [refreshRate] = mLayerHistory->summarize(systemTime()); const uint32_t refreshRateRound = std::round(refreshRate); - RefreshRateType newRefreshRateType; + HwcConfigIndexType newConfigId; { std::lock_guard lock(mFeatureStateLock); - if (mFeatures.contentRefreshRate == refreshRateRound && mFeatures.isHDRContent == isHDR) { + if (mFeatures.contentRefreshRate == refreshRateRound) { return; } mFeatures.contentRefreshRate = refreshRateRound; ATRACE_INT("ContentFPS", refreshRateRound); - mFeatures.isHDRContent = isHDR; - ATRACE_INT("ContentHDR", isHDR); - mFeatures.contentDetection = refreshRateRound > 0 ? ContentDetectionState::On : ContentDetectionState::Off; - newRefreshRateType = calculateRefreshRateType(); - if (mFeatures.refreshRateType == newRefreshRateType) { + newConfigId = calculateRefreshRateType(); + if (mFeatures.configId == newConfigId) { return; } - mFeatures.refreshRateType = newRefreshRateType; - } - changeRefreshRate(newRefreshRateType, ConfigEvent::Changed); + mFeatures.configId = newConfigId; + }; + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + changeRefreshRate(newRefreshRate, ConfigEvent::Changed); } -void Scheduler::setChangeRefreshRateCallback(ChangeRefreshRateCallback&& callback) { +void Scheduler::setSchedulerCallback(android::Scheduler::ISchedulerCallback* callback) { std::lock_guard lock(mCallbackLock); - mChangeRefreshRateCallback = std::move(callback); + mSchedulerCallback = callback; } void Scheduler::resetIdleTimer() { @@ -423,13 +418,16 @@ void Scheduler::setDisplayPowerState(bool normal) { void Scheduler::kernelIdleTimerCallback(TimerState state) { ATRACE_INT("ExpiredKernelIdleTimer", static_cast(state)); + // TODO(145561154): cleanup the kernel idle timer implementation and the refresh rate + // magic number const auto refreshRate = mRefreshRateConfigs.getCurrentRefreshRate(); - if (state == TimerState::Reset && refreshRate.first == RefreshRateType::PERFORMANCE) { + constexpr float FPS_THRESHOLD_FOR_KERNEL_TIMER = 65.0f; + if (state == TimerState::Reset && refreshRate.fps > FPS_THRESHOLD_FOR_KERNEL_TIMER) { // If we're not in performance mode then the kernel timer shouldn't do // anything, as the refresh rate during DPU power collapse will be the // same. - resyncToHardwareVsync(true /* makeAvailable */, refreshRate.second.vsyncPeriod); - } else if (state == TimerState::Expired && refreshRate.first != RefreshRateType::PERFORMANCE) { + resyncToHardwareVsync(true /* makeAvailable */, refreshRate.vsyncPeriod); + } else if (state == TimerState::Expired && refreshRate.fps <= FPS_THRESHOLD_FOR_KERNEL_TIMER) { // Disable HW VSYNC if the timer expired, as we don't need it enabled if // we're not pushing frames, and if we're in PERFORMANCE mode then we'll // need to update the DispSync model anyway. @@ -471,96 +469,67 @@ void Scheduler::dump(std::string& result) const { template void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventOnContentDetection) { ConfigEvent event = ConfigEvent::None; - RefreshRateType newRefreshRateType; + HwcConfigIndexType newConfigId; { std::lock_guard lock(mFeatureStateLock); if (*currentState == newState) { return; } *currentState = newState; - newRefreshRateType = calculateRefreshRateType(); - if (mFeatures.refreshRateType == newRefreshRateType) { + newConfigId = calculateRefreshRateType(); + if (mFeatures.configId == newConfigId) { return; } - mFeatures.refreshRateType = newRefreshRateType; + mFeatures.configId = newConfigId; if (eventOnContentDetection && mFeatures.contentDetection == ContentDetectionState::On) { event = ConfigEvent::Changed; } } - changeRefreshRate(newRefreshRateType, event); + const RefreshRate& newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + changeRefreshRate(newRefreshRate, event); } -Scheduler::RefreshRateType Scheduler::calculateRefreshRateType() { +HwcConfigIndexType Scheduler::calculateRefreshRateType() { if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) { - return RefreshRateType::DEFAULT; - } - - // HDR content is not supported on PERFORMANCE mode - if (mForceHDRContentToDefaultRefreshRate && mFeatures.isHDRContent) { - return RefreshRateType::DEFAULT; + return mRefreshRateConfigs.getCurrentRefreshRate().configId; } // If Display Power is not in normal operation we want to be in performance mode. // When coming back to normal mode, a grace period is given with DisplayPowerTimer if (!mFeatures.isDisplayPowerStateNormal || mFeatures.displayPowerTimer == TimerState::Reset) { - return RefreshRateType::PERFORMANCE; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // As long as touch is active we want to be in performance mode if (mFeatures.touch == TouchState::Active) { - return RefreshRateType::PERFORMANCE; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // If timer has expired as it means there is no new content on the screen if (mFeatures.idleTimer == TimerState::Expired) { - return RefreshRateType::DEFAULT; + return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; } // If content detection is off we choose performance as we don't know the content fps if (mFeatures.contentDetection == ContentDetectionState::Off) { - return RefreshRateType::PERFORMANCE; + return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } // Content detection is on, find the appropriate refresh rate with minimal error - // TODO(b/139751853): Scan allowed refresh rates only (SurfaceFlinger::mAllowedDisplayConfigs) - const float rate = static_cast(mFeatures.contentRefreshRate); - auto iter = min_element(mRefreshRateConfigs.getRefreshRateMap().cbegin(), - mRefreshRateConfigs.getRefreshRateMap().cend(), - [rate](const auto& lhs, const auto& rhs) -> bool { - return std::abs(lhs.second.fps - rate) < - std::abs(rhs.second.fps - rate); - }); - RefreshRateType currRefreshRateType = iter->first; - - // Some content aligns better on higher refresh rate. For example for 45fps we should choose - // 90Hz config. However we should still prefer a lower refresh rate if the content doesn't - // align well with both - constexpr float MARGIN = 0.05f; - float ratio = mRefreshRateConfigs.getRefreshRateFromType(currRefreshRateType).fps / rate; - if (std::abs(std::round(ratio) - ratio) > MARGIN) { - while (iter != mRefreshRateConfigs.getRefreshRateMap().cend()) { - ratio = iter->second.fps / rate; - - if (std::abs(std::round(ratio) - ratio) <= MARGIN) { - currRefreshRateType = iter->first; - break; - } - ++iter; - } - } - - return currRefreshRateType; + return mRefreshRateConfigs + .getRefreshRateForContent(static_cast(mFeatures.contentRefreshRate)) + .configId; } -Scheduler::RefreshRateType Scheduler::getPreferredRefreshRateType() { +std::optional Scheduler::getPreferredConfigId() { std::lock_guard lock(mFeatureStateLock); - return mFeatures.refreshRateType; + return mFeatures.configId; } -void Scheduler::changeRefreshRate(RefreshRateType refreshRateType, ConfigEvent configEvent) { +void Scheduler::changeRefreshRate(const RefreshRate& refreshRate, ConfigEvent configEvent) { std::lock_guard lock(mCallbackLock); - if (mChangeRefreshRateCallback) { - mChangeRefreshRateCallback(refreshRateType, configEvent); + if (mSchedulerCallback) { + mSchedulerCallback->changeRefreshRate(refreshRate, configEvent); } } diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index 346896c44f..04a83906b1 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -34,6 +34,8 @@ namespace android { +using namespace std::chrono_literals; + class DispSync; class FenceTime; class InjectVSyncSource; @@ -41,10 +43,14 @@ struct DisplayStateInfo; class Scheduler { public: - using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; + using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; using ConfigEvent = scheduler::RefreshRateConfigEvent; - using ChangeRefreshRateCallback = std::function; + class ISchedulerCallback { + public: + virtual ~ISchedulerCallback() = default; + virtual void changeRefreshRate(const RefreshRate&, ConfigEvent) = 0; + }; // Indicates whether to start the transaction early, or at vsync time. enum class TransactionStart { EARLY, NORMAL }; @@ -67,7 +73,7 @@ public: sp getEventConnection(ConnectionHandle); void onHotplugReceived(ConnectionHandle, PhysicalDisplayId, bool connected); - void onConfigChanged(ConnectionHandle, PhysicalDisplayId, int32_t configId); + void onConfigChanged(ConnectionHandle, PhysicalDisplayId, HwcConfigIndexType configId); void onScreenAcquired(ConnectionHandle); void onScreenReleased(ConnectionHandle); @@ -103,13 +109,13 @@ public: // Layers are registered on creation, and unregistered when the weak reference expires. void registerLayer(Layer*); - void recordLayerHistory(Layer*, nsecs_t presentTime, bool isHDR); + void recordLayerHistory(Layer*, nsecs_t presentTime); // Detects content using layer history, and selects a matching refresh rate. void chooseRefreshRateForContent(); - // Called by Scheduler to change refresh rate. - void setChangeRefreshRateCallback(ChangeRefreshRateCallback&&); + // Called by Scheduler to control SurfaceFlinger operations. + void setSchedulerCallback(ISchedulerCallback*); bool isIdleTimerEnabled() const { return mIdleTimer.has_value(); } void resetIdleTimer(); @@ -122,8 +128,8 @@ public: void dump(std::string&) const; void dump(ConnectionHandle, std::string&) const; - // Get the appropriate refresh type for current conditions. - RefreshRateType getPreferredRefreshRateType(); + // Get the appropriate refresh for current conditions. + std::optional getPreferredConfigId(); private: friend class TestableScheduler; @@ -158,9 +164,9 @@ private: void setVsyncPeriod(nsecs_t period); - RefreshRateType calculateRefreshRateType() REQUIRES(mFeatureStateLock); + HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock); // Acquires a lock and calls the ChangeRefreshRateCallback with given parameters. - void changeRefreshRate(RefreshRateType, ConfigEvent); + void changeRefreshRate(const RefreshRate&, ConfigEvent); // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { @@ -198,7 +204,7 @@ private: std::optional mDisplayPowerTimer; std::mutex mCallbackLock; - ChangeRefreshRateCallback mChangeRefreshRateCallback GUARDED_BY(mCallbackLock); + ISchedulerCallback* mSchedulerCallback GUARDED_BY(mCallbackLock) = nullptr; // In order to make sure that the features don't override themselves, we need a state machine // to keep track which feature requested the config change. @@ -210,17 +216,13 @@ private: TouchState touch = TouchState::Inactive; TimerState displayPowerTimer = TimerState::Expired; - RefreshRateType refreshRateType = RefreshRateType::DEFAULT; + std::optional configId; uint32_t contentRefreshRate = 0; - bool isHDRContent = false; bool isDisplayPowerStateNormal = true; } mFeatures GUARDED_BY(mFeatureStateLock); const scheduler::RefreshRateConfigs& mRefreshRateConfigs; - - // Global config to force HDR content to work on DEFAULT refreshRate - static constexpr bool mForceHDRContentToDefaultRefreshRate = false; }; } // namespace android diff --git a/services/surfaceflinger/Scheduler/StrongTyping.h b/services/surfaceflinger/Scheduler/StrongTyping.h index 02db022e08..e8ca0ba836 100644 --- a/services/surfaceflinger/Scheduler/StrongTyping.h +++ b/services/surfaceflinger/Scheduler/StrongTyping.h @@ -51,13 +51,22 @@ struct Compare : Ability { inline bool operator>(T const& other) const { return !(*this < other || *this == other); } }; +template +struct Hash : Ability { + [[nodiscard]] std::size_t hash() const { + return std::hashbase().value())>::type>::type>{}( + this->base().value()); + } +}; + template class... Ability> struct StrongTyping : Ability>... { StrongTyping() : mValue(0) {} explicit StrongTyping(T const& value) : mValue(value) {} StrongTyping(StrongTyping const&) = default; StrongTyping& operator=(StrongTyping const&) = default; - inline operator T() const { return mValue; } + explicit inline operator T() const { return mValue; } T const& value() const { return mValue; } T& value() { return mValue; } @@ -65,3 +74,12 @@ private: T mValue; }; } // namespace android + +namespace std { +template class... Ability> +struct hash> { + std::size_t operator()(android::StrongTyping const& k) const { + return k.hash(); + } +}; +} // namespace std diff --git a/services/surfaceflinger/Scheduler/VSyncDispatch.h b/services/surfaceflinger/Scheduler/VSyncDispatch.h index 4a4bef8b2e..e001080015 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatch.h +++ b/services/surfaceflinger/Scheduler/VSyncDispatch.h @@ -34,7 +34,7 @@ enum class CancelResult { Cancelled, TooLate, Error }; */ class VSyncDispatch { public: - using CallbackToken = StrongTyping; + using CallbackToken = StrongTyping; virtual ~VSyncDispatch(); diff --git a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h index f0580999c6..0e12e7f321 100644 --- a/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h +++ b/services/surfaceflinger/Scheduler/VSyncDispatchTimerQueue.h @@ -106,7 +106,8 @@ private: VSyncDispatchTimerQueue(VSyncDispatchTimerQueue const&) = delete; VSyncDispatchTimerQueue& operator=(VSyncDispatchTimerQueue const&) = delete; - using CallbackMap = std::unordered_map>; + using CallbackMap = + std::unordered_map>; void timerCallback(); void setTimer(nsecs_t, nsecs_t) REQUIRES(mMutex); diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp index 27fd76cba3..8de35b1c2f 100644 --- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp +++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp @@ -134,18 +134,13 @@ void VSyncModulator::updateOffsetsLocked() { return; } - const bool isDefault = mOffsets.fpsMode == RefreshRateType::DEFAULT; - const bool isPerformance = mOffsets.fpsMode == RefreshRateType::PERFORMANCE; const bool isEarly = &offsets == &mOffsetsConfig.early; const bool isEarlyGl = &offsets == &mOffsetsConfig.earlyGl; const bool isLate = &offsets == &mOffsetsConfig.late; - ATRACE_INT("Vsync-EarlyOffsetsOn", isDefault && isEarly); - ATRACE_INT("Vsync-EarlyGLOffsetsOn", isDefault && isEarlyGl); - ATRACE_INT("Vsync-LateOffsetsOn", isDefault && isLate); - ATRACE_INT("Vsync-HighFpsEarlyOffsetsOn", isPerformance && isEarly); - ATRACE_INT("Vsync-HighFpsEarlyGLOffsetsOn", isPerformance && isEarlyGl); - ATRACE_INT("Vsync-HighFpsLateOffsetsOn", isPerformance && isLate); + ATRACE_INT("Vsync-EarlyOffsetsOn", isEarly); + ATRACE_INT("Vsync-EarlyGLOffsetsOn", isEarlyGl); + ATRACE_INT("Vsync-LateOffsetsOn", isLate); } } // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.h b/services/surfaceflinger/Scheduler/VSyncModulator.h index 727cef26fe..63c0feb9cc 100644 --- a/services/surfaceflinger/Scheduler/VSyncModulator.h +++ b/services/surfaceflinger/Scheduler/VSyncModulator.h @@ -37,13 +37,10 @@ private: // switch in and out of gl composition. static constexpr int MIN_EARLY_GL_FRAME_COUNT_TRANSACTION = 2; - using RefreshRateType = RefreshRateConfigs::RefreshRateType; - public: // Wrapper for a collection of surfaceflinger/app offsets for a particular // configuration. struct Offsets { - RefreshRateType fpsMode; nsecs_t sf; nsecs_t app; }; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index bf3b4c9f01..5aa2447419 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -542,14 +542,8 @@ void SurfaceFlinger::bootFinished() if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { // set the refresh rate according to the policy - const auto& performanceRefreshRate = - mRefreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE); - - if (isDisplayConfigAllowed(performanceRefreshRate.configId)) { - setRefreshRateTo(RefreshRateType::PERFORMANCE, Scheduler::ConfigEvent::None); - } else { - setRefreshRateTo(RefreshRateType::DEFAULT, Scheduler::ConfigEvent::None); - } + const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy(); + changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None); } })); } @@ -821,9 +815,8 @@ status_t SurfaceFlinger::getDisplayConfigs(const sp& displayToken, info.xdpi = xdpi; info.ydpi = ydpi; info.fps = 1e9 / hwConfig->getVsyncPeriod(); - const auto refreshRateType = - mRefreshRateConfigs->getRefreshRateTypeFromHwcConfigId(hwConfig->getId()); - const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(refreshRateType); + + const auto offset = mPhaseOffsets->getOffsetsForRefreshRate(info.fps); info.appVsyncOffset = offset.late.app; // This is how far in advance a buffer must be queued for @@ -873,17 +866,17 @@ int SurfaceFlinger::getActiveConfig(const sp& displayToken) { if (display->isPrimary()) { std::lock_guard lock(mActiveConfigLock); if (mDesiredActiveConfigChanged) { - return mDesiredActiveConfig.configId; - } else { - return display->getActiveConfig(); + return mDesiredActiveConfig.configId.value(); } - } else { - return display->getActiveConfig(); } + + return display->getActiveConfig().value(); } void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { ATRACE_CALL(); + auto refreshRate = mRefreshRateConfigs->getRefreshRateFromConfigId(info.configId); + ALOGV("setDesiredActiveConfig(%s)", refreshRate.name.c_str()); // Don't check against the current mode yet. Worst case we set the desired // config twice. However event generation config might have changed so we need to update it @@ -902,13 +895,14 @@ void SurfaceFlinger::setDesiredActiveConfig(const ActiveConfigInfo& info) { // As we called to set period, we will call to onRefreshRateChangeCompleted once // DispSync model is locked. mVSyncModulator->onRefreshRateChangeInitiated(); - mPhaseOffsets->setRefreshRateType(info.type); + + mPhaseOffsets->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets()); } mDesiredActiveConfigChanged = true; if (mRefreshRateOverlay) { - mRefreshRateOverlay->changeRefreshRate(mDesiredActiveConfig.type); + mRefreshRateOverlay->changeRefreshRate(refreshRate); } } @@ -930,14 +924,15 @@ void SurfaceFlinger::setActiveConfigInternal() { } std::lock_guard lock(mActiveConfigLock); - mRefreshRateConfigs->setCurrentConfig(mUpcomingActiveConfig.configId); + mRefreshRateConfigs->setCurrentConfigId(mUpcomingActiveConfig.configId); mRefreshRateStats->setConfigMode(mUpcomingActiveConfig.configId); - display->setActiveConfig(mUpcomingActiveConfig.configId); - mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type); + auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(mUpcomingActiveConfig.configId); + mPhaseOffsets->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets()); - ATRACE_INT("ActiveConfigMode", mUpcomingActiveConfig.configId); + ATRACE_INT("ActiveConfigFPS", refreshRate.fps); if (mUpcomingActiveConfig.event != Scheduler::ConfigEvent::None) { mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, @@ -951,12 +946,15 @@ void SurfaceFlinger::desiredActiveConfigChangeDone() { mDesiredActiveConfigChanged = false; mScheduler->resyncToHardwareVsync(true, getVsyncPeriod()); - mPhaseOffsets->setRefreshRateType(mUpcomingActiveConfig.type); + auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(mDesiredActiveConfig.configId); + mPhaseOffsets->setRefreshRateFps(refreshRate.fps); mVSyncModulator->setPhaseOffsets(mPhaseOffsets->getCurrentOffsets()); } bool SurfaceFlinger::performSetActiveConfig() { ATRACE_CALL(); + ALOGV("performSetActiveConfig"); if (mCheckPendingFence) { if (previousFrameMissed()) { // fence has not signaled yet. wait for the next invalidate @@ -980,6 +978,10 @@ bool SurfaceFlinger::performSetActiveConfig() { desiredActiveConfig = mDesiredActiveConfig; } + auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(desiredActiveConfig.configId); + ALOGV("performSetActiveConfig changing active config to %d(%s)", refreshRate.configId.value(), + refreshRate.name.c_str()); const auto display = getDefaultDisplayDeviceLocked(); if (!display || display->getActiveConfig() == desiredActiveConfig.configId) { // display is not valid or we are already in the requested mode @@ -1000,8 +1002,8 @@ bool SurfaceFlinger::performSetActiveConfig() { const auto displayId = display->getId(); LOG_ALWAYS_FATAL_IF(!displayId); - ATRACE_INT("ActiveConfigModeHWC", mUpcomingActiveConfig.configId); - getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId); + ATRACE_INT("ActiveConfigFPS_HWC", refreshRate.fps); + getHwComposer().setActiveConfig(*displayId, mUpcomingActiveConfig.configId.value()); // we need to submit an empty frame to HWC to start the process mCheckPendingFence = true; @@ -1396,11 +1398,12 @@ void SurfaceFlinger::getCompositorTiming(CompositorTiming* compositorTiming) { *compositorTiming = getBE().mCompositorTiming; } -bool SurfaceFlinger::isDisplayConfigAllowed(int32_t configId) const { +bool SurfaceFlinger::isDisplayConfigAllowed(HwcConfigIndexType configId) const { return mAllowedDisplayConfigs.empty() || mAllowedDisplayConfigs.count(configId); } -void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::ConfigEvent event) { +void SurfaceFlinger::changeRefreshRateLocked(const RefreshRate& refreshRate, + Scheduler::ConfigEvent event) { const auto display = getDefaultDisplayDeviceLocked(); if (!display || mBootStage != BootStage::FINISHED) { return; @@ -1408,15 +1411,13 @@ void SurfaceFlinger::setRefreshRateTo(RefreshRateType refreshRate, Scheduler::Co ATRACE_CALL(); // Don't do any updating if the current fps is the same as the new one. - const auto& refreshRateConfig = mRefreshRateConfigs->getRefreshRateFromType(refreshRate); - const int desiredConfigId = refreshRateConfig.configId; - - if (!isDisplayConfigAllowed(desiredConfigId)) { - ALOGV("Skipping config %d as it is not part of allowed configs", desiredConfigId); + if (!isDisplayConfigAllowed(refreshRate.configId)) { + ALOGV("Skipping config %d as it is not part of allowed configs", + refreshRate.configId.value()); return; } - setDesiredActiveConfig({refreshRate, desiredConfigId, event}); + setDesiredActiveConfig({refreshRate.configId, event}); } void SurfaceFlinger::onHotplugReceived(int32_t sequenceId, hwc2_display_t hwcDisplayId, @@ -2180,7 +2181,8 @@ sp SurfaceFlinger::setupNewDisplayDeviceInternal( Dataspace::UNKNOWN}); if (!state.isVirtual()) { LOG_ALWAYS_FATAL_IF(!displayId); - display->setActiveConfig(getHwComposer().getActiveConfigIndex(*displayId)); + auto activeConfigId = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(*displayId)); + display->setActiveConfig(activeConfigId); } display->setLayerStack(state.layerStack); @@ -2520,6 +2522,12 @@ void SurfaceFlinger::updateCursorAsync() mCompositionEngine->updateCursorAsync(refreshArgs); } +void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, + Scheduler::ConfigEvent event) { + Mutex::Autolock lock(mStateLock); + changeRefreshRateLocked(refreshRate, event); +} + void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { if (mScheduler) { // In practice it's not allowed to hotplug in/out the primary display once it's been @@ -2528,7 +2536,7 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { return; } - int currentConfig = getHwComposer().getActiveConfigIndex(primaryDisplayId); + auto currentConfig = HwcConfigIndexType(getHwComposer().getActiveConfigIndex(primaryDisplayId)); mRefreshRateConfigs = std::make_unique(refresh_rate_switching(false), getHwComposer().getConfigs( @@ -2562,11 +2570,7 @@ void SurfaceFlinger::initScheduler(DisplayId primaryDisplayId) { new RegionSamplingThread(*this, *mScheduler, RegionSamplingThread::EnvironmentTimingTunables()); - mScheduler->setChangeRefreshRateCallback( - [this](RefreshRateType type, Scheduler::ConfigEvent event) { - Mutex::Autolock lock(mStateLock); - setRefreshRateTo(type, event); - }); + mScheduler->setSchedulerCallback(this); } void SurfaceFlinger::commitTransaction() @@ -3966,9 +3970,10 @@ void SurfaceFlinger::dumpVSync(std::string& result) const { dispSyncPresentTimeOffset, getVsyncPeriod()); StringAppendF(&result, "Allowed Display Configs: "); - for (int32_t configId : mAllowedDisplayConfigs) { + for (auto configId : mAllowedDisplayConfigs) { StringAppendF(&result, "%" PRIu32 " Hz, ", - mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps); + static_cast( + mRefreshRateConfigs->getRefreshRateFromConfigId(configId).fps)); } StringAppendF(&result, "(config override by backdoor: %s)\n\n", mDebugDisplayConfigSetByBackdoor ? "yes" : "no"); @@ -4809,13 +4814,9 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r n = data.readInt32(); if (n && !mRefreshRateOverlay && mRefreshRateConfigs->refreshRateSwitchingSupported()) { - RefreshRateType type; - { - std::lock_guard lock(mActiveConfigLock); - type = mDesiredActiveConfig.type; - } mRefreshRateOverlay = std::make_unique(*this); - mRefreshRateOverlay->changeRefreshRate(type); + auto current = mRefreshRateConfigs->getCurrentRefreshRate(); + mRefreshRateOverlay->changeRefreshRate(current); } else if (!n) { mRefreshRateOverlay.reset(); } @@ -5417,28 +5418,48 @@ void SurfaceFlinger::setAllowedDisplayConfigsInternal(const sp& d mScheduler->onConfigChanged(mAppConnectionHandle, display->getId()->value, display->getActiveConfig()); + // Prepare the parameters needed for RefreshRateConfigs::setPolicy. This will change to just + // passthrough once DisplayManager provide these parameters directly. + const auto refreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(HwcConfigIndexType(allowedConfigs[0])); + const auto defaultModeId = refreshRate.configId; + auto minRefreshRateFps = refreshRate.fps; + auto maxRefreshRateFps = minRefreshRateFps; + + for (auto config : allowedConfigs) { + const auto configRefreshRate = + mRefreshRateConfigs->getRefreshRateFromConfigId(HwcConfigIndexType(config)); + if (configRefreshRate.fps < minRefreshRateFps) { + minRefreshRateFps = configRefreshRate.fps; + } else if (configRefreshRate.fps > maxRefreshRateFps) { + maxRefreshRateFps = configRefreshRate.fps; + } + } + mRefreshRateConfigs->setPolicy(defaultModeId, minRefreshRateFps, maxRefreshRateFps); + if (mRefreshRateConfigs->refreshRateSwitchingSupported()) { - const auto& type = mScheduler->getPreferredRefreshRateType(); - const auto& config = mRefreshRateConfigs->getRefreshRateFromType(type); - if (isDisplayConfigAllowed(config.configId)) { - ALOGV("switching to Scheduler preferred config %d", config.configId); - setDesiredActiveConfig({type, config.configId, Scheduler::ConfigEvent::Changed}); + auto configId = mScheduler->getPreferredConfigId(); + auto preferredRefreshRate = configId + ? mRefreshRateConfigs->getRefreshRateFromConfigId(*configId) + : mRefreshRateConfigs->getMinRefreshRateByPolicy(); + ALOGV("trying to switch to Scheduler preferred config %d (%s)", + preferredRefreshRate.configId.value(), preferredRefreshRate.name.c_str()); + if (isDisplayConfigAllowed(preferredRefreshRate.configId)) { + ALOGV("switching to Scheduler preferred config %d", + preferredRefreshRate.configId.value()); + setDesiredActiveConfig( + {preferredRefreshRate.configId, Scheduler::ConfigEvent::Changed}); } else { - // Set the highest allowed config by iterating backwards on available refresh rates - const auto& refreshRates = mRefreshRateConfigs->getRefreshRateMap(); - for (auto iter = refreshRates.crbegin(); iter != refreshRates.crend(); ++iter) { - if (isDisplayConfigAllowed(iter->second.configId)) { - ALOGV("switching to allowed config %d", iter->second.configId); - setDesiredActiveConfig( - {iter->first, iter->second.configId, Scheduler::ConfigEvent::Changed}); - break; - } - } + // Set the highest allowed config + setDesiredActiveConfig({mRefreshRateConfigs->getMaxRefreshRateByPolicy().configId, + Scheduler::ConfigEvent::Changed}); + } + } else { + if (!allowedConfigs.empty()) { + ALOGV("switching to config %d", allowedConfigs[0]); + auto configId = HwcConfigIndexType(allowedConfigs[0]); + setDesiredActiveConfig({configId, Scheduler::ConfigEvent::Changed}); } - } else if (!allowedConfigs.empty()) { - ALOGV("switching to config %d", allowedConfigs[0]); - setDesiredActiveConfig( - {RefreshRateType::DEFAULT, allowedConfigs[0], Scheduler::ConfigEvent::Changed}); } } @@ -5487,7 +5508,10 @@ status_t SurfaceFlinger::getAllowedDisplayConfigs(const sp& displayToke } if (display->isPrimary()) { - outAllowedConfigs->assign(mAllowedDisplayConfigs.begin(), mAllowedDisplayConfigs.end()); + outAllowedConfigs->reserve(mAllowedDisplayConfigs.size()); + for (auto configId : mAllowedDisplayConfigs) { + outAllowedConfigs->push_back(configId.value()); + } } return NO_ERROR; diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 8e1199ca59..900c5f7f71 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -174,7 +174,8 @@ class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, public ClientCache::ErasedRecipient, private IBinder::DeathRecipient, - private HWC2::ComposerCallback { + private HWC2::ComposerCallback, + private Scheduler::ISchedulerCallback { public: SurfaceFlingerBE& getBE() { return mBE; } const SurfaceFlingerBE& getBE() const { return mBE; } @@ -494,6 +495,10 @@ private: int32_t sequenceId, hwc2_display_t display, const hwc_vsync_period_change_timeline_t& updatedTimeline) override; + /* ------------------------------------------------------------------------ + * Scheduler::ISchedulerCallback + */ + void changeRefreshRate(const Scheduler::RefreshRate&, Scheduler::ConfigEvent) override; /* ------------------------------------------------------------------------ * Message handling */ @@ -504,15 +509,14 @@ private: void signalLayerUpdate(); void signalRefresh(); - using RefreshRateType = scheduler::RefreshRateConfigs::RefreshRateType; + using RefreshRate = scheduler::RefreshRateConfigs::RefreshRate; struct ActiveConfigInfo { - RefreshRateType type = RefreshRateType::DEFAULT; - int configId = 0; + HwcConfigIndexType configId; Scheduler::ConfigEvent event = Scheduler::ConfigEvent::None; bool operator!=(const ActiveConfigInfo& other) const { - return type != other.type || configId != other.configId || event != other.event; + return configId != other.configId || event != other.event; } }; @@ -787,9 +791,10 @@ private: // Sets the refresh rate by switching active configs, if they are available for // the desired refresh rate. - void setRefreshRateTo(RefreshRateType, Scheduler::ConfigEvent event) REQUIRES(mStateLock); + void changeRefreshRateLocked(const RefreshRate&, Scheduler::ConfigEvent event) + REQUIRES(mStateLock); - bool isDisplayConfigAllowed(int32_t configId) const REQUIRES(mStateLock); + bool isDisplayConfigAllowed(HwcConfigIndexType configId) const REQUIRES(mStateLock); bool previousFrameMissed(int graceTimeMs = 0); @@ -1113,7 +1118,7 @@ private: std::atomic mExpectedPresentTime = 0; // All configs are allowed if the set is empty. - using DisplayConfigs = std::set; + using DisplayConfigs = std::set; DisplayConfigs mAllowedDisplayConfigs GUARDED_BY(mStateLock); std::mutex mActiveConfigLock; diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index db7d04c8e3..76e8171255 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -1427,7 +1427,7 @@ void SetupNewDisplayDeviceInternalTest::setupNewDisplayDeviceInternalTest() { // Note: This is not Case::Display::HWC_ACTIVE_CONFIG_ID as the ids are // remapped, and the test only ever sets up one config. If there were an error // looking up the remapped index, device->getActiveConfig() would be -1 instead. - EXPECT_EQ(0, device->getActiveConfig()); + EXPECT_EQ(0, device->getActiveConfig().value()); EXPECT_EQ(Case::PerFrameMetadataSupport::PER_FRAME_METADATA_KEYS, device->getSupportedPerFrameMetadata()); } diff --git a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp index 2662f52581..80bca021ab 100644 --- a/services/surfaceflinger/tests/unittests/EventThreadTest.cpp +++ b/services/surfaceflinger/tests/unittests/EventThreadTest.cpp @@ -26,6 +26,7 @@ #include "AsyncCallRecorder.h" #include "Scheduler/EventThread.h" +#include "Scheduler/HwcStrongTypes.h" using namespace std::chrono_literals; using namespace std::placeholders; @@ -34,6 +35,7 @@ using testing::_; using testing::Invoke; namespace android { + namespace { constexpr PhysicalDisplayId INTERNAL_DISPLAY_ID = 111; @@ -448,17 +450,17 @@ TEST_F(EventThreadTest, postHotplugExternalConnect) { } TEST_F(EventThreadTest, postConfigChangedPrimary) { - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 7); + mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(7)); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 7); } TEST_F(EventThreadTest, postConfigChangedExternal) { - mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, 5); + mThread->onConfigChanged(EXTERNAL_DISPLAY_ID, HwcConfigIndexType(5)); expectConfigChangedEventReceivedByConnection(EXTERNAL_DISPLAY_ID, 5); } TEST_F(EventThreadTest, postConfigChangedPrimary64bit) { - mThread->onConfigChanged(DISPLAY_ID_64BIT, 7); + mThread->onConfigChanged(DISPLAY_ID_64BIT, HwcConfigIndexType(7)); expectConfigChangedEventReceivedByConnection(DISPLAY_ID_64BIT, 7); } @@ -468,7 +470,7 @@ TEST_F(EventThreadTest, suppressConfigChanged) { createConnection(suppressConnectionEventRecorder, ISurfaceComposer::eConfigChangedSuppress); - mThread->onConfigChanged(INTERNAL_DISPLAY_ID, 9); + mThread->onConfigChanged(INTERNAL_DISPLAY_ID, HwcConfigIndexType(9)); expectConfigChangedEventReceivedByConnection(INTERNAL_DISPLAY_ID, 9); auto args = suppressConnectionEventRecorder.waitForCall(); diff --git a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h index 66c7f6b81f..da4eea0221 100644 --- a/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h +++ b/services/surfaceflinger/tests/unittests/FakePhaseOffsets.h @@ -25,16 +25,16 @@ namespace android::scheduler { struct FakePhaseOffsets : PhaseOffsets { static constexpr nsecs_t FAKE_PHASE_OFFSET_NS = 0; - Offsets getOffsetsForRefreshRate(RefreshRateType) const override { return getCurrentOffsets(); } + Offsets getOffsetsForRefreshRate(float) const override { return getCurrentOffsets(); } Offsets getCurrentOffsets() const override { - return {{RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, - {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, - {RefreshRateType::DEFAULT, FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, + return {{FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, + {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, + {FAKE_PHASE_OFFSET_NS, FAKE_PHASE_OFFSET_NS}, FAKE_PHASE_OFFSET_NS}; } - void setRefreshRateType(RefreshRateType) override {} + void setRefreshRateFps(float) override {} void dump(std::string&) const override {} }; diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index e93d31e7f2..d95252b67f 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -44,9 +44,15 @@ protected: auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } RefreshRateConfigs mConfigs{true, - {RefreshRateConfigs::InputConfig{0, LO_FPS_PERIOD}, - RefreshRateConfigs::InputConfig{1, HI_FPS_PERIOD}}, - 0}; + { + RefreshRateConfigs::InputConfig{HwcConfigIndexType(0), + HwcConfigGroupType(0), + LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{HwcConfigIndexType(1), + HwcConfigGroupType(0), + HI_FPS_PERIOD}, + }, + HwcConfigIndexType(0)}; TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; TestableSurfaceFlinger mFlinger; @@ -57,7 +63,6 @@ namespace { TEST_F(LayerHistoryTest, oneLayer) { const auto layer = createLayer(); - constexpr bool isHDR = false; EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_EQ(1, layerCount()); @@ -69,14 +74,14 @@ TEST_F(LayerHistoryTest, oneLayer) { // 0 FPS is returned if active layers have insufficient history. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { - history().record(layer.get(), 0, isHDR, mTime); + history().record(layer.get(), 0, mTime); EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); EXPECT_EQ(1, activeLayerCount()); } // High FPS is returned once enough history has been recorded. for (int i = 0; i < 10; i++) { - history().record(layer.get(), 0, isHDR, mTime); + history().record(layer.get(), 0, mTime); EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); EXPECT_EQ(1, activeLayerCount()); } @@ -84,29 +89,25 @@ TEST_F(LayerHistoryTest, oneLayer) { TEST_F(LayerHistoryTest, oneHDRLayer) { const auto layer = createLayer(); - constexpr bool isHDR = true; EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); - history().record(layer.get(), 0, isHDR, mTime); + history().record(layer.get(), 0, mTime); auto summary = history().summarize(mTime); EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_TRUE(summary.isHDR); EXPECT_EQ(1, activeLayerCount()); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); summary = history().summarize(mTime); EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_FALSE(summary.isHDR); EXPECT_EQ(0, activeLayerCount()); } TEST_F(LayerHistoryTest, explicitTimestamp) { const auto layer = createLayer(); - constexpr bool isHDR = false; EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_EQ(1, layerCount()); @@ -114,7 +115,7 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { nsecs_t time = mTime; for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer.get(), time, isHDR, time); + history().record(layer.get(), time, time); time += LO_FPS_PERIOD; } @@ -127,7 +128,6 @@ TEST_F(LayerHistoryTest, multipleLayers) { auto layer1 = createLayer(); auto layer2 = createLayer(); auto layer3 = createLayer(); - constexpr bool isHDR = false; EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); @@ -141,7 +141,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer1 is active but infrequent. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer1.get(), time, isHDR, time); + history().record(layer1.get(), time, time); time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } @@ -151,12 +151,12 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer2 is frequent and has high refresh rate. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); time += HI_FPS_PERIOD; } // layer1 is still active but infrequent. - history().record(layer1.get(), time, isHDR, time); + history().record(layer1.get(), time, time); EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); EXPECT_EQ(2, activeLayerCount()); @@ -165,7 +165,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer1 is no longer active. // layer2 is frequent and has low refresh rate. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); time += LO_FPS_PERIOD; } @@ -178,10 +178,10 @@ TEST_F(LayerHistoryTest, multipleLayers) { constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { if (i % RATIO == 0) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); } - history().record(layer3.get(), time, isHDR, time); + history().record(layer3.get(), time, time); time += HI_FPS_PERIOD; } @@ -190,7 +190,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { EXPECT_EQ(2, frequentLayerCount(time)); // layer3 becomes recently active. - history().record(layer3.get(), time, isHDR, time); + history().record(layer3.get(), time, time); EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -205,7 +205,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer2 still has low refresh rate. // layer3 becomes inactive. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer2.get(), time, isHDR, time); + history().record(layer2.get(), time, time); time += LO_FPS_PERIOD; } @@ -222,7 +222,7 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer3 becomes active and has high refresh rate. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { - history().record(layer3.get(), time, isHDR, time); + history().record(layer3.get(), time, time); time += HI_FPS_PERIOD; } diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index f315a8a86c..546e65c1ea 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -30,27 +30,19 @@ using testing::_; namespace android { namespace scheduler { -using RefreshRateType = RefreshRateConfigs::RefreshRateType; using RefreshRate = RefreshRateConfigs::RefreshRate; class RefreshRateConfigsTest : public testing::Test { protected: - static constexpr int CONFIG_ID_60 = 0; - static constexpr hwc2_config_t HWC2_CONFIG_ID_60 = 0; - static constexpr int CONFIG_ID_90 = 1; - static constexpr hwc2_config_t HWC2_CONFIG_ID_90 = 1; + static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0); + static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1); + static inline const HwcConfigGroupType HWC_GROUP_ID_0 = HwcConfigGroupType(0); + static inline const HwcConfigGroupType HWC_GROUP_ID_1 = HwcConfigGroupType(1); static constexpr int64_t VSYNC_60 = 16666667; static constexpr int64_t VSYNC_90 = 11111111; RefreshRateConfigsTest(); ~RefreshRateConfigsTest(); - - void assertRatesEqual(const RefreshRate& left, const RefreshRate& right) { - ASSERT_EQ(left.configId, right.configId); - ASSERT_EQ(left.name, right.name); - ASSERT_EQ(left.fps, right.fps); - ASSERT_EQ(left.vsyncPeriod, right.vsyncPeriod); - } }; RefreshRateConfigsTest::RefreshRateConfigsTest() { @@ -69,40 +61,173 @@ namespace { /* ------------------------------------------------------------------------ * Test cases */ -TEST_F(RefreshRateConfigsTest, oneDeviceConfig_isRejected) { - std::vector configs{{HWC2_CONFIG_ID_60, VSYNC_60}}; +TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingSupported) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}}; auto refreshRateConfigs = std::make_unique(/*refreshRateSwitching=*/true, configs, - /*currentConfig=*/0); + /*currentConfigId=*/HWC_CONFIG_ID_60); + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); +} + +TEST_F(RefreshRateConfigsTest, oneDeviceConfig_SwitchingNotSupported) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/false, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_FALSE(refreshRateConfigs->refreshRateSwitchingSupported()); } TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap) { - std::vector configs{{HWC2_CONFIG_ID_60, VSYNC_60}, - {HWC2_CONFIG_ID_90, VSYNC_90}}; + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; auto refreshRateConfigs = std::make_unique(/*refreshRateSwitching=*/true, configs, - /*currentConfig=*/0); + /*currentConfigId=*/HWC_CONFIG_ID_60); ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); - const auto& rates = refreshRateConfigs->getRefreshRateMap(); - ASSERT_EQ(2, rates.size()); - const auto& defaultRate = rates.find(RefreshRateType::DEFAULT); - const auto& performanceRate = rates.find(RefreshRateType::PERFORMANCE); - ASSERT_NE(rates.end(), defaultRate); - ASSERT_NE(rates.end(), performanceRate); - - RefreshRate expectedDefaultConfig = {CONFIG_ID_60, "60fps", 60, VSYNC_60, HWC2_CONFIG_ID_60}; - assertRatesEqual(expectedDefaultConfig, defaultRate->second); - RefreshRate expectedPerformanceConfig = {CONFIG_ID_90, "90fps", 90, VSYNC_90, - HWC2_CONFIG_ID_90}; - assertRatesEqual(expectedPerformanceConfig, performanceRate->second); - - assertRatesEqual(expectedDefaultConfig, - refreshRateConfigs->getRefreshRateFromType(RefreshRateType::DEFAULT)); - assertRatesEqual(expectedPerformanceConfig, - refreshRateConfigs->getRefreshRateFromType(RefreshRateType::PERFORMANCE)); + + const auto minRate = refreshRateConfigs->getMinRefreshRate(); + const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); + + RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + ASSERT_EQ(expectedDefaultConfig, minRate); + RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", + 90}; + ASSERT_EQ(expectedPerformanceConfig, performanceRate); + + const auto minRateByPolicy = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRateByPolicy = refreshRateConfigs->getMaxRefreshRateByPolicy(); + ASSERT_EQ(minRateByPolicy, minRate); + ASSERT_EQ(performanceRateByPolicy, performanceRate); } + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_storesFullRefreshRateMap_differentGroups) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_1, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + const auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRate = refreshRateConfigs->getMaxRefreshRate(); + const auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + ASSERT_EQ(expectedDefaultConfig, minRate); + ASSERT_EQ(expectedDefaultConfig, minRate60); + ASSERT_EQ(expectedDefaultConfig, performanceRate60); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 60, 90); + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + const auto minRate90 = refreshRateConfigs->getMinRefreshRateByPolicy(); + const auto performanceRate90 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_1, "90fps", + 90}; + ASSERT_EQ(expectedPerformanceConfig, performanceRate); + ASSERT_EQ(expectedPerformanceConfig, minRate90); + ASSERT_EQ(expectedPerformanceConfig, performanceRate90); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_policyChange) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + auto minRate = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto performanceRate = refreshRateConfigs->getMaxRefreshRateByPolicy(); + + RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + ASSERT_EQ(expectedDefaultConfig, minRate); + RefreshRate expectedPerformanceConfig = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", + 90}; + ASSERT_EQ(expectedPerformanceConfig, performanceRate); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60); + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + auto minRate60 = refreshRateConfigs->getMinRefreshRateByPolicy(); + auto performanceRate60 = refreshRateConfigs->getMaxRefreshRateByPolicy(); + ASSERT_EQ(expectedDefaultConfig, minRate60); + ASSERT_EQ(expectedDefaultConfig, performanceRate60); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getCurrentRefreshRate) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + { + auto current = refreshRateConfigs->getCurrentRefreshRate(); + EXPECT_EQ(current.configId, HWC_CONFIG_ID_60); + } + + refreshRateConfigs->setCurrentConfigId(HWC_CONFIG_ID_90); + { + auto current = refreshRateConfigs->getCurrentRefreshRate(); + EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); + } + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 90, 90); + { + auto current = refreshRateConfigs->getCurrentRefreshRate(); + EXPECT_EQ(current.configId, HWC_CONFIG_ID_90); + } +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 90, 90); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); + ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); + ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); +} + } // namespace } // namespace scheduler } // namespace android diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index cec0b32a6b..ef4699f628 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -33,8 +33,9 @@ namespace scheduler { class RefreshRateStatsTest : public testing::Test { protected: - static constexpr int CONFIG_ID_90 = 0; - static constexpr int CONFIG_ID_60 = 1; + static inline const auto CONFIG_ID_0 = HwcConfigIndexType(0); + static inline const auto CONFIG_ID_1 = HwcConfigIndexType(1); + static inline const auto CONFIG_GROUP_0 = HwcConfigGroupType(0); static constexpr int64_t VSYNC_90 = 11111111; static constexpr int64_t VSYNC_60 = 16666667; @@ -43,10 +44,10 @@ protected: void init(const std::vector& configs) { mRefreshRateConfigs = std::make_unique( - /*refreshRateSwitching=*/true, configs, /*currentConfig=*/0); + /*refreshRateSwitching=*/true, configs, /*currentConfig=*/CONFIG_ID_0); mRefreshRateStats = std::make_unique(*mRefreshRateConfigs, mTimeStats, - /*currentConfig=*/0, + /*currentConfigId=*/CONFIG_ID_0, /*currentPowerMode=*/HWC_POWER_MODE_OFF); } @@ -72,7 +73,7 @@ namespace { * Test cases */ TEST_F(RefreshRateStatsTest, oneConfigTest) { - init({{CONFIG_ID_90, VSYNC_90}}); + init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}}}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(90, _)).Times(AtLeast(1)); @@ -91,7 +92,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(0u, times.count("90fps")); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -107,7 +108,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { EXPECT_LT(screenOff, times["ScreenOff"]); EXPECT_EQ(ninety, times["90fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -118,7 +119,7 @@ TEST_F(RefreshRateStatsTest, oneConfigTest) { } TEST_F(RefreshRateStatsTest, twoConfigsTest) { - init({{CONFIG_ID_90, VSYNC_90}, {CONFIG_ID_60, VSYNC_60}}); + init({{{CONFIG_ID_0, CONFIG_GROUP_0, VSYNC_90}, {CONFIG_ID_1, CONFIG_GROUP_0, VSYNC_60}}}); EXPECT_CALL(mTimeStats, recordRefreshRate(0, _)).Times(AtLeast(1)); EXPECT_CALL(mTimeStats, recordRefreshRate(60, _)).Times(AtLeast(1)); @@ -137,7 +138,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { times = mRefreshRateStats->getTotalTimes(); EXPECT_LT(screenOff, times["ScreenOff"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); mRefreshRateStats->setPowerMode(HWC_POWER_MODE_NORMAL); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); @@ -147,7 +148,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_LT(0, times["90fps"]); // When power mode is normal, time for configs updates. - mRefreshRateStats->setConfigMode(CONFIG_ID_60); + mRefreshRateStats->setConfigMode(CONFIG_ID_1); int ninety = mRefreshRateStats->getTotalTimes()["90fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -156,7 +157,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { ASSERT_EQ(1u, times.count("60fps")); EXPECT_LT(0, times["60fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); int sixty = mRefreshRateStats->getTotalTimes()["60fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -164,7 +165,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_LT(ninety, times["90fps"]); EXPECT_EQ(sixty, times["60fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_60); + mRefreshRateStats->setConfigMode(CONFIG_ID_1); ninety = mRefreshRateStats->getTotalTimes()["90fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -175,7 +176,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { // Because the power mode is not HWC_POWER_MODE_NORMAL, switching the config // does not update refresh rates that come from the config. mRefreshRateStats->setPowerMode(HWC_POWER_MODE_DOZE); - mRefreshRateStats->setConfigMode(CONFIG_ID_90); + mRefreshRateStats->setConfigMode(CONFIG_ID_0); sixty = mRefreshRateStats->getTotalTimes()["60fps"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); @@ -183,7 +184,7 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { EXPECT_EQ(ninety, times["90fps"]); EXPECT_EQ(sixty, times["60fps"]); - mRefreshRateStats->setConfigMode(CONFIG_ID_60); + mRefreshRateStats->setConfigMode(CONFIG_ID_1); screenOff = mRefreshRateStats->getTotalTimes()["ScreenOff"]; std::this_thread::sleep_for(std::chrono::milliseconds(2)); times = mRefreshRateStats->getTotalTimes(); diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index b4cc1e15e8..40536abc5d 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -50,10 +50,11 @@ SchedulerTest::SchedulerTest() { ::testing::UnitTest::GetInstance()->current_test_info(); ALOGD("**** Setting up for %s.%s\n", test_info->test_case_name(), test_info->name()); - std::vector configs{{/*hwcId=*/0, 16666667}}; - mRefreshRateConfigs = - std::make_unique(/*refreshRateSwitching=*/false, configs, - /*currentConfig=*/0); + std::vector configs{ + {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; + mRefreshRateConfigs = std::make_unique< + scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs, + /*currentConfig=*/HwcConfigIndexType(0)); mScheduler = std::make_unique(*mRefreshRateConfigs); diff --git a/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp b/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp index b9ddcd77d0..54068797a1 100644 --- a/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp +++ b/services/surfaceflinger/tests/unittests/StrongTypingTest.cpp @@ -56,18 +56,18 @@ TEST(StrongTypeTest, addition) { EXPECT_THAT(f1 + f2, Eq(FunkyType(32))); EXPECT_THAT(f2 + f1, Eq(FunkyType(32))); - EXPECT_THAT(++f1, Eq(11)); - EXPECT_THAT(f1, Eq(11)); - EXPECT_THAT(f1++, Eq(11)); - EXPECT_THAT(f1++, Eq(12)); - EXPECT_THAT(f1, Eq(13)); + EXPECT_THAT(++f1.value(), Eq(11)); + EXPECT_THAT(f1.value(), Eq(11)); + EXPECT_THAT(f1++.value(), Eq(11)); + EXPECT_THAT(f1++.value(), Eq(12)); + EXPECT_THAT(f1.value(), Eq(13)); auto f3 = f1; EXPECT_THAT(f1, Eq(f3)); EXPECT_THAT(f1, Lt(f2)); f3 += f1; - EXPECT_THAT(f1, Eq(13)); - EXPECT_THAT(f3, Eq(26)); + EXPECT_THAT(f1.value(), Eq(13)); + EXPECT_THAT(f3.value(), Eq(26)); } } // namespace android diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 94fc5f7273..c4b8408202 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -193,15 +193,15 @@ public: std::unique_ptr eventControlThread, std::unique_ptr appEventThread, std::unique_ptr sfEventThread) { - std::vector configs{{/*hwcId=*/0, 16666667}}; - mFlinger->mRefreshRateConfigs = - std::make_unique(/*refreshRateSwitching=*/false, - configs, /*currentConfig=*/0); - mFlinger->mRefreshRateStats = - std::make_unique(*mFlinger->mRefreshRateConfigs, - *mFlinger->mTimeStats, - /*currentConfig=*/0, - /*powerMode=*/HWC_POWER_MODE_OFF); + std::vector configs{ + {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; + mFlinger->mRefreshRateConfigs = std::make_unique< + scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs, + /*currentConfig=*/HwcConfigIndexType(0)); + mFlinger->mRefreshRateStats = std::make_unique< + scheduler::RefreshRateStats>(*mFlinger->mRefreshRateConfigs, *mFlinger->mTimeStats, + /*currentConfig=*/HwcConfigIndexType(0), + /*powerMode=*/HWC_POWER_MODE_OFF); mScheduler = new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread), @@ -429,6 +429,7 @@ public: static constexpr int32_t DEFAULT_WIDTH = 1920; static constexpr int32_t DEFAULT_HEIGHT = 1280; static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666; + static constexpr int32_t DEFAULT_CONFIG_GROUP = 7; static constexpr int32_t DEFAULT_DPI = 320; static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; static constexpr int32_t DEFAULT_POWER_MODE = 2; @@ -452,7 +453,7 @@ public: return *this; } - auto& setRefreshRate(int32_t refreshRate) { + auto& setRefreshRate(uint32_t refreshRate) { mRefreshRate = refreshRate; return *this; } @@ -499,6 +500,7 @@ public: config.setVsyncPeriod(mRefreshRate); config.setDpiX(mDpiX); config.setDpiY(mDpiY); + config.setConfigGroup(mConfigGroup); display->mutableConfigs().emplace(mActiveConfig, config.build()); display->mutableIsConnected() = true; display->setPowerMode(static_cast(mPowerMode)); @@ -522,8 +524,9 @@ public: hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; int32_t mWidth = DEFAULT_WIDTH; int32_t mHeight = DEFAULT_HEIGHT; - int32_t mRefreshRate = DEFAULT_REFRESH_RATE; + uint32_t mRefreshRate = DEFAULT_REFRESH_RATE; int32_t mDpiX = DEFAULT_DPI; + int32_t mConfigGroup = DEFAULT_CONFIG_GROUP; int32_t mDpiY = DEFAULT_DPI; int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; int32_t mPowerMode = DEFAULT_POWER_MODE; diff --git a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h index ed35ebf2b6..f7c380490b 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockEventThread.h +++ b/services/surfaceflinger/tests/unittests/mock/MockEventThread.h @@ -33,7 +33,7 @@ public: MOCK_METHOD0(onScreenReleased, void()); MOCK_METHOD0(onScreenAcquired, void()); MOCK_METHOD2(onHotplugReceived, void(PhysicalDisplayId, bool)); - MOCK_METHOD2(onConfigChanged, void(PhysicalDisplayId, int32_t)); + MOCK_METHOD2(onConfigChanged, void(PhysicalDisplayId, HwcConfigIndexType)); MOCK_CONST_METHOD1(dump, void(std::string&)); MOCK_METHOD1(setPhaseOffset, void(nsecs_t phaseOffset)); MOCK_METHOD1(registerDisplayEventConnection, -- cgit v1.2.3-59-g8ed1b From ba45baec175b66cacd28b52b0a27adefbb8a0332 Mon Sep 17 00:00:00 2001 From: Adithya Srinivasan Date: Mon, 30 Dec 2019 12:39:11 -0800 Subject: Add tracing for onFrameReplaced As a part of the queueBuffer call, in async mode, the buffer at the front of the queue can be replaced. This change adds a tracing for such replace call and will use the same event type as Queue. Test: Run GAPID vulkan cube app or any other app that uses async mode and check if Queue event shows up Bug: 145828619 Change-Id: I9f86c79dab09bf1071a79adbb743276e07a9b47f --- services/surfaceflinger/BufferQueueLayer.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index 945abd77d6..e4e4bc7db6 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -455,6 +455,10 @@ void BufferQueueLayer::onFrameReplaced(const BufferItem& item) { mLastFrameNumberReceived = item.mFrameNumber; mQueueItemCondition.broadcast(); } + + const int32_t layerId = getSequence(); + mFlinger->mFrameTracer->traceTimestamp(layerId, item.mGraphicBuffer->getId(), item.mFrameNumber, + systemTime(), FrameTracer::FrameEvent::QUEUE); mConsumer->onBufferAvailable(item); } -- cgit v1.2.3-59-g8ed1b From b0dbdaaf3b1a42ab072af9d111d56900b1197af4 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Mon, 6 Jan 2020 16:19:42 -0800 Subject: SurfaceFlinger: Enable -WConversion in Android.bp Enable global -WConversion in Android.bp and turn it off in individual files. This is the first step to enable -WConversion in SurfaceFlinger. Test: boot Bug: 129481165 Change-Id: Ia752df39ef380bde71705a32582d618242c466f7 --- libs/renderengine/tests/RenderEngineTest.cpp | 7 +++++++ services/surfaceflinger/Android.bp | 1 + services/surfaceflinger/BufferLayer.cpp | 7 +++++++ services/surfaceflinger/BufferLayerConsumer.cpp | 7 +++++++ services/surfaceflinger/BufferQueueLayer.cpp | 7 +++++++ services/surfaceflinger/BufferStateLayer.cpp | 7 +++++++ services/surfaceflinger/Client.cpp | 7 +++++++ services/surfaceflinger/ColorLayer.cpp | 7 +++++++ .../CompositionEngine/mock/Display.cpp | 7 +++++++ .../CompositionEngine/mock/Layer.cpp | 7 +++++++ .../CompositionEngine/mock/LayerFE.cpp | 7 +++++++ .../CompositionEngine/mock/Output.cpp | 7 +++++++ .../CompositionEngine/mock/OutputLayer.cpp | 7 +++++++ .../CompositionEngine/src/CompositionEngine.cpp | 7 +++++++ .../CompositionEngine/src/Display.cpp | 7 +++++++ .../CompositionEngine/src/HwcBufferCache.cpp | 7 +++++++ .../surfaceflinger/CompositionEngine/src/Layer.cpp | 7 +++++++ .../src/LayerFECompositionState.cpp | 7 +++++++ .../CompositionEngine/src/Output.cpp | 7 +++++++ .../CompositionEngine/src/OutputLayer.cpp | 7 +++++++ .../src/OutputLayerCompositionState.cpp | 7 +++++++ .../CompositionEngine/src/RenderSurface.cpp | 7 +++++++ .../tests/CompositionEngineTest.cpp | 7 +++++++ .../CompositionEngine/tests/DisplayTest.cpp | 7 +++++++ .../CompositionEngine/tests/LayerTest.cpp | 7 +++++++ .../CompositionEngine/tests/OutputLayerTest.cpp | 7 +++++++ .../CompositionEngine/tests/OutputTest.cpp | 7 +++++++ .../CompositionEngine/tests/RenderSurfaceTest.cpp | 7 +++++++ services/surfaceflinger/ContainerLayer.cpp | 7 +++++++ services/surfaceflinger/DisplayDevice.cpp | 7 +++++++ .../surfaceflinger/DisplayHardware/ComposerHal.cpp | 7 +++++++ .../DisplayHardware/DisplayIdentification.cpp | 7 +++++++ .../DisplayHardware/FramebufferSurface.cpp | 7 +++++++ services/surfaceflinger/DisplayHardware/HWC2.cpp | 7 +++++++ .../surfaceflinger/DisplayHardware/HWComposer.cpp | 7 +++++++ .../DisplayHardware/VirtualDisplaySurface.cpp | 7 +++++++ services/surfaceflinger/Effects/Daltonizer.cpp | 7 +++++++ services/surfaceflinger/EventLog/EventLog.cpp | 7 +++++++ .../surfaceflinger/FrameTracer/FrameTracer.cpp | 7 +++++++ services/surfaceflinger/FrameTracker.cpp | 7 +++++++ services/surfaceflinger/Layer.cpp | 7 +++++++ services/surfaceflinger/LayerProtoHelper.cpp | 7 +++++++ services/surfaceflinger/LayerRejecter.cpp | 7 +++++++ services/surfaceflinger/LayerVector.cpp | 7 +++++++ services/surfaceflinger/MonitoredProducer.cpp | 7 +++++++ services/surfaceflinger/RefreshRateOverlay.cpp | 7 +++++++ services/surfaceflinger/RegionSamplingThread.cpp | 7 +++++++ services/surfaceflinger/RenderArea.cpp | 23 ++++++++++++++++++++++ services/surfaceflinger/Scheduler/DispSync.cpp | 7 +++++++ .../surfaceflinger/Scheduler/DispSyncSource.cpp | 7 +++++++ .../Scheduler/EventControlThread.cpp | 7 +++++++ services/surfaceflinger/Scheduler/EventThread.cpp | 7 +++++++ services/surfaceflinger/Scheduler/LayerHistory.cpp | 7 +++++++ services/surfaceflinger/Scheduler/MessageQueue.cpp | 7 +++++++ services/surfaceflinger/Scheduler/PhaseOffsets.cpp | 7 +++++++ .../Scheduler/RefreshRateConfigs.cpp | 6 ++++++ services/surfaceflinger/Scheduler/Scheduler.cpp | 7 +++++++ .../surfaceflinger/Scheduler/SchedulerUtils.cpp | 7 +++++++ .../surfaceflinger/Scheduler/VSyncModulator.cpp | 7 +++++++ .../surfaceflinger/Scheduler/VSyncPredictor.cpp | 7 +++++++ services/surfaceflinger/SurfaceFlinger.cpp | 7 +++++++ .../SurfaceFlingerDefaultFactory.cpp | 7 +++++++ services/surfaceflinger/SurfaceFlingerFactory.cpp | 7 +++++++ services/surfaceflinger/SurfaceInterceptor.cpp | 7 +++++++ services/surfaceflinger/SurfaceTracing.cpp | 7 +++++++ services/surfaceflinger/TimeStats/TimeStats.cpp | 7 +++++++ .../surfaceflinger/TransactionCompletedThread.cpp | 7 +++++++ services/surfaceflinger/main_surfaceflinger.cpp | 7 +++++++ services/surfaceflinger/tests/BufferGenerator.cpp | 7 +++++++ services/surfaceflinger/tests/Credentials_test.cpp | 7 +++++++ .../tests/DereferenceSurfaceControl_test.cpp | 7 +++++++ .../surfaceflinger/tests/DisplayConfigs_test.cpp | 7 +++++++ .../surfaceflinger/tests/LayerCallback_test.cpp | 7 +++++++ .../tests/LayerRenderTypeTransaction_test.cpp | 7 +++++++ .../surfaceflinger/tests/LayerTransaction_test.cpp | 7 +++++++ .../LayerTypeAndRenderTypeTransaction_test.cpp | 7 +++++++ .../tests/LayerTypeTransaction_test.cpp | 7 +++++++ services/surfaceflinger/tests/LayerUpdate_test.cpp | 7 +++++++ services/surfaceflinger/tests/MirrorLayer_test.cpp | 7 +++++++ .../tests/MultiDisplayLayerBounds_test.cpp | 7 +++++++ services/surfaceflinger/tests/RelativeZ_test.cpp | 7 +++++++ services/surfaceflinger/tests/SetGeometry_test.cpp | 7 +++++++ services/surfaceflinger/tests/Stress_test.cpp | 7 +++++++ .../tests/SurfaceInterceptor_test.cpp | 7 +++++++ .../tests/fakehwc/FakeComposerClient.cpp | 7 +++++++ .../tests/fakehwc/FakeComposerService.cpp | 7 +++++++ .../tests/fakehwc/FakeComposerUtils.cpp | 7 +++++++ .../tests/fakehwc/SFFakeHwc_test.cpp | 7 +++++++ services/surfaceflinger/tests/hwc2/Hwc2Test.cpp | 7 +++++++ .../surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp | 7 +++++++ .../surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp | 7 +++++++ .../tests/hwc2/Hwc2TestPixelComparator.cpp | 7 +++++++ .../tests/hwc2/Hwc2TestProperties.cpp | 7 +++++++ .../surfaceflinger/tests/unittests/CachingTest.cpp | 7 +++++++ .../tests/unittests/CompositionTest.cpp | 7 +++++++ .../tests/unittests/DisplayTransactionTest.cpp | 7 +++++++ .../tests/unittests/FrameTracerTest.cpp | 7 +++++++ .../tests/unittests/LayerHistoryTest.cpp | 23 ++++++++++++++++++++++ .../tests/unittests/PhaseOffsetsTest.cpp | 7 +++++++ .../tests/unittests/RefreshRateConfigsTest.cpp | 8 ++++---- .../tests/unittests/RefreshRateStatsTest.cpp | 7 +++++++ .../tests/unittests/RegionSamplingTest.cpp | 7 +++++++ .../tests/unittests/SchedulerTest.cpp | 23 ++++++++++++++++++++++ .../tests/unittests/SchedulerUtilsTest.cpp | 8 +++++++- .../tests/unittests/TimeStatsTest.cpp | 7 +++++++ .../tests/unittests/TransactionApplicationTest.cpp | 7 +++++++ .../unittests/VSyncDispatchTimerQueueTest.cpp | 7 +++++++ .../tests/unittests/VSyncPredictorTest.cpp | 7 +++++++ .../mock/DisplayHardware/MockComposer.cpp | 7 +++++++ .../unittests/mock/MockSurfaceInterceptor.cpp | 7 +++++++ services/surfaceflinger/tests/vsync/vsync.cpp | 7 +++++++ 111 files changed, 815 insertions(+), 5 deletions(-) (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/renderengine/tests/RenderEngineTest.cpp b/libs/renderengine/tests/RenderEngineTest.cpp index ba5a3f5550..7700b2e01f 100644 --- a/libs/renderengine/tests/RenderEngineTest.cpp +++ b/libs/renderengine/tests/RenderEngineTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -1339,3 +1343,6 @@ TEST_F(RenderEngineTest, drawLayers_fillShadow_translucentCasterWithAlpha) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 4c5e5da36a..8fa35d83e7 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -7,6 +7,7 @@ cc_defaults { "-Wthread-safety", "-Wunused", "-Wunreachable-code", + "-Wconversion", ], } diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 3b1b796076..7845cab397 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "BufferLayer" @@ -795,3 +799,6 @@ void BufferLayer::updateCloneBufferInfo() { #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/BufferLayerConsumer.cpp b/services/surfaceflinger/BufferLayerConsumer.cpp index ea55795119..5e04d9597a 100644 --- a/services/surfaceflinger/BufferLayerConsumer.cpp +++ b/services/surfaceflinger/BufferLayerConsumer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "BufferLayerConsumer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -519,3 +523,6 @@ BufferLayerConsumer::Image::~Image() { } } }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e4e4bc7db6..c1b87751a4 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "BufferQueueLayer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -612,3 +616,6 @@ void BufferQueueLayer::ContentsChangedListener::abandon() { // ----------------------------------------------------------------------- } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index 067aa46b71..c173c66b4e 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "BufferStateLayer" @@ -681,3 +685,6 @@ sp BufferStateLayer::createClone() { return layer; } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index f3313645fa..fb72ab8065 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -131,3 +135,6 @@ status_t Client::getLayerFrameStats(const sp& handle, FrameStats* outSt // --------------------------------------------------------------------------- }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 8bfa569eeb..6aea88abd6 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "ColorLayer" @@ -116,3 +120,6 @@ sp ColorLayer::createClone() { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/Display.cpp b/services/surfaceflinger/CompositionEngine/mock/Display.cpp index 01cf11278b..dc303d736f 100644 --- a/services/surfaceflinger/CompositionEngine/mock/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/Display.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ Display::Display() = default; Display::~Display() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp index 08483cb301..a733bacee9 100644 --- a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ Layer::Layer() = default; Layer::~Layer() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp b/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp index 607eaad826..232756f247 100644 --- a/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/LayerFE.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ LayerFE::LayerFE() = default; LayerFE::~LayerFE() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/Output.cpp b/services/surfaceflinger/CompositionEngine/mock/Output.cpp index 44df4c3da3..2608ef0cc0 100644 --- a/services/surfaceflinger/CompositionEngine/mock/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/Output.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ Output::Output() = default; Output::~Output() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp index 4da9377123..c1153e3596 100644 --- a/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/mock/OutputLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include namespace android::compositionengine::mock { @@ -24,3 +28,6 @@ OutputLayer::OutputLayer() = default; OutputLayer::~OutputLayer() = default; } // namespace android::compositionengine::mock + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index 5eabecd3ca..030c7039f7 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -155,3 +159,6 @@ void CompositionEngine::updateLayerStateFromFE(CompositionRefreshArgs& args) { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index e885629c4b..20f765c4a8 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -337,3 +341,6 @@ void Display::finishFrame(const compositionengine::CompositionRefreshArgs& refre } } // namespace android::compositionengine::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp index f72862be07..995a0ca71f 100644 --- a/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp +++ b/services/surfaceflinger/CompositionEngine/src/HwcBufferCache.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -48,3 +52,6 @@ void HwcBufferCache::getHwcBuffer(int slot, const sp& buffer, uin } } // namespace android::compositionengine::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp index ecacaeee9c..22ecd33a2a 100644 --- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -41,3 +45,6 @@ void Layer::dump(std::string& out) const { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index e74052994a..085e83838e 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -86,3 +90,6 @@ void LayerFECompositionState::dump(std::string& out) const { } } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 6e2816715f..01413b9478 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -1058,3 +1062,6 @@ compositionengine::Output::FrameFences Output::presentAndGetFrameFences() { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp index 82d24222f1..ac66d8cbe3 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -645,3 +649,6 @@ void OutputLayer::dump(std::string& out) const { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp index cc3c54c8b1..20c8f9a112 100644 --- a/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/OutputLayerCompositionState.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -70,3 +74,6 @@ void OutputLayerCompositionState::dump(std::string& out) const { } } // namespace android::compositionengine::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp index 949feb4041..10512eb9e9 100644 --- a/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp +++ b/services/surfaceflinger/CompositionEngine/src/RenderSurface.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include @@ -249,3 +253,6 @@ sp& RenderSurface::mutableGraphicBufferForTest() { } // namespace impl } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp index 989494d13f..ebcd0a0594 100644 --- a/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/CompositionEngineTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -298,3 +302,6 @@ TEST_F(CompositionTestPreComposition, } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp index ae939693fa..0fe5843331 100644 --- a/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/DisplayTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -833,3 +837,6 @@ TEST_F(DisplayFunctionalTest, postFramebufferCriticalCallsAreOrdered) { } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp index 787f973215..44df2893d7 100644 --- a/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -59,3 +63,6 @@ TEST_F(LayerTest, canInstantiateLayer) {} } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp index 0e579fa7e1..bd830be68c 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputLayerTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -1054,3 +1058,6 @@ TEST_F(OutputLayerTest, needsFilteringReturnsTrueIfDisplaySizeDifferentFromSourc } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp index 80528e3cb9..24311c7e5b 100644 --- a/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/OutputTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -3781,3 +3785,6 @@ TEST_F(GenerateClientCompositionRequestsTest_ThreeLayers, } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp index fd47e453c8..4fba10bf66 100644 --- a/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp +++ b/services/surfaceflinger/CompositionEngine/tests/RenderSurfaceTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -350,3 +354,6 @@ TEST_F(RenderSurfaceTest, flipForwardsSignal) { } // namespace } // namespace android::compositionengine + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp index ab664be5e2..841e79f8af 100644 --- a/services/surfaceflinger/ContainerLayer.cpp +++ b/services/surfaceflinger/ContainerLayer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "ContainerLayer" @@ -39,3 +43,6 @@ sp ContainerLayer::createClone() { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp index e0dc3e7751..e2122d1d30 100644 --- a/services/surfaceflinger/DisplayDevice.cpp +++ b/services/surfaceflinger/DisplayDevice.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "DisplayDevice" @@ -327,3 +331,6 @@ const HdrCapabilities& DisplayDevice::getHdrCapabilities() const { std::atomic DisplayDeviceState::sNextSequenceId(1); } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp index eb032f3fe8..6892dd8ed0 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "HwcComposer" @@ -1622,3 +1626,6 @@ void CommandReader::takePresentOrValidateStage(Display display, uint32_t* state) } // namespace Hwc2 } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp index ba7818dd02..277081f230 100644 --- a/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp +++ b/services/surfaceflinger/DisplayHardware/DisplayIdentification.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "DisplayIdentification" @@ -204,3 +208,6 @@ DisplayId getVirtualDisplayId(uint32_t id) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp index 7370b0ccb2..36544b6653 100644 --- a/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp +++ b/services/surfaceflinger/DisplayHardware/FramebufferSurface.cpp @@ -15,6 +15,10 @@ ** limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FramebufferSurface" @@ -193,3 +197,6 @@ const sp& FramebufferSurface::getClientTargetAcquireFence() const { // ---------------------------------------------------------------------------- }; // namespace android // ---------------------------------------------------------------------------- + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/HWC2.cpp b/services/surfaceflinger/DisplayHardware/HWC2.cpp index 12b0ddd26d..41e787980a 100644 --- a/services/surfaceflinger/DisplayHardware/HWC2.cpp +++ b/services/surfaceflinger/DisplayHardware/HWC2.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG @@ -977,3 +981,6 @@ Error Layer::setColorTransform(const android::mat4& matrix) { } // namespace impl } // namespace HWC2 + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.cpp b/services/surfaceflinger/DisplayHardware/HWComposer.cpp index 1960f431a8..153cfe7f9d 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.cpp +++ b/services/surfaceflinger/DisplayHardware/HWComposer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG @@ -948,3 +952,6 @@ uint32_t HWComposer::getMaxVirtualDisplayCount() const { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp index 56b0ea61e3..fba3261388 100644 --- a/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp +++ b/services/surfaceflinger/DisplayHardware/VirtualDisplaySurface.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #include "VirtualDisplaySurface.h" @@ -694,3 +698,6 @@ const char* VirtualDisplaySurface::dbgSourceStr(Source s) { // --------------------------------------------------------------------------- } // namespace android // --------------------------------------------------------------------------- + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Effects/Daltonizer.cpp b/services/surfaceflinger/Effects/Daltonizer.cpp index 01c9c0fc68..a7090c51f2 100644 --- a/services/surfaceflinger/Effects/Daltonizer.cpp +++ b/services/surfaceflinger/Effects/Daltonizer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "Daltonizer.h" #include @@ -171,3 +175,6 @@ void Daltonizer::update() { } } /* namespace android */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/EventLog/EventLog.cpp b/services/surfaceflinger/EventLog/EventLog.cpp index a532fc130f..3b609524e8 100644 --- a/services/surfaceflinger/EventLog/EventLog.cpp +++ b/services/surfaceflinger/EventLog/EventLog.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -124,3 +128,6 @@ void EventLog::TagBuffer::writeString(const std::string_view& value) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/FrameTracer/FrameTracer.cpp b/services/surfaceflinger/FrameTracer/FrameTracer.cpp index 441811646b..b986f3844a 100644 --- a/services/surfaceflinger/FrameTracer/FrameTracer.cpp +++ b/services/surfaceflinger/FrameTracer/FrameTracer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "FrameTracer" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -179,3 +183,6 @@ std::string FrameTracer::miniDump() { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/FrameTracker.cpp b/services/surfaceflinger/FrameTracker.cpp index a6e511e76e..8ad805b1d8 100644 --- a/services/surfaceflinger/FrameTracker.cpp +++ b/services/surfaceflinger/FrameTracker.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // This is needed for stdint.h to define INT64_MAX in C++ #define __STDC_LIMIT_MACROS @@ -246,3 +250,6 @@ void FrameTracker::dumpStats(std::string& result) const { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 2593681b6b..b0c94a279e 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "Layer" @@ -2304,3 +2308,6 @@ void Layer::addChildToDrawing(const sp& layer) { #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/LayerProtoHelper.cpp b/services/surfaceflinger/LayerProtoHelper.cpp index b4022704d5..0fe1421926 100644 --- a/services/surfaceflinger/LayerProtoHelper.cpp +++ b/services/surfaceflinger/LayerProtoHelper.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerProtoHelper.h" namespace android { @@ -165,3 +169,6 @@ void LayerProtoHelper::writeToProto(const mat4 matrix, ColorTransformProto* colo } // namespace surfaceflinger } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/LayerRejecter.cpp b/services/surfaceflinger/LayerRejecter.cpp index 412f9779c8..d3364a0929 100644 --- a/services/surfaceflinger/LayerRejecter.cpp +++ b/services/surfaceflinger/LayerRejecter.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerRejecter.h" #include @@ -136,3 +140,6 @@ bool LayerRejecter::reject(const sp& buf, const BufferItem& item) } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 8271fd97ea..7c959b9e56 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerVector.h" #include "Layer.h" @@ -83,3 +87,6 @@ void LayerVector::traverseInReverseZOrder(StateSet stateSet, const Visitor& visi } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 7a959f7b19..5009e10532 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "MonitoredProducer.h" #include "Layer.h" #include "SurfaceFlinger.h" @@ -168,3 +172,6 @@ sp MonitoredProducer::getLayer() const { // --------------------------------------------------------------------------- }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index c69859e32a..33e5796e6f 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "RefreshRateOverlay.h" #include "Client.h" #include "Layer.h" @@ -211,3 +215,6 @@ void RefreshRateOverlay::changeRefreshRate(const RefreshRate& refreshRate) { } }; // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RegionSamplingThread.cpp b/services/surfaceflinger/RegionSamplingThread.cpp index 73de4f8b78..0031d70160 100644 --- a/services/surfaceflinger/RegionSamplingThread.cpp +++ b/services/surfaceflinger/RegionSamplingThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS #undef LOG_TAG @@ -472,3 +476,6 @@ void RegionSamplingThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/RenderArea.cpp b/services/surfaceflinger/RenderArea.cpp index 93759e8ad7..9a6c8533ea 100644 --- a/services/surfaceflinger/RenderArea.cpp +++ b/services/surfaceflinger/RenderArea.cpp @@ -1,3 +1,23 @@ +/* + * Copyright 2017 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. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "RenderArea.h" namespace android { @@ -13,3 +33,6 @@ float RenderArea::getCaptureFillValue(CaptureFill captureFill) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/DispSync.cpp b/services/surfaceflinger/Scheduler/DispSync.cpp index 4bdfad94eb..ca41608c1c 100644 --- a/services/surfaceflinger/Scheduler/DispSync.cpp +++ b/services/surfaceflinger/Scheduler/DispSync.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 @@ -847,3 +851,6 @@ nsecs_t DispSync::expectedPresentTime() { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/DispSyncSource.cpp b/services/surfaceflinger/Scheduler/DispSyncSource.cpp index bd4b0ec0d1..776e98463f 100644 --- a/services/surfaceflinger/Scheduler/DispSyncSource.cpp +++ b/services/surfaceflinger/Scheduler/DispSyncSource.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "DispSyncSource.h" @@ -104,3 +108,6 @@ void DispSyncSource::onDispSyncEvent(nsecs_t when) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/EventControlThread.cpp b/services/surfaceflinger/Scheduler/EventControlThread.cpp index 85a7f82a3c..7f9db9ca2d 100644 --- a/services/surfaceflinger/Scheduler/EventControlThread.cpp +++ b/services/surfaceflinger/Scheduler/EventControlThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -73,3 +77,6 @@ void EventControlThread::threadMain() NO_THREAD_SAFETY_ANALYSIS { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/EventThread.cpp b/services/surfaceflinger/Scheduler/EventThread.cpp index 5bdef5807f..14e3ec6ead 100644 --- a/services/surfaceflinger/Scheduler/EventThread.cpp +++ b/services/surfaceflinger/Scheduler/EventThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include @@ -517,3 +521,6 @@ const char* EventThread::toCString(State state) { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index cf79d9fcf7..db16f8df1f 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LayerHistory" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -158,3 +162,6 @@ void LayerHistory::clear() { } } // namespace android::scheduler::impl + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/MessageQueue.cpp b/services/surfaceflinger/Scheduler/MessageQueue.cpp index 5318b00983..005d157fd5 100644 --- a/services/surfaceflinger/Scheduler/MessageQueue.cpp +++ b/services/surfaceflinger/Scheduler/MessageQueue.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -159,3 +163,6 @@ int MessageQueue::eventReceiver(int /*fd*/, int /*events*/) { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp index 13014c789b..106aa9bccb 100644 --- a/services/surfaceflinger/Scheduler/PhaseOffsets.cpp +++ b/services/surfaceflinger/Scheduler/PhaseOffsets.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "PhaseOffsets.h" #include @@ -330,3 +334,6 @@ void PhaseDurations::dump(std::string& result) const { } // namespace impl } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 692ded928d..45d1f23029 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #include "RefreshRateConfigs.h" @@ -217,3 +221,5 @@ void RefreshRateConfigs::init(const std::vector& configs, } } // namespace android::scheduler +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 73dc753c7e..c96eba40fd 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "Scheduler" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -595,3 +599,6 @@ void Scheduler::onDisplayRefreshed(nsecs_t timestamp) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/SchedulerUtils.cpp b/services/surfaceflinger/Scheduler/SchedulerUtils.cpp index fb5414fd4b..27120be272 100644 --- a/services/surfaceflinger/Scheduler/SchedulerUtils.cpp +++ b/services/surfaceflinger/Scheduler/SchedulerUtils.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "SchedulerUtils.h" #include @@ -36,3 +40,6 @@ int64_t calculate_median(std::vector* v) { } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/VSyncModulator.cpp b/services/surfaceflinger/Scheduler/VSyncModulator.cpp index 8de35b1c2f..40a992cf01 100644 --- a/services/surfaceflinger/Scheduler/VSyncModulator.cpp +++ b/services/surfaceflinger/Scheduler/VSyncModulator.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "VSyncModulator.h" @@ -144,3 +148,6 @@ void VSyncModulator::updateOffsetsLocked() { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp index 3b99a58838..915419154f 100644 --- a/services/surfaceflinger/Scheduler/VSyncPredictor.cpp +++ b/services/surfaceflinger/Scheduler/VSyncPredictor.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define ATRACE_TAG ATRACE_TAG_GRAPHICS //#define LOG_NDEBUG 0 #include "VSyncPredictor.h" @@ -224,3 +228,6 @@ bool VSyncPredictor::needsMoreSamples(nsecs_t now) const { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index b7a2c760e6..3dcf7d1665 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -5772,3 +5776,6 @@ status_t SurfaceFlinger::setGlobalShadowSettings(const half4& ambientColor, cons #if defined(__gl2_h_) #error "don't include gl2/gl2.h in this file" #endif + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index d5c2306e1f..e12d31a99a 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -138,3 +142,6 @@ sp DefaultFactory::createColorLayer(const LayerCreationArgs& args) { } } // namespace android::surfaceflinger + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceFlingerFactory.cpp b/services/surfaceflinger/SurfaceFlingerFactory.cpp index 9b1f658661..3997b04f5f 100644 --- a/services/surfaceflinger/SurfaceFlingerFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerFactory.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "SurfaceFlinger.h" #include "SurfaceFlingerDefaultFactory.h" @@ -26,3 +30,6 @@ sp createSurfaceFlinger() { } } // namespace android::surfaceflinger + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 8e0462ab52..79123f979b 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #undef LOG_TAG #define LOG_TAG "SurfaceInterceptor" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -677,3 +681,6 @@ void SurfaceInterceptor::savePowerModeUpdate(int32_t sequenceId, int32_t mode) { } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index eb26cd0379..6fd4e46c73 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #undef LOG_TAG #define LOG_TAG "SurfaceTracing" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -202,3 +206,6 @@ void SurfaceTracing::dump(std::string& result) const { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/TimeStats/TimeStats.cpp b/services/surfaceflinger/TimeStats/TimeStats.cpp index a5fabf2c16..0939fa4f9b 100644 --- a/services/surfaceflinger/TimeStats/TimeStats.cpp +++ b/services/surfaceflinger/TimeStats/TimeStats.cpp @@ -13,6 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #undef LOG_TAG #define LOG_TAG "TimeStats" #define ATRACE_TAG ATRACE_TAG_GRAPHICS @@ -657,3 +661,6 @@ void TimeStats::dump(bool asProto, std::optional maxLayers, std::strin } // namespace impl } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/TransactionCompletedThread.cpp b/services/surfaceflinger/TransactionCompletedThread.cpp index 1475889cd9..daa67ae043 100644 --- a/services/surfaceflinger/TransactionCompletedThread.cpp +++ b/services/surfaceflinger/TransactionCompletedThread.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "TransactionCompletedThread" @@ -355,3 +359,6 @@ CallbackHandle::CallbackHandle(const sp& transactionListener, : listener(transactionListener), callbackIds(ids), surfaceControl(sc) {} } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/main_surfaceflinger.cpp b/services/surfaceflinger/main_surfaceflinger.cpp index e7986d3344..d7ad9deb03 100644 --- a/services/surfaceflinger/main_surfaceflinger.cpp +++ b/services/surfaceflinger/main_surfaceflinger.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -121,3 +125,6 @@ int main(int, char**) { return 0; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/BufferGenerator.cpp b/services/surfaceflinger/tests/BufferGenerator.cpp index 8ddda60cd2..293738cfcb 100644 --- a/services/surfaceflinger/tests/BufferGenerator.cpp +++ b/services/surfaceflinger/tests/BufferGenerator.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -379,3 +383,6 @@ void BufferGenerator::setBuffer(const sp& buffer, int32_t fence, } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/Credentials_test.cpp b/services/surfaceflinger/tests/Credentials_test.cpp index f6188738b2..a7c095d327 100644 --- a/services/surfaceflinger/tests/Credentials_test.cpp +++ b/services/surfaceflinger/tests/Credentials_test.cpp @@ -31,6 +31,10 @@ const float FRAME_SCALE = 1.0f; * Methods like EnableVsyncInjections and InjectVsync are not tested since they do not * return anything meaningful. */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" class CredentialsTest : public ::testing::Test { protected: void SetUp() override { @@ -362,3 +366,6 @@ TEST_F(CredentialsTest, GetActiveColorModeBasicCorrectness) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp index 0cef0d1c87..46b98f9193 100644 --- a/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp +++ b/services/surfaceflinger/tests/DereferenceSurfaceControl_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -67,3 +71,6 @@ TEST_F(DereferenceSurfaceControlTest, LayerInTransaction) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/DisplayConfigs_test.cpp b/services/surfaceflinger/tests/DisplayConfigs_test.cpp index d51b9a146f..3aa4474b6b 100644 --- a/services/surfaceflinger/tests/DisplayConfigs_test.cpp +++ b/services/surfaceflinger/tests/DisplayConfigs_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include "LayerTransactionTest.h" namespace android { @@ -68,3 +72,6 @@ TEST_F(RefreshRateRangeTest, setAllConfigs) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/LayerCallback_test.cpp b/services/surfaceflinger/tests/LayerCallback_test.cpp index 7a5ed484d1..6d28e621ac 100644 --- a/services/surfaceflinger/tests/LayerCallback_test.cpp +++ b/services/surfaceflinger/tests/LayerCallback_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" #include "utils/CallbackUtils.h" @@ -870,3 +874,6 @@ TEST_F(LayerCallbackTest, DesiredPresentTime_Past) { EXPECT_NO_FATAL_FAILURE(waitForCallback(callback, expected, true)); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp index 92698f0142..24874b010b 100644 --- a/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerRenderTypeTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -1841,3 +1845,6 @@ TEST_P(LayerRenderTypeTransactionTest, SetColorTransformOnChildAndParent) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerTransaction_test.cpp b/services/surfaceflinger/tests/LayerTransaction_test.cpp index 7816c667bb..97cba63192 100644 --- a/services/surfaceflinger/tests/LayerTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include "LayerTransactionTest.h" @@ -190,3 +194,6 @@ TEST_F(LayerTransactionTest, DISABLED_BufferQueueLayerMergeDamageRegionWhenDropp ASSERT_EQ(OK, producer->disconnect(NATIVE_WINDOW_API_CPU)); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp index daeff17ea3..71f01b0c1d 100644 --- a/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeAndRenderTypeTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include "TransactionTestHarnesses.h" @@ -267,3 +271,6 @@ TEST_P(LayerTypeAndRenderTypeTransactionTest, SetLayerStackBasic) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp index 42ec34a129..7e9202bb82 100644 --- a/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp +++ b/services/surfaceflinger/tests/LayerTypeTransaction_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include "TransactionTestHarnesses.h" @@ -186,3 +190,6 @@ TEST_P(LayerTypeTransactionTest, RefreshRateIsInitialized) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/LayerUpdate_test.cpp b/services/surfaceflinger/tests/LayerUpdate_test.cpp index 0ad122b5ed..0459386936 100644 --- a/services/surfaceflinger/tests/LayerUpdate_test.cpp +++ b/services/surfaceflinger/tests/LayerUpdate_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -1708,3 +1712,6 @@ TEST_F(ScreenCaptureTest, CaptureInvalidLayer) { ASSERT_EQ(NAME_NOT_FOUND, sf->captureLayers(redLayerHandle, &outBuffer, Rect::EMPTY_RECT, 1.0)); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp index 0bcac1a880..b49bd54599 100644 --- a/services/surfaceflinger/tests/MirrorLayer_test.cpp +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -224,3 +228,6 @@ TEST_F(MirrorLayerTest, MirrorBufferLayer) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp index 066c9aa3ce..e525e2af9b 100644 --- a/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp +++ b/services/surfaceflinger/tests/MultiDisplayLayerBounds_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -122,3 +126,6 @@ TEST_F(MultiDisplayLayerBoundsTest, RenderLayerInMirroredVirtualDisplay) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/RelativeZ_test.cpp b/services/surfaceflinger/tests/RelativeZ_test.cpp index 8c56d27e8a..1180cacf7f 100644 --- a/services/surfaceflinger/tests/RelativeZ_test.cpp +++ b/services/surfaceflinger/tests/RelativeZ_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -204,3 +208,6 @@ TEST_F(RelativeZTest, LayerAndRelativeRemoved) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/SetGeometry_test.cpp b/services/surfaceflinger/tests/SetGeometry_test.cpp index dca06ec8d4..5fe2513bb3 100644 --- a/services/surfaceflinger/tests/SetGeometry_test.cpp +++ b/services/surfaceflinger/tests/SetGeometry_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "LayerTransactionTest.h" namespace android { @@ -97,3 +101,6 @@ TEST_F(SetGeometryTest, Scale) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/Stress_test.cpp b/services/surfaceflinger/tests/Stress_test.cpp index ee857b01f2..e9b6ba0f64 100644 --- a/services/surfaceflinger/tests/Stress_test.cpp +++ b/services/surfaceflinger/tests/Stress_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -107,3 +111,6 @@ TEST(LayerProtoStress, mem_info) { } } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp index 1fa426d14e..75d0761907 100644 --- a/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp +++ b/services/surfaceflinger/tests/SurfaceInterceptor_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -1011,3 +1015,6 @@ TEST_F(SurfaceInterceptorTest, InterceptSimultaneousUpdatesWorks) { ASSERT_TRUE(singleIncrementFound(capturedTrace, Increment::IncrementCase::kSurfaceCreation)); } } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp index 0c370a6fdb..5824e589d1 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerClient.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + //#define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeComposer" @@ -896,3 +900,6 @@ Layer FakeComposerClient::getLayer(size_t index) const { // this might get more involving. return static_cast(index); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp index f727bc4079..c656eed0fb 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerService.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeHwcService" @@ -170,3 +174,6 @@ Return FakeComposerService_2_4::createClient_2_4(createClient_2_4_cb hidl_ } } // namespace sftest + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp index 4d2146810b..2f89696e8e 100644 --- a/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp +++ b/services/surfaceflinger/tests/fakehwc/FakeComposerUtils.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeHwcUtil" @@ -183,3 +187,6 @@ void FakeHwcEnvironment::TearDown() { } } // namespace sftest + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp index 09fdbdf114..18572064b6 100644 --- a/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp +++ b/services/surfaceflinger/tests/fakehwc/SFFakeHwc_test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + // #define LOG_NDEBUG 0 #undef LOG_TAG #define LOG_TAG "FakeHwcTest" @@ -1970,3 +1974,6 @@ int main(int argc, char** argv) { ::testing::InitGoogleMock(&argc, argv); return RUN_ALL_TESTS(); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp index 13774b4ed3..f9a1fe9a73 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2Test.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -4770,3 +4774,6 @@ TEST_F(Hwc2Test, PRESENT_VIRTUAL_DISPLAY_default_5) ASSERT_NO_FATAL_FAILURE(createAndPresentVirtualDisplay(layerCnt, coverage, virtualDisplayExceptions)); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp index 648456295d..fcd0d31078 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestBuffer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -789,3 +793,6 @@ int Hwc2TestOutputBuffer::getOutputBuffer(buffer_handle_t* outHandle, return 0; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp index 90127a1302..b76ace8752 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestLayers.cpp @@ -13,6 +13,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -279,3 +283,6 @@ bool Hwc2TestLayers::setVisibleRegions() return optimized; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp index 904b927abf..8ca88150e9 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestPixelComparator.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include @@ -111,3 +115,6 @@ std::string ComparatorResult::dumpComparison() const } return stream.str(); } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp index c5b92d0664..1efb21e639 100644 --- a/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp +++ b/services/surfaceflinger/tests/hwc2/Hwc2TestProperties.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -780,3 +784,6 @@ const std::array Hwc2TestSurfaceDamage::mCompositionSupport = {{ const std::array Hwc2TestTransform::mCompositionSupport = {{ false, true, true, false, true, true, }}; + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/CachingTest.cpp b/services/surfaceflinger/tests/unittests/CachingTest.cpp index 74ce540626..1b8c76d1b9 100644 --- a/services/surfaceflinger/tests/unittests/CachingTest.cpp +++ b/services/surfaceflinger/tests/unittests/CachingTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "CachingTest" @@ -91,3 +95,6 @@ TEST_F(SlotGenerationTest, getHwcCacheSlot_Reuse) { } } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp index cce21ceddb..8a762d4030 100644 --- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp +++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -1423,3 +1427,6 @@ TEST_F(CompositionTest, DebugOptionForcingClientCompositionOfBufferLayerWithDirt } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp index 55c3ab8b22..33563eaed6 100644 --- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -3239,3 +3243,6 @@ TEST_F(SetPowerModeInternalTest, transitionsDisplayFromOnToUnknownExternalDispla } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp index c334bcf85d..68cb52fe87 100644 --- a/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp +++ b/services/surfaceflinger/tests/unittests/FrameTracerTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -394,3 +398,6 @@ TEST_F(FrameTracerTest, traceFenceWithValidStartTime_ShouldHaveCorrectDuration) } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index f055fe72ac..c9af057ae5 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -1,3 +1,23 @@ +/* + * Copyright 2019 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. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LayerHistoryTest" @@ -241,3 +261,6 @@ TEST_F(LayerHistoryTest, multipleLayers) { } // namespace } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp index 6360ec14cd..910e73baf2 100644 --- a/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp +++ b/services/surfaceflinger/tests/unittests/PhaseOffsetsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -124,3 +128,6 @@ TEST_F(PhaseOffsetsTest, getOffsetsForRefreshRate_DefaultOffsets) { } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" \ No newline at end of file diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index cc3c985aa1..86aa8fb22b 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -242,11 +242,11 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { TEST_F(RefreshRateConfigsTest, testInPolicy) { RefreshRate expectedDefaultConfig = {HWC_CONFIG_ID_60, VSYNC_60_POINT_4, HWC_GROUP_ID_0, "60fps", 60}; - ASSERT_TRUE(expectedDefaultConfig.inPolicy(60.000004, 60.000004)); + ASSERT_TRUE(expectedDefaultConfig.inPolicy(60.000004f, 60.000004f)); ASSERT_TRUE(expectedDefaultConfig.inPolicy(59.0f, 60.1f)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(75.0, 90.0)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(60.0011, 90.0)); - ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0, 59.998)); + ASSERT_FALSE(expectedDefaultConfig.inPolicy(75.0f, 90.0f)); + ASSERT_FALSE(expectedDefaultConfig.inPolicy(60.0011f, 90.0f)); + ASSERT_FALSE(expectedDefaultConfig.inPolicy(50.0f, 59.998f)); } } // namespace diff --git a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp index ef4699f628..8e07c79656 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateStatsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -195,3 +199,6 @@ TEST_F(RefreshRateStatsTest, twoConfigsTest) { } // namespace } // namespace scheduler } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp index d8de804ad8..f19e55409c 100644 --- a/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp +++ b/services/surfaceflinger/tests/unittests/RegionSamplingTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "RegionSamplingTest" @@ -137,3 +141,6 @@ TEST_F(RegionSamplingTest, orientation_90) { } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index 40536abc5d..b1ecf4da6e 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -1,3 +1,23 @@ +/* + * Copyright 2019 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. + */ + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -144,3 +164,6 @@ TEST_F(SchedulerTest, validConnectionHandle) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp index 5865579641..5f6a7150d6 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerUtilsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "SchedulerUnittests" @@ -128,4 +132,6 @@ TEST_F(SchedulerUtilsTest, calculate_mode) { } // namespace } // namespace scheduler -} // namespace android \ No newline at end of file +} // namespace android +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp index 3e808c0abb..bcf3ba8856 100644 --- a/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp +++ b/services/surfaceflinger/tests/unittests/TimeStatsTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" @@ -656,3 +660,6 @@ TEST_F(TimeStatsTest, canSurviveMonkey) { } // namespace } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp index 994a509e4f..f1739e5e8a 100644 --- a/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp +++ b/services/surfaceflinger/tests/unittests/TransactionApplicationTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "CompositionTest" @@ -321,3 +325,6 @@ TEST_F(TransactionApplicationTest, FromHandle) { EXPECT_EQ(nullptr, ret.get()); } } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp index 5aff4296f9..82919abe03 100644 --- a/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncDispatchTimerQueueTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 @@ -803,3 +807,6 @@ TEST_F(VSyncDispatchTimerQueueEntryTest, reportsScheduledIfStillTime) { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp index 4cb6a38217..00d3cc6e0b 100644 --- a/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp +++ b/services/surfaceflinger/tests/unittests/VSyncPredictorTest.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #undef LOG_TAG #define LOG_TAG "LibSurfaceFlingerUnittests" #define LOG_NDEBUG 0 @@ -352,3 +356,6 @@ TEST_F(VSyncPredictorTest, doesNotPredictBeforeTimePointWithHigherIntercept) { } } // namespace android::scheduler + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp index 7ed57b9d96..0780af1f26 100644 --- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp +++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "mock/DisplayHardware/MockComposer.h" namespace android { @@ -27,3 +31,6 @@ Composer::~Composer() = default; } // namespace mock } // namespace Hwc2 } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp index 4129328ba9..7e925b94ee 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp +++ b/services/surfaceflinger/tests/unittests/mock/MockSurfaceInterceptor.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include "mock/MockSurfaceInterceptor.h" namespace android { @@ -25,3 +29,6 @@ SurfaceInterceptor::~SurfaceInterceptor() = default; } // namespace mock } // namespace android + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" diff --git a/services/surfaceflinger/tests/vsync/vsync.cpp b/services/surfaceflinger/tests/vsync/vsync.cpp index a1b45e6adb..667dfb92d5 100644 --- a/services/surfaceflinger/tests/vsync/vsync.cpp +++ b/services/surfaceflinger/tests/vsync/vsync.cpp @@ -14,6 +14,10 @@ * limitations under the License. */ +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #include #include #include @@ -82,3 +86,6 @@ int main(int /*argc*/, char** /*argv*/) return 0; } + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" -- cgit v1.2.3-59-g8ed1b From 3172e2028b191ed485385f02a443b1f9b0d730f9 Mon Sep 17 00:00:00 2001 From: Steven Thomas Date: Mon, 6 Jan 2020 19:25:30 -0800 Subject: Add plumbing for upcoming setFrameRate() api Add plumbing from the app to surface flinger for the ANativeWindow_setFrameRate() and ASurfaceTransaction_setFrameRate() api calls we'll be adding soon. We don't do anything in surface flinger with this data yet. Bug: 143912624 Test: Added a new test, SetFrameRateTest. Change-Id: I1cab87f3ce5afca4591a39d8e7a42cb1e86a368f --- libs/gui/BufferHubConsumer.cpp | 10 +++ libs/gui/BufferQueueConsumer.cpp | 12 ++++ libs/gui/BufferQueueProducer.cpp | 10 +++ libs/gui/ConsumerBase.cpp | 18 ++++++ libs/gui/IGraphicBufferConsumer.cpp | 16 +++++ libs/gui/IGraphicBufferProducer.cpp | 24 ++++++++ libs/gui/LayerState.cpp | 10 +-- libs/gui/Surface.cpp | 15 +++++ libs/gui/SurfaceComposerClient.cpp | 12 ++++ libs/gui/include/gui/BufferHubConsumer.h | 6 ++ libs/gui/include/gui/BufferQueueConsumer.h | 6 ++ libs/gui/include/gui/BufferQueueCore.h | 3 + libs/gui/include/gui/BufferQueueProducer.h | 3 + libs/gui/include/gui/ConsumerBase.h | 6 ++ libs/gui/include/gui/IGraphicBufferConsumer.h | 10 +++ libs/gui/include/gui/IGraphicBufferProducer.h | 3 + libs/gui/include/gui/LayerState.h | 6 +- libs/gui/include/gui/Surface.h | 4 ++ libs/gui/include/gui/SurfaceComposerClient.h | 2 + libs/gui/include/gui/mock/GraphicBufferConsumer.h | 2 + libs/nativewindow/include/system/window.h | 7 ++- services/surfaceflinger/BufferQueueLayer.cpp | 15 +++++ services/surfaceflinger/BufferQueueLayer.h | 6 ++ services/surfaceflinger/Layer.cpp | 17 ++++++ services/surfaceflinger/Layer.h | 5 ++ services/surfaceflinger/MonitoredProducer.cpp | 4 ++ services/surfaceflinger/MonitoredProducer.h | 1 + services/surfaceflinger/SurfaceFlinger.cpp | 3 + services/surfaceflinger/tests/Android.bp | 1 + .../surfaceflinger/tests/SetFrameRate_test.cpp | 71 ++++++++++++++++++++++ 30 files changed, 302 insertions(+), 6 deletions(-) create mode 100644 services/surfaceflinger/tests/SetFrameRate_test.cpp (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/libs/gui/BufferHubConsumer.cpp b/libs/gui/BufferHubConsumer.cpp index b5cdeb280a..0ddb87e0be 100644 --- a/libs/gui/BufferHubConsumer.cpp +++ b/libs/gui/BufferHubConsumer.cpp @@ -147,6 +147,16 @@ status_t BufferHubConsumer::discardFreeBuffers() { return INVALID_OPERATION; } +status_t BufferHubConsumer::setFrameRate(float /*frameRate*/) { + ALOGE("BufferHubConsumer::setFrameRate: not implemented."); + return INVALID_OPERATION; +} + +status_t BufferHubConsumer::getFrameRate(float* /*frameRate*/) const { + ALOGE("BufferHubConsumer::getFrameRate: not implemented."); + return INVALID_OPERATION; +} + status_t BufferHubConsumer::dumpState(const String8& /*prefix*/, String8* /*outResult*/) const { ALOGE("BufferHubConsumer::dumpState: not implemented."); return INVALID_OPERATION; diff --git a/libs/gui/BufferQueueConsumer.cpp b/libs/gui/BufferQueueConsumer.cpp index 6418e8c9a9..9b74fef752 100644 --- a/libs/gui/BufferQueueConsumer.cpp +++ b/libs/gui/BufferQueueConsumer.cpp @@ -775,6 +775,18 @@ status_t BufferQueueConsumer::discardFreeBuffers() { return NO_ERROR; } +status_t BufferQueueConsumer::setFrameRate(float frameRate) { + std::lock_guard lock(mCore->mMutex); + mCore->mFrameRate = frameRate; + return NO_ERROR; +} + +status_t BufferQueueConsumer::getFrameRate(float* frameRate) const { + std::lock_guard lock(mCore->mMutex); + *frameRate = mCore->mFrameRate; + return NO_ERROR; +} + status_t BufferQueueConsumer::dumpState(const String8& prefix, String8* outResult) const { struct passwd* pwd = getpwnam("shell"); uid_t shellUid = pwd ? pwd->pw_uid : 0; diff --git a/libs/gui/BufferQueueProducer.cpp b/libs/gui/BufferQueueProducer.cpp index e6df7572de..6b11a54e2b 100644 --- a/libs/gui/BufferQueueProducer.cpp +++ b/libs/gui/BufferQueueProducer.cpp @@ -1670,4 +1670,14 @@ status_t BufferQueueProducer::setAutoPrerotation(bool autoPrerotation) { return NO_ERROR; } +status_t BufferQueueProducer::setFrameRate(float frameRate) { + ATRACE_CALL(); + BQ_LOGV("setFrameRate: %.0f", frameRate); + + std::lock_guard lock(mCore->mMutex); + + mCore->mFrameRate = frameRate; + return NO_ERROR; +} + } // namespace android diff --git a/libs/gui/ConsumerBase.cpp b/libs/gui/ConsumerBase.cpp index 9f91d9d3aa..515f45c546 100644 --- a/libs/gui/ConsumerBase.cpp +++ b/libs/gui/ConsumerBase.cpp @@ -363,6 +363,24 @@ status_t ConsumerBase::discardFreeBuffers() { return OK; } +status_t ConsumerBase::setFrameRate(float frameRate) { + Mutex::Autolock _l(mMutex); + if (mAbandoned) { + CB_LOGE("setFrameRate: ConsumerBase is abandoned!"); + return NO_INIT; + } + return mConsumer->setFrameRate(frameRate); +} + +status_t ConsumerBase::getFrameRate(float* frameRate) { + Mutex::Autolock _l(mMutex); + if (mAbandoned) { + CB_LOGE("getFrameRate: ConsumerBase is abandoned!"); + return NO_INIT; + } + return mConsumer->getFrameRate(frameRate); +} + void ConsumerBase::dumpState(String8& result) const { dumpState(result, ""); } diff --git a/libs/gui/IGraphicBufferConsumer.cpp b/libs/gui/IGraphicBufferConsumer.cpp index c705d3926d..2521a7cbd7 100644 --- a/libs/gui/IGraphicBufferConsumer.cpp +++ b/libs/gui/IGraphicBufferConsumer.cpp @@ -51,6 +51,8 @@ enum class Tag : uint32_t { GET_SIDEBAND_STREAM, GET_OCCUPANCY_HISTORY, DISCARD_FREE_BUFFERS, + SET_FRAME_RATE, + GET_FRAME_RATE, DUMP_STATE, LAST = DUMP_STATE, }; @@ -163,6 +165,16 @@ public: Tag::DISCARD_FREE_BUFFERS); } + status_t setFrameRate(float frameRate) override { + using Signature = decltype(&IGraphicBufferConsumer::setFrameRate); + return callRemote(Tag::SET_FRAME_RATE, frameRate); + } + + status_t getFrameRate(float* frameRate) const override { + using Signature = decltype(&IGraphicBufferConsumer::getFrameRate); + return callRemote(Tag::GET_FRAME_RATE, frameRate); + } + status_t dumpState(const String8& prefix, String8* outResult) const override { using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const; return callRemote(Tag::DUMP_STATE, prefix, outResult); @@ -220,6 +232,10 @@ status_t BnGraphicBufferConsumer::onTransact(uint32_t code, const Parcel& data, return callLocal(data, reply, &IGraphicBufferConsumer::getOccupancyHistory); case Tag::DISCARD_FREE_BUFFERS: return callLocal(data, reply, &IGraphicBufferConsumer::discardFreeBuffers); + case Tag::SET_FRAME_RATE: + return callLocal(data, reply, &IGraphicBufferConsumer::setFrameRate); + case Tag::GET_FRAME_RATE: + return callLocal(data, reply, &IGraphicBufferConsumer::getFrameRate); case Tag::DUMP_STATE: { using Signature = status_t (IGraphicBufferConsumer::*)(const String8&, String8*) const; return callLocal(data, reply, &IGraphicBufferConsumer::dumpState); diff --git a/libs/gui/IGraphicBufferProducer.cpp b/libs/gui/IGraphicBufferProducer.cpp index 0009a57653..75876f26f3 100644 --- a/libs/gui/IGraphicBufferProducer.cpp +++ b/libs/gui/IGraphicBufferProducer.cpp @@ -74,6 +74,7 @@ enum { GET_CONSUMER_USAGE, SET_LEGACY_BUFFER_DROP, SET_AUTO_PREROTATION, + SET_FRAME_RATE, }; class BpGraphicBufferProducer : public BpInterface @@ -559,6 +560,14 @@ public: } return result; } + + virtual status_t setFrameRate(float frameRate) { + Parcel data, reply; + data.writeInterfaceToken(IGraphicBufferProducer::getInterfaceDescriptor()); + data.writeFloat(frameRate); + status_t result = remote()->transact(SET_FRAME_RATE, data, &reply, IBinder::FLAG_ONEWAY); + return result; + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -691,6 +700,8 @@ public: status_t setAutoPrerotation(bool autoPrerotation) override { return mBase->setAutoPrerotation(autoPrerotation); } + + status_t setFrameRate(float frameRate) override { return mBase->setFrameRate(frameRate); } }; IMPLEMENT_HYBRID_META_INTERFACE(GraphicBufferProducer, @@ -710,6 +721,12 @@ status_t IGraphicBufferProducer::setAutoPrerotation(bool autoPrerotation) { return INVALID_OPERATION; } +status_t IGraphicBufferProducer::setFrameRate(float frameRate) { + // No-op for IGBP other than BufferQueue. + (void)frameRate; + return INVALID_OPERATION; +} + status_t IGraphicBufferProducer::exportToParcel(Parcel* parcel) { status_t res = OK; res = parcel->writeUint32(USE_BUFFER_QUEUE); @@ -1079,6 +1096,13 @@ status_t BnGraphicBufferProducer::onTransact( reply->writeInt32(result); return NO_ERROR; } + case SET_FRAME_RATE: { + CHECK_INTERFACE(IGraphicBuffer, data, reply); + float frameRate = data.readFloat(); + status_t result = setFrameRate(frameRate); + reply->writeInt32(result); + return NO_ERROR; + } } return BBinder::onTransact(code, data, reply, flags); } diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 8b448ff3f6..39b4d4bbb6 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -110,9 +110,8 @@ status_t layer_state_t::write(Parcel& output) const } } output.writeFloat(shadowRadius); - output.writeInt32(frameRateSelectionPriority); - + output.writeFloat(frameRate); return NO_ERROR; } @@ -191,9 +190,8 @@ status_t layer_state_t::read(const Parcel& input) listeners.emplace_back(listener, callbackIds); } shadowRadius = input.readFloat(); - frameRateSelectionPriority = input.readInt32(); - + frameRate = input.readFloat(); return NO_ERROR; } @@ -420,6 +418,10 @@ void layer_state_t::merge(const layer_state_t& other) { what |= eFrameRateSelectionPriority; frameRateSelectionPriority = other.frameRateSelectionPriority; } + if (other.what & eFrameRateChanged) { + what |= eFrameRateChanged; + frameRate = other.frameRate; + } if ((other.what & what) != other.what) { ALOGE("Unmerged SurfaceComposer Transaction properties. LayerState::merge needs updating? " "other.what=0x%" PRIu64 " what=0x%" PRIu64, diff --git a/libs/gui/Surface.cpp b/libs/gui/Surface.cpp index e490d6d17d..d5cf11d305 100644 --- a/libs/gui/Surface.cpp +++ b/libs/gui/Surface.cpp @@ -1093,6 +1093,9 @@ int Surface::perform(int operation, va_list args) case NATIVE_WINDOW_GET_LAST_QUEUE_DURATION: res = dispatchGetLastQueueDuration(args); break; + case NATIVE_WINDOW_SET_FRAME_RATE: + res = dispatchSetFrameRate(args); + break; default: res = NAME_NOT_FOUND; break; @@ -1321,6 +1324,11 @@ int Surface::dispatchGetLastQueueDuration(va_list args) { return NO_ERROR; } +int Surface::dispatchSetFrameRate(va_list args) { + float frameRate = static_cast(va_arg(args, double)); + return setFrameRate(frameRate); +} + bool Surface::transformToDisplayInverse() { return (mTransform & NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY) == NATIVE_WINDOW_TRANSFORM_INVERSE_DISPLAY; @@ -2064,4 +2072,11 @@ void Surface::ProducerListenerProxy::onBuffersDiscarded(const std::vectoronBuffersDiscarded(discardedBufs); } +status_t Surface::setFrameRate(float frameRate) { + ATRACE_CALL(); + ALOGV("Surface::setTargetFrameRate"); + Mutex::Autolock lock(mMutex); + return mGraphicBufferProducer->setFrameRate(frameRate); +} + }; // namespace android diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 2ef33cf253..20614f8d85 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1376,6 +1376,18 @@ SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setShado return *this; } +SurfaceComposerClient::Transaction& SurfaceComposerClient::Transaction::setFrameRate( + const sp& sc, float frameRate) { + layer_state_t* s = getLayerState(sc); + if (!s) { + mStatus = BAD_INDEX; + return *this; + } + s->what |= layer_state_t::eFrameRateChanged; + s->frameRate = frameRate; + return *this; +} + // --------------------------------------------------------------------------- DisplayState& SurfaceComposerClient::Transaction::getDisplayState(const sp& token) { diff --git a/libs/gui/include/gui/BufferHubConsumer.h b/libs/gui/include/gui/BufferHubConsumer.h index d38077014b..d75620342e 100644 --- a/libs/gui/include/gui/BufferHubConsumer.h +++ b/libs/gui/include/gui/BufferHubConsumer.h @@ -93,6 +93,12 @@ public: // See |IGraphicBufferConsumer::discardFreeBuffers| status_t discardFreeBuffers() override; + // See |IGraphicBufferConsumer::setFrameRate| + status_t setFrameRate(float frameRate) override; + + // See |IGraphicBufferConsumer::getFrameRate| + status_t getFrameRate(float* frameRate) const override; + // See |IGraphicBufferConsumer::dumpState| status_t dumpState(const String8& prefix, String8* outResult) const override; diff --git a/libs/gui/include/gui/BufferQueueConsumer.h b/libs/gui/include/gui/BufferQueueConsumer.h index 7db69eca9d..e9f04490d8 100644 --- a/libs/gui/include/gui/BufferQueueConsumer.h +++ b/libs/gui/include/gui/BufferQueueConsumer.h @@ -149,6 +149,12 @@ public: // See IGraphicBufferConsumer::discardFreeBuffers virtual status_t discardFreeBuffers() override; + // See IGraphicBufferConsumer::setFrameRate. + virtual status_t setFrameRate(float frameRate) override; + + // See IGraphicBufferConsumer::getFrameRate. + virtual status_t getFrameRate(float* frameRate) const override; + // dump our state in a String status_t dumpState(const String8& prefix, String8* outResult) const override; diff --git a/libs/gui/include/gui/BufferQueueCore.h b/libs/gui/include/gui/BufferQueueCore.h index 557c28b1b7..05c20742f9 100644 --- a/libs/gui/include/gui/BufferQueueCore.h +++ b/libs/gui/include/gui/BufferQueueCore.h @@ -354,6 +354,9 @@ private: // mTransformHintInUse is to cache the mTransformHint used by the producer. uint32_t mTransformHintInUse; + // The frame rate the app intends to run at. + float mFrameRate; + }; // class BufferQueueCore } // namespace android diff --git a/libs/gui/include/gui/BufferQueueProducer.h b/libs/gui/include/gui/BufferQueueProducer.h index 9ad92a6e78..2dec663183 100644 --- a/libs/gui/include/gui/BufferQueueProducer.h +++ b/libs/gui/include/gui/BufferQueueProducer.h @@ -193,6 +193,9 @@ public: // See IGraphicBufferProducer::setAutoPrerotation virtual status_t setAutoPrerotation(bool autoPrerotation); + // See IGraphicBufferProducer::setFrameRate + virtual status_t setFrameRate(float frameRate) override; + private: // This is required by the IBinder::DeathRecipient interface virtual void binderDied(const wp& who); diff --git a/libs/gui/include/gui/ConsumerBase.h b/libs/gui/include/gui/ConsumerBase.h index 8ff0cd0f6e..cfed9aa6bd 100644 --- a/libs/gui/include/gui/ConsumerBase.h +++ b/libs/gui/include/gui/ConsumerBase.h @@ -111,6 +111,12 @@ public: // See IGraphicBufferConsumer::discardFreeBuffers status_t discardFreeBuffers(); + // See IGraphicBufferConsumer::setFrameRate + status_t setFrameRate(float frameRate); + + // See IGraphicBufferConsumer::getFrameRate + status_t getFrameRate(float* frameRate); + private: ConsumerBase(const ConsumerBase&); void operator=(const ConsumerBase&); diff --git a/libs/gui/include/gui/IGraphicBufferConsumer.h b/libs/gui/include/gui/IGraphicBufferConsumer.h index 9fb7580912..54f77b424a 100644 --- a/libs/gui/include/gui/IGraphicBufferConsumer.h +++ b/libs/gui/include/gui/IGraphicBufferConsumer.h @@ -271,6 +271,16 @@ public: // call to free up any of its locally cached buffers. virtual status_t discardFreeBuffers() = 0; + // Set the frame rate the producer will run at. + // + // Return of a value other than NO_ERROR means an unknown error has occurred. + virtual status_t setFrameRate(float frameRate) = 0; + + // Get the frame rate the producer will run at. + // + // Return of a value other than NO_ERROR means an unknown error has occurred. + virtual status_t getFrameRate(float* frameRate) const = 0; + // dump state into a string virtual status_t dumpState(const String8& prefix, String8* outResult) const = 0; diff --git a/libs/gui/include/gui/IGraphicBufferProducer.h b/libs/gui/include/gui/IGraphicBufferProducer.h index 25ce1ca3dc..680d64ed75 100644 --- a/libs/gui/include/gui/IGraphicBufferProducer.h +++ b/libs/gui/include/gui/IGraphicBufferProducer.h @@ -637,6 +637,9 @@ public: // the width and height used for dequeueBuffer will be additionally swapped. virtual status_t setAutoPrerotation(bool autoPrerotation); + // Sets the apps intended frame rate. + virtual status_t setFrameRate(float frameRate); + // Static method exports any IGraphicBufferProducer object to a parcel. It // handles null producer as well. static status_t exportToParcel(const sp& producer, diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h index 03e91c4905..cf641939e8 100644 --- a/libs/gui/include/gui/LayerState.h +++ b/libs/gui/include/gui/LayerState.h @@ -100,6 +100,7 @@ struct layer_state_t { eMetadataChanged = 0x8'00000000, eColorSpaceAgnosticChanged = 0x10'00000000, eFrameRateSelectionPriority = 0x20'00000000, + eFrameRateChanged = 0x40'00000000, }; layer_state_t() @@ -130,7 +131,8 @@ struct layer_state_t { bgColorDataspace(ui::Dataspace::UNKNOWN), colorSpaceAgnostic(false), shadowRadius(0.0f), - frameRateSelectionPriority(-1) { + frameRateSelectionPriority(-1), + frameRate(0.0f) { matrix.dsdx = matrix.dtdy = 1.0f; matrix.dsdy = matrix.dtdx = 0.0f; hdrMetadata.validTypes = 0; @@ -214,6 +216,8 @@ struct layer_state_t { // Priority of the layer assigned by Window Manager. int32_t frameRateSelectionPriority; + + float frameRate; }; struct ComposerState { diff --git a/libs/gui/include/gui/Surface.h b/libs/gui/include/gui/Surface.h index e582509b6e..86cc61f3ec 100644 --- a/libs/gui/include/gui/Surface.h +++ b/libs/gui/include/gui/Surface.h @@ -179,6 +179,9 @@ public: status_t getUniqueId(uint64_t* outId) const; status_t getConsumerUsage(uint64_t* outUsage) const; + // See IGraphicBufferProducer::setFrameRate + status_t setFrameRate(float frameRate); + protected: virtual ~Surface(); @@ -248,6 +251,7 @@ private: int dispatchSetDequeueTimeout(va_list args); int dispatchGetLastDequeueDuration(va_list args); int dispatchGetLastQueueDuration(va_list args); + int dispatchSetFrameRate(va_list args); bool transformToDisplayInverse(); protected: diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 6a3f452f77..71ee82a72f 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -520,6 +520,8 @@ public: const Rect& source, const Rect& dst, int transform); Transaction& setShadowRadius(const sp& sc, float cornerRadius); + Transaction& setFrameRate(const sp& sc, float frameRate); + status_t setDisplaySurface(const sp& token, const sp& bufferProducer); diff --git a/libs/gui/include/gui/mock/GraphicBufferConsumer.h b/libs/gui/include/gui/mock/GraphicBufferConsumer.h index 98f24c2d44..e940cf3248 100644 --- a/libs/gui/include/gui/mock/GraphicBufferConsumer.h +++ b/libs/gui/include/gui/mock/GraphicBufferConsumer.h @@ -49,6 +49,8 @@ public: MOCK_CONST_METHOD1(getSidebandStream, status_t(sp*)); MOCK_METHOD2(getOccupancyHistory, status_t(bool, std::vector*)); MOCK_METHOD0(discardFreeBuffers, status_t()); + MOCK_METHOD1(setFrameRate, status_t(float)); + MOCK_CONST_METHOD1(getFrameRate, status_t(float*)); MOCK_CONST_METHOD2(dumpState, status_t(const String8&, String8*)); }; diff --git a/libs/nativewindow/include/system/window.h b/libs/nativewindow/include/system/window.h index 1814ab5568..14f7214882 100644 --- a/libs/nativewindow/include/system/window.h +++ b/libs/nativewindow/include/system/window.h @@ -34,12 +34,12 @@ #include #include #include +#include #include #include #include #include #include -#include // system/window.h is a superset of the vndk and apex apis #include @@ -247,6 +247,7 @@ enum { NATIVE_WINDOW_SET_DEQUEUE_TIMEOUT = 37, /* private */ NATIVE_WINDOW_GET_LAST_DEQUEUE_DURATION = 38, /* private */ NATIVE_WINDOW_GET_LAST_QUEUE_DURATION = 39, /* private */ + NATIVE_WINDOW_SET_FRAME_RATE = 40, // clang-format on }; @@ -1008,4 +1009,8 @@ static inline int native_window_set_auto_prerotation(struct ANativeWindow* windo return window->perform(window, NATIVE_WINDOW_SET_AUTO_PREROTATION, autoPrerotation); } +static inline int native_window_set_frame_rate(struct ANativeWindow* window, float frameRate) { + return window->perform(window, NATIVE_WINDOW_SET_FRAME_RATE, (double)frameRate); +} + __END_DECLS diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e4e4bc7db6..56b50eb7cb 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -117,6 +117,18 @@ bool BufferQueueLayer::shouldPresentNow(nsecs_t expectedPresentTime) const { return isDue || !isPlausible; } +bool BufferQueueLayer::setFrameRate(float frameRate) { + float oldFrameRate = 0.f; + status_t result = mConsumer->getFrameRate(&oldFrameRate); + bool frameRateChanged = result < 0 || frameRate != oldFrameRate; + mConsumer->setFrameRate(frameRate); + return frameRateChanged; +} + +float BufferQueueLayer::getFrameRate() const { + return mLatchedFrameRate; +} + // ----------------------------------------------------------------------- // Interface implementation for BufferLayer // ----------------------------------------------------------------------- @@ -547,6 +559,9 @@ void BufferQueueLayer::gatherBufferInfo() { mBufferInfo.mApi = mConsumer->getCurrentApi(); mBufferInfo.mPixelFormat = mFormat; mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse(); + float latchedFrameRate; + mConsumer->getFrameRate(&latchedFrameRate); + mLatchedFrameRate = latchedFrameRate; } sp BufferQueueLayer::createClone() { diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index b0405561bb..0777953c17 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -55,6 +55,10 @@ public: int32_t getQueuedFrameCount() const override; bool shouldPresentNow(nsecs_t expectedPresentTime) const override; + + bool setFrameRate(float frameRate) override; + float getFrameRate() const override; + // ----------------------------------------------------------------------- // ----------------------------------------------------------------------- @@ -151,6 +155,8 @@ private: std::atomic mSidebandStreamChanged{false}; sp mContentsChangedListener; + + std::atomic mLatchedFrameRate = 0.f; }; } // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5bba7d312b..2e2d7450b4 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -111,6 +111,7 @@ Layer::Layer(const LayerCreationArgs& args) mCurrentState.frameRateSelectionPriority = PRIORITY_UNSET; mCurrentState.metadata = args.metadata; mCurrentState.shadowRadius = 0.f; + mCurrentState.frameRate = 0.f; // drawing state & current state are identical mDrawingState = mCurrentState; @@ -1221,6 +1222,22 @@ bool Layer::setShadowRadius(float shadowRadius) { return true; } +bool Layer::setFrameRate(float frameRate) { + if (mCurrentState.frameRate == frameRate) { + return false; + } + + mCurrentState.sequence++; + mCurrentState.frameRate = frameRate; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); + return true; +} + +float Layer::getFrameRate() const { + return getDrawingState().frameRate; +} + void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { ATRACE_CALL(); mCurrentState.barrierLayer_legacy = barrierLayer; diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index b8a35392f8..025309894a 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -224,6 +224,8 @@ public: // Priority of the layer assigned by Window Manager. int32_t frameRateSelectionPriority; + + float frameRate; }; explicit Layer(const LayerCreationArgs& args); @@ -737,6 +739,9 @@ public: */ Rect getCroppedBufferSize(const Layer::State& s) const; + virtual bool setFrameRate(float frameRate); + virtual float getFrameRate() const; + protected: // constant sp mFlinger; diff --git a/services/surfaceflinger/MonitoredProducer.cpp b/services/surfaceflinger/MonitoredProducer.cpp index 7a959f7b19..081f8dbe23 100644 --- a/services/surfaceflinger/MonitoredProducer.cpp +++ b/services/surfaceflinger/MonitoredProducer.cpp @@ -158,6 +158,10 @@ status_t MonitoredProducer::setAutoPrerotation(bool autoPrerotation) { return mProducer->setAutoPrerotation(autoPrerotation); } +status_t MonitoredProducer::setFrameRate(float frameRate) { + return mProducer->setFrameRate(frameRate); +} + IBinder* MonitoredProducer::onAsBinder() { return this; } diff --git a/services/surfaceflinger/MonitoredProducer.h b/services/surfaceflinger/MonitoredProducer.h index 788919b3da..4bda831aeb 100644 --- a/services/surfaceflinger/MonitoredProducer.h +++ b/services/surfaceflinger/MonitoredProducer.h @@ -71,6 +71,7 @@ public: virtual status_t getUniqueId(uint64_t* outId) const override; virtual status_t getConsumerUsage(uint64_t* outUsage) const override; virtual status_t setAutoPrerotation(bool autoPrerotation) override; + virtual status_t setFrameRate(float frameRate) override; // The Layer which created this producer, and on which queued Buffer's will be displayed. sp getLayer() const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index e90cf41707..4f042db376 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3480,6 +3480,9 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } } + if (what & layer_state_t::eFrameRateChanged) { + if (layer->setFrameRate(s.frameRate)) flags |= eTraversalNeeded; + } // This has to happen after we reparent children because when we reparent to null we remove // child layers from current state and remove its relative z. If the children are reparented in // the same transaction, then we have to make sure we reparent the children first so we do not diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index 1c8199ac6d..94ebe8949b 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -32,6 +32,7 @@ cc_test { "MirrorLayer_test.cpp", "MultiDisplayLayerBounds_test.cpp", "RelativeZ_test.cpp", + "SetFrameRate_test.cpp", "SetGeometry_test.cpp", "Stress_test.cpp", "SurfaceInterceptor_test.cpp", diff --git a/services/surfaceflinger/tests/SetFrameRate_test.cpp b/services/surfaceflinger/tests/SetFrameRate_test.cpp new file mode 100644 index 0000000000..4d1477cf8d --- /dev/null +++ b/services/surfaceflinger/tests/SetFrameRate_test.cpp @@ -0,0 +1,71 @@ +/* + * Copyright (C) 2020 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. + */ + +#include + +#include + +#include "LayerTransactionTest.h" + +namespace android { + +class SetFrameRateTest : public LayerTransactionTest { +protected: + void TearDown() { + mLayer = nullptr; + LayerTransactionTest::TearDown(); + } + + void CreateLayer(uint32_t layerType) { + ASSERT_EQ(nullptr, mLayer.get()); + mLayerType = layerType; + ASSERT_NO_FATAL_FAILURE(mLayer = createLayer("TestLayer", mLayerWidth, mLayerHeight, + /*flags=*/mLayerType)); + ASSERT_NE(nullptr, mLayer.get()); + } + + void PostBuffers(const Color& color) { + auto startTime = systemTime(); + while (systemTime() - startTime < s2ns(1)) { + ASSERT_NO_FATAL_FAILURE( + fillLayerColor(mLayerType, mLayer, color, mLayerWidth, mLayerHeight)); + std::this_thread::sleep_for(100ms); + } + } + + const int mLayerWidth = 32; + const int mLayerHeight = 32; + sp mLayer; + uint32_t mLayerType; +}; + +TEST_F(SetFrameRateTest, BufferQueueLayerSetFrameRate) { + CreateLayer(ISurfaceComposerClient::eFXSurfaceBufferQueue); + native_window_set_frame_rate(mLayer->getSurface().get(), 100.f); + ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED)); + Transaction().setFrameRate(mLayer, 200.f).apply(); + ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED)); + native_window_set_frame_rate(mLayer->getSurface().get(), 300.f); + ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::RED)); +} + +TEST_F(SetFrameRateTest, BufferStateLayerSetFrameRate) { + CreateLayer(ISurfaceComposerClient::eFXSurfaceBufferState); + Transaction().setFrameRate(mLayer, 400.f).apply(); + ASSERT_NO_FATAL_FAILURE(PostBuffers(Color::GREEN)); +} + +} // namespace android -- cgit v1.2.3-59-g8ed1b From 8a82ba66a22238fe59c02a6309ba8bd3dae4f074 Mon Sep 17 00:00:00 2001 From: Ady Abraham Date: Fri, 17 Jan 2020 12:43:17 -0800 Subject: SurfaceFlinger: enhance refresh rate selection Enhance the refresh rate selection algorithm to allow having multiple refresh rate. The new process attaches scores to each one of the available refresh rate and chooses the refresh rate with the highest score. This behavior is currently controlled by the sysprop flag 'debug.sf.use_content_detection_v2' and currently turned off. This algorithm stills needs some tunings which will be done in layer CLs. Test: adb shell /data/nativetest64/SurfaceFlinger_test/SurfaceFlinger_test Test: adb shell /data/nativetest64/libsurfaceflinger_unittest/libsurfaceflinger_unittest Test: go/90hzscenarios manual tests Bug: 147516364 Fixes: 146068419 Change-Id: I06e07459e469482799ff80fa54fa8dd311325e0e --- services/surfaceflinger/Android.bp | 2 + services/surfaceflinger/BufferQueueLayer.cpp | 7 +- services/surfaceflinger/BufferQueueLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 3 +- services/surfaceflinger/DisplayDevice.h | 6 +- .../surfaceflinger/DisplayHardware/ComposerHal.h | 7 + .../surfaceflinger/DisplayHardware/HWComposer.h | 6 + services/surfaceflinger/Layer.cpp | 7 +- services/surfaceflinger/Layer.h | 3 +- services/surfaceflinger/RefreshRateOverlay.cpp | 1 + services/surfaceflinger/RenderArea.h | 4 +- services/surfaceflinger/Scheduler/LayerHistory.cpp | 53 +-- services/surfaceflinger/Scheduler/LayerHistory.h | 88 +++- .../surfaceflinger/Scheduler/LayerHistoryV2.cpp | 213 +++++++++ services/surfaceflinger/Scheduler/LayerInfoV2.cpp | 139 ++++++ services/surfaceflinger/Scheduler/LayerInfoV2.h | 117 +++++ .../Scheduler/RefreshRateConfigs.cpp | 157 ++++++- .../surfaceflinger/Scheduler/RefreshRateConfigs.h | 33 +- .../surfaceflinger/Scheduler/RefreshRateStats.h | 3 +- services/surfaceflinger/Scheduler/Scheduler.cpp | 119 +++-- services/surfaceflinger/Scheduler/Scheduler.h | 15 +- services/surfaceflinger/SurfaceFlinger.cpp | 30 +- .../SurfaceFlingerDefaultFactory.cpp | 4 +- services/surfaceflinger/tests/unittests/Android.bp | 1 + .../tests/unittests/LayerHistoryTest.cpp | 73 ++- .../tests/unittests/LayerHistoryTestV2.cpp | 418 +++++++++++++++++ .../tests/unittests/RefreshRateConfigsTest.cpp | 499 ++++++++++++++++++++- .../tests/unittests/SchedulerTest.cpp | 2 +- .../tests/unittests/TestableScheduler.h | 32 +- .../tests/unittests/TestableSurfaceFlinger.h | 17 +- .../tests/unittests/mock/MockLayer.h | 1 + 31 files changed, 1877 insertions(+), 185 deletions(-) create mode 100644 services/surfaceflinger/Scheduler/LayerHistoryV2.cpp create mode 100644 services/surfaceflinger/Scheduler/LayerInfoV2.cpp create mode 100644 services/surfaceflinger/Scheduler/LayerInfoV2.h create mode 100644 services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp index 9a7eabd498..1b1e8890ab 100644 --- a/services/surfaceflinger/Android.bp +++ b/services/surfaceflinger/Android.bp @@ -165,7 +165,9 @@ filegroup { "Scheduler/EventThread.cpp", "Scheduler/OneShotTimer.cpp", "Scheduler/LayerHistory.cpp", + "Scheduler/LayerHistoryV2.cpp", "Scheduler/LayerInfo.cpp", + "Scheduler/LayerInfoV2.cpp", "Scheduler/MessageQueue.cpp", "Scheduler/PhaseOffsets.cpp", "Scheduler/RefreshRateConfigs.cpp", diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index b55e62b88c..e85281d8a9 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -129,8 +129,11 @@ bool BufferQueueLayer::setFrameRate(float frameRate) { return frameRateChanged; } -float BufferQueueLayer::getFrameRate() const { - return mLatchedFrameRate; +std::optional BufferQueueLayer::getFrameRate() const { + if (mLatchedFrameRate > 0.f || mLatchedFrameRate == FRAME_RATE_NO_VOTE) + return mLatchedFrameRate; + + return {}; } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 0777953c17..2bd1e3d6cc 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -57,7 +57,7 @@ public: bool shouldPresentNow(nsecs_t expectedPresentTime) const override; bool setFrameRate(float frameRate) override; - float getFrameRate() const override; + std::optional getFrameRate() const override; // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index c173c66b4e..2967164764 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -251,7 +251,8 @@ bool BufferStateLayer::setBuffer(const sp& buffer, nsecs_t postTi FrameTracer::FrameEvent::POST); mCurrentState.desiredPresentTime = desiredPresentTime; - mFlinger->mScheduler->recordLayerHistory(this, desiredPresentTime); + mFlinger->mScheduler->recordLayerHistory(this, + desiredPresentTime <= 0 ? 0 : desiredPresentTime); return true; } diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 605e7c8ab4..ff48ecdedc 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -227,8 +227,10 @@ class DisplayRenderArea : public RenderArea { public: DisplayRenderArea(const sp& display, RotationFlags rotation = ui::Transform::ROT_0) - : DisplayRenderArea(display, display->getBounds(), display->getWidth(), - display->getHeight(), display->getCompositionDataSpace(), rotation) {} + : DisplayRenderArea(display, display->getBounds(), + static_cast(display->getWidth()), + static_cast(display->getHeight()), + display->getCompositionDataSpace(), rotation) {} DisplayRenderArea(sp display, const Rect& sourceCrop, uint32_t reqWidth, uint32_t reqHeight, ui::Dataspace reqDataSpace, RotationFlags rotation, diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h index 6f0f38a58a..a2b7421269 100644 --- a/services/surfaceflinger/DisplayHardware/ComposerHal.h +++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h @@ -23,6 +23,10 @@ #include #include +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + #if defined(USE_VR_COMPOSER) && USE_VR_COMPOSER #include #endif // defined(USE_VR_COMPOSER) && USE_VR_COMPOSER @@ -36,6 +40,9 @@ #include #include +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" + namespace android { namespace Hwc2 { diff --git a/services/surfaceflinger/DisplayHardware/HWComposer.h b/services/surfaceflinger/DisplayHardware/HWComposer.h index a0dabb427d..effe43b548 100644 --- a/services/surfaceflinger/DisplayHardware/HWComposer.h +++ b/services/surfaceflinger/DisplayHardware/HWComposer.h @@ -27,7 +27,13 @@ #include #include + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" #include +#pragma clang diagnostic pop + #include #include diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index f4d4329f6d..af906dc64c 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1251,8 +1251,11 @@ bool Layer::setFrameRate(float frameRate) { return true; } -float Layer::getFrameRate() const { - return getDrawingState().frameRate; +std::optional Layer::getFrameRate() const { + const auto frameRate = getDrawingState().frameRate; + if (frameRate > 0.f || frameRate == FRAME_RATE_NO_VOTE) return frameRate; + + return {}; } void Layer::deferTransactionUntil_legacy(const sp& barrierLayer, uint64_t frameNumber) { diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ffe004f9e9..b8423f0232 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -744,8 +744,9 @@ public: */ Rect getCroppedBufferSize(const Layer::State& s) const; + constexpr static auto FRAME_RATE_NO_VOTE = -1.0f; virtual bool setFrameRate(float frameRate); - virtual float getFrameRate() const; + virtual std::optional getFrameRate() const; protected: // constant diff --git a/services/surfaceflinger/RefreshRateOverlay.cpp b/services/surfaceflinger/RefreshRateOverlay.cpp index 33e5796e6f..d3d9d3aec7 100644 --- a/services/surfaceflinger/RefreshRateOverlay.cpp +++ b/services/surfaceflinger/RefreshRateOverlay.cpp @@ -155,6 +155,7 @@ bool RefreshRateOverlay::createLayer() { Mutex::Autolock _l(mFlinger.mStateLock); mLayer = mClient->getLayerUser(mIBinder); + mLayer->setFrameRate(Layer::FRAME_RATE_NO_VOTE); // setting Layer's Z requires resorting layersSortedByZ ssize_t idx = mFlinger.mCurrentState.layersSortedByZ.indexOf(mLayer); diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h index a7a6dd5fc1..9b3a9f4309 100644 --- a/services/surfaceflinger/RenderArea.h +++ b/services/surfaceflinger/RenderArea.h @@ -71,8 +71,8 @@ public: RotationFlags getRotationFlags() const { return mRotationFlags; } // Returns the size of the physical render area. - int getReqWidth() const { return mReqWidth; } - int getReqHeight() const { return mReqHeight; } + int getReqWidth() const { return static_cast(mReqWidth); } + int getReqHeight() const { return static_cast(mReqHeight); } // Returns the composition data space of the render area. ui::Dataspace getReqDataSpace() const { return mReqDataSpace; } diff --git a/services/surfaceflinger/Scheduler/LayerHistory.cpp b/services/surfaceflinger/Scheduler/LayerHistory.cpp index abf0cd673a..ebd617faef 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.cpp +++ b/services/surfaceflinger/Scheduler/LayerHistory.cpp @@ -43,7 +43,7 @@ namespace android::scheduler::impl { namespace { bool isLayerActive(const Layer& layer, const LayerInfo& info, nsecs_t threshold) { - if (layer.getFrameRate() > .0f) { + if (layer.getFrameRate().has_value()) { return layer.isVisible(); } return layer.isVisible() && info.getLastUpdatedTime() >= threshold; @@ -77,7 +77,8 @@ LayerHistory::LayerHistory() : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {} LayerHistory::~LayerHistory() = default; -void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate) { +void LayerHistory::registerLayer(Layer* layer, float lowRefreshRate, float highRefreshRate, + LayerVoteType /*type*/) { auto info = std::make_unique(lowRefreshRate, highRefreshRate); std::lock_guard lock(mLock); mLayerInfos.emplace_back(layer, std::move(info)); @@ -101,8 +102,6 @@ void LayerHistory::record(Layer* layer, nsecs_t presentTime, nsecs_t now) { } LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { - float maxRefreshRate = 0; - std::lock_guard lock(mLock); partitionLayers(now); @@ -113,7 +112,7 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { if (recent || CC_UNLIKELY(mTraceEnabled)) { const float refreshRate = info->getRefreshRate(now); - if (recent && refreshRate > maxRefreshRate) { + if (recent && refreshRate > 0.0f) { if (const auto layer = activeLayer.promote(); layer) { const int32_t priority = layer->getFrameRateSelectionPriority(); // TODO(b/142507166): This is where the scoring algorithm should live. @@ -124,36 +123,30 @@ LayerHistory::Summary LayerHistory::summarize(nsecs_t now) { } } + LayerHistory::Summary summary; for (const auto& [weakLayer, info] : activeLayers()) { const bool recent = info->isRecentlyActive(now); auto layer = weakLayer.promote(); // Only use the layer if the reference still exists. if (layer || CC_UNLIKELY(mTraceEnabled)) { - float refreshRate = 0.f; - // Default content refresh rate is only used when dealing with recent layers. - if (recent) { - refreshRate = info->getRefreshRate(now); - } // Check if frame rate was set on layer. - float frameRate = layer->getFrameRate(); - if (frameRate > 0.f) { - // Override content detection refresh rate, if it was set. - refreshRate = frameRate; - } - if (refreshRate > maxRefreshRate) { - maxRefreshRate = refreshRate; + auto frameRate = layer->getFrameRate(); + if (frameRate.has_value() && frameRate.value() > 0.f) { + summary.push_back( + {layer->getName(), LayerVoteType::Explicit, *frameRate, /* weight */ 1.0f}); + } else if (recent) { + frameRate = info->getRefreshRate(now); + summary.push_back({layer->getName(), LayerVoteType::Heuristic, *frameRate, + /* weight */ 1.0f}); } if (CC_UNLIKELY(mTraceEnabled)) { - trace(weakLayer, std::round(refreshRate)); + trace(weakLayer, std::round(*frameRate)); } } } - if (CC_UNLIKELY(mTraceEnabled)) { - ALOGD("%s: maxRefreshRate=%.2f", __FUNCTION__, maxRefreshRate); - } - return {maxRefreshRate}; + return summary; } void LayerHistory::partitionLayers(nsecs_t now) { @@ -199,22 +192,6 @@ void LayerHistory::clear() { mActiveLayersEnd = 0; } -bool LayerHistory::hasClientSpecifiedFrameRate() { - std::lock_guard lock(mLock); - for (const auto& [weakLayer, info] : activeLayers()) { - auto layer = weakLayer.promote(); - if (layer) { - float frameRate = layer->getFrameRate(); - // Found a layer that has a frame rate set on it. - if (fabs(frameRate) > 0.f) { - return true; - } - } - } - // Did not find any layers that have frame rate. - return false; -} - } // namespace android::scheduler::impl // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/Scheduler/LayerHistory.h b/services/surfaceflinger/Scheduler/LayerHistory.h index f21713411a..bef04e9b42 100644 --- a/services/surfaceflinger/Scheduler/LayerHistory.h +++ b/services/surfaceflinger/Scheduler/LayerHistory.h @@ -25,6 +25,8 @@ #include #include +#include "RefreshRateConfigs.h" + namespace android { class Layer; @@ -33,29 +35,32 @@ class TestableScheduler; namespace scheduler { class LayerHistoryTest; +class LayerHistoryTestV2; class LayerInfo; +class LayerInfoV2; class LayerHistory { public: + using LayerVoteType = RefreshRateConfigs::LayerVoteType; + virtual ~LayerHistory() = default; // Layers are unregistered when the weak reference expires. - virtual void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate) = 0; + virtual void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, + LayerVoteType type) = 0; + + // Sets the display size. Client is responsible for synchronization. + virtual void setDisplayArea(uint32_t displayArea) = 0; // Marks the layer as active, and records the given state to its history. virtual void record(Layer*, nsecs_t presentTime, nsecs_t now) = 0; - struct Summary { - float maxRefreshRate; // Maximum refresh rate among recently active layers. - }; + using Summary = std::vector; // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. virtual Summary summarize(nsecs_t now) = 0; virtual void clear() = 0; - - // Checks whether any of the active layers have a desired frame rate bit set on them. - virtual bool hasClientSpecifiedFrameRate() = 0; }; namespace impl { @@ -68,7 +73,10 @@ public: virtual ~LayerHistory(); // Layers are unregistered when the weak reference expires. - void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate) override; + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, + LayerVoteType type) override; + + void setDisplayArea(uint32_t /*displayArea*/) override {} // Marks the layer as active, and records the given state to its history. void record(Layer*, nsecs_t presentTime, nsecs_t now) override; @@ -78,10 +86,6 @@ public: void clear() override; - // Traverses all active layers and checks whether any of them have a desired frame - // rate bit set on them. - bool hasClientSpecifiedFrameRate() override; - private: friend class android::scheduler::LayerHistoryTest; friend TestableScheduler; @@ -91,7 +95,7 @@ private: struct ActiveLayers { LayerInfos& infos; - const size_t index; + const long index; auto begin() { return infos.begin(); } auto end() { return begin() + index; } @@ -106,11 +110,69 @@ private: mutable std::mutex mLock; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active + // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. + LayerInfos mLayerInfos GUARDED_BY(mLock); + long mActiveLayersEnd GUARDED_BY(mLock) = 0; + + // Whether to emit systrace output and debug logs. + const bool mTraceEnabled; + + // Whether to use priority sent from WindowManager to determine the relevancy of the layer. + const bool mUseFrameRatePriority; +}; + +class LayerHistoryV2 : public android::scheduler::LayerHistory { +public: + LayerHistoryV2(); + virtual ~LayerHistoryV2(); + + // Layers are unregistered when the weak reference expires. + void registerLayer(Layer*, float lowRefreshRate, float highRefreshRate, + LayerVoteType type) override; + + // Sets the display size. Client is responsible for synchronization. + void setDisplayArea(uint32_t displayArea) override { mDisplayArea = displayArea; } + + // Marks the layer as active, and records the given state to its history. + void record(Layer*, nsecs_t presentTime, nsecs_t now) override; + + // Rebuilds sets of active/inactive layers, and accumulates stats for active layers. + android::scheduler::LayerHistory::Summary summarize(nsecs_t /*now*/) override; + + void clear() override; + +private: + friend android::scheduler::LayerHistoryTestV2; + friend TestableScheduler; + + using LayerPair = std::pair, std::unique_ptr>; + using LayerInfos = std::vector; + + struct ActiveLayers { + LayerInfos& infos; + const size_t index; + + auto begin() { return infos.begin(); } + auto end() { return begin() + static_cast(index); } + }; + + ActiveLayers activeLayers() REQUIRES(mLock) { return {mLayerInfos, mActiveLayersEnd}; } + + // Iterates over layers in a single pass, swapping pairs such that active layers precede + // inactive layers, and inactive layers precede expired layers. Removes expired layers by + // truncating after inactive layers. + void partitionLayers(nsecs_t now) REQUIRES(mLock); + + mutable std::mutex mLock; + // Partitioned such that active layers precede inactive layers. For fast lookup, the few active // layers are at the front, and weak pointers are stored in contiguous memory to hit the cache. LayerInfos mLayerInfos GUARDED_BY(mLock); size_t mActiveLayersEnd GUARDED_BY(mLock) = 0; + uint32_t mDisplayArea = 0; + // Whether to emit systrace output and debug logs. const bool mTraceEnabled; diff --git a/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp new file mode 100644 index 0000000000..884b46add2 --- /dev/null +++ b/services/surfaceflinger/Scheduler/LayerHistoryV2.cpp @@ -0,0 +1,213 @@ +/* + * Copyright 2020 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. + */ + +#undef LOG_TAG +#define LOG_TAG "LayerHistoryV2" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +#include "LayerHistory.h" + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wconversion" + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "../Layer.h" +#include "SchedulerUtils.h" + +// TODO(b/129481165): remove the #pragma below and fix conversion issues +#pragma clang diagnostic pop // ignored "-Wconversion" + +#include "LayerInfoV2.h" + +namespace android::scheduler::impl { + +namespace { + +bool isLayerActive(const Layer& layer, const LayerInfoV2& info, nsecs_t threshold) { + if (layer.getFrameRate().has_value()) { + return layer.isVisible(); + } + return layer.isVisible() && info.getLastUpdatedTime() >= threshold; +} + +bool traceEnabled() { + return property_get_bool("debug.sf.layer_history_trace", false); +} + +bool useFrameRatePriority() { + char value[PROPERTY_VALUE_MAX]; + property_get("debug.sf.use_frame_rate_priority", value, "1"); + return atoi(value); +} + +void trace(const wp& weak, LayerHistory::LayerVoteType type, int fps) { + const auto layer = weak.promote(); + if (!layer) return; + + const auto& name = layer->getName(); + const auto noVoteTag = "LFPS NoVote " + name; + const auto heuristicVoteTag = "LFPS Heuristic " + name; + const auto explicitVoteTag = "LFPS Explicit " + name; + const auto minVoteTag = "LFPS Min " + name; + const auto maxVoteTag = "LFPS Max " + name; + + ATRACE_INT(noVoteTag.c_str(), type == LayerHistory::LayerVoteType::NoVote ? 1 : 0); + ATRACE_INT(heuristicVoteTag.c_str(), type == LayerHistory::LayerVoteType::Heuristic ? fps : 0); + ATRACE_INT(explicitVoteTag.c_str(), type == LayerHistory::LayerVoteType::Explicit ? fps : 0); + ATRACE_INT(minVoteTag.c_str(), type == LayerHistory::LayerVoteType::Min ? 1 : 0); + ATRACE_INT(maxVoteTag.c_str(), type == LayerHistory::LayerVoteType::Max ? 1 : 0); + + ALOGD("%s: %s @ %d Hz", __FUNCTION__, name.c_str(), fps); +} + +} // namespace + +LayerHistoryV2::LayerHistoryV2() + : mTraceEnabled(traceEnabled()), mUseFrameRatePriority(useFrameRatePriority()) {} +LayerHistoryV2::~LayerHistoryV2() = default; + +void LayerHistoryV2::registerLayer(Layer* layer, float /*lowRefreshRate*/, float highRefreshRate, + LayerVoteType type) { + const nsecs_t highRefreshRatePeriod = static_cast(1e9f / highRefreshRate); + auto info = std::make_unique(highRefreshRatePeriod, type); + std::lock_guard lock(mLock); + mLayerInfos.emplace_back(layer, std::move(info)); +} + +void LayerHistoryV2::record(Layer* layer, nsecs_t presentTime, nsecs_t now) { + std::lock_guard lock(mLock); + + const auto it = std::find_if(mLayerInfos.begin(), mLayerInfos.end(), + [layer](const auto& pair) { return pair.first == layer; }); + LOG_FATAL_IF(it == mLayerInfos.end(), "%s: unknown layer %p", __FUNCTION__, layer); + + const auto& info = it->second; + info->setLastPresentTime(presentTime, now); + + // Activate layer if inactive. + if (const auto end = activeLayers().end(); it >= end) { + std::iter_swap(it, end); + mActiveLayersEnd++; + } +} + +LayerHistoryV2::Summary LayerHistoryV2::summarize(nsecs_t now) { + LayerHistory::Summary summary; + + std::lock_guard lock(mLock); + + partitionLayers(now); + + for (const auto& [layer, info] : activeLayers()) { + const auto strong = layer.promote(); + if (!strong) { + continue; + } + + const bool recent = info->isRecentlyActive(now); + if (recent) { + const auto [type, refreshRate] = info->getRefreshRate(now); + // Skip NoVote layer as those don't have any requirements + if (type == LayerHistory::LayerVoteType::NoVote) { + continue; + } + + // Compute the layer's position on the screen + const Rect bounds = Rect(strong->getBounds()); + const ui::Transform transform = strong->getTransform(); + constexpr bool roundOutwards = true; + Rect transformed = transform.transform(bounds, roundOutwards); + + const float layerArea = transformed.getWidth() * transformed.getHeight(); + float weight = mDisplayArea ? layerArea / mDisplayArea : 0.0f; + summary.push_back({strong->getName(), type, refreshRate, weight}); + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(layer, type, static_cast(std::round(refreshRate))); + } + } else if (CC_UNLIKELY(mTraceEnabled)) { + trace(layer, LayerHistory::LayerVoteType::NoVote, 0); + } + } + + return summary; +} + +void LayerHistoryV2::partitionLayers(nsecs_t now) { + const nsecs_t threshold = getActiveLayerThreshold(now); + + // Collect expired and inactive layers after active layers. + size_t i = 0; + while (i < mActiveLayersEnd) { + auto& [weak, info] = mLayerInfos[i]; + if (const auto layer = weak.promote(); layer && isLayerActive(*layer, *info, threshold)) { + i++; + // Set layer vote if set + const auto frameRate = layer->getFrameRate(); + if (frameRate.has_value()) { + if (*frameRate == Layer::FRAME_RATE_NO_VOTE) { + info->setLayerVote(LayerVoteType::NoVote, 0.f); + } else { + info->setLayerVote(LayerVoteType::Explicit, *frameRate); + } + } else { + info->resetLayerVote(); + } + continue; + } + + if (CC_UNLIKELY(mTraceEnabled)) { + trace(weak, LayerHistory::LayerVoteType::NoVote, 0); + } + + info->clearHistory(); + std::swap(mLayerInfos[i], mLayerInfos[--mActiveLayersEnd]); + } + + // Collect expired layers after inactive layers. + size_t end = mLayerInfos.size(); + while (i < end) { + if (mLayerInfos[i].first.promote()) { + i++; + } else { + std::swap(mLayerInfos[i], mLayerInfos[--end]); + } + } + + mLayerInfos.erase(mLayerInfos.begin() + static_cast(end), mLayerInfos.end()); +} + +void LayerHistoryV2::clear() { + std::lock_guard lock(mLock); + + for (const auto& [layer, info] : activeLayers()) { + info->clearHistory(); + } + + mActiveLayersEnd = 0; +} + +} // namespace android::scheduler::impl diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.cpp b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp new file mode 100644 index 0000000000..d94d758ec5 --- /dev/null +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.cpp @@ -0,0 +1,139 @@ +/* + * Copyright 2020 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. + */ + +// #define LOG_NDEBUG 0 + +#include "LayerInfoV2.h" + +#include +#include + +#undef LOG_TAG +#define LOG_TAG "LayerInfoV2" +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + +namespace android::scheduler { + +LayerInfoV2::LayerInfoV2(nsecs_t highRefreshRatePeriod, LayerHistory::LayerVoteType defaultVote) + : mHighRefreshRatePeriod(highRefreshRatePeriod), + mDefaultVote(defaultVote), + mLayerVote({defaultVote, 0.0f}) {} + +void LayerInfoV2::setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now) { + lastPresentTime = std::max(lastPresentTime, static_cast(0)); + + mLastUpdatedTime = std::max(lastPresentTime, now); + + FrameTimeData frameTime = {.presetTime = lastPresentTime, .queueTime = mLastUpdatedTime}; + + mFrameTimes.push_back(frameTime); + if (mFrameTimes.size() > HISTORY_SIZE) { + mFrameTimes.pop_front(); + } +} + +// Returns whether the earliest present time is within the active threshold. +bool LayerInfoV2::isRecentlyActive(nsecs_t now) const { + if (mFrameTimes.empty()) { + return false; + } + + return mFrameTimes.back().queueTime >= getActiveLayerThreshold(now); +} + +bool LayerInfoV2::isFrequent(nsecs_t now) const { + // Assume layer is infrequent if too few present times have been recorded. + if (mFrameTimes.size() < FREQUENT_LAYER_WINDOW_SIZE) { + return true; + } + + // Layer is frequent if the earliest value in the window of most recent present times is + // within threshold. + const auto it = mFrameTimes.end() - FREQUENT_LAYER_WINDOW_SIZE; + const nsecs_t threshold = now - MAX_FREQUENT_LAYER_PERIOD_NS.count(); + return it->queueTime >= threshold; +} + +bool LayerInfoV2::hasEnoughDataForHeuristic() const { + // The layer had to publish at least HISTORY_SIZE or HISTORY_TIME of updates + if (mFrameTimes.size() < HISTORY_SIZE && + mFrameTimes.back().queueTime - mFrameTimes.front().queueTime < HISTORY_TIME.count()) { + return false; + } + + return true; +} + +std::optional LayerInfoV2::calculateRefreshRateIfPossible() { + static constexpr float MARGIN = 1.0f; // 1Hz + + if (!hasEnoughDataForHeuristic()) { + ALOGV("Not enough data"); + return std::nullopt; + } + + // Calculate the refresh rate by finding the average delta between frames + nsecs_t totalPresentTimeDeltas = 0; + for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) { + // If there are no presentation timestamp provided we can't calculate the refresh rate + if (it->presetTime == 0 || (it + 1)->presetTime == 0) { + return std::nullopt; + } + + totalPresentTimeDeltas += + std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod); + } + const float averageFrameTime = + static_cast(totalPresentTimeDeltas) / (mFrameTimes.size() - 1); + + // Now once we calculated the refresh rate we need to make sure that all the frames we captured + // are evenly distrubuted and we don't calculate the average across some burst of frames. + + for (auto it = mFrameTimes.begin(); it != mFrameTimes.end() - 1; ++it) { + const nsecs_t presentTimeDeltas = + std::max(((it + 1)->presetTime - it->presetTime), mHighRefreshRatePeriod); + if (std::abs(presentTimeDeltas - averageFrameTime) > 2 * averageFrameTime) { + return std::nullopt; + } + } + + const auto refreshRate = 1e9f / averageFrameTime; + if (std::abs(refreshRate - mLastReportedRefreshRate) > MARGIN) { + mLastReportedRefreshRate = refreshRate; + } + + ALOGV("Refresh rate: %.2f", mLastReportedRefreshRate); + return mLastReportedRefreshRate; +} + +std::pair LayerInfoV2::getRefreshRate(nsecs_t now) { + if (mLayerVote.type != LayerHistory::LayerVoteType::Heuristic) { + return {mLayerVote.type, mLayerVote.fps}; + } + + if (!isFrequent(now)) { + return {LayerHistory::LayerVoteType::Min, 0}; + } + + auto refreshRate = calculateRefreshRateIfPossible(); + if (refreshRate.has_value()) { + return {LayerHistory::LayerVoteType::Heuristic, refreshRate.value()}; + } + + return {LayerHistory::LayerVoteType::Max, 0}; +} + +} // namespace android::scheduler diff --git a/services/surfaceflinger/Scheduler/LayerInfoV2.h b/services/surfaceflinger/Scheduler/LayerInfoV2.h new file mode 100644 index 0000000000..564f05efa2 --- /dev/null +++ b/services/surfaceflinger/Scheduler/LayerInfoV2.h @@ -0,0 +1,117 @@ +/* + * Copyright 2020 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. + */ + +#pragma once + +#include + +#include +#include + +#include "LayerHistory.h" +#include "RefreshRateConfigs.h" +#include "SchedulerUtils.h" + +namespace android { + +class Layer; + +namespace scheduler { + +using namespace std::chrono_literals; + +// Maximum period between presents for a layer to be considered active. +constexpr std::chrono::nanoseconds MAX_ACTIVE_LAYER_PERIOD_NS = 1200ms; + +// Earliest present time for a layer to be considered active. +constexpr nsecs_t getActiveLayerThreshold(nsecs_t now) { + return now - MAX_ACTIVE_LAYER_PERIOD_NS.count(); +} + +// Stores history of present times and refresh rates for a layer. +class LayerInfoV2 { + // Layer is considered frequent if the earliest value in the window of most recent present times + // is within a threshold. If a layer is infrequent, its average refresh rate is disregarded in + // favor of a low refresh rate. + static constexpr size_t FREQUENT_LAYER_WINDOW_SIZE = 3; + static constexpr std::chrono::nanoseconds MAX_FREQUENT_LAYER_PERIOD_NS = 250ms; + + friend class LayerHistoryTestV2; + +public: + LayerInfoV2(nsecs_t highRefreshRatePeriod, LayerHistory::LayerVoteType defaultVote); + + LayerInfoV2(const LayerInfo&) = delete; + LayerInfoV2& operator=(const LayerInfoV2&) = delete; + + // Records the last requested present time. It also stores information about when + // the layer was last updated. If the present time is farther in the future than the + // updated time, the updated time is the present time. + void setLastPresentTime(nsecs_t lastPresentTime, nsecs_t now); + + bool isRecentlyActive(nsecs_t now) const; + + // Sets an explicit layer vote. This usually comes directly from the application via + // ANativeWindow_setFrameRate API + void setLayerVote(LayerHistory::LayerVoteType type, float fps) { mLayerVote = {type, fps}; } + + // Sets the default layer vote. This will be the layer vote after calling to resetLayerVote(). + // This is used for layers that called to setLayerVote() and then removed the vote, so that the + // layer can go back to whatever vote it had before the app voted for it. + void setDefaultLayerVote(LayerHistory::LayerVoteType type) { mDefaultVote = type; } + + // Resets the layer vote to its default. + void resetLayerVote() { mLayerVote = {mDefaultVote, 0.0f}; } + + std::pair getRefreshRate(nsecs_t now); + + // Return the last updated time. If the present time is farther in the future than the + // updated time, the updated time is the present time. + nsecs_t getLastUpdatedTime() const { return mLastUpdatedTime; } + + void clearHistory() { mFrameTimes.clear(); } + +private: + bool isFrequent(nsecs_t now) const; + bool hasEnoughDataForHeuristic() const; + std::optional calculateRefreshRateIfPossible(); + + // Used for sanitizing the heuristic data + const nsecs_t mHighRefreshRatePeriod; + LayerHistory::LayerVoteType mDefaultVote; + + nsecs_t mLastUpdatedTime = 0; + + float mLastReportedRefreshRate = 0.0f; + + // Holds information about the layer vote + struct { + LayerHistory::LayerVoteType type; + float fps; + } mLayerVote; + + // Used to store the layer timestamps + struct FrameTimeData { + nsecs_t presetTime; // desiredPresentTime, if provided + nsecs_t queueTime; // buffer queue time + }; + std::deque mFrameTimes; + static constexpr size_t HISTORY_SIZE = 90; + static constexpr std::chrono::nanoseconds HISTORY_TIME = 1s; +}; + +} // namespace scheduler +} // namespace android diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp index 45d1f23029..a8f8e0e245 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.cpp @@ -14,24 +14,51 @@ * limitations under the License. */ +// #define LOG_NDEBUG 0 +#define ATRACE_TAG ATRACE_TAG_GRAPHICS + // TODO(b/129481165): remove the #pragma below and fix conversion issues #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wconversion" -// #define LOG_NDEBUG 0 #include "RefreshRateConfigs.h" +#include +#include +#include +#include + +using namespace std::chrono_literals; namespace android::scheduler { using AllRefreshRatesMapType = RefreshRateConfigs::AllRefreshRatesMapType; using RefreshRate = RefreshRateConfigs::RefreshRate; -// Returns the refresh rate map. This map won't be modified at runtime, so it's safe to access -// from multiple threads. This can only be called if refreshRateSwitching() returns true. -// TODO(b/122916473): Get this information from configs prepared by vendors, instead of -// baking them in. -const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(float contentFramerate) const { +const RefreshRate& RefreshRateConfigs::getRefreshRateForContent( + const std::vector& layers) const { std::lock_guard lock(mLock); + float contentFramerate = 0.0f; + float explicitContentFramerate = 0.0f; + for (const auto& layer : layers) { + if (layer.vote == LayerVoteType::Explicit) { + if (layer.desiredRefreshRate > explicitContentFramerate) { + explicitContentFramerate = layer.desiredRefreshRate; + } + } else { + if (layer.desiredRefreshRate > contentFramerate) { + contentFramerate = layer.desiredRefreshRate; + } + } + } + + if (explicitContentFramerate != 0.0f) { + contentFramerate = explicitContentFramerate; + } else if (contentFramerate == 0.0f) { + contentFramerate = mMaxSupportedRefreshRate->fps; + } + contentFramerate = std::round(contentFramerate); + ATRACE_INT("ContentFPS", contentFramerate); + // Find the appropriate refresh rate with minimal error auto iter = min_element(mAvailableRefreshRates.cbegin(), mAvailableRefreshRates.cend(), [contentFramerate](const auto& lhs, const auto& rhs) -> bool { @@ -60,6 +87,113 @@ const RefreshRate& RefreshRateConfigs::getRefreshRateForContent(float contentFra return *bestSoFar; } +const RefreshRate& RefreshRateConfigs::getRefreshRateForContentV2( + const std::vector& layers) const { + constexpr nsecs_t MARGIN = std::chrono::nanoseconds(800us).count(); + ATRACE_CALL(); + ALOGV("getRefreshRateForContent %zu layers", layers.size()); + + std::lock_guard lock(mLock); + + int noVoteLayers = 0; + int minVoteLayers = 0; + int maxVoteLayers = 0; + int explicitVoteLayers = 0; + for (const auto& layer : layers) { + if (layer.vote == LayerVoteType::NoVote) + noVoteLayers++; + else if (layer.vote == LayerVoteType::Min) + minVoteLayers++; + else if (layer.vote == LayerVoteType::Max) + maxVoteLayers++; + else if (layer.vote == LayerVoteType::Explicit) + explicitVoteLayers++; + } + + // Only if all layers want Min we should return Min + if (noVoteLayers + minVoteLayers == layers.size()) { + return *mAvailableRefreshRates.front(); + } + + // If we have some Max layers and no Explicit we should return Max + if (maxVoteLayers > 0 && explicitVoteLayers == 0) { + return *mAvailableRefreshRates.back(); + } + + // Find the best refresh rate based on score + std::vector> scores; + scores.reserve(mAvailableRefreshRates.size()); + + for (const auto refreshRate : mAvailableRefreshRates) { + scores.emplace_back(refreshRate, 0.0f); + } + + for (const auto& layer : layers) { + if (layer.vote == LayerVoteType::NoVote || layer.vote == LayerVoteType::Min || + layer.vote == LayerVoteType::Max) { + continue; + } + + // If we have Explicit layers, ignore the Huristic ones + if (explicitVoteLayers > 0 && layer.vote == LayerVoteType::Heuristic) { + continue; + } + + for (auto& [refreshRate, overallScore] : scores) { + const auto displayPeriod = refreshRate->vsyncPeriod; + const auto layerPeriod = 1e9f / layer.desiredRefreshRate; + + // Calculate how many display vsyncs we need to present a single frame for this layer + auto [displayFramesQuot, displayFramesRem] = std::div(layerPeriod, displayPeriod); + if (displayFramesRem <= MARGIN || + std::abs(displayFramesRem - displayPeriod) <= MARGIN) { + displayFramesQuot++; + displayFramesRem = 0; + } + + float layerScore; + if (displayFramesRem == 0) { + // Layer desired refresh rate matches the display rate. + layerScore = layer.weight * 1.0f; + } else if (displayFramesQuot == 0) { + // Layer desired refresh rate is higher the display rate. + layerScore = layer.weight * layerPeriod / displayPeriod; + } else { + // Layer desired refresh rate is lower the display rate. Check how well it fits the + // cadence + auto diff = std::abs(displayFramesRem - (displayPeriod - displayFramesRem)); + int iter = 2; + static constexpr size_t MAX_ITERATOR = 10; // Stop calculating when score < 0.1 + while (diff > MARGIN && iter < MAX_ITERATOR) { + diff = diff - (displayPeriod - diff); + iter++; + } + + layerScore = layer.weight * 1.0f / iter; + } + + ALOGV("%s (weight %.2f) %.2fHz gives %s score of %.2f", layer.name.c_str(), + layer.weight, 1e9f / layerPeriod, refreshRate->name.c_str(), layerScore); + overallScore += layerScore; + } + } + + float max = 0; + const RefreshRate* bestRefreshRate = nullptr; + for (const auto [refreshRate, score] : scores) { + ALOGV("%s scores %.2f", refreshRate->name.c_str(), score); + + ATRACE_INT(refreshRate->name.c_str(), std::round(score * 100)); + + if (score > max) { + max = score; + bestRefreshRate = refreshRate; + } + } + + return bestRefreshRate == nullptr ? *mCurrentRefreshRate : *bestRefreshRate; +} + const AllRefreshRatesMapType& RefreshRateConfigs::getAllRefreshRates() const { return mRefreshRates; } @@ -180,14 +314,21 @@ void RefreshRateConfigs::getSortedRefreshRateList( void RefreshRateConfigs::constructAvailableRefreshRates() { // Filter configs based on current policy and sort based on vsync period HwcConfigGroupType group = mRefreshRates.at(mDefaultConfig).configGroup; - ALOGV("constructRefreshRateMap: default %d group %d min %.2f max %.2f", mDefaultConfig.value(), - group.value(), mMinRefreshRateFps, mMaxRefreshRateFps); + ALOGV("constructAvailableRefreshRates: default %d group %d min %.2f max %.2f", + mDefaultConfig.value(), group.value(), mMinRefreshRateFps, mMaxRefreshRateFps); getSortedRefreshRateList( [&](const RefreshRate& refreshRate) REQUIRES(mLock) { return refreshRate.configGroup == group && refreshRate.inPolicy(mMinRefreshRateFps, mMaxRefreshRateFps); }, &mAvailableRefreshRates); + + std::string availableRefreshRates; + for (const auto& refreshRate : mAvailableRefreshRates) { + base::StringAppendF(&availableRefreshRates, "%s ", refreshRate->name.c_str()); + } + + ALOGV("Available refresh rates: %s", availableRefreshRates.c_str()); LOG_ALWAYS_FATAL_IF(mAvailableRefreshRates.empty(), "No compatible display configs for default=%d min=%.0f max=%.0f", mDefaultConfig.value(), mMinRefreshRateFps, mMaxRefreshRateFps); diff --git a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h index 0c3369a22a..80d42cc620 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateConfigs.h +++ b/services/surfaceflinger/Scheduler/RefreshRateConfigs.h @@ -97,8 +97,39 @@ public: // Returns true if this device is doing refresh rate switching. This won't change at runtime. bool refreshRateSwitchingSupported() const { return mRefreshRateSwitching; } + // Describes the different options the layer voted for refresh rate + enum class LayerVoteType { + NoVote, // Doesn't care about the refresh rate + Min, // Minimal refresh rate available + Max, // Maximal refresh rate available + Heuristic, // Specific refresh rate that was calculated by platform using a heuristic + Explicit, // Specific refresh rate that was provided by the app + }; + + // Captures the layer requirements for a refresh rate. This will be used to determine the + // display refresh rate. + struct LayerRequirement { + std::string name; // Layer's name. Used for debugging purposes. + LayerVoteType vote; // Layer vote type. + float desiredRefreshRate; // Layer's desired refresh rate, if applicable. + float weight; // Layer's weight in the range of [0, 1]. The higher the weight the more + // impact this layer would have on choosing the refresh rate. + + bool operator==(const LayerRequirement& other) const { + return name == other.name && vote == other.vote && + desiredRefreshRate == other.desiredRefreshRate && weight == other.weight; + } + + bool operator!=(const LayerRequirement& other) const { return !(*this == other); } + }; + + // Returns all available refresh rates according to the current policy. + const RefreshRate& getRefreshRateForContent(const std::vector& layers) const + EXCLUDES(mLock); + // Returns all available refresh rates according to the current policy. - const RefreshRate& getRefreshRateForContent(float contentFramerate) const EXCLUDES(mLock); + const RefreshRate& getRefreshRateForContentV2(const std::vector& layers) const + EXCLUDES(mLock); // Returns all the refresh rates supported by the device. This won't change at runtime. const AllRefreshRatesMapType& getAllRefreshRates() const EXCLUDES(mLock); diff --git a/services/surfaceflinger/Scheduler/RefreshRateStats.h b/services/surfaceflinger/Scheduler/RefreshRateStats.h index a384dbe29b..e44cd528b5 100644 --- a/services/surfaceflinger/Scheduler/RefreshRateStats.h +++ b/services/surfaceflinger/Scheduler/RefreshRateStats.h @@ -114,7 +114,8 @@ private: mConfigModesTotalTime[mCurrentConfigMode] = 0; } mConfigModesTotalTime[mCurrentConfigMode] += timeElapsedMs; - fps = mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps; + fps = static_cast(std::round( + mRefreshRateConfigs.getRefreshRateFromConfigId(mCurrentConfigMode).fps)); } else { mScreenOffTime += timeElapsedMs; } diff --git a/services/surfaceflinger/Scheduler/Scheduler.cpp b/services/surfaceflinger/Scheduler/Scheduler.cpp index 0b645c41c1..6a437a25ed 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.cpp +++ b/services/surfaceflinger/Scheduler/Scheduler.cpp @@ -103,16 +103,21 @@ std::unique_ptr createDispSync() { Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, const scheduler::RefreshRateConfigs& refreshRateConfig, - ISchedulerCallback& schedulerCallback) + ISchedulerCallback& schedulerCallback, bool useContentDetectionV2) : mPrimaryDispSync(createDispSync()), mEventControlThread(new impl::EventControlThread(std::move(function))), mSupportKernelTimer(sysprop::support_kernel_idle_timer(false)), mSchedulerCallback(schedulerCallback), - mRefreshRateConfigs(refreshRateConfig) { + mRefreshRateConfigs(refreshRateConfig), + mUseContentDetectionV2(useContentDetectionV2) { using namespace sysprop; if (property_get_bool("debug.sf.use_smart_90_for_video", 0) || use_smart_90_for_video(false)) { - mLayerHistory = std::make_unique(); + if (mUseContentDetectionV2) { + mLayerHistory = std::make_unique(); + } else { + mLayerHistory = std::make_unique(); + } } const int setIdleTimerMs = property_get_int32("debug.sf.set_idle_timer_ms", 0); @@ -120,7 +125,6 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, if (const auto millis = setIdleTimerMs ? setIdleTimerMs : set_idle_timer_ms(0); millis > 0) { const auto callback = mSupportKernelTimer ? &Scheduler::kernelIdleTimerCallback : &Scheduler::idleTimerCallback; - mIdleTimer.emplace( std::chrono::milliseconds(millis), [this, callback] { std::invoke(callback, this, TimerState::Reset); }, @@ -149,12 +153,13 @@ Scheduler::Scheduler(impl::EventControlThread::SetVSyncEnabledFunction function, Scheduler::Scheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, const scheduler::RefreshRateConfigs& configs, - ISchedulerCallback& schedulerCallback) + ISchedulerCallback& schedulerCallback, bool useContentDetectionV2) : mPrimaryDispSync(std::move(primaryDispSync)), mEventControlThread(std::move(eventControlThread)), mSupportKernelTimer(false), mSchedulerCallback(schedulerCallback), - mRefreshRateConfigs(configs) {} + mRefreshRateConfigs(configs), + mUseContentDetectionV2(useContentDetectionV2) {} Scheduler::~Scheduler() { // Ensure the OneShotTimer threads are joined before we start destroying state. @@ -375,12 +380,42 @@ nsecs_t Scheduler::getDispSyncExpectedPresentTime() { void Scheduler::registerLayer(Layer* layer) { if (!mLayerHistory) return; - const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; - const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER - ? lowFps - : mRefreshRateConfigs.getMaxRefreshRate().fps; + if (!mUseContentDetectionV2) { + const auto lowFps = mRefreshRateConfigs.getMinRefreshRate().fps; + const auto highFps = layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER + ? lowFps + : mRefreshRateConfigs.getMaxRefreshRate().fps; - mLayerHistory->registerLayer(layer, lowFps, highFps); + mLayerHistory->registerLayer(layer, lowFps, highFps, + scheduler::LayerHistory::LayerVoteType::Heuristic); + } else { + if (layer->getWindowType() == InputWindowInfo::TYPE_WALLPAPER) { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::Min); + } else if (layer->getWindowType() == InputWindowInfo::TYPE_STATUS_BAR) { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::NoVote); + } else { + mLayerHistory->registerLayer(layer, mRefreshRateConfigs.getMinRefreshRate().fps, + mRefreshRateConfigs.getMaxRefreshRate().fps, + scheduler::LayerHistory::LayerVoteType::Heuristic); + } + + // TODO(146935143): Simulate youtube app vote. This should be removed once youtube calls the + // API to set desired rate + { + const auto vote = property_get_int32("experimental.sf.force_youtube_vote", 0); + if (vote != 0 && + layer->getName() == + "SurfaceView - " + "com.google.android.youtube/" + "com.google.android.apps.youtube.app.WatchWhileActivity#0") { + layer->setFrameRate(vote); + } + } + } } void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) { @@ -392,27 +427,27 @@ void Scheduler::recordLayerHistory(Layer* layer, nsecs_t presentTime) { void Scheduler::chooseRefreshRateForContent() { if (!mLayerHistory) return; - auto [refreshRate] = mLayerHistory->summarize(systemTime()); - const uint32_t refreshRateRound = std::round(refreshRate); + ATRACE_CALL(); + + scheduler::LayerHistory::Summary summary = mLayerHistory->summarize(systemTime()); HwcConfigIndexType newConfigId; { std::lock_guard lock(mFeatureStateLock); - if (mFeatures.contentRefreshRate == refreshRateRound) { + if (mFeatures.contentRequirements == summary) { return; } - mFeatures.contentRefreshRate = refreshRateRound; - ATRACE_INT("ContentFPS", refreshRateRound); - + mFeatures.contentRequirements = summary; mFeatures.contentDetection = - refreshRateRound > 0 ? ContentDetectionState::On : ContentDetectionState::Off; + !summary.empty() ? ContentDetectionState::On : ContentDetectionState::Off; + newConfigId = calculateRefreshRateType(); if (mFeatures.configId == newConfigId) { return; } mFeatures.configId = newConfigId; - }; - auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); - mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed); + auto newRefreshRate = mRefreshRateConfigs.getRefreshRateFromConfigId(newConfigId); + mSchedulerCallback.changeRefreshRate(newRefreshRate, ConfigEvent::Changed); + } } void Scheduler::resetIdleTimer() { @@ -422,16 +457,17 @@ void Scheduler::resetIdleTimer() { } void Scheduler::notifyTouchEvent() { + if (!mTouchTimer) return; + // Touch event will boost the refresh rate to performance. // Clear Layer History to get fresh FPS detection. // NOTE: Instead of checking all the layers, we should be checking the layer // that is currently on top. b/142507166 will give us this capability. - if (mLayerHistory && !mLayerHistory->hasClientSpecifiedFrameRate()) { + std::lock_guard lock(mFeatureStateLock); + if (mLayerHistory && !layerHistoryHasClientSpecifiedFrameRate()) { mLayerHistory->clear(); - if (mTouchTimer) { - mTouchTimer->reset(); - } + mTouchTimer->reset(); if (mSupportKernelTimer && mIdleTimer) { mIdleTimer->reset(); @@ -530,6 +566,16 @@ void Scheduler::handleTimerStateChanged(T* currentState, T newState, bool eventO mSchedulerCallback.changeRefreshRate(newRefreshRate, event); } +bool Scheduler::layerHistoryHasClientSpecifiedFrameRate() { + for (const auto& layer : mFeatures.contentRequirements) { + if (layer.vote == scheduler::RefreshRateConfigs::LayerVoteType::Explicit) { + return true; + } + } + + return false; +} + HwcConfigIndexType Scheduler::calculateRefreshRateType() { if (!mRefreshRateConfigs.refreshRateSwitchingSupported()) { return mRefreshRateConfigs.getCurrentRefreshRate().configId; @@ -538,7 +584,7 @@ HwcConfigIndexType Scheduler::calculateRefreshRateType() { // If the layer history doesn't have the frame rate specified, use the old path. NOTE: // if we remove the kernel idle timer, and use our internal idle timer, this code will have to // be refactored. - if (!mLayerHistory->hasClientSpecifiedFrameRate()) { + if (!layerHistoryHasClientSpecifiedFrameRate()) { // If Display Power is not in normal operation we want to be in performance mode. // When coming back to normal mode, a grace period is given with DisplayPowerTimer if (!mFeatures.isDisplayPowerStateNormal || @@ -555,17 +601,26 @@ HwcConfigIndexType Scheduler::calculateRefreshRateType() { if (mFeatures.idleTimer == TimerState::Expired) { return mRefreshRateConfigs.getMinRefreshRateByPolicy().configId; } + } + if (!mUseContentDetectionV2) { // If content detection is off we choose performance as we don't know the content fps if (mFeatures.contentDetection == ContentDetectionState::Off) { return mRefreshRateConfigs.getMaxRefreshRateByPolicy().configId; } + + // Content detection is on, find the appropriate refresh rate with minimal error + return mRefreshRateConfigs.getRefreshRateForContent(mFeatures.contentRequirements).configId; } // Content detection is on, find the appropriate refresh rate with minimal error - return mRefreshRateConfigs - .getRefreshRateForContent(static_cast(mFeatures.contentRefreshRate)) - .configId; + if (mFeatures.contentDetection == ContentDetectionState::On) { + return mRefreshRateConfigs.getRefreshRateForContentV2(mFeatures.contentRequirements) + .configId; + } + + // There are no signals for refresh rate, just leave it as is + return mRefreshRateConfigs.getCurrentRefreshRate().configId; } std::optional Scheduler::getPreferredConfigId() { @@ -606,6 +661,12 @@ void Scheduler::onDisplayRefreshed(nsecs_t timestamp) { } } +void Scheduler::onPrimaryDisplayAreaChanged(uint32_t displayArea) { + if (mLayerHistory) { + mLayerHistory->setDisplayArea(displayArea); + } +} + } // namespace android // TODO(b/129481165): remove the #pragma below and fix conversion issues diff --git a/services/surfaceflinger/Scheduler/Scheduler.h b/services/surfaceflinger/Scheduler/Scheduler.h index c6430c30f5..2987424c99 100644 --- a/services/surfaceflinger/Scheduler/Scheduler.h +++ b/services/surfaceflinger/Scheduler/Scheduler.h @@ -58,7 +58,8 @@ public: enum class TransactionStart { EARLY, NORMAL }; Scheduler(impl::EventControlThread::SetVSyncEnabledFunction, - const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback); + const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, + bool useContentDetectionV2); virtual ~Scheduler(); @@ -136,6 +137,9 @@ public: // Notifies the scheduler when the display was refreshed void onDisplayRefreshed(nsecs_t timestamp); + // Notifies the scheduler when the display size has changed. Called from SF's main thread + void onPrimaryDisplayAreaChanged(uint32_t displayArea); + private: friend class TestableScheduler; @@ -147,7 +151,8 @@ private: // Used by tests to inject mocks. Scheduler(std::unique_ptr, std::unique_ptr, - const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback); + const scheduler::RefreshRateConfigs&, ISchedulerCallback& schedulerCallback, + bool useContentDetectionV2); std::unique_ptr makePrimaryDispSyncSource(const char* name, nsecs_t phaseOffsetNs); @@ -170,6 +175,8 @@ private: HwcConfigIndexType calculateRefreshRateType() REQUIRES(mFeatureStateLock); + bool layerHistoryHasClientSpecifiedFrameRate() REQUIRES(mFeatureStateLock); + // Stores EventThread associated with a given VSyncSource, and an initial EventThreadConnection. struct Connection { sp connection; @@ -218,7 +225,7 @@ private: TimerState displayPowerTimer = TimerState::Expired; std::optional configId; - uint32_t contentRefreshRate = 0; + scheduler::LayerHistory::Summary contentRequirements; bool isDisplayPowerStateNormal = true; } mFeatures GUARDED_BY(mFeatureStateLock); @@ -229,6 +236,8 @@ private: std::optional mLastVsyncPeriodChangeTimeline GUARDED_BY(mVsyncTimelineLock); static constexpr std::chrono::nanoseconds MAX_VSYNC_APPLIED_TIME = 200ms; + + const bool mUseContentDetectionV2; }; } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 6d18922a78..adf5f9f4a4 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -540,6 +540,11 @@ void SurfaceFlinger::bootFinished() const auto& performanceRefreshRate = mRefreshRateConfigs->getMaxRefreshRateByPolicy(); changeRefreshRateLocked(performanceRefreshRate, Scheduler::ConfigEvent::None); } + + if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { + mRefreshRateOverlay = std::make_unique(*this); + mRefreshRateOverlay->changeRefreshRate(mRefreshRateConfigs->getCurrentRefreshRate()); + } })); } @@ -1779,7 +1784,13 @@ void SurfaceFlinger::onMessageReceived(int32_t what) NO_THREAD_SAFETY_ANALYSIS { // Layers need to get updated (in the previous line) before we can use them for // choosing the refresh rate. - mScheduler->chooseRefreshRateForContent(); + // Hold mStateLock as chooseRefreshRateForContent promotes wp to sp + // and may eventually call to ~Layer() if it holds the last reference + { + Mutex::Autolock _l(mStateLock); + mScheduler->chooseRefreshRateForContent(); + } + if (performSetActiveConfig()) { break; } @@ -2378,6 +2389,9 @@ void SurfaceFlinger::processDisplayChangesLocked() { } if (state.width != draw[i].width || state.height != draw[i].height) { display->setDisplaySize(state.width, state.height); + if (display->isPrimary()) { + mScheduler->onPrimaryDisplayAreaChanged(state.width * state.height); + } } } } @@ -2450,6 +2464,12 @@ void SurfaceFlinger::processDisplayChangesLocked() { LOG_ALWAYS_FATAL_IF(!displayId); dispatchDisplayHotplugEvent(displayId->value, true); } + + const auto displayDevice = mDisplays[displayToken]; + if (displayDevice->isPrimary()) { + mScheduler->onPrimaryDisplayAreaChanged(displayDevice->getWidth() * + displayDevice->getHeight()); + } } } } @@ -2647,8 +2667,12 @@ void SurfaceFlinger::updateCursorAsync() } void SurfaceFlinger::changeRefreshRate(const RefreshRate& refreshRate, - Scheduler::ConfigEvent event) { - Mutex::Autolock lock(mStateLock); + Scheduler::ConfigEvent event) NO_THREAD_SAFETY_ANALYSIS { + // If this is called from the main thread mStateLock must be locked before + // Currently the only way to call this function from the main thread is from + // Sheduler::chooseRefreshRateForContent + + ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); changeRefreshRateLocked(refreshRate, event); } diff --git a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp index e12d31a99a..45889a564e 100644 --- a/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp +++ b/services/surfaceflinger/SurfaceFlingerDefaultFactory.cpp @@ -75,7 +75,9 @@ std::unique_ptr DefaultFactory::createPhaseConfig std::unique_ptr DefaultFactory::createScheduler( SetVSyncEnabled setVSyncEnabled, const scheduler::RefreshRateConfigs& configs, ISchedulerCallback& schedulerCallback) { - return std::make_unique(std::move(setVSyncEnabled), configs, schedulerCallback); + return std::make_unique(std::move(setVSyncEnabled), configs, schedulerCallback, + property_get_bool("debug.sf.use_content_detection_v2", + false)); } std::unique_ptr DefaultFactory::createSurfaceInterceptor( diff --git a/services/surfaceflinger/tests/unittests/Android.bp b/services/surfaceflinger/tests/unittests/Android.bp index 1eaf2dd004..d046f765e8 100644 --- a/services/surfaceflinger/tests/unittests/Android.bp +++ b/services/surfaceflinger/tests/unittests/Android.bp @@ -44,6 +44,7 @@ cc_test { "EventThreadTest.cpp", "OneShotTimerTest.cpp", "LayerHistoryTest.cpp", + "LayerHistoryTestV2.cpp", "LayerMetadataTest.cpp", "PhaseOffsetsTest.cpp", "SchedulerTest.cpp", diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp index ca51cb6f6d..9ca1b70a1f 100644 --- a/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTest.cpp @@ -73,7 +73,7 @@ protected: HI_FPS_PERIOD}, }, HwcConfigIndexType(0)}; - TestableScheduler* const mScheduler{new TestableScheduler(mConfigs)}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, false)}; TestableSurfaceFlinger mFlinger; const nsecs_t mTime = systemTime(); @@ -85,53 +85,36 @@ TEST_F(LayerHistoryTest, oneLayer) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); - // 0 FPS is returned if no layers are active. - EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + // no layers are returned if no layers are active. + ASSERT_TRUE(history().summarize(mTime).empty()); EXPECT_EQ(0, activeLayerCount()); - // 0 FPS is returned if active layers have insufficient history. + // no layers are returned if active layers have insufficient history. for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { history().record(layer.get(), 0, mTime); - EXPECT_FLOAT_EQ(0, history().summarize(mTime).maxRefreshRate); + ASSERT_TRUE(history().summarize(mTime).empty()); EXPECT_EQ(1, activeLayerCount()); } // High FPS is returned once enough history has been recorded. for (int i = 0; i < 10; i++) { history().record(layer.get(), 0, mTime); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime).maxRefreshRate); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(mTime)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); } } -TEST_F(LayerHistoryTest, oneHDRLayer) { - const auto layer = createLayer(); - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); - EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - - EXPECT_EQ(1, layerCount()); - EXPECT_EQ(0, activeLayerCount()); - - history().record(layer.get(), 0, mTime); - auto summary = history().summarize(mTime); - EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_EQ(1, activeLayerCount()); - - EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); - - summary = history().summarize(mTime); - EXPECT_FLOAT_EQ(0, summary.maxRefreshRate); - EXPECT_EQ(0, activeLayerCount()); -} - TEST_F(LayerHistoryTest, explicitTimestamp) { const auto layer = createLayer(); EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); @@ -142,7 +125,8 @@ TEST_F(LayerHistoryTest, explicitTimestamp) { time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime).maxRefreshRate); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(mTime)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); } @@ -154,13 +138,15 @@ TEST_F(LayerHistoryTest, multipleLayers) { EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer1, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer2, getFrameSelectionPriority()).WillRepeatedly(Return(1)); + EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(std::nullopt)); EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); EXPECT_CALL(*layer3, getFrameSelectionPriority()).WillRepeatedly(Return(1)); - + EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(std::nullopt)); nsecs_t time = mTime; EXPECT_EQ(3, layerCount()); @@ -173,7 +159,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); @@ -186,7 +173,9 @@ TEST_F(LayerHistoryTest, multipleLayers) { // layer1 is still active but infrequent. history().record(layer1.get(), time, time); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -197,7 +186,8 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); @@ -213,19 +203,24 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); // layer3 becomes recently active. history().record(layer3.get(), time, time); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); // layer1 expires. layer1.clear(); - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); EXPECT_EQ(2, layerCount()); EXPECT_EQ(2, activeLayerCount()); EXPECT_EQ(2, frequentLayerCount(time)); @@ -237,13 +232,14 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += LO_FPS_PERIOD; } - EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); // layer2 expires. layer2.clear(); - EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + ASSERT_TRUE(history().summarize(time).empty()); EXPECT_EQ(1, layerCount()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); @@ -254,14 +250,15 @@ TEST_F(LayerHistoryTest, multipleLayers) { time += HI_FPS_PERIOD; } - EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time).maxRefreshRate); + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[0].desiredRefreshRate); EXPECT_EQ(1, layerCount()); EXPECT_EQ(1, activeLayerCount()); EXPECT_EQ(1, frequentLayerCount(time)); // layer3 expires. layer3.clear(); - EXPECT_FLOAT_EQ(0, history().summarize(time).maxRefreshRate); + ASSERT_TRUE(history().summarize(time).empty()); EXPECT_EQ(0, layerCount()); EXPECT_EQ(0, activeLayerCount()); EXPECT_EQ(0, frequentLayerCount(time)); diff --git a/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp new file mode 100644 index 0000000000..11ace0576d --- /dev/null +++ b/services/surfaceflinger/tests/unittests/LayerHistoryTestV2.cpp @@ -0,0 +1,418 @@ +/* + * Copyright 2020 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. + */ + +#undef LOG_TAG +#define LOG_TAG "LayerHistoryTestV2" + +#include +#include +#include + +#include "Scheduler/LayerHistory.h" +#include "Scheduler/LayerInfoV2.h" +#include "TestableScheduler.h" +#include "TestableSurfaceFlinger.h" +#include "mock/MockLayer.h" + +using testing::_; +using testing::Return; + +namespace android::scheduler { + +class LayerHistoryTestV2 : public testing::Test { +protected: + static constexpr auto PRESENT_TIME_HISTORY_SIZE = LayerInfoV2::HISTORY_SIZE; + static constexpr auto MAX_FREQUENT_LAYER_PERIOD_NS = LayerInfoV2::MAX_FREQUENT_LAYER_PERIOD_NS; + + static constexpr float LO_FPS = 30.f; + static constexpr auto LO_FPS_PERIOD = static_cast(1e9f / LO_FPS); + + static constexpr float HI_FPS = 90.f; + static constexpr auto HI_FPS_PERIOD = static_cast(1e9f / HI_FPS); + + LayerHistoryTestV2() { mFlinger.resetScheduler(mScheduler); } + + impl::LayerHistoryV2& history() { return *mScheduler->mutableLayerHistoryV2(); } + const impl::LayerHistoryV2& history() const { return *mScheduler->mutableLayerHistoryV2(); } + + size_t layerCount() const { return mScheduler->layerHistorySize(); } + size_t activeLayerCount() const NO_THREAD_SAFETY_ANALYSIS { return history().mActiveLayersEnd; } + + auto frequentLayerCount(nsecs_t now) const NO_THREAD_SAFETY_ANALYSIS { + const auto& infos = history().mLayerInfos; + return std::count_if(infos.begin(), + infos.begin() + static_cast(history().mActiveLayersEnd), + [now](const auto& pair) { return pair.second->isFrequent(now); }); + } + + void setLayerInfoVote(Layer* layer, + LayerHistory::LayerVoteType vote) NO_THREAD_SAFETY_ANALYSIS { + for (auto& [weak, info] : history().mLayerInfos) { + if (auto strong = weak.promote(); strong && strong.get() == layer) { + info->setDefaultLayerVote(vote); + info->setLayerVote(vote, 0); + return; + } + } + } + + auto createLayer() { return sp(new mock::MockLayer(mFlinger.flinger())); } + + RefreshRateConfigs mConfigs{true, + { + RefreshRateConfigs::InputConfig{HwcConfigIndexType(0), + HwcConfigGroupType(0), + LO_FPS_PERIOD}, + RefreshRateConfigs::InputConfig{HwcConfigIndexType(1), + HwcConfigGroupType(0), + HI_FPS_PERIOD}, + }, + HwcConfigIndexType(0)}; + TestableScheduler* const mScheduler{new TestableScheduler(mConfigs, true)}; + TestableSurfaceFlinger mFlinger; + + const nsecs_t mTime = systemTime(); +}; + +namespace { + +TEST_F(LayerHistoryTestV2, oneLayer) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + // No layers returned if no layers are active. + EXPECT_TRUE(history().summarize(mTime).empty()); + EXPECT_EQ(0, activeLayerCount()); + + // Max returned if active layers have insufficient history. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + history().record(layer.get(), 0, mTime); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + } + + // Max is returned since we have enough history but there is no timestamp votes. + for (int i = 0; i < 10; i++) { + history().record(layer.get(), 0, mTime); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + } +} + +TEST_F(LayerHistoryTestV2, oneInvisibleLayer) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + history().record(layer.get(), 0, mTime); + auto summary = history().summarize(mTime); + ASSERT_EQ(1, history().summarize(mTime).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(mTime)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(false)); + + summary = history().summarize(mTime); + EXPECT_TRUE(history().summarize(mTime).empty()); + EXPECT_EQ(0, activeLayerCount()); +} + +TEST_F(LayerHistoryTestV2, explicitTimestamp) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerNoVote) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::NoVote); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerMinVote) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Min); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerMaxVote) { + const auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Max); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, oneLayerExplicitVote) { + auto layer = createLayer(); + EXPECT_CALL(*layer, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer, getFrameRate()).WillRepeatedly(Return(73.4f)); + + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + + nsecs_t time = mTime; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Explicit, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(73.4f, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer became inactive + setLayerInfoVote(layer.get(), LayerHistory::LayerVoteType::Heuristic); + time += MAX_ACTIVE_LAYER_PERIOD_NS.count(); + ASSERT_TRUE(history().summarize(time).empty()); + // TODO: activeLayerCount() should be 0 but it is 1 since getFrameRate() returns a value > 0 + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +TEST_F(LayerHistoryTestV2, multipleLayers) { + auto layer1 = createLayer(); + auto layer2 = createLayer(); + auto layer3 = createLayer(); + + EXPECT_CALL(*layer1, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer1, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_CALL(*layer2, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer2, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + EXPECT_CALL(*layer3, isVisible()).WillRepeatedly(Return(true)); + EXPECT_CALL(*layer3, getFrameRate()).WillRepeatedly(Return(std::nullopt)); + + nsecs_t time = mTime; + + EXPECT_EQ(3, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer1 is active but infrequent. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer1.get(), time, time); + time += MAX_FREQUENT_LAYER_PERIOD_NS.count(); + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer2 is frequent and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, time); + time += HI_FPS_PERIOD; + } + + // layer1 is still active but infrequent. + history().record(layer1.get(), time, time); + + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Min, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer1 is no longer active. + // layer2 is frequent and has low refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 has high refresh rate but not enough history. + constexpr int RATIO = LO_FPS_PERIOD / HI_FPS_PERIOD; + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE - 1; i++) { + if (i % RATIO == 0) { + history().record(layer2.get(), time, time); + } + + history().record(layer3.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Max, history().summarize(time)[1].vote); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer3 becomes recently active. + history().record(layer3.get(), time, time); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer1 expires. + layer1.clear(); + ASSERT_EQ(2, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[1].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[1].desiredRefreshRate); + EXPECT_EQ(2, layerCount()); + EXPECT_EQ(2, activeLayerCount()); + EXPECT_EQ(2, frequentLayerCount(time)); + + // layer2 still has low refresh rate. + // layer3 becomes inactive. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer2.get(), time, time); + time += LO_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(LO_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer2 expires. + layer2.clear(); + EXPECT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); + + // layer3 becomes active and has high refresh rate. + for (int i = 0; i < PRESENT_TIME_HISTORY_SIZE; i++) { + history().record(layer3.get(), time, time); + time += HI_FPS_PERIOD; + } + + ASSERT_EQ(1, history().summarize(time).size()); + EXPECT_EQ(LayerHistory::LayerVoteType::Heuristic, history().summarize(time)[0].vote); + EXPECT_FLOAT_EQ(HI_FPS, history().summarize(time)[0].desiredRefreshRate); + EXPECT_EQ(1, layerCount()); + EXPECT_EQ(1, activeLayerCount()); + EXPECT_EQ(1, frequentLayerCount(time)); + + // layer3 expires. + layer3.clear(); + EXPECT_TRUE(history().summarize(time).empty()); + EXPECT_EQ(0, layerCount()); + EXPECT_EQ(0, activeLayerCount()); + EXPECT_EQ(0, frequentLayerCount(time)); +} + +} // namespace +} // namespace android::scheduler diff --git a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp index 86aa8fb22b..78009b8122 100644 --- a/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp +++ b/services/surfaceflinger/tests/unittests/RefreshRateConfigsTest.cpp @@ -31,16 +31,24 @@ namespace android { namespace scheduler { using RefreshRate = RefreshRateConfigs::RefreshRate; +using LayerVoteType = RefreshRateConfigs::LayerVoteType; +using LayerRequirement = RefreshRateConfigs::LayerRequirement; class RefreshRateConfigsTest : public testing::Test { protected: static inline const HwcConfigIndexType HWC_CONFIG_ID_60 = HwcConfigIndexType(0); - static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(1); + static inline const HwcConfigIndexType HWC_CONFIG_ID_72 = HwcConfigIndexType(1); + static inline const HwcConfigIndexType HWC_CONFIG_ID_90 = HwcConfigIndexType(2); + static inline const HwcConfigIndexType HWC_CONFIG_ID_120 = HwcConfigIndexType(3); + static inline const HwcConfigIndexType HWC_CONFIG_ID_30 = HwcConfigIndexType(4); static inline const HwcConfigGroupType HWC_GROUP_ID_0 = HwcConfigGroupType(0); static inline const HwcConfigGroupType HWC_GROUP_ID_1 = HwcConfigGroupType(1); - static constexpr int64_t VSYNC_60 = 16666667; + static constexpr auto VSYNC_30 = static_cast(1e9f / 30); + static constexpr auto VSYNC_60 = static_cast(1e9f / 60); + static constexpr auto VSYNC_72 = static_cast(1e9f / 72); + static constexpr auto VSYNC_90 = static_cast(1e9f / 90); + static constexpr auto VSYNC_120 = static_cast(1e9f / 120); static constexpr int64_t VSYNC_60_POINT_4 = 16666665; - static constexpr int64_t VSYNC_90 = 11111111; RefreshRateConfigsTest(); ~RefreshRateConfigsTest(); @@ -212,31 +220,476 @@ TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent) { RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + const auto makeLayerRequirements = [](float refreshRate) -> std::vector { + return {{"testLayer", LayerVoteType::Heuristic, refreshRate, 1.0f}}; + }; + + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(90.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(60.0f)); - ASSERT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(45.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(30.0f)); - ASSERT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(24.0f)); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(90.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(60.0f))); + EXPECT_EQ(expected90Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(45.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(30.0f))); + EXPECT_EQ(expected60Config, + refreshRateConfigs->getRefreshRateForContent(makeLayerRequirements(24.0f))); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_60_90) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 60, 60, nullptr), 0); + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_90, 90, 90, nullptr), 0); + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + ASSERT_GE(refreshRateConfigs->setPolicy(HWC_CONFIG_ID_60, 0, 120, nullptr), 0); + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_60_72_90) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60_72_90_120) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}, + {HWC_CONFIG_ID_120, HWC_GROUP_ID_0, VSYNC_120}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + RefreshRate expected120Config = {HWC_CONFIG_ID_120, VSYNC_120, HWC_GROUP_ID_0, "120fps", 120}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected120Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 48.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.desiredRefreshRate = 24.0f; + lr1.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 48.0f; + lr2.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_30_60_72_90) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_72, HWC_GROUP_ID_0, VSYNC_72}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected72Config = {HWC_CONFIG_ID_72, VSYNC_72, HWC_GROUP_ID_0, "72fps", 70}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Min; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 90.0f; + lr.vote = LayerVoteType::Heuristic; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 30.0f; + EXPECT_EQ(expected30Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected72Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_PriorityTest) { + std::vector configs{ + {{HWC_CONFIG_ID_30, HWC_GROUP_ID_0, VSYNC_30}, + {HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::Min; + lr2.vote = LayerVoteType::Max; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Min; + lr2.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Min; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 24.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Max; + lr2.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Max; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 15.0f; + lr2.vote = LayerVoteType::Heuristic; + lr2.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 30.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 45.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_24FpsVideo) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected30Config = {HWC_CONFIG_ID_30, VSYNC_30, HWC_GROUP_ID_0, "30fps", 30}; + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}}; + auto& lr = layers[0]; + + lr.vote = LayerVoteType::Explicit; + for (float fps = 23.0f; fps < 25.0f; fps += 0.1f) { + lr.desiredRefreshRate = fps; + const auto& refreshRate = refreshRateConfigs->getRefreshRateForContentV2(layers); + printf("%.2fHz chooses %s\n", fps, refreshRate.name.c_str()); + EXPECT_EQ(expected60Config, refreshRate); + } +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContent_Explicit) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 90.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContent(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContent(layers)); +} + +TEST_F(RefreshRateConfigsTest, twoDeviceConfigs_getRefreshRateForContentV2_Explicit) { + std::vector configs{ + {{HWC_CONFIG_ID_60, HWC_GROUP_ID_0, VSYNC_60}, + {HWC_CONFIG_ID_90, HWC_GROUP_ID_0, VSYNC_90}}}; + auto refreshRateConfigs = + std::make_unique(/*refreshRateSwitching=*/true, configs, + /*currentConfigId=*/HWC_CONFIG_ID_60); + + ASSERT_TRUE(refreshRateConfigs->refreshRateSwitchingSupported()); + + RefreshRate expected60Config = {HWC_CONFIG_ID_60, VSYNC_60, HWC_GROUP_ID_0, "60fps", 60}; + RefreshRate expected90Config = {HWC_CONFIG_ID_90, VSYNC_90, HWC_GROUP_ID_0, "90fps", 90}; + + auto layers = std::vector{LayerRequirement{.weight = 1.0f}, + LayerRequirement{.weight = 1.0f}}; + auto& lr1 = layers[0]; + auto& lr2 = layers[1]; + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 60.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 90.0f; + EXPECT_EQ(expected90Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); + + lr1.vote = LayerVoteType::Heuristic; + lr1.desiredRefreshRate = 90.0f; + lr2.vote = LayerVoteType::Explicit; + lr2.desiredRefreshRate = 60.0f; + EXPECT_EQ(expected60Config, refreshRateConfigs->getRefreshRateForContentV2(layers)); } TEST_F(RefreshRateConfigsTest, testInPolicy) { diff --git a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp index b1ecf4da6e..82a00ee734 100644 --- a/services/surfaceflinger/tests/unittests/SchedulerTest.cpp +++ b/services/surfaceflinger/tests/unittests/SchedulerTest.cpp @@ -76,7 +76,7 @@ SchedulerTest::SchedulerTest() { scheduler::RefreshRateConfigs>(/*refreshRateSwitching=*/false, configs, /*currentConfig=*/HwcConfigIndexType(0)); - mScheduler = std::make_unique(*mRefreshRateConfigs); + mScheduler = std::make_unique(*mRefreshRateConfigs, false); auto eventThread = std::make_unique(); mEventThread = eventThread.get(); diff --git a/services/surfaceflinger/tests/unittests/TestableScheduler.h b/services/surfaceflinger/tests/unittests/TestableScheduler.h index a67c24c2d6..52da34b69a 100644 --- a/services/surfaceflinger/tests/unittests/TestableScheduler.h +++ b/services/surfaceflinger/tests/unittests/TestableScheduler.h @@ -28,16 +28,25 @@ namespace android { class TestableScheduler : public Scheduler, private ISchedulerCallback { public: - explicit TestableScheduler(const scheduler::RefreshRateConfigs& configs) - : Scheduler([](bool) {}, configs, *this) { - mLayerHistory = std::make_unique(); + TestableScheduler(const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) + : Scheduler([](bool) {}, configs, *this, useContentDetectionV2) { + if (mUseContentDetectionV2) { + mLayerHistory = std::make_unique(); + } else { + mLayerHistory = std::make_unique(); + } } TestableScheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, - const scheduler::RefreshRateConfigs& configs) - : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this) { - mLayerHistory = std::make_unique(); + const scheduler::RefreshRateConfigs& configs, bool useContentDetectionV2) + : Scheduler(std::move(primaryDispSync), std::move(eventControlThread), configs, *this, + useContentDetectionV2) { + if (mUseContentDetectionV2) { + mLayerHistory = std::make_unique(); + } else { + mLayerHistory = std::make_unique(); + } } // Used to inject mock event thread. @@ -46,7 +55,13 @@ public: } size_t layerHistorySize() const NO_THREAD_SAFETY_ANALYSIS { - return static_cast(mLayerHistory.get())->mLayerInfos.size(); + if (mUseContentDetectionV2) { + return static_cast(mLayerHistory.get()) + ->mLayerInfos.size(); + } else { + return static_cast(mLayerHistory.get()) + ->mLayerInfos.size(); + } } /* ------------------------------------------------------------------------ @@ -60,6 +75,9 @@ public: auto mutableLayerHistory() { return static_cast(mLayerHistory.get()); } + auto mutableLayerHistoryV2() { + return static_cast(mLayerHistory.get()); + } ~TestableScheduler() { // All these pointer and container clears help ensure that GMock does diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h index 8ddb872582..2491533ea4 100644 --- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h +++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h @@ -198,7 +198,8 @@ public: void setupScheduler(std::unique_ptr primaryDispSync, std::unique_ptr eventControlThread, std::unique_ptr appEventThread, - std::unique_ptr sfEventThread) { + std::unique_ptr sfEventThread, + bool useContentDetectionV2 = false) { std::vector configs{ {{HwcConfigIndexType(0), HwcConfigGroupType(0), 16666667}}}; mFlinger->mRefreshRateConfigs = std::make_unique< @@ -213,7 +214,7 @@ public: mScheduler = new TestableScheduler(std::move(primaryDispSync), std::move(eventControlThread), - *mFlinger->mRefreshRateConfigs); + *mFlinger->mRefreshRateConfigs, useContentDetectionV2); mFlinger->mAppConnectionHandle = mScheduler->createConnection(std::move(appEventThread)); mFlinger->mSfConnectionHandle = mScheduler->createConnection(std::move(sfEventThread)); @@ -443,7 +444,7 @@ public: static constexpr int32_t DEFAULT_REFRESH_RATE = 16'666'666; static constexpr int32_t DEFAULT_CONFIG_GROUP = 7; static constexpr int32_t DEFAULT_DPI = 320; - static constexpr int32_t DEFAULT_ACTIVE_CONFIG = 0; + static constexpr hwc2_config_t DEFAULT_ACTIVE_CONFIG = 0; static constexpr int32_t DEFAULT_POWER_MODE = 2; FakeHwcDisplayInjector(DisplayId displayId, HWC2::DisplayType hwcDisplayType, @@ -465,7 +466,7 @@ public: return *this; } - auto& setRefreshRate(uint32_t refreshRate) { + auto& setRefreshRate(int32_t refreshRate) { mRefreshRate = refreshRate; return *this; } @@ -480,7 +481,7 @@ public: return *this; } - auto& setActiveConfig(int32_t config) { + auto& setActiveConfig(hwc2_config_t config) { mActiveConfig = config; return *this; } @@ -513,7 +514,7 @@ public: config.setDpiX(mDpiX); config.setDpiY(mDpiY); config.setConfigGroup(mConfigGroup); - display->mutableConfigs().emplace(mActiveConfig, config.build()); + display->mutableConfigs().emplace(static_cast(mActiveConfig), config.build()); display->mutableIsConnected() = true; display->setPowerMode(static_cast(mPowerMode)); @@ -534,11 +535,11 @@ public: hwc2_display_t mHwcDisplayId = DEFAULT_HWC_DISPLAY_ID; int32_t mWidth = DEFAULT_WIDTH; int32_t mHeight = DEFAULT_HEIGHT; - uint32_t mRefreshRate = DEFAULT_REFRESH_RATE; + int32_t mRefreshRate = DEFAULT_REFRESH_RATE; int32_t mDpiX = DEFAULT_DPI; int32_t mConfigGroup = DEFAULT_CONFIG_GROUP; int32_t mDpiY = DEFAULT_DPI; - int32_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; + hwc2_config_t mActiveConfig = DEFAULT_ACTIVE_CONFIG; int32_t mPowerMode = DEFAULT_POWER_MODE; const std::unordered_set* mCapabilities = nullptr; }; diff --git a/services/surfaceflinger/tests/unittests/mock/MockLayer.h b/services/surfaceflinger/tests/unittests/mock/MockLayer.h index 1fd0e617c2..494e73dda9 100644 --- a/services/surfaceflinger/tests/unittests/mock/MockLayer.h +++ b/services/surfaceflinger/tests/unittests/mock/MockLayer.h @@ -31,6 +31,7 @@ public: MOCK_METHOD0(getFrameSelectionPriority, int32_t()); MOCK_CONST_METHOD0(isVisible, bool()); MOCK_METHOD0(createClone, sp()); + MOCK_CONST_METHOD0(getFrameRate, std::optional()); }; } // namespace android::mock -- cgit v1.2.3-59-g8ed1b From de19665154a7dbb66a4932f43f6499d67bede4b8 Mon Sep 17 00:00:00 2001 From: Lloyd Pique Date: Wed, 22 Jan 2020 17:29:58 -0800 Subject: CE: Remove compositionengine::Layer This was a mostly straightforward refactor that restructures the interface between SurfaceFlinger and CompositionEngine. 1) Instead of each SurfaceFlinger Layer creating and owning a compositionengine::Layer, each Layer instead creates and owns a compositionengine::LayerFECompositionState structure. Containing this state structure was the only real purpose for compositionengine::Layer. 2) Use the compositionengine::LayerFE interface in CompositionEngine in place of compositionengine::Layer. This includes passing a std::vector for the layers when SurfaceFlinger calls into CompositionEngine. 3) Alters the LayerFE interface to add the ability to get the state, as well as changing the existing "latchCompositionState" calls taking a state reference as the first argument into "prepareCompositionState" calls that do not need it, as the target of the call owns the state. 4) Alters the SurfaceFlinger Layer implementations to match the LayerFE interface changes. Test: atest libcompositionengine_test libsurfaceflinger_unittest Test: atest CtsColorModeTestCases Test: atest CtsDisplayTestCases Test: atest CtsGraphicsTestCases Test: atest CtsUiRenderingTestCases Test: atest CtsViewTestCases Test: atest android.media.cts.EncodeVirtualDisplayWithCompositionTest Test: go/wm-smoke Bug: 144117494 Change-Id: Id45df7c9cc389c8fd834ba379bc0d6360a984dac --- services/surfaceflinger/BufferLayer.cpp | 37 +- services/surfaceflinger/BufferLayer.h | 8 +- services/surfaceflinger/BufferQueueLayer.cpp | 26 +- services/surfaceflinger/BufferQueueLayer.h | 2 +- services/surfaceflinger/BufferStateLayer.cpp | 22 +- services/surfaceflinger/BufferStateLayer.h | 2 +- services/surfaceflinger/ColorLayer.cpp | 27 +- services/surfaceflinger/ColorLayer.h | 8 +- .../surfaceflinger/CompositionEngine/Android.bp | 3 - .../include/compositionengine/CompositionEngine.h | 5 +- .../compositionengine/CompositionRefreshArgs.h | 7 +- .../include/compositionengine/Layer.h | 55 -- .../include/compositionengine/LayerCreationArgs.h | 35 - .../include/compositionengine/LayerFE.h | 16 +- .../compositionengine/LayerFECompositionState.h | 4 +- .../include/compositionengine/Output.h | 10 +- .../include/compositionengine/OutputLayer.h | 4 - .../compositionengine/impl/CompositionEngine.h | 4 +- .../include/compositionengine/impl/Display.h | 3 +- .../include/compositionengine/impl/Layer.h | 84 --- .../include/compositionengine/impl/Output.h | 30 +- .../include/compositionengine/impl/OutputLayer.h | 12 +- .../compositionengine/mock/CompositionEngine.h | 5 +- .../include/compositionengine/mock/Layer.h | 39 -- .../include/compositionengine/mock/LayerFE.h | 6 +- .../include/compositionengine/mock/Output.h | 13 +- .../include/compositionengine/mock/OutputLayer.h | 2 - .../CompositionEngine/mock/Layer.cpp | 26 - .../CompositionEngine/src/CompositionEngine.cpp | 14 +- .../CompositionEngine/src/Display.cpp | 17 +- .../surfaceflinger/CompositionEngine/src/Layer.cpp | 43 -- .../src/LayerFECompositionState.cpp | 2 + .../CompositionEngine/src/Output.cpp | 98 ++- .../CompositionEngine/src/OutputLayer.cpp | 56 +- .../tests/CompositionEngineTest.cpp | 88 +-- .../CompositionEngine/tests/DisplayTest.cpp | 145 ++-- .../CompositionEngine/tests/LayerTest.cpp | 61 -- .../CompositionEngine/tests/OutputLayerTest.cpp | 41 +- .../CompositionEngine/tests/OutputTest.cpp | 775 +++++++++++---------- services/surfaceflinger/Layer.cpp | 138 ++-- services/surfaceflinger/Layer.h | 19 +- services/surfaceflinger/SurfaceFlinger.cpp | 18 +- .../tests/unittests/CompositionTest.cpp | 4 +- .../tests/unittests/TestableSurfaceFlinger.h | 3 +- 44 files changed, 828 insertions(+), 1189 deletions(-) delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h delete mode 100644 services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h delete mode 100644 services/surfaceflinger/CompositionEngine/mock/Layer.cpp delete mode 100644 services/surfaceflinger/CompositionEngine/src/Layer.cpp delete mode 100644 services/surfaceflinger/CompositionEngine/tests/LayerTest.cpp (limited to 'services/surfaceflinger/BufferQueueLayer.cpp') diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp index 35d0215fa1..f4f45be49f 100644 --- a/services/surfaceflinger/BufferLayer.cpp +++ b/services/surfaceflinger/BufferLayer.cpp @@ -26,8 +26,6 @@ #include "BufferLayer.h" #include -#include -#include #include #include #include @@ -66,8 +64,7 @@ static constexpr float defaultMaxContentLuminance = 1000.0; BufferLayer::BufferLayer(const LayerCreationArgs& args) : Layer(args), mTextureName(args.textureName), - mCompositionLayer{mFlinger->getCompositionEngine().createLayer( - compositionengine::LayerCreationArgs{this})} { + mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()} { ALOGV("Creating Layer %s", getDebugName()); mPremultipliedAlpha = !(args.flags & ISurfaceComposerClient::eNonPremultiplied); @@ -184,7 +181,7 @@ std::optional BufferLayer::prepareCli bool blackOutLayer = (isProtected() && !targetSettings.supportsProtectedContent) || (isSecure() && !targetSettings.isSecure); const State& s(getDrawingState()); - LayerFE::LayerSettings& layer = *result; + compositionengine::LayerFE::LayerSettings& layer = *result; if (!blackOutLayer) { layer.source.buffer.buffer = mBufferInfo.mBuffer; layer.source.buffer.isOpaque = isOpaque(s); @@ -282,17 +279,29 @@ bool BufferLayer::isHdrY410() const { mBufferInfo.mBuffer->getPixelFormat() == HAL_PIXEL_FORMAT_RGBA_1010102); } -void BufferLayer::latchPerFrameState( - compositionengine::LayerFECompositionState& compositionState) const { - Layer::latchPerFrameState(compositionState); +sp BufferLayer::getCompositionEngineLayerFE() const { + return asLayerFE(); +} + +compositionengine::LayerFECompositionState* BufferLayer::editCompositionState() { + return mCompositionState.get(); +} + +const compositionengine::LayerFECompositionState* BufferLayer::getCompositionState() const { + return mCompositionState.get(); +} + +void BufferLayer::preparePerFrameCompositionState() { + Layer::preparePerFrameCompositionState(); // Sideband layers - if (compositionState.sidebandStream.get()) { - compositionState.compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; + auto* compositionState = editCompositionState(); + if (compositionState->sidebandStream.get()) { + compositionState->compositionType = Hwc2::IComposerClient::Composition::SIDEBAND; } else { // Normal buffer layers - compositionState.hdrMetadata = mBufferInfo.mHdrMetadata; - compositionState.compositionType = mPotentialCursor + compositionState->hdrMetadata = mBufferInfo.mHdrMetadata; + compositionState->compositionType = mPotentialCursor ? Hwc2::IComposerClient::Composition::CURSOR : Hwc2::IComposerClient::Composition::DEVICE; } @@ -641,10 +650,6 @@ Rect BufferLayer::getBufferSize(const State& s) const { return Rect(bufWidth, bufHeight); } -std::shared_ptr BufferLayer::getCompositionLayer() const { - return mCompositionLayer; -} - FloatRect BufferLayer::computeSourceBounds(const FloatRect& parentBounds) const { const State& s(getDrawingState()); diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h index b2398a8ef7..4085b52449 100644 --- a/services/surfaceflinger/BufferLayer.h +++ b/services/surfaceflinger/BufferLayer.h @@ -54,7 +54,8 @@ public: // Overriden from Layer // ----------------------------------------------------------------------- public: - std::shared_ptr getCompositionLayer() const override; + sp getCompositionEngineLayerFE() const override; + compositionengine::LayerFECompositionState* editCompositionState() override; // If we have received a new buffer this frame, we will pass its surface // damage down to hardware composer. Otherwise, we must send a region with @@ -175,8 +176,9 @@ protected: /* * compositionengine::LayerFE overrides */ + const compositionengine::LayerFECompositionState* getCompositionState() const override; bool onPreComposition(nsecs_t) override; - void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + void preparePerFrameCompositionState() override; std::optional prepareClientComposition( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; @@ -210,7 +212,7 @@ private: // and its parent layer is not bounded Rect getBufferSize(const State& s) const override; - std::shared_ptr mCompositionLayer; + std::unique_ptr mCompositionState; FloatRect computeSourceBounds(const FloatRect& parentBounds) const override; }; diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp index e85281d8a9..128739394b 100644 --- a/services/surfaceflinger/BufferQueueLayer.cpp +++ b/services/surfaceflinger/BufferQueueLayer.cpp @@ -23,7 +23,6 @@ #define ATRACE_TAG ATRACE_TAG_GRAPHICS #include "BufferQueueLayer.h" -#include #include #include #include @@ -215,9 +214,9 @@ bool BufferQueueLayer::latchSidebandStream(bool& recomputeVisibleRegions) { if (mSidebandStreamChanged.compare_exchange_strong(sidebandStreamChanged, false)) { // mSidebandStreamChanged was changed to false mSidebandStream = mConsumer->getSidebandStream(); - auto& layerCompositionState = getCompositionLayer()->editFEState(); - layerCompositionState.sidebandStream = mSidebandStream; - if (layerCompositionState.sidebandStream != nullptr) { + auto* layerCompositionState = editCompositionState(); + layerCompositionState->sidebandStream = mSidebandStream; + if (layerCompositionState->sidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); } @@ -351,8 +350,8 @@ status_t BufferQueueLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = mConsumer->getCurrentBuffer(&mBufferInfo.mBufferSlot, &mBufferInfo.mFence); - auto& layerCompositionState = getCompositionLayer()->editFEState(); - layerCompositionState.buffer = mBufferInfo.mBuffer; + auto* layerCompositionState = editCompositionState(); + layerCompositionState->buffer = mBufferInfo.mBuffer; if (mBufferInfo.mBuffer == nullptr) { // this can only happen if the very first buffer was rejected. @@ -372,18 +371,19 @@ status_t BufferQueueLayer::updateFrameNumber(nsecs_t latchTime) { return NO_ERROR; } -void BufferQueueLayer::latchPerFrameState( - compositionengine::LayerFECompositionState& compositionState) const { - BufferLayer::latchPerFrameState(compositionState); - if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { +void BufferQueueLayer::preparePerFrameCompositionState() { + BufferLayer::preparePerFrameCompositionState(); + + auto* compositionState = editCompositionState(); + if (compositionState->compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { return; } - compositionState.buffer = mBufferInfo.mBuffer; - compositionState.bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) + compositionState->buffer = mBufferInfo.mBuffer; + compositionState->bufferSlot = (mBufferInfo.mBufferSlot == BufferQueue::INVALID_BUFFER_SLOT) ? 0 : mBufferInfo.mBufferSlot; - compositionState.acquireFence = mBufferInfo.mFence; + compositionState->acquireFence = mBufferInfo.mFence; } // ----------------------------------------------------------------------- diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h index 2bd1e3d6cc..486c1bca63 100644 --- a/services/surfaceflinger/BufferQueueLayer.h +++ b/services/surfaceflinger/BufferQueueLayer.h @@ -85,7 +85,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + void preparePerFrameCompositionState() override; sp createClone() override; void onFrameAvailable(const BufferItem& item); diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp index cd4227ccc0..664c19961f 100644 --- a/services/surfaceflinger/BufferStateLayer.cpp +++ b/services/surfaceflinger/BufferStateLayer.cpp @@ -27,7 +27,6 @@ #include -#include #include #include #include @@ -430,9 +429,8 @@ bool BufferStateLayer::latchSidebandStream(bool& recomputeVisibleRegions) { if (mSidebandStreamChanged.exchange(false)) { const State& s(getDrawingState()); // mSidebandStreamChanged was true - LOG_ALWAYS_FATAL_IF(!getCompositionLayer()); mSidebandStream = s.sidebandStream; - getCompositionLayer()->editFEState().sidebandStream = mSidebandStream; + editCompositionState()->sidebandStream = mSidebandStream; if (mSidebandStream != nullptr) { setTransactionFlags(eTransactionNeeded); mFlinger->setTransactionFlags(eTraversalNeeded); @@ -539,8 +537,7 @@ status_t BufferStateLayer::updateActiveBuffer() { mPreviousBufferId = getCurrentBufferId(); mBufferInfo.mBuffer = s.buffer; mBufferInfo.mFence = s.acquireFence; - auto& layerCompositionState = getCompositionLayer()->editFEState(); - layerCompositionState.buffer = mBufferInfo.mBuffer; + editCompositionState()->buffer = mBufferInfo.mBuffer; return NO_ERROR; } @@ -552,16 +549,17 @@ status_t BufferStateLayer::updateFrameNumber(nsecs_t /*latchTime*/) { return NO_ERROR; } -void BufferStateLayer::latchPerFrameState( - compositionengine::LayerFECompositionState& compositionState) const { - BufferLayer::latchPerFrameState(compositionState); - if (compositionState.compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { +void BufferStateLayer::preparePerFrameCompositionState() { + BufferLayer::preparePerFrameCompositionState(); + + auto* compositionState = editCompositionState(); + if (compositionState->compositionType == Hwc2::IComposerClient::Composition::SIDEBAND) { return; } - compositionState.buffer = mBufferInfo.mBuffer; - compositionState.bufferSlot = mBufferInfo.mBufferSlot; - compositionState.acquireFence = mBufferInfo.mFence; + compositionState->buffer = mBufferInfo.mBuffer; + compositionState->bufferSlot = mBufferInfo.mBufferSlot; + compositionState->acquireFence = mBufferInfo.mFence; } void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) { diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h index 94272833c2..020c1b356f 100644 --- a/services/surfaceflinger/BufferStateLayer.h +++ b/services/surfaceflinger/BufferStateLayer.h @@ -125,7 +125,7 @@ private: status_t updateActiveBuffer() override; status_t updateFrameNumber(nsecs_t latchTime) override; - void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + void preparePerFrameCompositionState() override; sp createClone() override; // Crop that applies to the buffer diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp index 04854d0803..6a81817423 100644 --- a/services/surfaceflinger/ColorLayer.cpp +++ b/services/surfaceflinger/ColorLayer.cpp @@ -29,8 +29,6 @@ #include #include -#include -#include #include #include #include @@ -45,8 +43,7 @@ namespace android { ColorLayer::ColorLayer(const LayerCreationArgs& args) : Layer(args), - mCompositionLayer{mFlinger->getCompositionEngine().createLayer( - compositionengine::LayerCreationArgs{this})} {} + mCompositionState{mFlinger->getCompositionEngine().createLayerFECompositionState()} {} ColorLayer::~ColorLayer() = default; @@ -91,16 +88,24 @@ bool ColorLayer::setDataspace(ui::Dataspace dataspace) { return true; } -void ColorLayer::latchPerFrameState( - compositionengine::LayerFECompositionState& compositionState) const { - Layer::latchPerFrameState(compositionState); +void ColorLayer::preparePerFrameCompositionState() { + Layer::preparePerFrameCompositionState(); - compositionState.color = getColor(); - compositionState.compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; + auto* compositionState = editCompositionState(); + compositionState->color = getColor(); + compositionState->compositionType = Hwc2::IComposerClient::Composition::SOLID_COLOR; } -std::shared_ptr ColorLayer::getCompositionLayer() const { - return mCompositionLayer; +sp ColorLayer::getCompositionEngineLayerFE() const { + return asLayerFE(); +} + +compositionengine::LayerFECompositionState* ColorLayer::editCompositionState() { + return mCompositionState.get(); +} + +const compositionengine::LayerFECompositionState* ColorLayer::getCompositionState() const { + return mCompositionState.get(); } bool ColorLayer::isOpaque(const Layer::State& s) const { diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h index 9246eb2ed2..4deb162191 100644 --- a/services/surfaceflinger/ColorLayer.h +++ b/services/surfaceflinger/ColorLayer.h @@ -28,7 +28,8 @@ public: explicit ColorLayer(const LayerCreationArgs&); ~ColorLayer() override; - std::shared_ptr getCompositionLayer() const override; + sp getCompositionEngineLayerFE() const override; + compositionengine::LayerFECompositionState* editCompositionState() override; const char* getType() const override { return "ColorLayer"; } bool isVisible() const override; @@ -45,11 +46,12 @@ protected: /* * compositionengine::LayerFE overrides */ - void latchPerFrameState(compositionengine::LayerFECompositionState&) const override; + const compositionengine::LayerFECompositionState* getCompositionState() const override; + void preparePerFrameCompositionState() override; std::optional prepareClientComposition( compositionengine::LayerFE::ClientCompositionTargetSettings&) override; - std::shared_ptr mCompositionLayer; + std::unique_ptr mCompositionState; sp createClone() override; }; diff --git a/services/surfaceflinger/CompositionEngine/Android.bp b/services/surfaceflinger/CompositionEngine/Android.bp index a634f2f83c..27922900cf 100644 --- a/services/surfaceflinger/CompositionEngine/Android.bp +++ b/services/surfaceflinger/CompositionEngine/Android.bp @@ -51,7 +51,6 @@ cc_library { "src/DisplaySurface.cpp", "src/DumpHelpers.cpp", "src/HwcBufferCache.cpp", - "src/Layer.cpp", "src/LayerFECompositionState.cpp", "src/Output.cpp", "src/OutputCompositionState.cpp", @@ -71,7 +70,6 @@ cc_library { "mock/Display.cpp", "mock/DisplayColorProfile.cpp", "mock/DisplaySurface.cpp", - "mock/Layer.cpp", "mock/LayerFE.cpp", "mock/NativeWindow.cpp", "mock/Output.cpp", @@ -96,7 +94,6 @@ cc_test { "tests/DisplayColorProfileTest.cpp", "tests/DisplayTest.cpp", "tests/HwcBufferCacheTest.cpp", - "tests/LayerTest.cpp", "tests/MockHWC2.cpp", "tests/MockHWComposer.cpp", "tests/MockPowerAdvisor.cpp", diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h index e3650f386a..3faa068c03 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionEngine.h @@ -32,11 +32,11 @@ class RenderEngine; namespace compositionengine { class Display; -class Layer; struct CompositionRefreshArgs; struct DisplayCreationArgs; struct LayerCreationArgs; +struct LayerFECompositionState; /** * Encapsulates all the interfaces and implementation details for performing @@ -48,7 +48,8 @@ public: // Create a composition Display virtual std::shared_ptr createDisplay(const DisplayCreationArgs&) = 0; - virtual std::shared_ptr createLayer(const LayerCreationArgs&) = 0; + virtual std::unique_ptr + createLayerFECompositionState() = 0; virtual HWComposer& getHwComposer() const = 0; virtual void setHwComposer(std::unique_ptr) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h index 90158c721d..4a0d6ee140 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/CompositionRefreshArgs.h @@ -21,15 +21,14 @@ #include #include -#include +#include #include #include namespace android::compositionengine { -using Layers = std::vector>; +using Layers = std::vector>; using Outputs = std::vector>; -using RawLayers = std::vector; /** * A parameter object for refreshing a set of outputs @@ -44,7 +43,7 @@ struct CompositionRefreshArgs { Layers layers; // All the layers that have queued updates. - RawLayers layersWithQueuedFrames; + Layers layersWithQueuedFrames; // If true, forces the entire display to be considered dirty and repainted bool repaintEverything{false}; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h deleted file mode 100644 index 1259c524b2..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Layer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include -#include - -#include - -namespace android::compositionengine { - -class Display; -class LayerFE; - -struct LayerFECompositionState; - -/** - * A layer contains the output-independent composition state for a front-end - * Layer - */ -class Layer { -public: - virtual ~Layer(); - - // Gets the front-end interface for this layer. Can return nullptr if the - // front-end layer no longer exists. - virtual sp getLayerFE() const = 0; - - // Gets the raw front-end composition state data for the layer - // TODO(lpique): Make this protected once it is only internally called. - virtual const LayerFECompositionState& getFEState() const = 0; - - // Allows mutable access to the raw front-end composition state - // TODO(lpique): Make this protected once it is only internally called. - virtual LayerFECompositionState& editFEState() = 0; - - // Debugging - virtual void dump(std::string& result) const = 0; -}; - -} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h deleted file mode 100644 index db3312b6e9..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerCreationArgs.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include - -namespace android::compositionengine { - -class CompositionEngine; -class LayerFE; - -/** - * A parameter object for creating Layer instances - */ -struct LayerCreationArgs { - // A weak pointer to the front-end layer instance that the new layer will - // represent. - wp layerFE; -}; - -} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h index 26442d9bd0..912dffd029 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFE.h @@ -44,6 +44,9 @@ struct LayerFECompositionState; // of the front-end layer class LayerFE : public virtual RefBase { public: + // Gets the raw front-end composition state data for the layer + virtual const LayerFECompositionState* getCompositionState() const = 0; + // Called before composition starts. Should return true if this layer has // pending updates which would require an extra display refresh cycle to // process. @@ -60,19 +63,18 @@ public: // content (buffer or color) state for the layer. GeometryAndContent, - // Gets the per frame content (buffer or color) state the layer. + // Gets the per frame content (buffer or color) state for the layer. Content, + + // Gets the cursor state for the layer. + Cursor, }; - // Latches the output-independent composition state for the layer. The + // Prepares the output-independent composition state for the layer. The // StateSubset argument selects what portion of the state is actually needed // by the CompositionEngine code, since computing everything may be // expensive. - virtual void latchCompositionState(LayerFECompositionState&, StateSubset) const = 0; - - // Latches the minimal bit of state for the cursor for a fast asynchronous - // update. - virtual void latchCursorCompositionState(LayerFECompositionState&) const = 0; + virtual void prepareCompositionState(StateSubset) = 0; struct ClientCompositionTargetSettings { // The clip region, or visible region that is being rendered to diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h index 1af99c5bf2..40cd3e0c20 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/LayerFECompositionState.h @@ -162,8 +162,10 @@ struct LayerFECompositionState { // The output-independent frame for the cursor Rect cursorFrame; + virtual ~LayerFECompositionState(); + // Debugging - void dump(std::string& out) const; + virtual void dump(std::string& out) const; }; } // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h index a5da0b1535..c04aff58ee 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/Output.h @@ -41,7 +41,6 @@ class Layer; namespace android::compositionengine { class DisplayColorProfile; -class Layer; class LayerFE; class RenderSurface; class OutputLayer; @@ -215,18 +214,17 @@ public: virtual bool belongsInOutput(std::optional layerStackId, bool internalOnly) const = 0; // Determines if a layer belongs to the output. - virtual bool belongsInOutput(const Layer*) const = 0; + virtual bool belongsInOutput(const sp&) const = 0; // Returns a pointer to the output layer corresponding to the given layer on // this output, or nullptr if the layer does not have one - virtual OutputLayer* getOutputLayerForLayer(Layer*) const = 0; + virtual OutputLayer* getOutputLayerForLayer(const sp&) const = 0; // Immediately clears all layers from the output. virtual void clearOutputLayers() = 0; // For tests use only. Creates and appends an OutputLayer into the output. - virtual OutputLayer* injectOutputLayerForTest(const std::shared_ptr&, - const sp&) = 0; + virtual OutputLayer* injectOutputLayerForTest(const sp&) = 0; // Gets the count of output layers managed by this output virtual size_t getOutputLayerCount() const = 0; @@ -256,7 +254,7 @@ protected: virtual void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) = 0; virtual void collectVisibleLayers(const CompositionRefreshArgs&, CoverageState&) = 0; - virtual void ensureOutputLayerIfVisible(std::shared_ptr, CoverageState&) = 0; + virtual void ensureOutputLayerIfVisible(sp&, CoverageState&) = 0; virtual void setReleasedLayers(const CompositionRefreshArgs&) = 0; virtual void updateAndWriteCompositionState(const CompositionRefreshArgs&) = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h index a466561d76..007b0e815e 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/OutputLayer.h @@ -41,7 +41,6 @@ namespace compositionengine { class CompositionEngine; class Output; -class Layer; class LayerFE; namespace impl { @@ -61,9 +60,6 @@ public: // Gets the output which owns this output layer virtual const Output& getOutput() const = 0; - // Gets the display-independent layer which this output layer represents - virtual Layer& getLayer() const = 0; - // Gets the front-end layer interface this output layer represents virtual LayerFE& getLayerFE() const = 0; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h index 450b9ca804..386808d714 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/CompositionEngine.h @@ -27,8 +27,8 @@ public: std::shared_ptr createDisplay( const compositionengine::DisplayCreationArgs&) override; - std::shared_ptr createLayer( - const compositionengine::LayerCreationArgs&) override; + std::unique_ptr createLayerFECompositionState() + override; HWComposer& getHwComposer() const override; void setHwComposer(std::unique_ptr) override; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h index 39acb37e0d..fb597ce1ff 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Display.h @@ -73,8 +73,7 @@ public: virtual void applyLayerRequestsToLayers(const LayerRequests&); // Internal - std::unique_ptr createOutputLayer( - const std::shared_ptr&, const sp&) const; + std::unique_ptr createOutputLayer(const sp&) const; private: const bool mIsVirtual; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h deleted file mode 100644 index 46489fb9cd..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Layer.h +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include - -#include -#include -#include - -namespace android::compositionengine { - -struct LayerCreationArgs; - -namespace impl { - -// The implementation class contains the common implementation, but does not -// actually contain the final layer state. -class Layer : public virtual compositionengine::Layer { -public: - ~Layer() override; - - // compositionengine::Layer overrides - void dump(std::string&) const override; - -protected: - // Implemented by the final implementation for the final state it uses. - virtual void dumpFEState(std::string&) const = 0; -}; - -// This template factory function standardizes the implementation details of the -// final class using the types actually required by the implementation. This is -// not possible to do in the base class as those types may not even be visible -// to the base code. -template -std::shared_ptr createLayerTemplated(const LayerCreationArgs& args) { - class Layer final : public BaseLayer { - public: -// Clang incorrectly complains that these are unused. -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wunused-local-typedef" - using LayerFE = std::remove_pointer_t().layerFE)>().unsafe_get())>; - using LayerFECompositionState = std::remove_const_t< - std::remove_reference_t().getFEState())>>; -#pragma clang diagnostic pop - - explicit Layer(const LayerCreationArgs& args) : mLayerFE(args.layerFE) {} - ~Layer() override = default; - - private: - // compositionengine::Layer overrides - sp getLayerFE() const override { return mLayerFE.promote(); } - const LayerFECompositionState& getFEState() const override { return mFrontEndState; } - LayerFECompositionState& editFEState() override { return mFrontEndState; } - - // compositionengine::impl::Layer overrides - void dumpFEState(std::string& out) const override { mFrontEndState.dump(out); } - - const wp mLayerFE; - LayerFECompositionState mFrontEndState; - }; - - return std::make_shared(args); -} - -std::shared_ptr createLayer(const LayerCreationArgs&); - -} // namespace impl -} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h index f469e62430..cc31e5f612 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/Output.h @@ -59,10 +59,9 @@ public: Region getDirtyRegion(bool repaintEverything) const override; bool belongsInOutput(std::optional, bool) const override; - bool belongsInOutput(const compositionengine::Layer*) const override; + bool belongsInOutput(const sp&) const override; - compositionengine::OutputLayer* getOutputLayerForLayer( - compositionengine::Layer*) const override; + compositionengine::OutputLayer* getOutputLayerForLayer(const sp&) const override; void setReleasedLayers(ReleasedLayers&&) override; @@ -72,7 +71,7 @@ public: void rebuildLayerStacks(const CompositionRefreshArgs&, LayerFESet&) override; void collectVisibleLayers(const CompositionRefreshArgs&, compositionengine::Output::CoverageState&) override; - void ensureOutputLayerIfVisible(std::shared_ptr, + void ensureOutputLayerIfVisible(sp&, compositionengine::Output::CoverageState&) override; void setReleasedLayers(const compositionengine::CompositionRefreshArgs&) override; @@ -93,9 +92,9 @@ public: void setRenderSurfaceForTest(std::unique_ptr); protected: - std::unique_ptr createOutputLayer( - const std::shared_ptr&, const sp&) const; - std::optional findCurrentOutputLayerForLayer(compositionengine::Layer*) const; + std::unique_ptr createOutputLayer(const sp&) const; + std::optional findCurrentOutputLayerForLayer( + const sp&) const; void chooseCompositionStrategy() override; bool getSkipColorTransform() const override; compositionengine::Output::FrameFences presentAndGetFrameFences() override; @@ -107,11 +106,9 @@ protected: void dumpBase(std::string&) const; // Implemented by the final implementation for the final state it uses. - virtual compositionengine::OutputLayer* ensureOutputLayer( - std::optional, const std::shared_ptr&, - const sp&) = 0; - virtual compositionengine::OutputLayer* injectOutputLayerForTest( - const std::shared_ptr&, const sp&) = 0; + virtual compositionengine::OutputLayer* ensureOutputLayer(std::optional, + const sp&) = 0; + virtual compositionengine::OutputLayer* injectOutputLayerForTest(const sp&) = 0; virtual void finalizePendingOutputLayers() = 0; virtual const compositionengine::CompositionEngine& getCompositionEngine() const = 0; virtual void dumpState(std::string& out) const = 0; @@ -180,11 +177,10 @@ std::shared_ptr createOutputTemplated(const CompositionEngine& compo }; OutputLayer* ensureOutputLayer(std::optional prevIndex, - const std::shared_ptr& layer, const sp& layerFE) { auto outputLayer = (prevIndex && *prevIndex <= mCurrentOutputLayersOrderedByZ.size()) ? std::move(mCurrentOutputLayersOrderedByZ[*prevIndex]) - : BaseOutput::createOutputLayer(layer, layerFE); + : BaseOutput::createOutputLayer(layerFE); auto result = outputLayer.get(); mPendingOutputLayersOrderedByZ.emplace_back(std::move(outputLayer)); return result; @@ -201,10 +197,8 @@ std::shared_ptr createOutputTemplated(const CompositionEngine& compo void dumpState(std::string& out) const override { mState.dump(out); } - OutputLayer* injectOutputLayerForTest( - const std::shared_ptr& layer, - const sp& layerFE) override { - auto outputLayer = BaseOutput::createOutputLayer(layer, layerFE); + OutputLayer* injectOutputLayerForTest(const sp& layerFE) override { + auto outputLayer = BaseOutput::createOutputLayer(layerFE); auto result = outputLayer.get(); mCurrentOutputLayersOrderedByZ.emplace_back(std::move(outputLayer)); return result; diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h index 95c8afbede..79df9b2551 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/impl/OutputLayer.h @@ -81,7 +81,6 @@ private: // to the base code. template std::unique_ptr createOutputLayerTemplated(const Output& output, - std::shared_ptr layer, sp layerFE) { class OutputLayer final : public BaseOutputLayer { public: @@ -93,21 +92,18 @@ std::unique_ptr createOutputLayerTemplated(const Output& output std::remove_reference_t().getState())>>; using Output = std::remove_const_t< std::remove_reference_t().getOutput())>>; - using Layer = std::remove_reference_t().getLayer())>; using LayerFE = std::remove_reference_t().getLayerFE())>; #pragma clang diagnostic pop - OutputLayer(const Output& output, const std::shared_ptr& layer, - const sp& layerFE) - : mOutput(output), mLayer(layer), mLayerFE(layerFE) {} + OutputLayer(const Output& output, const sp& layerFE) + : mOutput(output), mLayerFE(layerFE) {} ~OutputLayer() override = default; private: // compositionengine::OutputLayer overrides const Output& getOutput() const override { return mOutput; } - Layer& getLayer() const override { return *mLayer; } LayerFE& getLayerFE() const override { return *mLayerFE; } const OutputLayerCompositionState& getState() const override { return mState; } OutputLayerCompositionState& editState() override { return mState; } @@ -116,16 +112,14 @@ std::unique_ptr createOutputLayerTemplated(const Output& output void dumpState(std::string& out) const override { mState.dump(out); } const Output& mOutput; - const std::shared_ptr mLayer; const sp mLayerFE; OutputLayerCompositionState mState; }; - return std::make_unique(output, layer, layerFE); + return std::make_unique(output, layerFE); } std::unique_ptr createOutputLayer(const compositionengine::Output&, - const std::shared_ptr&, const sp&); } // namespace impl diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h index 104e20df42..f953d0b7d0 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/CompositionEngine.h @@ -19,7 +19,7 @@ #include #include #include -#include +#include #include #include @@ -33,7 +33,8 @@ public: ~CompositionEngine() override; MOCK_METHOD1(createDisplay, std::shared_ptr(const DisplayCreationArgs&)); - MOCK_METHOD1(createLayer, std::shared_ptr(const LayerCreationArgs&)); + MOCK_METHOD0(createLayerFECompositionState, + std::unique_ptr()); MOCK_CONST_METHOD0(getHwComposer, HWComposer&()); MOCK_METHOD1(setHwComposer, void(std::unique_ptr)); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h deleted file mode 100644 index 4f03cb46ae..0000000000 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Layer.h +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#pragma once - -#include -#include -#include -#include - -namespace android::compositionengine::mock { - -class Layer : public compositionengine::Layer { -public: - Layer(); - virtual ~Layer(); - - MOCK_CONST_METHOD0(getLayerFE, sp()); - - MOCK_CONST_METHOD0(getFEState, const LayerFECompositionState&()); - MOCK_METHOD0(editFEState, LayerFECompositionState&()); - - MOCK_CONST_METHOD1(dump, void(std::string&)); -}; - -} // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h index 163e302d88..5c2ad15268 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/LayerFE.h @@ -30,11 +30,11 @@ public: LayerFE(); virtual ~LayerFE(); + MOCK_CONST_METHOD0(getCompositionState, const LayerFECompositionState*()); + MOCK_METHOD1(onPreComposition, bool(nsecs_t)); - MOCK_CONST_METHOD2(latchCompositionState, - void(LayerFECompositionState&, compositionengine::LayerFE::StateSubset)); - MOCK_CONST_METHOD1(latchCursorCompositionState, void(LayerFECompositionState&)); + MOCK_METHOD1(prepareCompositionState, void(compositionengine::LayerFE::StateSubset)); MOCK_METHOD1(prepareClientComposition, std::optional( compositionengine::LayerFE::ClientCompositionTargetSettings&)); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h index c41302d1a2..2608b91677 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/Output.h @@ -18,7 +18,6 @@ #include #include -#include #include #include #include @@ -61,14 +60,13 @@ public: MOCK_CONST_METHOD1(getDirtyRegion, Region(bool)); MOCK_CONST_METHOD2(belongsInOutput, bool(std::optional, bool)); - MOCK_CONST_METHOD1(belongsInOutput, bool(const compositionengine::Layer*)); + MOCK_CONST_METHOD1(belongsInOutput, bool(const sp&)); MOCK_CONST_METHOD1(getOutputLayerForLayer, - compositionengine::OutputLayer*(compositionengine::Layer*)); + compositionengine::OutputLayer*(const sp&)); MOCK_METHOD0(clearOutputLayers, void()); - MOCK_METHOD2(injectOutputLayerForTest, - compositionengine::OutputLayer*(const std::shared_ptr&, - const sp&)); + MOCK_METHOD1(injectOutputLayerForTest, + compositionengine::OutputLayer*(const sp&)); MOCK_CONST_METHOD0(getOutputLayerCount, size_t()); MOCK_CONST_METHOD1(getOutputLayerOrderedByZByIndex, OutputLayer*(size_t)); @@ -83,8 +81,7 @@ public: void(const compositionengine::CompositionRefreshArgs&, compositionengine::Output::CoverageState&)); MOCK_METHOD2(ensureOutputLayerIfVisible, - void(std::shared_ptr, - compositionengine::Output::CoverageState&)); + void(sp&, compositionengine::Output::CoverageState&)); MOCK_METHOD1(setReleasedLayers, void(const compositionengine::CompositionRefreshArgs&)); MOCK_CONST_METHOD1(updateLayerStateFromFE, void(const CompositionRefreshArgs&)); diff --git a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h index 631760afe7..2ecbad803f 100644 --- a/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h +++ b/services/surfaceflinger/CompositionEngine/include/compositionengine/mock/OutputLayer.h @@ -17,7 +17,6 @@ #pragma once #include -#include #include #include #include @@ -34,7 +33,6 @@ public: MOCK_METHOD1(setHwcLayer, void(std::shared_ptr)); MOCK_CONST_METHOD0(getOutput, const compositionengine::Output&()); - MOCK_CONST_METHOD0(getLayer, compositionengine::Layer&()); MOCK_CONST_METHOD0(getLayerFE, compositionengine::LayerFE&()); MOCK_CONST_METHOD0(getState, const impl::OutputLayerCompositionState&()); diff --git a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp b/services/surfaceflinger/CompositionEngine/mock/Layer.cpp deleted file mode 100644 index 08483cb301..0000000000 --- a/services/surfaceflinger/CompositionEngine/mock/Layer.cpp +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#include - -namespace android::compositionengine::mock { - -// The Google Mock documentation recommends explicit non-header instantiations -// for better compile time performance. -Layer::Layer() = default; -Layer::~Layer() = default; - -} // namespace android::compositionengine::mock diff --git a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp index aeaa18aa95..6203dc6737 100644 --- a/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp +++ b/services/surfaceflinger/CompositionEngine/src/CompositionEngine.cpp @@ -16,10 +16,10 @@ #include #include +#include #include #include #include -#include #include #include @@ -51,9 +51,9 @@ std::shared_ptr CompositionEngine::createDisplay( return compositionengine::impl::createDisplay(*this, args); } -std::shared_ptr CompositionEngine::createLayer( - const LayerCreationArgs& args) { - return compositionengine::impl::createLayer(args); +std::unique_ptr +CompositionEngine::createLayerFECompositionState() { + return std::make_unique(); } HWComposer& CompositionEngine::getHwComposer() const { @@ -120,8 +120,7 @@ void CompositionEngine::updateCursorAsync(CompositionRefreshArgs& args) { for (auto* layer : output->getOutputLayersOrderedByZ()) { if (layer->isHardwareCursor()) { // Latch the cursor composition state from each front-end layer. - layer->getLayerFE().latchCursorCompositionState(layer->getLayer().editFEState()); - + layer->getLayerFE().prepareCompositionState(LayerFE::StateSubset::Cursor); layer->writeCursorPositionToHWC(); } } @@ -137,8 +136,7 @@ void CompositionEngine::preComposition(CompositionRefreshArgs& args) { mRefreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); for (auto& layer : args.layers) { - sp layerFE = layer->getLayerFE(); - if (layerFE && layerFE->onPreComposition(mRefreshStartTime)) { + if (layer->onPreComposition(mRefreshStartTime)) { needsAnotherUpdate = true; } } diff --git a/services/surfaceflinger/CompositionEngine/src/Display.cpp b/services/surfaceflinger/CompositionEngine/src/Display.cpp index ccd6572667..1d8a23f460 100644 --- a/services/surfaceflinger/CompositionEngine/src/Display.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Display.cpp @@ -147,9 +147,8 @@ void Display::createClientCompositionCache(uint32_t cacheSize) { } std::unique_ptr Display::createOutputLayer( - const std::shared_ptr& layer, const sp& layerFE) const { - auto result = impl::createOutputLayer(*this, layer, layerFE); + auto result = impl::createOutputLayer(*this, layerFE); if (result && mId) { auto& hwc = getCompositionEngine().getHwComposer(); @@ -184,16 +183,18 @@ void Display::setReleasedLayers(const compositionengine::CompositionRefreshArgs& // Any non-null entries in the current list of layers are layers that are no // longer going to be visible - for (auto* layer : getOutputLayersOrderedByZ()) { - if (!layer) { + for (auto* outputLayer : getOutputLayersOrderedByZ()) { + if (!outputLayer) { continue; } - sp layerFE(&layer->getLayerFE()); + compositionengine::LayerFE* layerFE = &outputLayer->getLayerFE(); const bool hasQueuedFrames = - std::find(refreshArgs.layersWithQueuedFrames.cbegin(), - refreshArgs.layersWithQueuedFrames.cend(), - &layer->getLayer()) != refreshArgs.layersWithQueuedFrames.cend(); + std::any_of(refreshArgs.layersWithQueuedFrames.cbegin(), + refreshArgs.layersWithQueuedFrames.cend(), + [layerFE](sp layerWithQueuedFrames) { + return layerFE == layerWithQueuedFrames.get(); + }); if (hasQueuedFrames) { releasedLayers.emplace_back(layerFE); diff --git a/services/surfaceflinger/CompositionEngine/src/Layer.cpp b/services/surfaceflinger/CompositionEngine/src/Layer.cpp deleted file mode 100644 index ecacaeee9c..0000000000 --- a/services/surfaceflinger/CompositionEngine/src/Layer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2019 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. - */ - -#include -#include -#include -#include - -namespace android::compositionengine { - -Layer::~Layer() = default; - -namespace impl { - -std::shared_ptr createLayer(const LayerCreationArgs& args) { - return compositionengine::impl::createLayerTemplated(args); -} - -Layer::~Layer() = default; - -void Layer::dump(std::string& out) const { - auto layerFE = getLayerFE(); - android::base::StringAppendF(&out, "* compositionengine::Layer %p (%s)\n", this, - layerFE ? layerFE->getDebugName() : ""); - out.append(" frontend:\n"); - dumpFEState(out); -} - -} // namespace impl -} // namespace android::compositionengine diff --git a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp index 016084f519..3e0f8038d7 100644 --- a/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp +++ b/services/surfaceflinger/CompositionEngine/src/LayerFECompositionState.cpp @@ -32,6 +32,8 @@ void dumpVal(std::string& out, const char* name, half4 value) { } // namespace +LayerFECompositionState::~LayerFECompositionState() = default; + void LayerFECompositionState::dump(std::string& out) const { out.append(" "); dumpVal(out, "isSecure", isSecure); diff --git a/services/surfaceflinger/CompositionEngine/src/Output.cpp b/services/surfaceflinger/CompositionEngine/src/Output.cpp index 55371dfef0..47704ecd95 100644 --- a/services/surfaceflinger/CompositionEngine/src/Output.cpp +++ b/services/surfaceflinger/CompositionEngine/src/Output.cpp @@ -20,7 +20,6 @@ #include #include #include -#include #include #include #include @@ -265,31 +264,26 @@ bool Output::belongsInOutput(std::optional layerStackId, bool internal (!internalOnly || outputState.layerStackInternal); } -bool Output::belongsInOutput(const compositionengine::Layer* layer) const { - if (!layer) { - return false; - } - - const auto& layerFEState = layer->getFEState(); - return belongsInOutput(layerFEState.layerStackId, layerFEState.internalOnly); +bool Output::belongsInOutput(const sp& layerFE) const { + const auto* layerFEState = layerFE->getCompositionState(); + return layerFEState && belongsInOutput(layerFEState->layerStackId, layerFEState->internalOnly); } std::unique_ptr Output::createOutputLayer( - const std::shared_ptr& layer, const sp& layerFE) const { - return impl::createOutputLayer(*this, layer, layerFE); + const sp& layerFE) const { + return impl::createOutputLayer(*this, layerFE); } -compositionengine::OutputLayer* Output::getOutputLayerForLayer( - compositionengine::Layer* layer) const { - auto index = findCurrentOutputLayerForLayer(layer); +compositionengine::OutputLayer* Output::getOutputLayerForLayer(const sp& layerFE) const { + auto index = findCurrentOutputLayerForLayer(layerFE); return index ? getOutputLayerOrderedByZByIndex(*index) : nullptr; } std::optional Output::findCurrentOutputLayerForLayer( - compositionengine::Layer* layer) const { + const sp& layer) const { for (size_t i = 0; i < getOutputLayerCount(); i++) { auto outputLayer = getOutputLayerOrderedByZByIndex(i); - if (outputLayer && &outputLayer->getLayer() == layer) { + if (outputLayer && &outputLayer->getLayerFE() == layer.get()) { return i; } } @@ -352,7 +346,7 @@ void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArg // Evaluate the layers from front to back to determine what is visible. This // also incrementally calculates the coverage information for each layer as // well as the entire output. - for (auto& layer : reversed(refreshArgs.layers)) { + for (auto layer : reversed(refreshArgs.layers)) { // Incrementally process the coverage for each layer ensureOutputLayerIfVisible(layer, coverage); @@ -371,28 +365,29 @@ void Output::collectVisibleLayers(const compositionengine::CompositionRefreshArg } } -void Output::ensureOutputLayerIfVisible(std::shared_ptr layer, +void Output::ensureOutputLayerIfVisible(sp& layerFE, compositionengine::Output::CoverageState& coverage) { - // Note: Converts a wp to a sp - auto layerFE = layer->getLayerFE(); - if (layerFE == nullptr) { - return; - } - // Ensure we have a snapshot of the basic geometry layer state. Limit the // snapshots to once per frame for each candidate layer, as layers may // appear on multiple outputs. if (!coverage.latchedLayers.count(layerFE)) { coverage.latchedLayers.insert(layerFE); - layerFE->latchCompositionState(layer->editFEState(), - compositionengine::LayerFE::StateSubset::BasicGeometry); + layerFE->prepareCompositionState(compositionengine::LayerFE::StateSubset::BasicGeometry); } - // Obtain a read-only reference to the front-end layer state - const auto& layerFEState = layer->getFEState(); - // Only consider the layers on the given layer stack - if (!belongsInOutput(layer.get())) { + if (!belongsInOutput(layerFE)) { + return; + } + + // Obtain a read-only pointer to the front-end layer state + const auto* layerFEState = layerFE->getCompositionState(); + if (CC_UNLIKELY(!layerFEState)) { + return; + } + + // handle hidden surfaces by setting the visible region to empty + if (CC_UNLIKELY(!layerFEState->isVisible)) { return; } @@ -430,23 +425,18 @@ void Output::ensureOutputLayerIfVisible(std::shared_ptr