Loading services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ cc_defaults { "libui", "libinput", "libutils", "libutilscallstack", ], static_libs: [ "libcompositionengine", Loading services/surfaceflinger/SurfaceFlinger.cpp +98 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ #include <ui/GraphicBufferAllocator.h> #include <ui/PixelFormat.h> #include <ui/UiConfig.h> #include <utils/CallStack.h> #include <utils/StopWatch.h> #include <utils/String16.h> #include <utils/String8.h> Loading Loading @@ -1935,22 +1936,78 @@ void SurfaceFlinger::setCompositorTimingSnapped(const DisplayStatInfo& stats, getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; } // debug patch for b/119477596 - add stack guards to catch stack // corruptions and disable clang optimizations. // The code below is temporary and planned to be removed once stack // corruptions are found. #pragma clang optimize off class StackGuard { public: StackGuard(const char* name, const char* func, int line) { guarders.reserve(MIN_CAPACITY); guarders.push_back({this, name, func, line}); validate(); } ~StackGuard() { for (auto i = guarders.end() - 1; i >= guarders.begin(); --i) { if (i->guard == this) { guarders.erase(i); break; } } } static void validate() { for (const auto& guard : guarders) { if (guard.guard->cookie != COOKIE_VALUE) { ALOGE("%s:%d: Stack corruption detected at %s", guard.func, guard.line, guard.name); CallStack stack(LOG_TAG); abort(); } } } private: uint64_t cookie = COOKIE_VALUE; static constexpr uint64_t COOKIE_VALUE = 0xc0febebedeadbeef; static constexpr size_t MIN_CAPACITY = 16; struct GuarderElement { StackGuard* guard; const char* name; const char* func; int line; }; static std::vector<GuarderElement> guarders; }; std::vector<StackGuard::GuarderElement> StackGuard::guarders; #define DEFINE_STACK_GUARD(__n) StackGuard __n##StackGuard(#__n, __FUNCTION__, __LINE__); #define ASSERT_ON_STACK_GUARD() StackGuard::validate(); void SurfaceFlinger::postComposition() { DEFINE_STACK_GUARD(begin); ATRACE_CALL(); ALOGV("postComposition"); // Release any buffers which were replaced this frame nsecs_t dequeueReadyTime = systemTime(); DEFINE_STACK_GUARD(dequeueReadyTime); for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(dequeueReadyTime); } ASSERT_ON_STACK_GUARD(); // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); DEFINE_STACK_GUARD(display); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; DEFINE_STACK_GUARD(glCompositionDoneFenceTime); if (display && getHwComposer().hasClientComposition(display->getId())) { glCompositionDoneFenceTime = std::make_shared<FenceTime>(display->getClientTargetAcquireFence()); Loading @@ -1959,13 +2016,17 @@ void SurfaceFlinger::postComposition() glCompositionDoneFenceTime = FenceTime::NO_FENCE; } ASSERT_ON_STACK_GUARD(); getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFence = display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE; auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence); DEFINE_STACK_GUARD(presentFenceTime); getBE().mDisplayTimeline.push(presentFenceTime); DisplayStatInfo stats; DEFINE_STACK_GUARD(stats); if (mUseScheduler) { mScheduler->getDisplayStatInfo(&stats); } else { Loading @@ -1973,34 +2034,46 @@ void SurfaceFlinger::postComposition() stats.vsyncPeriod = mPrimaryDispSync->getPeriod(); } ASSERT_ON_STACK_GUARD(); // We use the mRefreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay // since updateCompositorTiming has snapping logic. updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime); CompositorTiming compositorTiming; DEFINE_STACK_GUARD(compositorTiming); { std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock); DEFINE_STACK_GUARD(lock); compositorTiming = getBE().mCompositorTiming; ASSERT_ON_STACK_GUARD(); } mDrawingState.traverseInZOrder([&](Layer* layer) { bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime, presentFenceTime, compositorTiming); DEFINE_STACK_GUARD(frameLatched); if (frameLatched) { recordBufferingStats(layer->getName().string(), layer->getOccupancyHistory(false)); } ASSERT_ON_STACK_GUARD(); }); if (presentFenceTime->isValid()) { ASSERT_ON_STACK_GUARD(); if (mUseScheduler) { mScheduler->addPresentFence(presentFenceTime); ASSERT_ON_STACK_GUARD(); } else { if (mPrimaryDispSync->addPresentFence(presentFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); } ASSERT_ON_STACK_GUARD(); } } Loading @@ -2014,61 +2087,86 @@ void SurfaceFlinger::postComposition() } } ASSERT_ON_STACK_GUARD(); if (mAnimCompositionPending) { mAnimCompositionPending = false; if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); ASSERT_ON_STACK_GUARD(); } else if (display && getHwComposer().isConnected(*display->getId())) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId()); DEFINE_STACK_GUARD(presentTime); mAnimFrameTracker.setActualPresentTime(presentTime); ASSERT_ON_STACK_GUARD(); } mAnimFrameTracker.advanceFrame(); } ASSERT_ON_STACK_GUARD(); mTimeStats->incrementTotalFrames(); if (mHadClientComposition) { mTimeStats->incrementClientCompositionFrames(); } ASSERT_ON_STACK_GUARD(); mTimeStats->setPresentFenceGlobal(presentFenceTime); ASSERT_ON_STACK_GUARD(); if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) { return; } nsecs_t currentTime = systemTime(); DEFINE_STACK_GUARD(currentTime); if (mHasPoweredOff) { mHasPoweredOff = false; } else { nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime; DEFINE_STACK_GUARD(elapsedTime); size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod); DEFINE_STACK_GUARD(numPeriods); if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) { getBE().mFrameBuckets[numPeriods] += elapsedTime; } else { getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime; } getBE().mTotalTime += elapsedTime; ASSERT_ON_STACK_GUARD(); } getBE().mLastSwapTime = currentTime; ASSERT_ON_STACK_GUARD(); { std::lock_guard lock(mTexturePoolMutex); DEFINE_STACK_GUARD(lock); const size_t refillCount = mTexturePoolSize - mTexturePool.size(); DEFINE_STACK_GUARD(refillCount); if (refillCount > 0) { const size_t offset = mTexturePool.size(); mTexturePool.resize(mTexturePoolSize); getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset); ATRACE_INT("TexturePoolSize", mTexturePool.size()); } ASSERT_ON_STACK_GUARD(); } mTransactionCompletedThread.addPresentFence(mPreviousPresentFence); mTransactionCompletedThread.sendCallbacks(); ASSERT_ON_STACK_GUARD(); } #pragma clang optimize on // b/119477596 void SurfaceFlinger::rebuildLayerStacks() { ATRACE_CALL(); Loading Loading
services/surfaceflinger/Android.bp +1 −0 Original line number Diff line number Diff line Loading @@ -55,6 +55,7 @@ cc_defaults { "libui", "libinput", "libutils", "libutilscallstack", ], static_libs: [ "libcompositionengine", Loading
services/surfaceflinger/SurfaceFlinger.cpp +98 −0 Original line number Diff line number Diff line Loading @@ -52,6 +52,7 @@ #include <ui/GraphicBufferAllocator.h> #include <ui/PixelFormat.h> #include <ui/UiConfig.h> #include <utils/CallStack.h> #include <utils/StopWatch.h> #include <utils/String16.h> #include <utils/String8.h> Loading Loading @@ -1935,22 +1936,78 @@ void SurfaceFlinger::setCompositorTimingSnapped(const DisplayStatInfo& stats, getBE().mCompositorTiming.presentLatency = snappedCompositeToPresentLatency; } // debug patch for b/119477596 - add stack guards to catch stack // corruptions and disable clang optimizations. // The code below is temporary and planned to be removed once stack // corruptions are found. #pragma clang optimize off class StackGuard { public: StackGuard(const char* name, const char* func, int line) { guarders.reserve(MIN_CAPACITY); guarders.push_back({this, name, func, line}); validate(); } ~StackGuard() { for (auto i = guarders.end() - 1; i >= guarders.begin(); --i) { if (i->guard == this) { guarders.erase(i); break; } } } static void validate() { for (const auto& guard : guarders) { if (guard.guard->cookie != COOKIE_VALUE) { ALOGE("%s:%d: Stack corruption detected at %s", guard.func, guard.line, guard.name); CallStack stack(LOG_TAG); abort(); } } } private: uint64_t cookie = COOKIE_VALUE; static constexpr uint64_t COOKIE_VALUE = 0xc0febebedeadbeef; static constexpr size_t MIN_CAPACITY = 16; struct GuarderElement { StackGuard* guard; const char* name; const char* func; int line; }; static std::vector<GuarderElement> guarders; }; std::vector<StackGuard::GuarderElement> StackGuard::guarders; #define DEFINE_STACK_GUARD(__n) StackGuard __n##StackGuard(#__n, __FUNCTION__, __LINE__); #define ASSERT_ON_STACK_GUARD() StackGuard::validate(); void SurfaceFlinger::postComposition() { DEFINE_STACK_GUARD(begin); ATRACE_CALL(); ALOGV("postComposition"); // Release any buffers which were replaced this frame nsecs_t dequeueReadyTime = systemTime(); DEFINE_STACK_GUARD(dequeueReadyTime); for (auto& layer : mLayersWithQueuedFrames) { layer->releasePendingBuffer(dequeueReadyTime); } ASSERT_ON_STACK_GUARD(); // |mStateLock| not needed as we are on the main thread const auto display = getDefaultDisplayDeviceLocked(); DEFINE_STACK_GUARD(display); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; DEFINE_STACK_GUARD(glCompositionDoneFenceTime); if (display && getHwComposer().hasClientComposition(display->getId())) { glCompositionDoneFenceTime = std::make_shared<FenceTime>(display->getClientTargetAcquireFence()); Loading @@ -1959,13 +2016,17 @@ void SurfaceFlinger::postComposition() glCompositionDoneFenceTime = FenceTime::NO_FENCE; } ASSERT_ON_STACK_GUARD(); getBE().mDisplayTimeline.updateSignalTimes(); mPreviousPresentFence = display ? getHwComposer().getPresentFence(*display->getId()) : Fence::NO_FENCE; auto presentFenceTime = std::make_shared<FenceTime>(mPreviousPresentFence); DEFINE_STACK_GUARD(presentFenceTime); getBE().mDisplayTimeline.push(presentFenceTime); DisplayStatInfo stats; DEFINE_STACK_GUARD(stats); if (mUseScheduler) { mScheduler->getDisplayStatInfo(&stats); } else { Loading @@ -1973,34 +2034,46 @@ void SurfaceFlinger::postComposition() stats.vsyncPeriod = mPrimaryDispSync->getPeriod(); } ASSERT_ON_STACK_GUARD(); // We use the mRefreshStartTime which might be sampled a little later than // when we started doing work for this frame, but that should be okay // since updateCompositorTiming has snapping logic. updateCompositorTiming(stats, mRefreshStartTime, presentFenceTime); CompositorTiming compositorTiming; DEFINE_STACK_GUARD(compositorTiming); { std::lock_guard<std::mutex> lock(getBE().mCompositorTimingLock); DEFINE_STACK_GUARD(lock); compositorTiming = getBE().mCompositorTiming; ASSERT_ON_STACK_GUARD(); } mDrawingState.traverseInZOrder([&](Layer* layer) { bool frameLatched = layer->onPostComposition(display->getId(), glCompositionDoneFenceTime, presentFenceTime, compositorTiming); DEFINE_STACK_GUARD(frameLatched); if (frameLatched) { recordBufferingStats(layer->getName().string(), layer->getOccupancyHistory(false)); } ASSERT_ON_STACK_GUARD(); }); if (presentFenceTime->isValid()) { ASSERT_ON_STACK_GUARD(); if (mUseScheduler) { mScheduler->addPresentFence(presentFenceTime); ASSERT_ON_STACK_GUARD(); } else { if (mPrimaryDispSync->addPresentFence(presentFenceTime)) { enableHardwareVsync(); } else { disableHardwareVsync(false); } ASSERT_ON_STACK_GUARD(); } } Loading @@ -2014,61 +2087,86 @@ void SurfaceFlinger::postComposition() } } ASSERT_ON_STACK_GUARD(); if (mAnimCompositionPending) { mAnimCompositionPending = false; if (presentFenceTime->isValid()) { mAnimFrameTracker.setActualPresentFence( std::move(presentFenceTime)); ASSERT_ON_STACK_GUARD(); } else if (display && getHwComposer().isConnected(*display->getId())) { // The HWC doesn't support present fences, so use the refresh // timestamp instead. const nsecs_t presentTime = getHwComposer().getRefreshTimestamp(*display->getId()); DEFINE_STACK_GUARD(presentTime); mAnimFrameTracker.setActualPresentTime(presentTime); ASSERT_ON_STACK_GUARD(); } mAnimFrameTracker.advanceFrame(); } ASSERT_ON_STACK_GUARD(); mTimeStats->incrementTotalFrames(); if (mHadClientComposition) { mTimeStats->incrementClientCompositionFrames(); } ASSERT_ON_STACK_GUARD(); mTimeStats->setPresentFenceGlobal(presentFenceTime); ASSERT_ON_STACK_GUARD(); if (display && getHwComposer().isConnected(*display->getId()) && !display->isPoweredOn()) { return; } nsecs_t currentTime = systemTime(); DEFINE_STACK_GUARD(currentTime); if (mHasPoweredOff) { mHasPoweredOff = false; } else { nsecs_t elapsedTime = currentTime - getBE().mLastSwapTime; DEFINE_STACK_GUARD(elapsedTime); size_t numPeriods = static_cast<size_t>(elapsedTime / stats.vsyncPeriod); DEFINE_STACK_GUARD(numPeriods); if (numPeriods < SurfaceFlingerBE::NUM_BUCKETS - 1) { getBE().mFrameBuckets[numPeriods] += elapsedTime; } else { getBE().mFrameBuckets[SurfaceFlingerBE::NUM_BUCKETS - 1] += elapsedTime; } getBE().mTotalTime += elapsedTime; ASSERT_ON_STACK_GUARD(); } getBE().mLastSwapTime = currentTime; ASSERT_ON_STACK_GUARD(); { std::lock_guard lock(mTexturePoolMutex); DEFINE_STACK_GUARD(lock); const size_t refillCount = mTexturePoolSize - mTexturePool.size(); DEFINE_STACK_GUARD(refillCount); if (refillCount > 0) { const size_t offset = mTexturePool.size(); mTexturePool.resize(mTexturePoolSize); getRenderEngine().genTextures(refillCount, mTexturePool.data() + offset); ATRACE_INT("TexturePoolSize", mTexturePool.size()); } ASSERT_ON_STACK_GUARD(); } mTransactionCompletedThread.addPresentFence(mPreviousPresentFence); mTransactionCompletedThread.sendCallbacks(); ASSERT_ON_STACK_GUARD(); } #pragma clang optimize on // b/119477596 void SurfaceFlinger::rebuildLayerStacks() { ATRACE_CALL(); Loading