diff options
| -rw-r--r-- | services/surfaceflinger/DisplayDevice.h | 24 | ||||
| -rw-r--r-- | services/surfaceflinger/Layer.cpp | 7 | ||||
| -rw-r--r-- | services/surfaceflinger/MutexUtils.h | 53 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 237 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 14 | ||||
| -rw-r--r-- | services/surfaceflinger/ThreadContext.h (renamed from services/surfaceflinger/MainThreadGuard.h) | 18 | ||||
| -rw-r--r-- | services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h | 6 | ||||
| -rw-r--r-- | services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp | 7 |
8 files changed, 181 insertions, 185 deletions
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h index 2c4a300a0b..d5d87b40de 100644 --- a/services/surfaceflinger/DisplayDevice.h +++ b/services/surfaceflinger/DisplayDevice.h @@ -21,6 +21,7 @@ #include <string> #include <unordered_map> +#include <android-base/thread_annotations.h> #include <android/native_window.h> #include <binder/IBinder.h> #include <gui/LayerState.h> @@ -28,6 +29,7 @@ #include <renderengine/RenderEngine.h> #include <system/window.h> #include <ui/DisplayId.h> +#include <ui/DisplayIdentification.h> #include <ui/DisplayState.h> #include <ui/GraphicTypes.h> #include <ui/HdrCapabilities.h> @@ -39,15 +41,11 @@ #include <utils/RefBase.h> #include <utils/Timers.h> -#include "MainThreadGuard.h" - -#include <ui/DisplayIdentification.h> #include "DisplayHardware/DisplayMode.h" #include "DisplayHardware/Hal.h" #include "DisplayHardware/PowerAdvisor.h" - #include "Scheduler/RefreshRateConfigs.h" - +#include "ThreadContext.h" #include "TracedOrdinal.h" namespace android { @@ -99,9 +97,9 @@ public: void setLayerStack(ui::LayerStack); void setDisplaySize(int width, int height); void setProjection(ui::Rotation orientation, Rect viewport, Rect frame); - void stageBrightness(float brightness) REQUIRES(SF_MAIN_THREAD); - void persistBrightness(bool needsComposite) REQUIRES(SF_MAIN_THREAD); - bool isBrightnessStale() const REQUIRES(SF_MAIN_THREAD); + void stageBrightness(float brightness) REQUIRES(kMainThreadContext); + void persistBrightness(bool needsComposite) REQUIRES(kMainThreadContext); + bool isBrightnessStale() const REQUIRES(kMainThreadContext); void setFlags(uint32_t flags); ui::Rotation getPhysicalOrientation() const { return mPhysicalOrientation; } @@ -109,7 +107,7 @@ public: static ui::Transform::RotationFlags getPrimaryDisplayRotationFlags(); - std::optional<float> getStagedBrightness() const REQUIRES(SF_MAIN_THREAD); + std::optional<float> getStagedBrightness() const REQUIRES(kMainThreadContext); ui::Transform::RotationFlags getTransformHint() const; const ui::Transform& getTransform() const; const Rect& getLayerStackSpaceRect() const; @@ -209,15 +207,15 @@ public: bool setDesiredActiveMode(const ActiveModeInfo&) EXCLUDES(mActiveModeLock); std::optional<ActiveModeInfo> getDesiredActiveMode() const EXCLUDES(mActiveModeLock); void clearDesiredActiveModeState() EXCLUDES(mActiveModeLock); - ActiveModeInfo getUpcomingActiveMode() const REQUIRES(SF_MAIN_THREAD) { + ActiveModeInfo getUpcomingActiveMode() const REQUIRES(kMainThreadContext) { return mUpcomingActiveMode; } - void setActiveMode(DisplayModeId) REQUIRES(SF_MAIN_THREAD); + void setActiveMode(DisplayModeId) REQUIRES(kMainThreadContext); status_t initiateModeChange(const ActiveModeInfo&, const hal::VsyncPeriodChangeConstraints& constraints, hal::VsyncPeriodChangeTimeline* outTimeline) - REQUIRES(SF_MAIN_THREAD); + REQUIRES(kMainThreadContext); // Return the immutable list of supported display modes. The HWC may report different modes // after a hotplug reconnect event, in which case the DisplayDevice object will be recreated. @@ -304,7 +302,7 @@ private: ActiveModeInfo mDesiredActiveMode GUARDED_BY(mActiveModeLock); TracedOrdinal<bool> mDesiredActiveModeChanged GUARDED_BY(mActiveModeLock) = {"DesiredActiveModeChanged", false}; - ActiveModeInfo mUpcomingActiveMode GUARDED_BY(SF_MAIN_THREAD); + ActiveModeInfo mUpcomingActiveMode GUARDED_BY(kMainThreadContext); }; struct DisplayDeviceState { diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index fa5a1c82ba..894fb8d47b 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -37,6 +37,7 @@ #include <cutils/native_handle.h> #include <cutils/properties.h> #include <ftl/enum.h> +#include <ftl/fake_guard.h> #include <gui/BufferItem.h> #include <gui/LayerDebugInfo.h> #include <gui/Surface.h> @@ -2045,10 +2046,10 @@ LayerProto* Layer::writeToProto(LayersProto& layersProto, uint32_t traceFlags) { writeToProtoCommonState(layerProto, LayerVector::StateSet::Drawing, traceFlags); if (traceFlags & LayerTracing::TRACE_COMPOSITION) { + ftl::FakeGuard guard(mFlinger->mStateLock); // Called from the main thread. + // Only populate for the primary display. - UnnecessaryLock assumeLocked(mFlinger->mStateLock); // called from the main thread. - const auto display = mFlinger->getDefaultDisplayDeviceLocked(); - if (display) { + if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) { const auto compositionType = getCompositionType(*display); layerProto->set_hwc_composition_type(static_cast<HwcCompositionType>(compositionType)); LayerProtoHelper::writeToProto(getVisibleRegion(display.get()), diff --git a/services/surfaceflinger/MutexUtils.h b/services/surfaceflinger/MutexUtils.h new file mode 100644 index 0000000000..f8be6f3b85 --- /dev/null +++ b/services/surfaceflinger/MutexUtils.h @@ -0,0 +1,53 @@ +/* + * Copyright 2022 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 <log/log.h> +#include <utils/Mutex.h> + +namespace android { + +struct SCOPED_CAPABILITY ConditionalLock { + ConditionalLock(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) { + if (lock) mutex.lock(); + } + + ~ConditionalLock() RELEASE() { + if (lock) mutex.unlock(); + } + + Mutex& mutex; + const bool lock; +}; + +struct SCOPED_CAPABILITY TimedLock { + TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex) + : mutex(mutex), status(mutex.timedLock(timeout)) { + ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status); + } + + ~TimedLock() RELEASE() { + if (locked()) mutex.unlock(); + } + + bool locked() const { return status == NO_ERROR; } + + Mutex& mutex; + const status_t status; +}; + +} // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 9f5a7df3aa..4fc9d273fc 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -24,7 +24,10 @@ #include "SurfaceFlinger.h" +#include <android-base/parseint.h> #include <android-base/properties.h> +#include <android-base/stringprintf.h> +#include <android-base/strings.h> #include <android/configuration.h> #include <android/gui/IDisplayEventConnection.h> #include <android/hardware/configstore/1.0/ISurfaceFlingerConfigs.h> @@ -49,6 +52,7 @@ #include <configstore/Utils.h> #include <cutils/compiler.h> #include <cutils/properties.h> +#include <ftl/fake_guard.h> #include <ftl/future.h> #include <ftl/small_map.h> #include <gui/BufferQueue.h> @@ -123,6 +127,7 @@ #include "LayerRenderArea.h" #include "LayerVector.h" #include "MonitoredProducer.h" +#include "MutexUtils.h" #include "NativeWindowSurface.h" #include "RefreshRateOverlay.h" #include "RegionSamplingThread.h" @@ -138,49 +143,26 @@ #include "TimeStats/TimeStats.h" #include "TunnelModeEnabledReporter.h" #include "WindowInfosListenerInvoker.h" -#include "android-base/parseint.h" -#include "android-base/stringprintf.h" -#include "android-base/strings.h" #include <aidl/android/hardware/graphics/common/DisplayDecorationSupport.h> #include <aidl/android/hardware/graphics/composer3/DisplayCapability.h> -#define MAIN_THREAD ACQUIRE(mStateLock) RELEASE(mStateLock) - -// Note: The parentheses around `expr` are needed to deduce an lvalue or rvalue reference. -#define ON_MAIN_THREAD(expr) \ - [&]() -> decltype(auto) { \ - LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \ - UnnecessaryLock lock(mStateLock); \ - return (expr); \ - }() - -#define MAIN_THREAD_GUARD(expr) \ - [&]() -> decltype(auto) { \ - LOG_FATAL_IF(std::this_thread::get_id() != mMainThreadId); \ - MainThreadScopedGuard lock(SF_MAIN_THREAD); \ - return (expr); \ - }() - #undef NO_THREAD_SAFETY_ANALYSIS #define NO_THREAD_SAFETY_ANALYSIS \ - _Pragma("GCC error \"Prefer MAIN_THREAD macros or {Conditional,Timed,Unnecessary}Lock.\"") - -using aidl::android::hardware::graphics::common::DisplayDecorationSupport; -using aidl::android::hardware::graphics::composer3::Capability; -using aidl::android::hardware::graphics::composer3::DisplayCapability; -using KernelIdleTimerController = - ::android::scheduler::RefreshRateConfigs::KernelIdleTimerController; + _Pragma("GCC error \"Prefer <ftl/fake_guard.h> or MutexUtils.h helpers.\"") namespace android { using namespace std::string_literals; -using namespace android::hardware::configstore; -using namespace android::hardware::configstore::V1_0; -using namespace android::sysprop; +using namespace hardware::configstore; +using namespace hardware::configstore::V1_0; +using namespace sysprop; + +using aidl::android::hardware::graphics::common::DisplayDecorationSupport; +using aidl::android::hardware::graphics::composer3::Capability; +using aidl::android::hardware::graphics::composer3::DisplayCapability; -using android::hardware::power::Boost; using base::StringAppendF; using gui::DisplayInfo; using gui::IDisplayEventConnection; @@ -191,6 +173,8 @@ using ui::Dataspace; using ui::DisplayPrimaries; using ui::RenderIntent; +using KernelIdleTimerController = scheduler::RefreshRateConfigs::KernelIdleTimerController; + namespace hal = android::hardware::graphics::composer::hal; namespace { @@ -222,38 +206,6 @@ bool isWideColorMode(const ColorMode colorMode) { #pragma clang diagnostic pop -template <typename Mutex> -struct SCOPED_CAPABILITY ConditionalLockGuard { - ConditionalLockGuard(Mutex& mutex, bool lock) ACQUIRE(mutex) : mutex(mutex), lock(lock) { - if (lock) mutex.lock(); - } - - ~ConditionalLockGuard() RELEASE() { - if (lock) mutex.unlock(); - } - - Mutex& mutex; - const bool lock; -}; - -using ConditionalLock = ConditionalLockGuard<Mutex>; - -struct SCOPED_CAPABILITY TimedLock { - TimedLock(Mutex& mutex, nsecs_t timeout, const char* whence) ACQUIRE(mutex) - : mutex(mutex), status(mutex.timedLock(timeout)) { - ALOGE_IF(!locked(), "%s timed out locking: %s (%d)", whence, strerror(-status), status); - } - - ~TimedLock() RELEASE() { - if (locked()) mutex.unlock(); - } - - bool locked() const { return status == NO_ERROR; } - - Mutex& mutex; - const status_t status; -}; - // TODO(b/141333600): Consolidate with DisplayMode::Builder::getDefaultDensity. constexpr float FALLBACK_DENSITY = ACONFIGURATION_DENSITY_TV; @@ -735,7 +687,7 @@ void SurfaceFlinger::bootFinished() { mBootStage = BootStage::FINISHED; if (property_get_bool("sf.debug.show_refresh_rate_overlay", false)) { - ON_MAIN_THREAD(enableRefreshRateOverlay(true)); + FTL_FAKE_GUARD(mStateLock, enableRefreshRateOverlay(true)); } })); } @@ -936,8 +888,9 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( FrameEvent::DEQUEUE_READY, FrameEvent::RELEASE, }; - ConditionalLock _l(mStateLock, - std::this_thread::get_id() != mMainThreadId); + + ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); + if (!getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { outSupported->push_back(FrameEvent::DISPLAY_PRESENT); } @@ -1142,7 +1095,7 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<IBinder>& displayTok } auto future = mScheduler->schedule([=]() -> status_t { - const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); + const auto display = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(displayToken)); if (!display) { ALOGE("Attempt to set allowed display modes for invalid display token %p", displayToken.get()); @@ -1183,7 +1136,9 @@ void SurfaceFlinger::updateInternalStateWithChangedMode() { return; } - const auto upcomingModeInfo = MAIN_THREAD_GUARD(display->getUpcomingActiveMode()); + const auto upcomingModeInfo = + FTL_FAKE_GUARD(kMainThreadContext, display->getUpcomingActiveMode()); + if (!upcomingModeInfo.mode) { // There is no pending mode change. This can happen if the active // display changed and the mode change happened on a different display. @@ -1202,9 +1157,8 @@ void SurfaceFlinger::updateInternalStateWithChangedMode() { return; } - // We just created this display so we can call even if we are not on - // the main thread - MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD); + // We just created this display so we can call even if we are not on the main thread. + ftl::FakeGuard guard(kMainThreadContext); display->setActiveMode(upcomingModeInfo.mode->getId()); const Fps refreshRate = upcomingModeInfo.mode->getFps(); @@ -1289,8 +1243,10 @@ void SurfaceFlinger::setActiveModeInHwcIfNeeded() { constraints.seamlessRequired = false; hal::VsyncPeriodChangeTimeline outTimeline; - const auto status = MAIN_THREAD_GUARD( - display->initiateModeChange(*desiredActiveMode, constraints, &outTimeline)); + const auto status = FTL_FAKE_GUARD(kMainThreadContext, + display->initiateModeChange(*desiredActiveMode, + constraints, &outTimeline)); + if (status != NO_ERROR) { // initiateModeChange may fail if a hotplug event is just about // to be sent. We just log the error in this case. @@ -1323,7 +1279,7 @@ void SurfaceFlinger::setActiveModeInHwcIfNeeded() { } void SurfaceFlinger::disableExpensiveRendering() { - auto future = mScheduler->schedule([=]() MAIN_THREAD { + auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { ATRACE_CALL(); if (mPowerAdvisor.isUsingExpensiveRendering()) { for (const auto& [_, display] : mDisplays) { @@ -1372,7 +1328,7 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col return BAD_VALUE; } - auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t { + auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t { const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("Attempt to set active color mode %s (%d) for invalid display token %p", @@ -1407,17 +1363,17 @@ status_t SurfaceFlinger::setActiveColorMode(const sp<IBinder>& displayToken, Col } status_t SurfaceFlinger::getBootDisplayModeSupport(bool* outSupport) const { - auto future = mScheduler->schedule([=]() MAIN_THREAD mutable -> status_t { - *outSupport = getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG); - return NO_ERROR; - }); - return future.get(); + auto future = mScheduler->schedule( + [this] { return getHwComposer().hasCapability(Capability::BOOT_DISPLAY_CONFIG); }); + + *outSupport = future.get(); + return NO_ERROR; } status_t SurfaceFlinger::setBootDisplayMode(const sp<IBinder>& displayToken, ui::DisplayModeId modeId) { const char* const whence = __func__; - auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t { + auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t { const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("%s: Invalid display token %p", whence, displayToken.get()); @@ -1444,7 +1400,7 @@ status_t SurfaceFlinger::setBootDisplayMode(const sp<IBinder>& displayToken, status_t SurfaceFlinger::clearBootDisplayMode(const sp<IBinder>& displayToken) { const char* const whence = __func__; - auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t { + auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { return getHwComposer().clearBootDisplayMode(*displayId); } else { @@ -1457,7 +1413,7 @@ status_t SurfaceFlinger::clearBootDisplayMode(const sp<IBinder>& displayToken) { void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool on) { const char* const whence = __func__; - static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD { + static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { getHwComposer().setAutoLowLatencyMode(*displayId, on); } else { @@ -1468,7 +1424,7 @@ void SurfaceFlinger::setAutoLowLatencyMode(const sp<IBinder>& displayToken, bool void SurfaceFlinger::setGameContentType(const sp<IBinder>& displayToken, bool on) { const char* const whence = __func__; - static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD { + static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { const auto type = on ? hal::ContentType::GAME : hal::ContentType::NONE; getHwComposer().setContentType(*displayId, type); @@ -1533,7 +1489,7 @@ status_t SurfaceFlinger::setDisplayContentSamplingEnabled(const sp<IBinder>& dis bool enable, uint8_t componentMask, uint64_t maxFrames) { const char* const whence = __func__; - auto future = mScheduler->schedule([=]() MAIN_THREAD -> status_t { + auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) -> status_t { if (const auto displayId = getPhysicalDisplayIdLocked(displayToken)) { return getHwComposer().setDisplayContentSamplingEnabled(*displayId, enable, componentMask, maxFrames); @@ -1610,7 +1566,7 @@ status_t SurfaceFlinger::injectVSync(nsecs_t when) { status_t SurfaceFlinger::getLayerDebugInfo(std::vector<LayerDebugInfo>* outLayers) { outLayers->clear(); auto future = mScheduler->schedule([=] { - const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); + const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()); mDrawingState.traverseInZOrder([&](Layer* layer) { outLayers->push_back(layer->getLayerDebugInfo(display.get())); }); @@ -1722,7 +1678,7 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, } const char* const whence = __func__; - return ftl::chain(mScheduler->schedule([=]() MAIN_THREAD { + return ftl::chain(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { if (const auto display = getDisplayDeviceLocked(displayToken)) { const bool supportsDisplayBrightnessCommand = getHwComposer().getComposer()->isSupported( @@ -1736,7 +1692,9 @@ status_t SurfaceFlinger::setDisplayBrightness(const sp<IBinder>& displayToken, compositionDisplay->editState().displayBrightnessNits; compositionDisplay->setDisplayBrightness(brightness.sdrWhitePointNits, brightness.displayBrightnessNits); - MAIN_THREAD_GUARD(display->stageBrightness(brightness.displayBrightness)); + FTL_FAKE_GUARD(kMainThreadContext, + display->stageBrightness(brightness.displayBrightness)); + if (brightness.sdrWhitePointNits / brightness.displayBrightnessNits != currentDimmingRatio) { scheduleComposite(FrameHint::kNone); @@ -1806,6 +1764,7 @@ status_t SurfaceFlinger::removeHdrLayerInfoListener( } status_t SurfaceFlinger::notifyPowerBoost(int32_t boostId) { + using hardware::power::Boost; Boost powerBoost = static_cast<Boost>(boostId); if (powerBoost == Boost::INTERACTION) { @@ -1966,7 +1925,7 @@ void SurfaceFlinger::setVsyncEnabled(bool enabled) { ATRACE_CALL(); // On main thread to avoid race conditions with display power state. - static_cast<void>(mScheduler->schedule([=]() MAIN_THREAD { + static_cast<void>(mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { mHWCVsyncPendingState = enabled ? hal::Vsync::ENABLE : hal::Vsync::DISABLE; if (const auto display = getDefaultDisplayDeviceLocked(); @@ -2014,8 +1973,8 @@ nsecs_t SurfaceFlinger::calculateExpectedPresentTime(DisplayStatInfo stats) cons : stats.vsyncTime + stats.vsyncPeriod; } -bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) { - MainThreadScopedGuard mainThreadGuard(SF_MAIN_THREAD); +bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expectedVsyncTime) + FTL_FAKE_GUARD(kMainThreadContext) { // we set this once at the beginning of commit to ensure consistency throughout the whole frame mPowerHintSessionData.sessionEnabled = mPowerAdvisor.usePowerHintSession(); if (mPowerHintSessionData.sessionEnabled) { @@ -2181,20 +2140,21 @@ bool SurfaceFlinger::commit(nsecs_t frameTime, int64_t vsyncId, nsecs_t expected mLayerTracing.notify(mVisibleRegionsDirty, frameTime); } - MAIN_THREAD_GUARD(persistDisplayBrightness(mustComposite)); + persistDisplayBrightness(mustComposite); return mustComposite && CC_LIKELY(mBootStage != BootStage::BOOTLOADER); } -void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId) { +void SurfaceFlinger::composite(nsecs_t frameTime, int64_t vsyncId) + FTL_FAKE_GUARD(kMainThreadContext) { ATRACE_FORMAT("%s %" PRId64, __func__, vsyncId); - MainThreadScopedGuard mainThreadGuard(SF_MAIN_THREAD); + if (mPowerHintSessionData.sessionEnabled) { mPowerHintSessionData.compositeStart = systemTime(); } compositionengine::CompositionRefreshArgs refreshArgs; - const auto& displays = ON_MAIN_THREAD(mDisplays); + const auto& displays = FTL_FAKE_GUARD(mStateLock, mDisplays); refreshArgs.outputs.reserve(displays.size()); for (const auto& [_, display] : displays) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); @@ -2432,7 +2392,7 @@ void SurfaceFlinger::postComposition() { ATRACE_CALL(); ALOGV("postComposition"); - const auto* display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()).get(); + const auto* display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get(); getBE().mGlCompositionDoneTimeline.updateSignalTimes(); std::shared_ptr<FenceTime> glCompositionDoneFenceTime; @@ -2632,44 +2592,37 @@ void SurfaceFlinger::postComposition() { } FloatRect SurfaceFlinger::getMaxDisplayBounds() { - // Find the largest width and height among all the displays. - int32_t maxDisplayWidth = 0; - int32_t maxDisplayHeight = 0; - - // If there are no displays, set a valid display bounds so we can still compute a valid layer - // bounds. - if (ON_MAIN_THREAD(mDisplays.size()) == 0) { - maxDisplayWidth = maxDisplayHeight = 5000; - } - - for (const auto& pair : ON_MAIN_THREAD(mDisplays)) { - const auto& displayDevice = pair.second; - int32_t width = displayDevice->getWidth(); - int32_t height = displayDevice->getHeight(); - if (width > maxDisplayWidth) { - maxDisplayWidth = width; - } - if (height > maxDisplayHeight) { - maxDisplayHeight = height; - } - } + const ui::Size maxSize = [this] { + ftl::FakeGuard guard(mStateLock); + + // The LayerTraceGenerator tool runs without displays. + if (mDisplays.empty()) return ui::Size{5000, 5000}; + + return std::accumulate(mDisplays.begin(), mDisplays.end(), ui::kEmptySize, + [](ui::Size size, const auto& pair) -> ui::Size { + const auto& display = pair.second; + return {std::max(size.getWidth(), display->getWidth()), + std::max(size.getHeight(), display->getHeight())}; + }); + }(); // Ignore display bounds for now since they will be computed later. Use a large Rect bound // to ensure it's bigger than an actual display will be. - FloatRect maxBounds = FloatRect(-maxDisplayWidth * 10, -maxDisplayHeight * 10, - maxDisplayWidth * 10, maxDisplayHeight * 10); - return maxBounds; + const float xMax = maxSize.getWidth() * 10.f; + const float yMax = maxSize.getHeight() * 10.f; + + return {-xMax, -yMax, xMax, yMax}; } void SurfaceFlinger::computeLayerBounds() { - FloatRect maxBounds = getMaxDisplayBounds(); + const FloatRect maxBounds = getMaxDisplayBounds(); for (const auto& layer : mDrawingState.layersSortedByZ) { layer->computeBounds(maxBounds, ui::Transform(), 0.f /* shadowRadius */); } } void SurfaceFlinger::postFrame() { - const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); + const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()); if (display && getHwComposer().isConnected(display->getPhysicalId())) { uint32_t flipCount = display->getPageFlipCount(); if (flipCount % LOG_FRAME_STATS_PERIOD == 0) { @@ -2923,7 +2876,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( RenderIntent::COLORIMETRIC, Dataspace::UNKNOWN}); if (!state.isVirtual()) { - MAIN_THREAD_GUARD(display->setActiveMode(state.physical->activeMode->getId())); + FTL_FAKE_GUARD(kMainThreadContext, + display->setActiveMode(state.physical->activeMode->getId())); display->setDeviceProductInfo(state.physical->deviceProductInfo); } @@ -3293,7 +3247,7 @@ void SurfaceFlinger::persistDisplayBrightness(bool needsComposite) { return; } - for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) { + for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { if (const auto brightness = display->getStagedBrightness(); brightness) { if (!needsComposite) { const status_t error = @@ -3316,7 +3270,7 @@ void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos, std::vector<DisplayInfo>& outDisplayInfos) { ftl::SmallMap<ui::LayerStack, DisplayDevice::InputInfo, 4> displayInputInfos; - for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) { + for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { const auto layerStack = display->getLayerStack(); const auto info = display->getInputInfo(); @@ -3361,7 +3315,7 @@ void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos, void SurfaceFlinger::updateCursorAsync() { compositionengine::CompositionRefreshArgs refreshArgs; - for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) { + for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { if (HalDisplayId::tryCast(display->getId())) { refreshArgs.outputs.push_back(display->getCompositionDisplay()); } @@ -3546,7 +3500,7 @@ void SurfaceFlinger::commitOffscreenLayers() { } void SurfaceFlinger::invalidateLayerStack(const sp<const Layer>& layer, const Region& dirty) { - for (const auto& [token, displayDevice] : ON_MAIN_THREAD(mDisplays)) { + for (const auto& [token, displayDevice] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { auto display = displayDevice->getCompositionDisplay(); if (display->includesLayer(layer->getOutputFilter())) { display->editState().dirtyRegion.orSelf(dirty); @@ -4832,7 +4786,8 @@ void SurfaceFlinger::onInitializeDisplays() { void SurfaceFlinger::initializeDisplays() { // Async since we may be called from the main thread. - static_cast<void>(mScheduler->schedule([this]() MAIN_THREAD { onInitializeDisplays(); })); + static_cast<void>( + mScheduler->schedule([this]() FTL_FAKE_GUARD(mStateLock) { onInitializeDisplays(); })); } void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal::PowerMode mode) { @@ -4932,7 +4887,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: } void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { - auto future = mScheduler->schedule([=]() MAIN_THREAD { + auto future = mScheduler->schedule([=]() FTL_FAKE_GUARD(mStateLock) { const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("Attempt to set power mode %d for invalid display token %p", mode, @@ -4979,7 +4934,7 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { bool dumpLayers = true; { - TimedLock lock(mStateLock, s2ns(1), __FUNCTION__); + TimedLock lock(mStateLock, s2ns(1), __func__); if (!lock.locked()) { StringAppendF(&result, "Dumping without lock after timeout: %s (%d)\n", strerror(-lock.status), lock.status); @@ -5067,8 +5022,6 @@ void SurfaceFlinger::dumpFrameTimeline(const DumpArgs& args, std::string& result mFrameTimeline->parseArgs(args, result); } -// This should only be called from the main thread. Otherwise it would need -// the lock and should use mCurrentState rather than mDrawingState. void SurfaceFlinger::logFrameStats() { mDrawingState.traverse([&](Layer* layer) { layer->logFrameStats(); @@ -5226,7 +5179,7 @@ LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t traceFlags) const { } void SurfaceFlinger::dumpDisplayProto(LayersTraceProto& layersTraceProto) const { - for (const auto& [_, display] : ON_MAIN_THREAD(mDisplays)) { + for (const auto& [_, display] : FTL_FAKE_GUARD(mStateLock, mDisplays)) { DisplayProto* displayProto = layersTraceProto.add_displays(); displayProto->set_id(display->getId().value); displayProto->set_name(display->getDisplayName()); @@ -5867,7 +5820,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r int64_t startingTime = (fixedStartingTime) ? fixedStartingTime : systemTime(); mScheduler - ->schedule([&]() MAIN_THREAD { + ->schedule([&]() FTL_FAKE_GUARD(mStateLock) { mLayerTracing.notify("start", startingTime); }) .wait(); @@ -5980,10 +5933,12 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r switch (n = data.readInt32()) { case 0: case 1: - ON_MAIN_THREAD(enableRefreshRateOverlay(static_cast<bool>(n))); + FTL_FAKE_GUARD(mStateLock, + enableRefreshRateOverlay(static_cast<bool>(n))); break; default: { - reply->writeBool(ON_MAIN_THREAD(isRefreshRateOverlayEnabled())); + reply->writeBool( + FTL_FAKE_GUARD(mStateLock, isRefreshRateOverlayEnabled())); } } }); @@ -6021,7 +5976,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return mScheduler ->schedule([this] { const auto display = - ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); + FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()); // This is a little racy, but not in a way that hurts anything. As // we grab the defaultMode from the display manager policy, we could @@ -6043,7 +5998,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r return mScheduler ->schedule([this] { const auto display = - ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); + FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()); constexpr bool kOverridePolicy = true; return setDesiredDisplayModeSpecsInternal(display, {}, kOverridePolicy); @@ -6159,7 +6114,7 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { // Update the overlay on the main thread to avoid race conditions with // mRefreshRateConfigs->getActiveMode() static_cast<void>(mScheduler->schedule([=] { - const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked()); + const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()); if (!display) { ALOGW("%s: default display is null", __func__); return; @@ -6957,7 +6912,7 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs( } auto future = mScheduler->schedule([=]() -> status_t { - const auto display = ON_MAIN_THREAD(getDisplayDeviceLocked(displayToken)); + const auto display = FTL_FAKE_GUARD(mStateLock, getDisplayDeviceLocked(displayToken)); if (!display) { ALOGE("Attempt to set desired display modes for invalid display token %p", displayToken.get()); @@ -7202,7 +7157,7 @@ uint32_t SurfaceFlinger::getMaxAcquiredBufferCountForCurrentRefreshRate(uid_t ui if (const auto frameRateOverride = mScheduler->getFrameRateOverride(uid)) { refreshRate = *frameRateOverride; } else if (!getHwComposer().isHeadless()) { - if (const auto display = ON_MAIN_THREAD(getDefaultDisplayDeviceLocked())) { + if (const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked())) { refreshRate = display->refreshRateConfigs().getActiveMode()->getFps(); } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f2636b446f..97b0e8db5c 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -64,6 +64,7 @@ #include "Scheduler/Scheduler.h" #include "Scheduler/VsyncModulator.h" #include "SurfaceFlingerFactory.h" +#include "ThreadContext.h" #include "TracedOrdinal.h" #include "Tracing/LayerTracing.h" #include "Tracing/TransactionTracing.h" @@ -183,11 +184,6 @@ struct SurfaceFlingerBE { std::atomic<nsecs_t> mLastSwapTime = 0; }; -struct SCOPED_CAPABILITY UnnecessaryLock { - explicit UnnecessaryLock(Mutex& mutex) ACQUIRE(mutex) {} - ~UnnecessaryLock() RELEASE() {} -}; - class SurfaceFlinger : public BnSurfaceComposer, public PriorityDumper, private IBinder::DeathRecipient, @@ -740,7 +736,7 @@ private: void updateLayerGeometry(); void updateInputFlinger(); - void persistDisplayBrightness(bool needsComposite) REQUIRES(SF_MAIN_THREAD); + void persistDisplayBrightness(bool needsComposite) REQUIRES(kMainThreadContext); void buildWindowInfos(std::vector<gui::WindowInfo>& outWindowInfos, std::vector<gui::DisplayInfo>& outDisplayInfos); void commitInputWindowCommands() REQUIRES(mStateLock); @@ -973,7 +969,7 @@ private: void setCompositorTimingSnapped(const DisplayStatInfo& stats, nsecs_t compositeToPresentLatency); - void postFrame(); + void postFrame() REQUIRES(kMainThreadContext); /* * Display management @@ -1088,7 +1084,7 @@ private: void clearStatsLocked(const DumpArgs& args, std::string& result); void dumpTimeStats(const DumpArgs& args, bool asProto, std::string& result) const; void dumpFrameTimeline(const DumpArgs& args, std::string& result) const; - void logFrameStats(); + void logFrameStats() REQUIRES(kMainThreadContext); void dumpVSync(std::string& result) const REQUIRES(mStateLock); void dumpStaticScreenStats(std::string& result) const; @@ -1431,7 +1427,7 @@ private: nsecs_t commitStart; nsecs_t compositeStart; nsecs_t presentEnd; - } mPowerHintSessionData GUARDED_BY(SF_MAIN_THREAD); + } mPowerHintSessionData GUARDED_BY(kMainThreadContext); nsecs_t mAnimationTransactionTimeout = s2ns(5); diff --git a/services/surfaceflinger/MainThreadGuard.h b/services/surfaceflinger/ThreadContext.h index c1aa118492..85c379d58f 100644 --- a/services/surfaceflinger/MainThreadGuard.h +++ b/services/surfaceflinger/ThreadContext.h @@ -1,5 +1,5 @@ /* - * Copyright 2021 The Android Open Source Project + * Copyright 2022 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. @@ -16,20 +16,10 @@ #pragma once -#include <utils/Mutex.h> - namespace android { -namespace { -// Helps to ensure that some functions runs on SF's main thread by using the -// clang thread safety annotations. -class CAPABILITY("mutex") MainThreadGuard { -} SF_MAIN_THREAD; +// Enforces exclusive access by the main thread. +constexpr class [[clang::capability("mutex")]] { +} kMainThreadContext; -struct SCOPED_CAPABILITY MainThreadScopedGuard { -public: - explicit MainThreadScopedGuard(MainThreadGuard& mutex) ACQUIRE(mutex) {} - ~MainThreadScopedGuard() RELEASE() {} -}; -} // namespace } // namespace android diff --git a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h index 1d0f62b99b..a80aca2f73 100644 --- a/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h +++ b/services/surfaceflinger/fuzzer/surfaceflinger_fuzzers_utils.h @@ -22,6 +22,7 @@ #include <compositionengine/impl/CompositionEngine.h> #include <compositionengine/impl/Display.h> #include <compositionengine/impl/OutputLayerCompositionState.h> +#include <ftl/fake_guard.h> #include <gui/LayerDebugInfo.h> #include <gui/ScreenCaptureResults.h> #include <gui/SurfaceComposerClient.h> @@ -50,6 +51,7 @@ #include "SurfaceFlinger.h" #include "SurfaceFlingerDefaultFactory.h" #include "SurfaceInterceptor.h" +#include "ThreadContext.h" #include "TimeStats/TimeStats.h" #include "renderengine/mock/RenderEngine.h" @@ -445,7 +447,7 @@ public: mFlinger->clearStatsLocked(dumpArgs, result); mFlinger->dumpTimeStats(dumpArgs, fdp->ConsumeBool(), result); - mFlinger->logFrameStats(); + FTL_FAKE_GUARD(kMainThreadContext, mFlinger->logFrameStats()); result = fdp->ConsumeRandomLengthString().c_str(); mFlinger->dumpFrameTimeline(dumpArgs, result); @@ -651,7 +653,7 @@ public: updateCompositorTiming(&mFdp); mFlinger->setCompositorTimingSnapped({}, mFdp.ConsumeIntegral<nsecs_t>()); - mFlinger->postFrame(); + FTL_FAKE_GUARD(kMainThreadContext, mFlinger->postFrame()); mFlinger->calculateExpectedPresentTime({}); mFlinger->enableHalVirtualDisplays(mFdp.ConsumeBool()); diff --git a/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp b/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp index 73c60e1035..225ad163d9 100644 --- a/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp +++ b/services/surfaceflinger/tests/unittests/DisplayDevice_SetDisplayBrightnessTest.cpp @@ -19,6 +19,7 @@ #include "DisplayTransactionTestHelpers.h" +#include <ftl/fake_guard.h> #include <gmock/gmock.h> #include <gtest/gtest.h> @@ -35,7 +36,7 @@ public: }; TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessNoComposite) { - MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD); + ftl::FakeGuard guard(kMainThreadContext); sp<DisplayDevice> displayDevice = getDisplayDevice(); EXPECT_EQ(std::nullopt, displayDevice->getStagedBrightness()); @@ -52,7 +53,7 @@ TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessNoComposite) { } TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessWithComposite) { - MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD); + ftl::FakeGuard guard(kMainThreadContext); sp<DisplayDevice> displayDevice = getDisplayDevice(); EXPECT_EQ(std::nullopt, displayDevice->getStagedBrightness()); @@ -70,7 +71,7 @@ TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessWithComposite) { } TEST_F(SetDisplayBrightnessTest, persistDisplayBrightnessWithCompositeShortCircuitsOnNoOp) { - MainThreadScopedGuard fakeMainThreadGuard(SF_MAIN_THREAD); + ftl::FakeGuard guard(kMainThreadContext); sp<DisplayDevice> displayDevice = getDisplayDevice(); EXPECT_EQ(std::nullopt, displayDevice->getStagedBrightness()); |