diff options
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 2041 |
1 files changed, 1117 insertions, 924 deletions
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 0f8e3bfb86..596ec12d9e 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -40,6 +40,8 @@ #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> #include <binder/PermissionCache.h> +#include <com_android_graphics_surfaceflinger_flags.h> +#include <common/FlagManager.h> #include <compositionengine/CompositionEngine.h> #include <compositionengine/CompositionRefreshArgs.h> #include <compositionengine/Display.h> @@ -55,6 +57,7 @@ #include <configstore/Utils.h> #include <cutils/compiler.h> #include <cutils/properties.h> +#include <fmt/format.h> #include <ftl/algorithm.h> #include <ftl/concat.h> #include <ftl/fake_guard.h> @@ -64,7 +67,6 @@ #include <gui/BufferQueue.h> #include <gui/DebugEGLImageTracker.h> #include <gui/IProducerListener.h> -#include <gui/LayerDebugInfo.h> #include <gui/LayerMetadata.h> #include <gui/LayerState.h> #include <gui/Surface.h> @@ -148,13 +150,13 @@ #include "MutexUtils.h" #include "NativeWindowSurface.h" #include "RegionSamplingThread.h" +#include "RenderAreaBuilder.h" #include "Scheduler/EventThread.h" #include "Scheduler/LayerHistory.h" #include "Scheduler/Scheduler.h" #include "Scheduler/VsyncConfiguration.h" #include "Scheduler/VsyncModulator.h" #include "ScreenCaptureOutput.h" -#include "StartPropertySetThread.h" #include "SurfaceFlingerProperties.h" #include "TimeStats/TimeStats.h" #include "TunnelModeEnabledReporter.h" @@ -169,10 +171,6 @@ #define NO_THREAD_SAFETY_ANALYSIS \ _Pragma("GCC error \"Prefer <ftl/fake_guard.h> or MutexUtils.h helpers.\"") -// To enable layer borders in the system, change the below flag to true. -#undef DOES_CONTAIN_BORDER -#define DOES_CONTAIN_BORDER false - namespace android { using namespace std::chrono_literals; using namespace std::string_literals; @@ -233,7 +231,7 @@ bool validateCompositionDataspace(Dataspace dataspace) { return dataspace == Dataspace::V0_SRGB || dataspace == Dataspace::DISPLAY_P3; } -std::chrono::milliseconds getIdleTimerTimeout(DisplayId displayId) { +std::chrono::milliseconds getIdleTimerTimeout(PhysicalDisplayId displayId) { if (const int32_t displayIdleTimerMs = base::GetIntProperty("debug.sf.set_idle_timer_ms_"s + std::to_string(displayId.value), @@ -247,7 +245,7 @@ std::chrono::milliseconds getIdleTimerTimeout(DisplayId displayId) { return std::chrono::milliseconds(millis); } -bool getKernelIdleTimerSyspropConfig(DisplayId displayId) { +bool getKernelIdleTimerSyspropConfig(PhysicalDisplayId displayId) { const bool displaySupportKernelIdleTimer = base::GetBoolProperty("debug.sf.support_kernel_idle_timer_"s + std::to_string(displayId.value), @@ -429,7 +427,8 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory, SkipInitializationTag) mInternalDisplayDensity( getDensityFromProperty("ro.sf.lcd_density", !mEmulatedDisplayDensity)), mPowerAdvisor(std::make_unique<Hwc2::impl::PowerAdvisor>(*this)), - mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()) { + mWindowInfosListenerInvoker(sp<WindowInfosListenerInvoker>::make()), + mSkipPowerOnForQuiescent(base::GetBoolProperty("ro.boot.quiescent"s, false)) { ALOGI("Using HWComposer service: %s", mHwcServiceName.c_str()); } @@ -536,8 +535,6 @@ SurfaceFlinger::SurfaceFlinger(Factory& factory) : SurfaceFlinger(factory, SkipI mLayerLifecycleManagerEnabled = base::GetBoolProperty("persist.debug.sf.enable_layer_lifecycle_manager"s, true); - mLegacyFrontEndEnabled = !mLayerLifecycleManagerEnabled || - base::GetBoolProperty("persist.debug.sf.enable_legacy_frontend"s, false); // These are set by the HWC implementation to indicate that they will use the workarounds. mIsHotplugErrViaNegVsync = @@ -567,20 +564,25 @@ void SurfaceFlinger::binderDied(const wp<IBinder>&) { initializeDisplays(); })); - startBootAnim(); + mInitBootPropsFuture.callOnce([this] { + return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); + }); + + mInitBootPropsFuture.wait(); } void SurfaceFlinger::run() { mScheduler->run(); } -sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secure, - float requestedRefreshRate) { - // onTransact already checks for some permissions, but adding an additional check here. - // This is to ensure that only system and graphics can request to create a secure +sp<IBinder> SurfaceFlinger::createVirtualDisplay(const std::string& displayName, bool isSecure, + const std::string& uniqueId, + float requestedRefreshRate) { + // SurfaceComposerAIDL checks for some permissions, but adding an additional check here. + // This is to ensure that only root, system, and graphics can request to create a secure // display. Secure displays can show secure content so we add an additional restriction on it. - const int uid = IPCThreadState::self()->getCallingUid(); - if (secure && uid != AID_GRAPHICS && uid != AID_SYSTEM) { + const uid_t uid = IPCThreadState::self()->getCallingUid(); + if (isSecure && uid != AID_ROOT && uid != AID_GRAPHICS && uid != AID_SYSTEM) { ALOGE("Only privileged processes can create a secure display"); return nullptr; } @@ -604,32 +606,34 @@ sp<IBinder> SurfaceFlinger::createDisplay(const String8& displayName, bool secur Mutex::Autolock _l(mStateLock); // Display ID is assigned when virtual display is allocated by HWC. DisplayDeviceState state; - state.isSecure = secure; + state.isSecure = isSecure; // Set display as protected when marked as secure to ensure no behavior change // TODO (b/314820005): separate as a different arg when creating the display. - state.isProtected = secure; + state.isProtected = isSecure; state.displayName = displayName; + state.uniqueId = uniqueId; state.requestedRefreshRate = Fps::fromValue(requestedRefreshRate); mCurrentState.displays.add(token, state); return token; } -void SurfaceFlinger::destroyDisplay(const sp<IBinder>& displayToken) { +status_t SurfaceFlinger::destroyVirtualDisplay(const sp<IBinder>& displayToken) { Mutex::Autolock lock(mStateLock); const ssize_t index = mCurrentState.displays.indexOfKey(displayToken); if (index < 0) { ALOGE("%s: Invalid display token %p", __func__, displayToken.get()); - return; + return NAME_NOT_FOUND; } const DisplayDeviceState& state = mCurrentState.displays.valueAt(index); if (state.physical) { ALOGE("%s: Invalid operation on physical display", __func__); - return; + return INVALID_OPERATION; } mCurrentState.displays.removeItemsAt(index); setTransactionFlags(eDisplayTransactionNeeded); + return NO_ERROR; } void SurfaceFlinger::enableHalVirtualDisplays(bool enable) { @@ -723,13 +727,10 @@ void SurfaceFlinger::bootFinished() { } mBootFinished = true; FlagManager::getMutableInstance().markBootCompleted(); - if (mStartPropertySetThread->join() != NO_ERROR) { - ALOGE("Join StartPropertySetThread failed!"); - } - if (mRenderEnginePrimeCacheFuture.valid()) { - mRenderEnginePrimeCacheFuture.get(); - } + mInitBootPropsFuture.wait(); + mRenderEnginePrimeCacheFuture.wait(); + const nsecs_t now = systemTime(); const nsecs_t duration = now - mBootTime; ALOGI("Boot is finished (%ld ms)", long(ns2ms(duration)) ); @@ -797,6 +798,8 @@ void chooseRenderEngineType(renderengine::RenderEngineCreationArgs::Builder& bui char prop[PROPERTY_VALUE_MAX]; property_get(PROPERTY_DEBUG_RENDERENGINE_BACKEND, prop, ""); + // TODO: b/293371537 - Once GraphiteVk is deemed relatively stable, log a warning that + // PROPERTY_DEBUG_RENDERENGINE_BACKEND is deprecated if (strcmp(prop, "skiagl") == 0) { builder.setThreaded(renderengine::RenderEngine::Threaded::NO) .setGraphicsApi(renderengine::RenderEngine::GraphicsApi::GL); @@ -811,14 +814,51 @@ void chooseRenderEngineType(renderengine::RenderEngineCreationArgs::Builder& bui .setGraphicsApi(renderengine::RenderEngine::GraphicsApi::VK); } else { const auto kVulkan = renderengine::RenderEngine::GraphicsApi::VK; - const bool useVulkan = FlagManager::getInstance().vulkan_renderengine() && +// TODO: b/341728634 - Clean up conditional compilation. +// Note: this guard in particular must check e.g. +// COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_GRAPHITE_RENDERENGINE directly (instead of calling e.g. +// COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS(GRAPHITE_RENDERENGINE)) because that macro is undefined +// in the libsurfaceflingerflags_test variant of com_android_graphics_surfaceflinger_flags.h, which +// is used by layertracegenerator (which also needs SurfaceFlinger.cpp). :) +#if COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_GRAPHITE_RENDERENGINE || \ + COM_ANDROID_GRAPHICS_SURFACEFLINGER_FLAGS_FORCE_COMPILE_GRAPHITE_RENDERENGINE + const bool useGraphite = FlagManager::getInstance().graphite_renderengine() && renderengine::RenderEngine::canSupport(kVulkan); +#else + const bool useGraphite = false; + if (FlagManager::getInstance().graphite_renderengine()) { + ALOGE("RenderEngine's Graphite Skia backend was requested with the " + "debug.renderengine.graphite system property, but it is not compiled in this " + "build! Falling back to Ganesh backend selection logic."); + } +#endif + const bool useVulkan = useGraphite || + (FlagManager::getInstance().vulkan_renderengine() && + renderengine::RenderEngine::canSupport(kVulkan)); + + builder.setSkiaBackend(useGraphite ? renderengine::RenderEngine::SkiaBackend::GRAPHITE + : renderengine::RenderEngine::SkiaBackend::GANESH); builder.setGraphicsApi(useVulkan ? kVulkan : renderengine::RenderEngine::GraphicsApi::GL); } } -// Do not call property_set on main thread which will be blocked by init -// Use StartPropertySetThread instead. +/** + * Choose a suggested blurring algorithm if supportsBlur is true. By default Kawase will be + * suggested as it's faster than a full Gaussian blur and looks close enough. + */ +renderengine::RenderEngine::BlurAlgorithm chooseBlurAlgorithm(bool supportsBlur) { + if (!supportsBlur) { + return renderengine::RenderEngine::BlurAlgorithm::NONE; + } + + auto const algorithm = base::GetProperty(PROPERTY_DEBUG_RENDERENGINE_BLUR_ALGORITHM, ""); + if (algorithm == "gaussian") { + return renderengine::RenderEngine::BlurAlgorithm::GAUSSIAN; + } else { + return renderengine::RenderEngine::BlurAlgorithm::KAWASE; + } +} + void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { ATRACE_CALL(); ALOGI( "SurfaceFlinger's main thread ready to run. " @@ -834,7 +874,7 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { .setImageCacheSize(maxFrameBufferAcquiredBuffers) .setEnableProtectedContext(enable_protected_contents(false)) .setPrecacheToneMapperShaderOnly(false) - .setSupportsBackgroundBlur(mSupportsBlur) + .setBlurAlgorithm(chooseBlurAlgorithm(mSupportsBlur)) .setContextPriority( useContextPriority ? renderengine::RenderEngine::ContextPriority::REALTIME @@ -851,10 +891,17 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { } mCompositionEngine->setTimeStats(mTimeStats); + mCompositionEngine->setHwComposer(getFactory().createHWComposer(mHwcServiceName)); - mCompositionEngine->getHwComposer().setCallback(*this); + auto& composer = mCompositionEngine->getHwComposer(); + composer.setCallback(*this); + mDisplayModeController.setHwComposer(&composer); + ClientCache::getInstance().setRenderEngine(&getRenderEngine()); + mHasReliablePresentFences = + !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE); + enableLatchUnsignaledConfig = getLatchUnsignaledConfig(); if (base::GetBoolProperty("debug.sf.enable_hwc_vds"s, false)) { @@ -888,6 +935,20 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { // initializing the Scheduler after configureLocked, once decoupled from DisplayDevice. initScheduler(display); + // Start listening after creating the Scheduler, since the listener calls into it. + mDisplayModeController.setActiveModeListener( + display::DisplayModeController::ActiveModeListener::make( + [this](PhysicalDisplayId displayId, Fps vsyncRate, Fps renderRate) { + // This callback cannot lock mStateLock, as some callers already lock it. + // Instead, switch context to the main thread. + static_cast<void>(mScheduler->schedule([=, + this]() FTL_FAKE_GUARD(mStateLock) { + if (const auto display = getDisplayDeviceLocked(displayId)) { + display->updateRefreshRateOverlayRate(vsyncRate, renderRate); + } + })); + })); + mLayerTracing.setTakeLayersSnapshotProtoFunction([&](uint32_t traceFlags) { auto snapshot = perfetto::protos::LayersSnapshotProto{}; mScheduler @@ -917,29 +978,65 @@ void SurfaceFlinger::init() FTL_FAKE_GUARD(kMainThreadContext) { ALOGW("Can't set SCHED_OTHER for primeCache"); } - bool shouldPrimeUltraHDR = - base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false); - mRenderEnginePrimeCacheFuture = getRenderEngine().primeCache(shouldPrimeUltraHDR); + mRenderEnginePrimeCacheFuture.callOnce([this] { + renderengine::PrimeCacheConfig config; + config.cacheHolePunchLayer = + base::GetBoolProperty("debug.sf.prime_shader_cache.hole_punch"s, true); + config.cacheSolidLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.solid_layers"s, true); + config.cacheSolidDimmedLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.solid_dimmed_layers"s, true); + config.cacheImageLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.image_layers"s, true); + config.cacheImageDimmedLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.image_dimmed_layers"s, true); + config.cacheClippedLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.clipped_layers"s, true); + config.cacheShadowLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.shadow_layers"s, true); + config.cachePIPImageLayers = + base::GetBoolProperty("debug.sf.prime_shader_cache.pip_image_layers"s, true); + config.cacheTransparentImageDimmedLayers = base:: + GetBoolProperty("debug.sf.prime_shader_cache.transparent_image_dimmed_layers"s, + true); + config.cacheClippedDimmedImageLayers = base:: + GetBoolProperty("debug.sf.prime_shader_cache.clipped_dimmed_image_layers"s, + true); + // ro.surface_flinger.prime_chader_cache.ultrahdr exists as a previous ro property + // which we maintain for backwards compatibility. + config.cacheUltraHDR = + base::GetBoolProperty("ro.surface_flinger.prime_shader_cache.ultrahdr"s, false); + return getRenderEngine().primeCache(config); + }); if (setSchedFifo(true) != NO_ERROR) { ALOGW("Can't set SCHED_FIFO after primeCache"); } } - // Inform native graphics APIs whether the present timestamp is supported: - - const bool presentFenceReliable = - !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE); - mStartPropertySetThread = getFactory().createStartPropertySetThread(presentFenceReliable); - - if (mStartPropertySetThread->Start() != NO_ERROR) { - ALOGE("Run StartPropertySetThread failed!"); - } + // Avoid blocking the main thread on `init` to set properties. + mInitBootPropsFuture.callOnce([this] { + return std::async(std::launch::async, &SurfaceFlinger::initBootProperties, this); + }); initTransactionTraceWriter(); ALOGV("Done initializing"); } +// During boot, offload `initBootProperties` to another thread. `property_set` depends on +// `property_service`, which may be delayed by slow operations like `mount_all --late` in +// the `init` process. See b/34499826 and b/63844978. +void SurfaceFlinger::initBootProperties() { + property_set("service.sf.present_timestamp", mHasReliablePresentFences ? "1" : "0"); + + if (base::GetBoolProperty("debug.sf.boot_animation"s, true)) { + // Reset and (if needed) start BootAnimation. + property_set("service.bootanim.exit", "0"); + property_set("service.bootanim.progress", "0"); + property_set("ctl.start", "bootanim"); + } +} + void SurfaceFlinger::initTransactionTraceWriter() { if (!mTransactionTracing) { return; @@ -951,8 +1048,9 @@ void SurfaceFlinger::initTransactionTraceWriter() { ALOGD("TransactionTraceWriter: file=%s already exists", filename.c_str()); return; } - mTransactionTracing->flush(); + ALOGD("TransactionTraceWriter: writing file=%s", filename.c_str()); mTransactionTracing->writeToFile(filename); + mTransactionTracing->flush(); }; if (std::this_thread::get_id() == mMainThreadId) { writeFn(); @@ -979,18 +1077,6 @@ void SurfaceFlinger::readPersistentProperties() { static_cast<ui::ColorMode>(base::GetIntProperty("persist.sys.sf.color_mode"s, 0)); } -void SurfaceFlinger::startBootAnim() { - // Start boot animation service by setting a property mailbox - // if property setting thread is already running, Start() will be just a NOP - mStartPropertySetThread->Start(); - // Wait until property was set - if (mStartPropertySetThread->join() != NO_ERROR) { - ALOGE("Join StartPropertySetThread failed!"); - } -} - -// ---------------------------------------------------------------------------- - status_t SurfaceFlinger::getSupportedFrameTimestamps( std::vector<FrameEvent>* outSupported) const { *outSupported = { @@ -1004,9 +1090,7 @@ status_t SurfaceFlinger::getSupportedFrameTimestamps( FrameEvent::RELEASE, }; - ConditionalLock lock(mStateLock, std::this_thread::get_id() != mMainThreadId); - - if (!getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + if (mHasReliablePresentFences) { outSupported->push_back(FrameEvent::DISPLAY_PRESENT); } return NO_ERROR; @@ -1230,19 +1314,19 @@ void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode) { ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str()); - const auto display = getDisplayDeviceLocked(displayId); - if (!display) { - ALOGW("%s: display is no longer valid", __func__); - return; - } - const bool emitEvent = desiredMode.emitEvent; - switch (display->setDesiredMode(std::move(desiredMode))) { - case DisplayDevice::DesiredModeAction::InitiateDisplayModeSwitch: - // DisplayDevice::setDesiredMode updated the render rate, so inform Scheduler. - mScheduler->setRenderRate(displayId, - display->refreshRateSelector().getActiveMode().fps); + using DesiredModeAction = display::DisplayModeController::DesiredModeAction; + + switch (mDisplayModeController.setDesiredMode(displayId, std::move(desiredMode))) { + case DesiredModeAction::InitiateDisplayModeSwitch: { + const auto selectorPtr = mDisplayModeController.selectorPtrFor(displayId); + if (!selectorPtr) break; + + const Fps renderRate = selectorPtr->getActiveMode().fps; + + // DisplayModeController::setDesiredMode updated the render rate, so inform Scheduler. + mScheduler->setRenderRate(displayId, renderRate, true /* applyImmediately */); // Schedule a new frame to initiate the display mode switch. scheduleComposite(FrameHint::kNone); @@ -1262,8 +1346,9 @@ void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode) { mScheduler->setModeChangePending(true); break; - case DisplayDevice::DesiredModeAction::InitiateRenderRateSwitch: - mScheduler->setRenderRate(displayId, mode.fps); + } + case DesiredModeAction::InitiateRenderRateSwitch: + mScheduler->setRenderRate(displayId, mode.fps, /*applyImmediately*/ false); if (displayId == mActiveDisplayId) { mScheduler->updatePhaseConfiguration(mode.fps); @@ -1273,7 +1358,7 @@ void SurfaceFlinger::setDesiredMode(display::DisplayModeRequest&& desiredMode) { dispatchDisplayModeChangeEvent(displayId, mode); } break; - case DisplayDevice::DesiredModeAction::None: + case DesiredModeAction::None: break; } } @@ -1329,11 +1414,10 @@ status_t SurfaceFlinger::setActiveModeFromBackdoor(const sp<display::DisplayToke return future.get(); } -void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { - const auto displayId = display.getPhysicalId(); +void SurfaceFlinger::finalizeDisplayModeChange(PhysicalDisplayId displayId) { ATRACE_NAME(ftl::Concat(__func__, ' ', displayId.value).c_str()); - const auto pendingModeOpt = display.getPendingMode(); + const auto pendingModeOpt = mDisplayModeController.getPendingMode(displayId); if (!pendingModeOpt) { // There is no pending mode change. This can happen if the active // display changed and the mode change happened on a different display. @@ -1342,8 +1426,12 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { const auto& activeMode = pendingModeOpt->mode; - if (display.getActiveMode().modePtr->getResolution() != activeMode.modePtr->getResolution()) { - auto& state = mCurrentState.displays.editValueFor(display.getDisplayToken()); + if (const auto oldResolution = + mDisplayModeController.getActiveMode(displayId).modePtr->getResolution(); + oldResolution != activeMode.modePtr->getResolution()) { + Mutex::Autolock lock(mStateLock); + + auto& state = mCurrentState.displays.editValueFor(getPhysicalDisplayTokenLocked(displayId)); // We need to generate new sequenceId in order to recreate the display (and this // way the framebuffer). state.sequenceId = DisplayDeviceState{}.sequenceId; @@ -1354,8 +1442,8 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { return; } - display.finalizeModeChange(activeMode.modePtr->getId(), activeMode.modePtr->getVsyncRate(), - activeMode.fps); + mDisplayModeController.finalizeModeChange(displayId, activeMode.modePtr->getId(), + activeMode.modePtr->getVsyncRate(), activeMode.fps); if (displayId == mActiveDisplayId) { mScheduler->updatePhaseConfiguration(activeMode.fps); @@ -1366,25 +1454,24 @@ void SurfaceFlinger::finalizeDisplayModeChange(DisplayDevice& display) { } } -void SurfaceFlinger::dropModeRequest(const sp<DisplayDevice>& display) { - display->clearDesiredMode(); - if (display->getPhysicalId() == mActiveDisplayId) { +void SurfaceFlinger::dropModeRequest(PhysicalDisplayId displayId) { + mDisplayModeController.clearDesiredMode(displayId); + if (displayId == mActiveDisplayId) { // TODO(b/255635711): Check for pending mode changes on other displays. mScheduler->setModeChangePending(false); } } -void SurfaceFlinger::applyActiveMode(const sp<DisplayDevice>& display) { - const auto activeModeOpt = display->getDesiredMode(); +void SurfaceFlinger::applyActiveMode(PhysicalDisplayId displayId) { + const auto activeModeOpt = mDisplayModeController.getDesiredMode(displayId); auto activeModePtr = activeModeOpt->mode.modePtr; - const auto displayId = activeModePtr->getPhysicalDisplayId(); const auto renderFps = activeModeOpt->mode.fps; - dropModeRequest(display); + dropModeRequest(displayId); constexpr bool kAllowToEnable = true; mScheduler->resyncToHardwareVsync(displayId, kAllowToEnable, std::move(activeModePtr).take()); - mScheduler->setRenderRate(displayId, renderFps); + mScheduler->setRenderRate(displayId, renderFps, /*applyImmediately*/ true); if (displayId == mActiveDisplayId) { mScheduler->updatePhaseConfiguration(renderFps); @@ -1396,20 +1483,12 @@ void SurfaceFlinger::initiateDisplayModeChanges() { std::optional<PhysicalDisplayId> displayToUpdateImmediately; - for (const auto& [id, physical] : mPhysicalDisplays) { - const auto display = getDisplayDeviceLocked(id); - if (!display) continue; - - auto desiredModeOpt = display->getDesiredMode(); + for (const auto& [displayId, physical] : FTL_FAKE_GUARD(mStateLock, mPhysicalDisplays)) { + auto desiredModeOpt = mDisplayModeController.getDesiredMode(displayId); if (!desiredModeOpt) { continue; } - if (!shouldApplyRefreshRateSelectorPolicy(*display)) { - dropModeRequest(display); - continue; - } - const auto desiredModeId = desiredModeOpt->mode.modePtr->getId(); const auto displayModePtrOpt = physical.snapshot().displayModes().get(desiredModeId); @@ -1422,19 +1501,21 @@ void SurfaceFlinger::initiateDisplayModeChanges() { ALOGV("%s changing active mode to %d(%s) for display %s", __func__, ftl::to_underlying(desiredModeId), to_string(displayModePtrOpt->get()->getVsyncRate()).c_str(), - to_string(display->getId()).c_str()); + to_string(displayId).c_str()); if ((!FlagManager::getInstance().connected_display() || !desiredModeOpt->force) && - display->getActiveMode() == desiredModeOpt->mode) { - applyActiveMode(display); + mDisplayModeController.getActiveMode(displayId) == desiredModeOpt->mode) { + applyActiveMode(displayId); continue; } + const auto selectorPtr = mDisplayModeController.selectorPtrFor(displayId); + // Desired active mode was set, it is different than the mode currently in use, however // allowed modes might have changed by the time we process the refresh. // Make sure the desired mode is still allowed - if (!display->refreshRateSelector().isModeAllowed(desiredModeOpt->mode)) { - dropModeRequest(display); + if (!selectorPtr->isModeAllowed(desiredModeOpt->mode)) { + dropModeRequest(displayId); continue; } @@ -1444,11 +1525,12 @@ void SurfaceFlinger::initiateDisplayModeChanges() { constraints.seamlessRequired = false; hal::VsyncPeriodChangeTimeline outTimeline; - if (!display->initiateModeChange(std::move(*desiredModeOpt), constraints, outTimeline)) { + if (!mDisplayModeController.initiateModeChange(displayId, std::move(*desiredModeOpt), + constraints, outTimeline)) { continue; } - display->refreshRateSelector().onModeChangeInitiated(); + selectorPtr->onModeChangeInitiated(); mScheduler->onNewVsyncPeriodChangeTimeline(outTimeline); if (outTimeline.refreshRequired) { @@ -1457,17 +1539,18 @@ void SurfaceFlinger::initiateDisplayModeChanges() { // TODO(b/255635711): Remove `displayToUpdateImmediately` to `finalizeDisplayModeChange` // for all displays. This was only needed when the loop iterated over `mDisplays` rather // than `mPhysicalDisplays`. - displayToUpdateImmediately = display->getPhysicalId(); + displayToUpdateImmediately = displayId; } } if (displayToUpdateImmediately) { - const auto display = getDisplayDeviceLocked(*displayToUpdateImmediately); - finalizeDisplayModeChange(*display); + const auto displayId = *displayToUpdateImmediately; + finalizeDisplayModeChange(displayId); - const auto desiredModeOpt = display->getDesiredMode(); - if (desiredModeOpt && display->getActiveMode() == desiredModeOpt->mode) { - applyActiveMode(display); + const auto desiredModeOpt = mDisplayModeController.getDesiredMode(displayId); + if (desiredModeOpt && + mDisplayModeController.getActiveMode(displayId) == desiredModeOpt->mode) { + applyActiveMode(displayId); } } } @@ -1840,19 +1923,6 @@ status_t SurfaceFlinger::isWideColorDisplay(const sp<IBinder>& displayToken, return NO_ERROR; } -status_t SurfaceFlinger::getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) { - outLayers->clear(); - auto future = mScheduler->schedule([=, this] { - const auto display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()); - mDrawingState.traverseInZOrder([&](Layer* layer) { - outLayers->push_back(layer->getLayerDebugInfo(display.get())); - }); - }); - - future.wait(); - return NO_ERROR; -} - status_t SurfaceFlinger::getCompositionPreference( Dataspace* outDataspace, ui::PixelFormat* outPixelFormat, Dataspace* outWideColorGamutDataspace, @@ -2085,10 +2155,17 @@ status_t SurfaceFlinger::getDisplayDecorationSupport( sp<IDisplayEventConnection> SurfaceFlinger::createDisplayEventConnection( gui::ISurfaceComposer::VsyncSource vsyncSource, EventRegistrationFlags eventRegistration, const sp<IBinder>& layerHandle) { - const auto cycle = vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger - ? scheduler::Cycle::LastComposite - : scheduler::Cycle::Render; + const auto cycle = [&] { + if (FlagManager::getInstance().deprecate_vsync_sf()) { + ALOGW_IF(vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger, + "requested unsupported config eVsyncSourceSurfaceFlinger"); + return scheduler::Cycle::Render; + } + return vsyncSource == gui::ISurfaceComposer::VsyncSource::eVsyncSourceSurfaceFlinger + ? scheduler::Cycle::LastComposite + : scheduler::Cycle::Render; + }(); return mScheduler->createDisplayEventConnection(cycle, eventRegistration, layerHandle); } @@ -2212,19 +2289,22 @@ void SurfaceFlinger::onComposerHalVsyncIdle(hal::HWDisplayId) { void SurfaceFlinger::onRefreshRateChangedDebug(const RefreshRateChangedDebugData& data) { ATRACE_CALL(); - if (const auto displayId = getHwComposer().toPhysicalDisplayId(data.display); displayId) { - const char* const whence = __func__; - static_cast<void>(mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) { - const Fps fps = Fps::fromPeriodNsecs(getHwComposer().getComposer()->isVrrSupported() - ? data.refreshPeriodNanos - : data.vsyncPeriodNanos); - ATRACE_FORMAT("%s Fps %d", whence, fps.getIntValue()); - const auto display = getDisplayDeviceLocked(*displayId); - FTL_FAKE_GUARD(kMainThreadContext, - display->updateRefreshRateOverlayRate(fps, display->getActiveMode().fps, - /* setByHwc */ true)); - })); - } + const char* const whence = __func__; + static_cast<void>(mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD( + kMainThreadContext) { + if (const auto displayIdOpt = getHwComposer().toPhysicalDisplayId(data.display)) { + if (const auto display = getDisplayDeviceLocked(*displayIdOpt)) { + const Fps refreshRate = Fps::fromPeriodNsecs( + getHwComposer().getComposer()->isVrrSupported() ? data.refreshPeriodNanos + : data.vsyncPeriodNanos); + ATRACE_FORMAT("%s refresh rate = %d", whence, refreshRate.getIntValue()); + + const auto renderRate = mDisplayModeController.getActiveMode(*displayIdOpt).fps; + constexpr bool kSetByHwc = true; + display->updateRefreshRateOverlayRate(refreshRate, renderRate, kSetByHwc); + } + } + })); } void SurfaceFlinger::configure() { @@ -2395,6 +2475,8 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, frontend::LayerSnapshotBuilder::Args args{.root = mLayerHierarchyBuilder.getHierarchy(), .layerLifecycleManager = mLayerLifecycleManager, + .includeMetadata = mCompositionEngine->getFeatureFlags().test( + compositionengine::Feature::kSnapshotLayerMetadata), .displays = mFrontEndDisplayInfos, .displayChanges = mFrontEndDisplayInfosChanged, .globalShadowSettings = mDrawingState.globalShadowSettings, @@ -2422,89 +2504,92 @@ bool SurfaceFlinger::updateLayerSnapshots(VsyncId vsyncId, nsecs_t frameTimeNs, mUpdateAttachedChoreographer = true; } outTransactionsAreEmpty = mLayerLifecycleManager.getGlobalChanges().get() == 0; - mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0; + if (FlagManager::getInstance().vrr_bugfix_24q4()) { + mustComposite |= mLayerLifecycleManager.getGlobalChanges().any( + frontend::RequestedLayerState::kMustComposite); + } else { + mustComposite |= mLayerLifecycleManager.getGlobalChanges().get() != 0; + } bool newDataLatched = false; - if (!mLegacyFrontEndEnabled) { - ATRACE_NAME("DisplayCallbackAndStatsUpdates"); - mustComposite |= applyTransactionsLocked(update.transactions, vsyncId); - traverseLegacyLayers([&](Layer* layer) { layer->commitTransaction(); }); - const nsecs_t latchTime = systemTime(); - bool unused = false; - - for (auto& layer : mLayerLifecycleManager.getLayers()) { - if (layer->changes.test(frontend::RequestedLayerState::Changes::Created) && - layer->bgColorLayer) { - sp<Layer> bgColorLayer = getFactory().createEffectLayer( - LayerCreationArgs(this, nullptr, layer->name, - ISurfaceComposerClient::eFXSurfaceEffect, LayerMetadata(), - std::make_optional(layer->id), true)); - mLegacyLayers[bgColorLayer->sequence] = bgColorLayer; - } - const bool willReleaseBufferOnLatch = layer->willReleaseBufferOnLatch(); - - auto it = mLegacyLayers.find(layer->id); - if (it == mLegacyLayers.end() && - layer->changes.test(frontend::RequestedLayerState::Changes::Destroyed)) { - // Layer handle was created and immediately destroyed. It was destroyed before it - // was added to the map. - continue; - } - - LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), - "Couldnt find layer object for %s", - layer->getDebugString().c_str()); - if (!layer->hasReadyFrame() && !willReleaseBufferOnLatch) { - if (!it->second->hasBuffer()) { - // The last latch time is used to classify a missed frame as buffer stuffing - // instead of a missed frame. This is used to identify scenarios where we - // could not latch a buffer or apply a transaction due to backpressure. - // We only update the latch time for buffer less layers here, the latch time - // is updated for buffer layers when the buffer is latched. - it->second->updateLastLatchTime(latchTime); - } - continue; - } + ATRACE_NAME("DisplayCallbackAndStatsUpdates"); + mustComposite |= applyTransactionsLocked(update.transactions, vsyncId); + traverseLegacyLayers([&](Layer* layer) { layer->commitTransaction(); }); + const nsecs_t latchTime = systemTime(); + bool unused = false; + + for (auto& layer : mLayerLifecycleManager.getLayers()) { + if (layer->changes.test(frontend::RequestedLayerState::Changes::Created) && + layer->bgColorLayer) { + sp<Layer> bgColorLayer = getFactory().createEffectLayer( + LayerCreationArgs(this, nullptr, layer->name, + ISurfaceComposerClient::eFXSurfaceEffect, LayerMetadata(), + std::make_optional(layer->id), true)); + mLegacyLayers[bgColorLayer->sequence] = bgColorLayer; + } + const bool willReleaseBufferOnLatch = layer->willReleaseBufferOnLatch(); + + auto it = mLegacyLayers.find(layer->id); + if (it == mLegacyLayers.end() && + layer->changes.test(frontend::RequestedLayerState::Changes::Destroyed)) { + // Layer handle was created and immediately destroyed. It was destroyed before it + // was added to the map. + continue; + } - const bool bgColorOnly = - !layer->externalTexture && (layer->bgColorLayerId != UNASSIGNED_LAYER_ID); - if (willReleaseBufferOnLatch) { - mLayersWithBuffersRemoved.emplace(it->second); + LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), + "Couldnt find layer object for %s", + layer->getDebugString().c_str()); + if (!layer->hasReadyFrame() && !willReleaseBufferOnLatch) { + if (!it->second->hasBuffer()) { + // The last latch time is used to classify a missed frame as buffer stuffing + // instead of a missed frame. This is used to identify scenarios where we + // could not latch a buffer or apply a transaction due to backpressure. + // We only update the latch time for buffer less layers here, the latch time + // is updated for buffer layers when the buffer is latched. + it->second->updateLastLatchTime(latchTime); } - it->second->latchBufferImpl(unused, latchTime, bgColorOnly); - newDataLatched = true; + continue; + } - mLayersWithQueuedFrames.emplace(it->second); - mLayersIdsWithQueuedFrames.emplace(it->second->sequence); + const bool bgColorOnly = + !layer->externalTexture && (layer->bgColorLayerId != UNASSIGNED_LAYER_ID); + if (willReleaseBufferOnLatch) { + mLayersWithBuffersRemoved.emplace(it->second); } + it->second->latchBufferImpl(unused, latchTime, bgColorOnly); + newDataLatched = true; - updateLayerHistory(latchTime); - mLayerSnapshotBuilder.forEachVisibleSnapshot([&](const frontend::LayerSnapshot& snapshot) { - if (mLayersIdsWithQueuedFrames.find(snapshot.path.id) == - mLayersIdsWithQueuedFrames.end()) - return; - Region visibleReg; - visibleReg.set(snapshot.transformedBoundsWithoutTransparentRegion); - invalidateLayerStack(snapshot.outputFilter, visibleReg); - }); + mLayersWithQueuedFrames.emplace(it->second); + mLayersIdsWithQueuedFrames.emplace(it->second->sequence); + } - for (auto& destroyedLayer : mLayerLifecycleManager.getDestroyedLayers()) { - mLegacyLayers.erase(destroyedLayer->id); - } + updateLayerHistory(latchTime); + mLayerSnapshotBuilder.forEachVisibleSnapshot([&](const frontend::LayerSnapshot& snapshot) { + if (mLayersIdsWithQueuedFrames.find(snapshot.path.id) == mLayersIdsWithQueuedFrames.end()) + return; + Region visibleReg; + visibleReg.set(snapshot.transformedBoundsWithoutTransparentRegion); + invalidateLayerStack(snapshot.outputFilter, visibleReg); + }); - { - ATRACE_NAME("LLM:commitChanges"); - mLayerLifecycleManager.commitChanges(); - } + for (auto& destroyedLayer : mLayerLifecycleManager.getDestroyedLayers()) { + mLegacyLayers.erase(destroyedLayer->id); + } - // enter boot animation on first buffer latch - if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) { - ALOGI("Enter boot animation"); - mBootStage = BootStage::BOOTANIMATION; - } + { + ATRACE_NAME("LLM:commitChanges"); + mLayerLifecycleManager.commitChanges(); + } + + // enter boot animation on first buffer latch + if (CC_UNLIKELY(mBootStage == BootStage::BOOTLOADER && newDataLatched)) { + ALOGI("Enter boot animation"); + mBootStage = BootStage::BOOTANIMATION; } + mustComposite |= (getTransactionFlags() & ~eTransactionFlushNeeded) || newDataLatched; - if (mustComposite && !mLegacyFrontEndEnabled) { + if (mustComposite) { commitTransactions(); } @@ -2524,33 +2609,18 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, // If a mode set is pending and the fence hasn't fired yet, wait for the next commit. if (std::any_of(frameTargets.begin(), frameTargets.end(), - [this](const auto& pair) FTL_FAKE_GUARD(mStateLock) - FTL_FAKE_GUARD(kMainThreadContext) { - if (!pair.second->isFramePending()) return false; - - if (const auto display = getDisplayDeviceLocked(pair.first)) { - return display->isModeSetPending(); - } - - return false; - })) { + [this](const auto& pair) FTL_FAKE_GUARD(kMainThreadContext) { + const auto [displayId, target] = pair; + return target->isFramePending() && + mDisplayModeController.isModeSetPending(displayId); + })) { mScheduler->scheduleFrame(); return false; } - { - Mutex::Autolock lock(mStateLock); - - for (const auto [id, target] : frameTargets) { - // TODO(b/241285876): This is `nullptr` when the DisplayDevice is about to be removed in - // this commit, since the PhysicalDisplay has already been removed. Rather than checking - // for `nullptr` below, change Scheduler::onFrameSignal to filter out the FrameTarget of - // the removed display. - const auto display = getDisplayDeviceLocked(id); - - if (display && display->isModeSetPending()) { - finalizeDisplayModeChange(*display); - } + for (const auto [displayId, _] : frameTargets) { + if (mDisplayModeController.isModeSetPending(displayId)) { + finalizeDisplayModeChange(displayId); } } @@ -2585,8 +2655,8 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, mPowerAdvisor->setFrameDelay(frameDelay); mPowerAdvisor->setTotalFrameTargetWorkDuration(idealSfWorkDuration); - const auto& display = FTL_FAKE_GUARD(mStateLock, getDefaultDisplayDeviceLocked()).get(); - const Period idealVsyncPeriod = display->getActiveMode().fps.getPeriod(); + const Period idealVsyncPeriod = + mDisplayModeController.getActiveMode(pacesetterId).fps.getPeriod(); mPowerAdvisor->updateTargetWorkDuration(idealVsyncPeriod); } @@ -2606,18 +2676,21 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, mScheduler->getPacesetterRefreshRate()); const bool flushTransactions = clearTransactionFlags(eTransactionFlushNeeded); - bool transactionsAreEmpty; - if (mLegacyFrontEndEnabled) { - mustComposite |= - updateLayerSnapshotsLegacy(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(), - flushTransactions, transactionsAreEmpty); - } + bool transactionsAreEmpty = false; if (mLayerLifecycleManagerEnabled) { mustComposite |= updateLayerSnapshots(vsyncId, pacesetterFrameTarget.frameBeginTime().ns(), flushTransactions, transactionsAreEmpty); } + // Tell VsyncTracker that we are going to present this frame before scheduling + // setTransactionFlags which will schedule another SF frame. This was if the tracker + // needs to adjust the vsync timeline, it will be done before the next frame. + if (FlagManager::getInstance().vrr_config() && mustComposite) { + mScheduler->getVsyncSchedule()->getTracker().onFrameBegin( + pacesetterFrameTarget.expectedPresentTime(), + pacesetterFrameTarget.lastSignaledFrameTime()); + } if (transactionFlushNeeded()) { setTransactionFlags(eTransactionFlushNeeded); } @@ -2646,9 +2719,10 @@ bool SurfaceFlinger::commit(PhysicalDisplayId pacesetterId, ? &mLayerHierarchyBuilder.getHierarchy() : nullptr, updateAttachedChoreographer); - initiateDisplayModeChanges(); } + initiateDisplayModeChanges(); + updateCursorAsync(); if (!mustComposite) { updateInputFlinger(vsyncId, pacesetterFrameTarget.frameBeginTime()); @@ -2711,34 +2785,22 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( mLayerMetadataSnapshotNeeded = false; } - if (DOES_CONTAIN_BORDER) { - refreshArgs.borderInfoList.clear(); - mDrawingState.traverse([&refreshArgs](Layer* layer) { - if (layer->isBorderEnabled()) { - compositionengine::BorderRenderInfo info; - info.width = layer->getBorderWidth(); - info.color = layer->getBorderColor(); - layer->traverse(LayerVector::StateSet::Drawing, [&info](Layer* ilayer) { - info.layerIds.push_back(ilayer->getSequence()); - }); - refreshArgs.borderInfoList.emplace_back(std::move(info)); - } - }); - } - refreshArgs.bufferIdsToUncache = std::move(mBufferIdsToUncache); - refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size()); - for (auto layer : mLayersWithQueuedFrames) { - if (auto layerFE = layer->getCompositionEngineLayerFE()) - refreshArgs.layersWithQueuedFrames.push_back(layerFE); + if (!FlagManager::getInstance().ce_fence_promise()) { + refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size()); + for (auto& layer : mLayersWithQueuedFrames) { + if (const auto& layerFE = layer->getCompositionEngineLayerFE()) + refreshArgs.layersWithQueuedFrames.push_back(layerFE); + } } refreshArgs.outputColorSetting = mDisplayColorSetting; refreshArgs.forceOutputColorMode = mForceColorMode; refreshArgs.updatingOutputGeometryThisFrame = mVisibleRegionsDirty; - refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) || mVisibleRegionsDirty; + refreshArgs.updatingGeometryThisFrame = mGeometryDirty.exchange(false) || + mVisibleRegionsDirty || mDrawingState.colorMatrixChanged; refreshArgs.internalDisplayRotationFlags = getActiveDisplayRotationFlags(); if (CC_UNLIKELY(mDrawingState.colorMatrixChanged)) { @@ -2791,19 +2853,57 @@ CompositeResultsPerDisplay SurfaceFlinger::composite( } } - mCompositionEngine->present(refreshArgs); - moveSnapshotsFromCompositionArgs(refreshArgs, layers); + refreshArgs.refreshStartTime = systemTime(SYSTEM_TIME_MONOTONIC); + for (auto& [layer, layerFE] : layers) { + layer->onPreComposition(refreshArgs.refreshStartTime); + } - for (auto [layer, layerFE] : layers) { - CompositionResult compositionResult{layerFE->stealCompositionResult()}; - layer->onPreComposition(compositionResult.refreshStartTime); - for (auto& [releaseFence, layerStack] : compositionResult.releaseFences) { - Layer* clonedFrom = layer->getClonedFrom().get(); - auto owningLayer = clonedFrom ? clonedFrom : layer; - owningLayer->onLayerDisplayed(std::move(releaseFence), layerStack); + if (FlagManager::getInstance().ce_fence_promise()) { + for (auto& [layer, layerFE] : layers) { + attachReleaseFenceFutureToLayer(layer, layerFE, + layerFE->mSnapshot->outputFilter.layerStack); } - if (compositionResult.lastClientCompositionFence) { - layer->setWasClientComposed(compositionResult.lastClientCompositionFence); + + refreshArgs.layersWithQueuedFrames.reserve(mLayersWithQueuedFrames.size()); + for (auto& layer : mLayersWithQueuedFrames) { + if (const auto& layerFE = layer->getCompositionEngineLayerFE()) { + refreshArgs.layersWithQueuedFrames.push_back(layerFE); + // Some layers are not displayed and do not yet have a future release fence + if (layerFE->getReleaseFencePromiseStatus() == + LayerFE::ReleaseFencePromiseStatus::UNINITIALIZED || + layerFE->getReleaseFencePromiseStatus() == + LayerFE::ReleaseFencePromiseStatus::FULFILLED) { + // layerStack is invalid because layer is not on a display + attachReleaseFenceFutureToLayer(layer.get(), layerFE.get(), + ui::INVALID_LAYER_STACK); + } + } + } + + mCompositionEngine->present(refreshArgs); + moveSnapshotsFromCompositionArgs(refreshArgs, layers); + + for (auto& [layer, layerFE] : layers) { + CompositionResult compositionResult{layerFE->stealCompositionResult()}; + if (compositionResult.lastClientCompositionFence) { + layer->setWasClientComposed(compositionResult.lastClientCompositionFence); + } + } + + } else { + mCompositionEngine->present(refreshArgs); + moveSnapshotsFromCompositionArgs(refreshArgs, layers); + + for (auto [layer, layerFE] : layers) { + CompositionResult compositionResult{layerFE->stealCompositionResult()}; + for (auto& [releaseFence, layerStack] : compositionResult.releaseFences) { + Layer* clonedFrom = layer->getClonedFrom().get(); + auto owningLayer = clonedFrom ? clonedFrom : layer; + owningLayer->onLayerDisplayed(std::move(releaseFence), layerStack); + } + if (compositionResult.lastClientCompositionFence) { + layer->setWasClientComposed(compositionResult.lastClientCompositionFence); + } } } @@ -3038,10 +3138,9 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, // but that should be okay since CompositorTiming has snapping logic. const TimePoint compositeTime = TimePoint::fromNs(mCompositionEngine->getLastFrameRefreshTimestamp()); - const Duration presentLatency = - getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE) - ? Duration::zero() - : mPresentLatencyTracker.trackPendingFrame(compositeTime, pacesetterPresentFenceTime); + const Duration presentLatency = mHasReliablePresentFences + ? mPresentLatencyTracker.trackPendingFrame(compositeTime, pacesetterPresentFenceTime) + : Duration::zero(); const auto schedule = mScheduler->getVsyncSchedule(); const TimePoint vsyncDeadline = schedule->vsyncDeadlineAfter(presentTime); @@ -3070,8 +3169,13 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, auto optDisplay = layerStackToDisplay.get(layerStack); if (optDisplay && !optDisplay->get()->isVirtual()) { auto fence = getHwComposer().getPresentFence(optDisplay->get()->getPhysicalId()); - layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share(), - ui::INVALID_LAYER_STACK); + if (FlagManager::getInstance().ce_fence_promise()) { + layer->prepareReleaseCallbacks(ftl::yield<FenceResult>(fence), + ui::INVALID_LAYER_STACK); + } else { + layer->onLayerDisplayed(ftl::yield<FenceResult>(fence).share(), + ui::INVALID_LAYER_STACK); + } } } layer->releasePendingBuffer(presentTime.ns()); @@ -3145,7 +3249,8 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, if (mLayerLifecycleManagerEnabled) { mLayerSnapshotBuilder.forEachVisibleSnapshot( [&, compositionDisplay = compositionDisplay]( - std::unique_ptr<frontend::LayerSnapshot>& snapshot) { + std::unique_ptr<frontend::LayerSnapshot>& + snapshot) FTL_FAKE_GUARD(kMainThreadContext) { auto it = mLegacyLayers.find(snapshot->sequence); LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), "Couldnt find layer object for %s", @@ -3204,7 +3309,7 @@ void SurfaceFlinger::onCompositionPresented(PhysicalDisplayId pacesetterId, if (mNumTrustedPresentationListeners > 0) { // We avoid any reverse traversal upwards so this shouldn't be too expensive - traverseLegacyLayers([&](Layer* layer) { + traverseLegacyLayers([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) { if (!layer->hasTrustedPresentationListener()) { return; } @@ -3461,12 +3566,45 @@ bool SurfaceFlinger::configureLocked() { for (const auto [hwcDisplayId, connection] : events) { if (auto info = getHwComposer().onHotplug(hwcDisplayId, connection)) { const auto displayId = info->id; - const bool connected = connection == hal::Connection::CONNECTED; + const ftl::Concat displayString("display ", displayId.value, "(HAL ID ", hwcDisplayId, + ')'); + + if (connection == hal::Connection::CONNECTED) { + const auto activeModeIdOpt = + processHotplugConnect(displayId, hwcDisplayId, std::move(*info), + displayString.c_str()); + if (!activeModeIdOpt) { + if (FlagManager::getInstance().hotplug2()) { + mScheduler->dispatchHotplugError( + static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN)); + } + getHwComposer().disconnectDisplay(displayId); + continue; + } + + const auto [kernelIdleTimerController, idleTimerTimeoutMs] = + getKernelIdleTimerProperties(displayId); + + using Config = scheduler::RefreshRateSelector::Config; + const Config config = + {.enableFrameRateOverride = sysprop::enable_frame_rate_override(true) + ? Config::FrameRateOverride::Enabled + : Config::FrameRateOverride::Disabled, + .frameRateMultipleThreshold = + base::GetIntProperty("debug.sf.frame_rate_multiple_threshold"s, 0), + .legacyIdleTimerTimeout = idleTimerTimeoutMs, + .kernelIdleTimerController = kernelIdleTimerController}; + + const auto snapshotOpt = + mPhysicalDisplays.get(displayId).transform(&PhysicalDisplay::snapshotRef); + LOG_ALWAYS_FATAL_IF(!snapshotOpt); - if (const char* const log = - processHotplug(displayId, hwcDisplayId, connected, std::move(*info))) { - ALOGI("%s display %s (HAL ID %" PRIu64 ")", log, to_string(displayId).c_str(), - hwcDisplayId); + mDisplayModeController.registerDisplay(*snapshotOpt, *activeModeIdOpt, config); + } else { + // Unregister before destroying the DisplaySnapshot below. + mDisplayModeController.unregisterDisplay(displayId); + + processHotplugDisconnect(displayId, displayString.c_str()); } } } @@ -3474,36 +3612,20 @@ bool SurfaceFlinger::configureLocked() { return !events.empty(); } -const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, - hal::HWDisplayId hwcDisplayId, bool connected, - DisplayIdentificationInfo&& info) { - const auto displayOpt = mPhysicalDisplays.get(displayId); - if (!connected) { - LOG_ALWAYS_FATAL_IF(!displayOpt); - const auto& display = displayOpt->get(); - - if (const ssize_t index = mCurrentState.displays.indexOfKey(display.token()); index >= 0) { - mCurrentState.displays.removeItemsAt(index); - } - - mPhysicalDisplays.erase(displayId); - return "Disconnecting"; - } - +std::optional<DisplayModeId> SurfaceFlinger::processHotplugConnect(PhysicalDisplayId displayId, + hal::HWDisplayId hwcDisplayId, + DisplayIdentificationInfo&& info, + const char* displayString) { auto [displayModes, activeMode] = loadDisplayModes(displayId); if (!activeMode) { - ALOGE("Failed to hotplug display %s", to_string(displayId).c_str()); - if (FlagManager::getInstance().hotplug2()) { - mScheduler->dispatchHotplugError( - static_cast<int32_t>(DisplayHotplugEvent::ERROR_UNKNOWN)); - } - getHwComposer().disconnectDisplay(displayId); - return nullptr; + ALOGE("Failed to hotplug %s", displayString); + return std::nullopt; } + const DisplayModeId activeModeId = activeMode->getId(); ui::ColorModes colorModes = getHwComposer().getColorModes(displayId); - if (displayOpt) { + if (const auto displayOpt = mPhysicalDisplays.get(displayId)) { const auto& display = displayOpt->get(); const auto& snapshot = display.snapshot(); @@ -3522,7 +3644,8 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, auto& state = mCurrentState.displays.editValueFor(it->second.token()); state.sequenceId = DisplayDeviceState{}.sequenceId; // Generate new sequenceId. state.physical->activeMode = std::move(activeMode); - return "Reconnecting"; + ALOGI("Reconnecting %s", displayString); + return activeModeId; } const sp<IBinder> token = sp<BBinder>::make(); @@ -3542,7 +3665,23 @@ const char* SurfaceFlinger::processHotplug(PhysicalDisplayId displayId, state.displayName = std::move(info.name); mCurrentState.displays.add(token, state); - return "Connecting"; + ALOGI("Connecting %s", displayString); + return activeModeId; +} + +void SurfaceFlinger::processHotplugDisconnect(PhysicalDisplayId displayId, + const char* displayString) { + ALOGI("Disconnecting %s", displayString); + + const auto displayOpt = mPhysicalDisplays.get(displayId); + LOG_ALWAYS_FATAL_IF(!displayOpt); + const auto& display = displayOpt->get(); + + if (const ssize_t index = mCurrentState.displays.indexOfKey(display.token()); index >= 0) { + mCurrentState.displays.removeItemsAt(index); + } + + mPhysicalDisplays.erase(displayId); } void SurfaceFlinger::dispatchDisplayModeChangeEvent(PhysicalDisplayId displayId, @@ -3570,43 +3709,21 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( creationArgs.hasWideColorGamut = false; creationArgs.supportedPerFrameMetadata = 0; - if (const auto& physical = state.physical) { - creationArgs.activeModeId = physical->activeMode->getId(); - const auto [kernelIdleTimerController, idleTimerTimeoutMs] = - getKernelIdleTimerProperties(compositionDisplay->getId()); - - using Config = scheduler::RefreshRateSelector::Config; - const auto enableFrameRateOverride = sysprop::enable_frame_rate_override(true) - ? Config::FrameRateOverride::Enabled - : Config::FrameRateOverride::Disabled; - const Config config = - {.enableFrameRateOverride = enableFrameRateOverride, - .frameRateMultipleThreshold = - base::GetIntProperty("debug.sf.frame_rate_multiple_threshold"s, 0), - .idleTimerTimeout = idleTimerTimeoutMs, - .kernelIdleTimerController = kernelIdleTimerController}; + if (const auto physicalIdOpt = PhysicalDisplayId::tryCast(compositionDisplay->getId())) { + const auto physicalId = *physicalIdOpt; + creationArgs.isPrimary = physicalId == getPrimaryDisplayIdLocked(); creationArgs.refreshRateSelector = - mPhysicalDisplays.get(physical->id) - .transform(&PhysicalDisplay::snapshotRef) - .transform([&](const display::DisplaySnapshot& snapshot) { - return std::make_shared< - scheduler::RefreshRateSelector>(snapshot.displayModes(), - creationArgs.activeModeId, - config); - }) - .value_or(nullptr); - - creationArgs.isPrimary = physical->id == getPrimaryDisplayIdLocked(); - - mPhysicalDisplays.get(physical->id) + FTL_FAKE_GUARD(kMainThreadContext, + mDisplayModeController.selectorPtrFor(physicalId)); + + mPhysicalDisplays.get(physicalId) .transform(&PhysicalDisplay::snapshotRef) .transform(ftl::unit_fn([&](const display::DisplaySnapshot& snapshot) { for (const auto mode : snapshot.colorModes()) { creationArgs.hasWideColorGamut |= ui::isWideColorMode(mode); creationArgs.hwcColorModes - .emplace(mode, - getHwComposer().getRenderIntents(physical->id, mode)); + .emplace(mode, getHwComposer().getRenderIntents(physicalId, mode)); } })); } @@ -3651,7 +3768,8 @@ sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal( if (const auto& physical = state.physical) { const auto& mode = *physical->activeMode; - display->setActiveMode(mode.getId(), mode.getVsyncRate(), mode.getVsyncRate()); + mDisplayModeController.setActiveMode(physical->id, mode.getId(), mode.getVsyncRate(), + mode.getVsyncRate()); } display->setLayerFilter(makeLayerFilterForDisplay(display->getId(), state.layerStack)); @@ -3824,11 +3942,15 @@ void SurfaceFlinger::processDisplayChanged(const wp<IBinder>& displayToken, if (currentState.physical) { const auto display = getDisplayDeviceLocked(displayToken); - setPowerModeInternal(display, hal::PowerMode::ON); + if (!mSkipPowerOnForQuiescent) { + setPowerModeInternal(display, hal::PowerMode::ON); + } // TODO(b/175678251) Call a listener instead. if (currentState.physical->hwcDisplayId == getHwComposer().getPrimaryHwcDisplayId()) { - mScheduler->resetPhaseConfiguration(display->getActiveMode().fps); + const Fps refreshRate = + mDisplayModeController.getActiveMode(display->getPhysicalId()).fps; + mScheduler->resetPhaseConfiguration(refreshRate); } } return; @@ -3966,19 +4088,7 @@ void SurfaceFlinger::commitTransactionsLocked(uint32_t transactionFlags) { } } - if (!hintDisplay) { - // NOTE: TEMPORARY FIX ONLY. Real fix should cause layers to - // redraw after transform hint changes. See bug 8508397. - // could be null when this layer is using a layerStack - // that is not visible on any display. Also can occur at - // screen off/on times. - // U Update: Don't provide stale hints to the clients. For - // special cases where we want the app to draw its - // first frame before the display is available, we rely - // on WMS and DMS to provide the right information - // so the client can calculate the hint. - layer->skipReportingTransformHint(); - } else { + if (hintDisplay) { layer->updateTransformHint(hintDisplay->getTransformHint()); } }); @@ -4117,7 +4227,7 @@ void SurfaceFlinger::buildWindowInfos(std::vector<WindowInfo>& outWindowInfos, outWindowInfos.push_back(snapshot.inputInfo); }); } else { - mDrawingState.traverseInReverseZOrder([&](Layer* layer) { + mDrawingState.traverseInReverseZOrder([&](Layer* layer) FTL_FAKE_GUARD(kMainThreadContext) { if (!layer->needsInputInfo()) return; const auto opt = mFrontEndDisplayInfos.get(layer->getLayerStack()) @@ -4177,12 +4287,6 @@ void SurfaceFlinger::requestDisplayModes(std::vector<display::DisplayModeRequest if (!display) continue; - if (ftl::FakeGuard guard(kMainThreadContext); - !shouldApplyRefreshRateSelectorPolicy(*display)) { - ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str()); - continue; - } - if (display->refreshRateSelector().isModeAllowed(request.mode)) { setDesiredMode(std::move(request)); } else { @@ -4354,6 +4458,12 @@ void SurfaceFlinger::sendNotifyExpectedPresentHint(PhysicalDisplayId displayId) scheduleNotifyExpectedPresentHint(displayId); } +void SurfaceFlinger::onCommitNotComposited(PhysicalDisplayId pacesetterDisplayId) { + if (FlagManager::getInstance().commit_not_composited()) { + mFrameTimeline->onCommitNotComposited(); + } +} + void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { using namespace scheduler; @@ -4377,7 +4487,7 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { features |= Feature::kTracePredictedVsync; } if (!base::GetBoolProperty("debug.sf.vsync_reactor_ignore_present_fences"s, false) && - !getHwComposer().hasCapability(Capability::PRESENT_FENCE_IS_NOT_RELIABLE)) { + mHasReliablePresentFences) { features |= Feature::kPresentFences; } if (display->refreshRateSelector().kernelIdleTimerController()) { @@ -4398,7 +4508,8 @@ void SurfaceFlinger::initScheduler(const sp<const DisplayDevice>& display) { // The pacesetter must be registered before EventThread creation below. mScheduler->registerDisplay(display->getPhysicalId(), display->holdRefreshRateSelector()); if (FlagManager::getInstance().vrr_config()) { - mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps); + mScheduler->setRenderRate(display->getPhysicalId(), activeMode.fps, + /*applyImmediately*/ true); } const auto configs = mScheduler->getVsyncConfiguration().getCurrentConfigs(); @@ -4821,6 +4932,8 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC if (listener && (flushState.queueProcessTime - transaction.postTime) > std::chrono::nanoseconds(4s).count()) { + // Used to add a stalled transaction which uses an internal lock. + ftl::FakeGuard guard(kMainThreadContext); mTransactionHandler .onTransactionQueueStalled(transaction.id, {.pid = layer->getOwnerPid(), @@ -4843,97 +4956,107 @@ TransactionHandler::TransactionReadiness SurfaceFlinger::transactionReadyBufferC const TransactionHandler::TransactionFlushState& flushState) { using TransactionReadiness = TransactionHandler::TransactionReadiness; auto ready = TransactionReadiness::Ready; - flushState.transaction->traverseStatesWithBuffersWhileTrue([&](const ResolvedComposerState& - resolvedState) -> bool { - const frontend::RequestedLayerState* layer = - mLayerLifecycleManager.getLayerFromId(resolvedState.layerId); - const auto& transaction = *flushState.transaction; - const auto& s = resolvedState.state; - // check for barrier frames - if (s.bufferData->hasBarrier) { - // The current producerId is already a newer producer than the buffer that has a - // barrier. This means the incoming buffer is older and we can release it here. We - // don't wait on the barrier since we know that's stale information. - if (layer->barrierProducerId > s.bufferData->producerId) { - if (s.bufferData->releaseBufferListener) { - uint32_t currentMaxAcquiredBufferCount = - getMaxAcquiredBufferCountForCurrentRefreshRate(layer->ownerUid.val()); - ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, - layer->name.c_str(), s.bufferData->frameNumber); - s.bufferData->releaseBufferListener - ->onReleaseBuffer({resolvedState.externalTexture->getBuffer()->getId(), - s.bufferData->frameNumber}, - s.bufferData->acquireFence - ? s.bufferData->acquireFence - : Fence::NO_FENCE, - currentMaxAcquiredBufferCount); - } + flushState.transaction->traverseStatesWithBuffersWhileTrue( + [&](const ResolvedComposerState& resolvedState) FTL_FAKE_GUARD( + kMainThreadContext) -> bool { + const frontend::RequestedLayerState* layer = + mLayerLifecycleManager.getLayerFromId(resolvedState.layerId); + const auto& transaction = *flushState.transaction; + const auto& s = resolvedState.state; + // check for barrier frames + if (s.bufferData->hasBarrier) { + // The current producerId is already a newer producer than the buffer that has a + // barrier. This means the incoming buffer is older and we can release it here. + // We don't wait on the barrier since we know that's stale information. + if (layer->barrierProducerId > s.bufferData->producerId) { + if (s.bufferData->releaseBufferListener) { + uint32_t currentMaxAcquiredBufferCount = + getMaxAcquiredBufferCountForCurrentRefreshRate( + layer->ownerUid.val()); + ATRACE_FORMAT_INSTANT("callReleaseBufferCallback %s - %" PRIu64, + layer->name.c_str(), s.bufferData->frameNumber); + s.bufferData->releaseBufferListener + ->onReleaseBuffer({resolvedState.externalTexture->getBuffer() + ->getId(), + s.bufferData->frameNumber}, + s.bufferData->acquireFence + ? s.bufferData->acquireFence + : Fence::NO_FENCE, + currentMaxAcquiredBufferCount); + } - // Delete the entire state at this point and not just release the buffer because - // everything associated with the Layer in this Transaction is now out of date. - ATRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", layer->name.c_str(), - layer->barrierProducerId, s.bufferData->producerId); - return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL; - } + // Delete the entire state at this point and not just release the buffer + // because everything associated with the Layer in this Transaction is now + // out of date. + ATRACE_FORMAT("DeleteStaleBuffer %s barrierProducerId:%d > %d", + layer->name.c_str(), layer->barrierProducerId, + s.bufferData->producerId); + return TraverseBuffersReturnValues::DELETE_AND_CONTINUE_TRAVERSAL; + } - if (layer->barrierFrameNumber < s.bufferData->barrierFrameNumber) { - const bool willApplyBarrierFrame = - flushState.bufferLayersReadyToPresent.contains(s.surface.get()) && - ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >= - s.bufferData->barrierFrameNumber)); - if (!willApplyBarrierFrame) { - ATRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 " > %" PRId64, - layer->name.c_str(), layer->barrierFrameNumber, - s.bufferData->barrierFrameNumber); - ready = TransactionReadiness::NotReadyBarrier; - return TraverseBuffersReturnValues::STOP_TRAVERSAL; + if (layer->barrierFrameNumber < s.bufferData->barrierFrameNumber) { + const bool willApplyBarrierFrame = + flushState.bufferLayersReadyToPresent.contains(s.surface.get()) && + ((flushState.bufferLayersReadyToPresent.get(s.surface.get()) >= + s.bufferData->barrierFrameNumber)); + if (!willApplyBarrierFrame) { + ATRACE_FORMAT("NotReadyBarrier %s barrierFrameNumber:%" PRId64 + " > %" PRId64, + layer->name.c_str(), layer->barrierFrameNumber, + s.bufferData->barrierFrameNumber); + ready = TransactionReadiness::NotReadyBarrier; + return TraverseBuffersReturnValues::STOP_TRAVERSAL; + } + } } - } - } - // If backpressure is enabled and we already have a buffer to commit, keep - // the transaction in the queue. - const bool hasPendingBuffer = - flushState.bufferLayersReadyToPresent.contains(s.surface.get()); - if (layer->backpressureEnabled() && hasPendingBuffer && transaction.isAutoTimestamp) { - ATRACE_FORMAT("hasPendingBuffer %s", layer->name.c_str()); - ready = TransactionReadiness::NotReady; - return TraverseBuffersReturnValues::STOP_TRAVERSAL; - } + // If backpressure is enabled and we already have a buffer to commit, keep + // the transaction in the queue. + const bool hasPendingBuffer = + flushState.bufferLayersReadyToPresent.contains(s.surface.get()); + if (layer->backpressureEnabled() && hasPendingBuffer && + transaction.isAutoTimestamp) { + ATRACE_FORMAT("hasPendingBuffer %s", layer->name.c_str()); + ready = TransactionReadiness::NotReady; + return TraverseBuffersReturnValues::STOP_TRAVERSAL; + } - const bool acquireFenceAvailable = s.bufferData && - s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) && - s.bufferData->acquireFence; - const bool fenceSignaled = !acquireFenceAvailable || - s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled; - if (!fenceSignaled) { - // check fence status - const bool allowLatchUnsignaled = shouldLatchUnsignaled(s, transaction.states.size(), - flushState.firstTransaction) && - layer->isSimpleBufferUpdate(s); - if (allowLatchUnsignaled) { - ATRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", layer->name.c_str()); - ready = TransactionReadiness::NotReadyUnsignaled; - } else { - ready = TransactionReadiness::NotReady; - auto& listener = s.bufferData->releaseBufferListener; - if (listener && - (flushState.queueProcessTime - transaction.postTime) > - std::chrono::nanoseconds(4s).count()) { - mTransactionHandler - .onTransactionQueueStalled(transaction.id, - {.pid = layer->ownerPid.val(), - .layerId = layer->id, - .layerName = layer->name, - .bufferId = s.bufferData->getId(), - .frameNumber = s.bufferData->frameNumber}); + const bool acquireFenceAvailable = s.bufferData && + s.bufferData->flags.test(BufferData::BufferDataChange::fenceChanged) && + s.bufferData->acquireFence; + const bool fenceSignaled = !acquireFenceAvailable || + s.bufferData->acquireFence->getStatus() != Fence::Status::Unsignaled; + if (!fenceSignaled) { + // check fence status + const bool allowLatchUnsignaled = + shouldLatchUnsignaled(s, transaction.states.size(), + flushState.firstTransaction) && + layer->isSimpleBufferUpdate(s); + if (allowLatchUnsignaled) { + ATRACE_FORMAT("fence unsignaled try allowLatchUnsignaled %s", + layer->name.c_str()); + ready = TransactionReadiness::NotReadyUnsignaled; + } else { + ready = TransactionReadiness::NotReady; + auto& listener = s.bufferData->releaseBufferListener; + if (listener && + (flushState.queueProcessTime - transaction.postTime) > + std::chrono::nanoseconds(4s).count()) { + mTransactionHandler + .onTransactionQueueStalled(transaction.id, + {.pid = layer->ownerPid.val(), + .layerId = layer->id, + .layerName = layer->name, + .bufferId = s.bufferData->getId(), + .frameNumber = + s.bufferData->frameNumber}); + } + ATRACE_FORMAT("fence unsignaled %s", layer->name.c_str()); + return TraverseBuffersReturnValues::STOP_TRAVERSAL; + } } - ATRACE_FORMAT("fence unsignaled %s", layer->name.c_str()); - return TraverseBuffersReturnValues::STOP_TRAVERSAL; - } - } - return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL; - }); + return TraverseBuffersReturnValues::CONTINUE_TRAVERSAL; + }); return ready; } @@ -5055,7 +5178,7 @@ status_t SurfaceFlinger::setTransactionState( const int originPid = ipc->getCallingPid(); const int originUid = ipc->getCallingUid(); uint32_t permissions = LayerStatePermissions::getTransactionPermissions(originPid, originUid); - for (auto composerState : states) { + for (auto& composerState : states) { composerState.state.sanitize(permissions); } @@ -5154,7 +5277,13 @@ status_t SurfaceFlinger::setTransactionState( }(state.flags); const auto frameHint = state.isFrameActive() ? FrameHint::kActive : FrameHint::kNone; - mTransactionHandler.queueTransaction(std::move(state)); + { + // Transactions are added via a lockless queue and does not need to be added from the main + // thread. + ftl::FakeGuard guard(kMainThreadContext); + mTransactionHandler.queueTransaction(std::move(state)); + } + for (const auto& [displayId, data] : mNotifyExpectedPresentMap) { if (data.hintStatus.load() == NotifyExpectedPresentHintStatus::ScheduleOnTx) { scheduleNotifyExpectedPresentHint(displayId, VsyncId{frameTimelineInfo.vsyncId}); @@ -5189,27 +5318,22 @@ bool SurfaceFlinger::applyTransactionState(const FrameTimelineInfo& frameTimelin nsecs_t now = systemTime(); uint32_t clientStateFlags = 0; for (auto& resolvedState : states) { - if (mLegacyFrontEndEnabled) { - clientStateFlags |= - setClientStateLocked(frameTimelineInfo, resolvedState, desiredPresentTime, - isAutoTimestamp, postTime, transactionId); - - } else /*mLayerLifecycleManagerEnabled*/ { - clientStateFlags |= updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, - desiredPresentTime, isAutoTimestamp, - postTime, transactionId); - } - if ((flags & eAnimation) && resolvedState.state.surface) { - if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) { - const auto layerProps = scheduler::LayerProps{ - .visible = layer->isVisible(), - .bounds = layer->getBounds(), - .transform = layer->getTransform(), - .setFrameRateVote = layer->getFrameRateForLayerTree(), - .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(), - .isFrontBuffered = layer->isFrontBuffered(), - }; - layer->recordLayerHistoryAnimationTx(layerProps, now); + clientStateFlags |= + updateLayerCallbacksAndStats(frameTimelineInfo, resolvedState, desiredPresentTime, + isAutoTimestamp, postTime, transactionId); + if (!mLayerLifecycleManagerEnabled) { + if ((flags & eAnimation) && resolvedState.state.surface) { + if (const auto layer = LayerHandle::getLayer(resolvedState.state.surface)) { + const auto layerProps = scheduler::LayerProps{ + .visible = layer->isVisible(), + .bounds = layer->getBounds(), + .transform = layer->getTransform(), + .setFrameRateVote = layer->getFrameRateForLayerTree(), + .frameRateSelectionPriority = layer->getFrameRateSelectionPriority(), + .isFrontBuffered = layer->isFrontBuffered(), + }; + layer->recordLayerHistoryAnimationTx(layerProps, now); + } } } } @@ -5268,7 +5392,7 @@ bool SurfaceFlinger::applyAndCommitDisplayTransactionStatesLocked( } mFrontEndDisplayInfosChanged = mTransactionFlags & eDisplayTransactionNeeded; - if (mFrontEndDisplayInfosChanged && !mLegacyFrontEndEnabled) { + if (mFrontEndDisplayInfosChanged) { processDisplayChangesLocked(); mFrontEndDisplayInfos.clear(); for (const auto& [_, display] : mDisplays) { @@ -5477,11 +5601,6 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime if (what & layer_state_t::eBlurRegionsChanged) { if (layer->setBlurRegions(s.blurRegions)) flags |= eTraversalNeeded; } - if (what & layer_state_t::eRenderBorderChanged) { - if (layer->enableBorder(s.borderEnabled, s.borderWidth, s.borderColor)) { - flags |= eTraversalNeeded; - } - } if (what & layer_state_t::eLayerStackChanged) { ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); // We only allow setting layer stacks for top level layers, @@ -5529,10 +5648,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime layer->setInputInfo(*s.windowInfoHandle->getInfo()); flags |= eTraversalNeeded; } - std::optional<nsecs_t> dequeueBufferTimestamp; if (what & layer_state_t::eMetadataChanged) { - dequeueBufferTimestamp = s.metadata.getInt64(gui::METADATA_DEQUEUE_TIME); - if (const int32_t gameMode = s.metadata.getInt32(gui::METADATA_GAME_MODE, -1); gameMode != -1) { // The transaction will be received on the Task layer and needs to be applied to all @@ -5622,7 +5738,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime if (layer->setHdrMetadata(s.hdrMetadata)) flags |= eTraversalNeeded; } if (what & layer_state_t::eTrustedOverlayChanged) { - if (layer->setTrustedOverlay(s.isTrustedOverlay)) { + if (layer->setTrustedOverlay(s.trustedOverlay == gui::TrustedOverlay::ENABLED)) { flags |= eTraversalNeeded; } } @@ -5674,8 +5790,7 @@ uint32_t SurfaceFlinger::setClientStateLocked(const FrameTimelineInfo& frameTime if (what & layer_state_t::eBufferChanged) { if (layer->setBuffer(composerState.externalTexture, *s.bufferData, postTime, - desiredPresentTime, isAutoTimestamp, dequeueBufferTimestamp, - frameTimelineInfo)) { + desiredPresentTime, isAutoTimestamp, frameTimelineInfo)) { flags |= eTraversalNeeded; } } else if (frameTimelineInfo.vsyncId != FrameTimelineInfo::INVALID_VSYNC_ID) { @@ -5761,10 +5876,6 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f if (what & layer_state_t::eProducerDisconnect) { layer->onDisconnect(); } - std::optional<nsecs_t> dequeueBufferTimestamp; - if (what & layer_state_t::eMetadataChanged) { - dequeueBufferTimestamp = s.metadata.getInt64(gui::METADATA_DEQUEUE_TIME); - } std::vector<sp<CallbackHandle>> callbackHandles; if ((what & layer_state_t::eHasListenerCallbacksChanged) && (!filteredListeners.empty())) { @@ -5811,8 +5922,7 @@ uint32_t SurfaceFlinger::updateLayerCallbacksAndStats(const FrameTimelineInfo& f } layer->setTransformHint(transformHint); if (layer->setBuffer(composerState.externalTexture, *s.bufferData, postTime, - desiredPresentTime, isAutoTimestamp, dequeueBufferTimestamp, - frameTimelineInfo)) { + desiredPresentTime, isAutoTimestamp, frameTimelineInfo)) { flags |= eTraversalNeeded; } mLayersWithQueuedFrames.emplace(layer); @@ -5870,7 +5980,7 @@ status_t SurfaceFlinger::mirrorLayer(const LayerCreationArgs& args, return result; } - mirrorLayer->setClonedChild(mirrorFrom->createClone(mirrorLayer->getSequence())); + mirrorLayer->setClonedChild(mirrorFrom->createClone()); } outResult.layerId = mirrorLayer->sequence; @@ -5916,11 +6026,6 @@ status_t SurfaceFlinger::mirrorDisplay(DisplayId displayId, const LayerCreationA return result; } - if (mLegacyFrontEndEnabled) { - std::scoped_lock<std::mutex> lock(mMirrorDisplayLock); - mMirrorDisplays.emplace_back(layerStack, outResult.handle, args.client); - } - setTransactionFlags(eTransactionFlushNeeded); return NO_ERROR; } @@ -6001,7 +6106,11 @@ void SurfaceFlinger::onHandleDestroyed(BBinder* handle, sp<Layer>& layer, uint32 mDestroyedHandles.emplace_back(layerId, layer->getDebugName()); } - mTransactionHandler.onLayerDestroyed(layerId); + { + // Used to remove stalled transactions which uses an internal lock. + ftl::FakeGuard guard(kMainThreadContext); + mTransactionHandler.onLayerDestroyed(layerId); + } Mutex::Autolock lock(mStateLock); markLayerPendingRemovalLocked(layer); @@ -6031,9 +6140,7 @@ void SurfaceFlinger::initializeDisplays() { std::vector<TransactionState> transactions; transactions.emplace_back(state); - if (mLegacyFrontEndEnabled) { - applyTransactions(transactions, VsyncId{0}); - } else { + { Mutex::Autolock lock(mStateLock); applyAndCommitDisplayTransactionStatesLocked(transactions); } @@ -6049,8 +6156,11 @@ void SurfaceFlinger::initializeDisplays() { // Power on all displays. The primary display is first, so becomes the active display. Also, // the DisplayCapability set of a display is populated on its first powering on. Do this now // before responding to any Binder query from DisplayManager about display capabilities. - for (const auto& [id, display] : mPhysicalDisplays) { - setPowerModeInternal(getDisplayDeviceLocked(id), hal::PowerMode::ON); + // Additionally, do not turn on displays if the boot should be quiescent. + if (!mSkipPowerOnForQuiescent) { + for (const auto& [id, display] : mPhysicalDisplays) { + setPowerModeInternal(getDisplayDeviceLocked(id), hal::PowerMode::ON); + } } } } @@ -6209,6 +6319,7 @@ void SurfaceFlinger::setPowerModeInternal(const sp<DisplayDevice>& display, hal: void SurfaceFlinger::setPowerMode(const sp<IBinder>& displayToken, int mode) { auto future = mScheduler->schedule([=, this]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD( kMainThreadContext) { + mSkipPowerOnForQuiescent = false; const auto display = getDisplayDeviceLocked(displayToken); if (!display) { ALOGE("Attempt to set power mode %d for invalid display token %p", mode, @@ -6261,9 +6372,9 @@ status_t SurfaceFlinger::doDump(int fd, const DumpArgs& args, bool asProto) { {"--frontend"s, mainThreadDumper(&SurfaceFlinger::dumpFrontEnd)}, {"--hdrinfo"s, dumper(&SurfaceFlinger::dumpHdrInfo)}, {"--hwclayers"s, mainThreadDumper(&SurfaceFlinger::dumpHwcLayersMinidump)}, - {"--latency"s, argsDumper(&SurfaceFlinger::dumpStatsLocked)}, - {"--latency-clear"s, argsDumper(&SurfaceFlinger::clearStatsLocked)}, - {"--list"s, dumper(&SurfaceFlinger::listLayersLocked)}, + {"--latency"s, argsMainThreadDumper(&SurfaceFlinger::dumpStats)}, + {"--latency-clear"s, argsMainThreadDumper(&SurfaceFlinger::clearStats)}, + {"--list"s, mainThreadDumper(&SurfaceFlinger::listLayers)}, {"--planner"s, argsDumper(&SurfaceFlinger::dumpPlannerInfo)}, {"--scheduler"s, dumper(&SurfaceFlinger::dumpScheduler)}, {"--timestats"s, protoDumper(&SurfaceFlinger::dumpTimeStats)}, @@ -6296,28 +6407,29 @@ status_t SurfaceFlinger::dumpCritical(int fd, const DumpArgs&, bool asProto) { return doDump(fd, DumpArgs(), asProto); } -void SurfaceFlinger::listLayersLocked(std::string& result) const { - mCurrentState.traverseInZOrder( - [&](Layer* layer) { StringAppendF(&result, "%s\n", layer->getDebugName()); }); +void SurfaceFlinger::listLayers(std::string& result) const { + for (const auto& layer : mLayerLifecycleManager.getLayers()) { + StringAppendF(&result, "%s\n", layer->getDebugString().c_str()); + } } -void SurfaceFlinger::dumpStatsLocked(const DumpArgs& args, std::string& result) const { +void SurfaceFlinger::dumpStats(const DumpArgs& args, std::string& result) const { StringAppendF(&result, "%" PRId64 "\n", getVsyncPeriodFromHWC()); if (args.size() < 2) return; const auto name = String8(args[1]); - mCurrentState.traverseInZOrder([&](Layer* layer) { + traverseLegacyLayers([&](Layer* layer) { if (layer->getName() == name.c_str()) { layer->dumpFrameStats(result); } }); } -void SurfaceFlinger::clearStatsLocked(const DumpArgs& args, std::string&) { +void SurfaceFlinger::clearStats(const DumpArgs& args, std::string&) { const bool clearAll = args.size() < 2; const auto name = clearAll ? String8() : String8(args[1]); - mCurrentState.traverse([&](Layer* layer) { + traverseLegacyLayers([&](Layer* layer) { if (clearAll || layer->getName() == name.c_str()) { layer->clearFrameStats(); } @@ -6474,18 +6586,19 @@ void SurfaceFlinger::dumpWideColorInfo(std::string& result) const { StringAppendF(&result, "DisplayColorSetting: %s\n", decodeDisplayColorSetting(mDisplayColorSetting).c_str()); - // TODO: print out if wide-color mode is active or not + // TODO: print out if wide-color mode is active or not. for (const auto& [id, display] : mPhysicalDisplays) { StringAppendF(&result, "Display %s color modes:\n", to_string(id).c_str()); for (const auto mode : display.snapshot().colorModes()) { - StringAppendF(&result, " %s (%d)\n", decodeColorMode(mode).c_str(), mode); + StringAppendF(&result, " %s (%d)\n", decodeColorMode(mode).c_str(), + fmt::underlying(mode)); } if (const auto display = getDisplayDeviceLocked(id)) { ui::ColorMode currentMode = display->getCompositionDisplay()->getState().colorMode; StringAppendF(&result, " Current color mode: %s (%d)\n", - decodeColorMode(currentMode).c_str(), currentMode); + decodeColorMode(currentMode).c_str(), fmt::underlying(currentMode)); } } result.append("\n"); @@ -6589,17 +6702,6 @@ perfetto::protos::LayersProto SurfaceFlinger::dumpDrawingStateProto(uint32_t tra } } - if (mLegacyFrontEndEnabled) { - perfetto::protos::LayersProto layersProto; - for (const sp<Layer>& layer : mDrawingState.layersSortedByZ) { - if (stackIdsToSkip.find(layer->getLayerStack().id) != stackIdsToSkip.end()) { - continue; - } - layer->writeToProto(layersProto, traceFlags); - } - return layersProto; - } - return LayerProtoFromSnapshotGenerator(mLayerSnapshotBuilder, mFrontEndDisplayInfos, mLegacyLayers, traceFlags) .generate(mLayerHierarchyBuilder.getHierarchy()); @@ -6657,7 +6759,11 @@ void SurfaceFlinger::dumpOffscreenLayersProto(perfetto::protos::LayersProto& lay } perfetto::protos::LayersProto SurfaceFlinger::dumpProtoFromMainThread(uint32_t traceFlags) { - return mScheduler->schedule([=, this] { return dumpDrawingStateProto(traceFlags); }).get(); + return mScheduler + ->schedule([=, this]() FTL_FAKE_GUARD(kMainThreadContext) { + return dumpDrawingStateProto(traceFlags); + }) + .get(); } void SurfaceFlinger::dumpOffscreenLayers(std::string& result) { @@ -6706,17 +6812,18 @@ void SurfaceFlinger::dumpHwcLayersMinidump(std::string& result) const { Layer::miniDumpHeader(result); const DisplayDevice& ref = *display; - mLayerSnapshotBuilder.forEachVisibleSnapshot([&](const frontend::LayerSnapshot& snapshot) { - if (!snapshot.hasSomethingToDraw() || - ref.getLayerStack() != snapshot.outputFilter.layerStack) { - return; - } - auto it = mLegacyLayers.find(snapshot.sequence); - LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), - "Couldnt find layer object for %s", - snapshot.getDebugString().c_str()); - it->second->miniDump(result, snapshot, ref); - }); + mLayerSnapshotBuilder.forEachVisibleSnapshot( + [&](const frontend::LayerSnapshot& snapshot) FTL_FAKE_GUARD(kMainThreadContext) { + if (!snapshot.hasSomethingToDraw() || + ref.getLayerStack() != snapshot.outputFilter.layerStack) { + return; + } + auto it = mLegacyLayers.find(snapshot.sequence); + LLOG_ALWAYS_FATAL_WITH_TRACE_IF(it == mLegacyLayers.end(), + "Couldnt find layer object for %s", + snapshot.getDebugString().c_str()); + it->second->miniDump(result, snapshot, ref); + }); result.append("\n"); } } @@ -6813,24 +6920,23 @@ void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositio StringAppendF(&result, " transaction-flags : %08x\n", mTransactionFlags.load()); if (const auto display = getDefaultDisplayDeviceLocked()) { - std::string fps, xDpi, yDpi; - if (const auto activeModePtr = - display->refreshRateSelector().getActiveMode().modePtr.get()) { - fps = to_string(activeModePtr->getVsyncRate()); - + std::string peakFps, xDpi, yDpi; + const auto activeMode = display->refreshRateSelector().getActiveMode(); + if (const auto activeModePtr = activeMode.modePtr.get()) { + peakFps = to_string(activeMode.modePtr->getPeakFps()); const auto dpi = activeModePtr->getDpi(); xDpi = base::StringPrintf("%.2f", dpi.x); yDpi = base::StringPrintf("%.2f", dpi.y); } else { - fps = "unknown"; + peakFps = "unknown"; xDpi = "unknown"; yDpi = "unknown"; } StringAppendF(&result, - " refresh-rate : %s\n" + " peak-refresh-rate : %s\n" " x-dpi : %s\n" " y-dpi : %s\n", - fps.c_str(), xDpi.c_str(), yDpi.c_str()); + peakFps.c_str(), xDpi.c_str(), yDpi.c_str()); } StringAppendF(&result, " transaction time: %f us\n", inTransactionDuration / 1000.0); @@ -6844,10 +6950,6 @@ void SurfaceFlinger::dumpAll(const DumpArgs& args, const std::string& compositio } result.push_back('\n'); - if (mLegacyFrontEndEnabled) { - dumpHwcLayersMinidumpLockedLegacy(result); - } - { DumpArgs plannerArgs; plannerArgs.add(); // first argument is ignored @@ -6953,8 +7055,8 @@ status_t SurfaceFlinger::CheckTransactCodeCredentials(uint32_t code) { // Used by apps to hook Choreographer to SurfaceFlinger. case CREATE_DISPLAY_EVENT_CONNECTION: case CREATE_CONNECTION: - case CREATE_DISPLAY: - case DESTROY_DISPLAY: + case CREATE_VIRTUAL_DISPLAY: + case DESTROY_VIRTUAL_DISPLAY: case GET_PRIMARY_PHYSICAL_DISPLAY_ID: case GET_PHYSICAL_DISPLAY_IDS: case GET_PHYSICAL_DISPLAY_TOKEN: @@ -7091,6 +7193,7 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r Mutex::Autolock _l(mStateLock); // daltonize n = data.readInt32(); + mDaltonizer.setLevel(data.readInt32()); switch (n % 10) { case 1: mDaltonizer.setType(ColorBlindnessType::Protanomaly); @@ -7454,14 +7557,11 @@ status_t SurfaceFlinger::onTransact(uint32_t code, const Parcel& data, Parcel* r auto future = mScheduler->schedule( [&]() FTL_FAKE_GUARD(mStateLock) FTL_FAKE_GUARD(kMainThreadContext) { n = data.readInt32(); - mHdrSdrRatioOverlay = n != 0; - switch (n) { - case 0: - case 1: - enableHdrSdrRatioOverlay(mHdrSdrRatioOverlay); - break; - default: - reply->writeBool(isHdrSdrRatioOverlayEnabled()); + if (n == 0 || n == 1) { + mHdrSdrRatioOverlay = n != 0; + enableHdrSdrRatioOverlay(mHdrSdrRatioOverlay); + } else { + reply->writeBool(isHdrSdrRatioOverlayEnabled()); } }); future.wait(); @@ -7588,9 +7688,10 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { if (!display->isRefreshRateOverlayEnabled()) return; const auto desiredModeIdOpt = - display->getDesiredMode().transform([](const display::DisplayModeRequest& request) { - return request.mode.modePtr->getId(); - }); + mDisplayModeController.getDesiredMode(display->getPhysicalId()) + .transform([](const display::DisplayModeRequest& request) { + return request.mode.modePtr->getId(); + }); const bool timerExpired = mKernelIdleTimerEnabled && expired; @@ -7601,13 +7702,12 @@ void SurfaceFlinger::kernelTimerChanged(bool expired) { } std::pair<std::optional<KernelIdleTimerController>, std::chrono::milliseconds> -SurfaceFlinger::getKernelIdleTimerProperties(DisplayId displayId) { +SurfaceFlinger::getKernelIdleTimerProperties(PhysicalDisplayId displayId) { const bool isKernelIdleTimerHwcSupported = getHwComposer().getComposer()->isSupported( android::Hwc2::Composer::OptionalFeature::KernelIdleTimer); const auto timeout = getIdleTimerTimeout(displayId); if (isKernelIdleTimerHwcSupported) { - if (const auto id = PhysicalDisplayId::tryCast(displayId); - getHwComposer().hasDisplayIdleTimerCapability(*id)) { + if (getHwComposer().hasDisplayIdleTimerCapability(displayId)) { // In order to decide if we can use the HWC api for idle timer // we query DisplayCapability::DISPLAY_IDLE_TIMER directly on the composer // without relying on hasDisplayCapability. @@ -7768,14 +7868,13 @@ status_t SurfaceFlinger::setSchedAttr(bool enabled) { namespace { -ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, const DisplayDevice* display, +ui::Dataspace pickBestDataspace(ui::Dataspace requestedDataspace, + const compositionengine::impl::OutputCompositionState& state, bool capturingHdrLayers, bool hintForSeamlessTransition) { - if (requestedDataspace != ui::Dataspace::UNKNOWN || display == nullptr) { + if (requestedDataspace != ui::Dataspace::UNKNOWN) { return requestedDataspace; } - const auto& state = display->getCompositionDisplay()->getState(); - const auto dataspaceForColorMode = ui::pickDataspaceFor(state.colorMode); // TODO: Enable once HDR screenshots are ready. @@ -7806,17 +7905,19 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, status_t validate = validateScreenshotPermissions(args); if (validate != OK) { + ALOGD("Permission denied to captureDisplay"); invokeScreenCaptureError(validate, captureListener); return; } if (!args.displayToken) { + ALOGD("Invalid display token to captureDisplay"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { - ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); + ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } @@ -7829,6 +7930,7 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, Mutex::Autolock lock(mStateLock); sp<DisplayDevice> display = getDisplayDeviceLocked(args.displayToken); if (!display) { + ALOGD("Unable to find display device for captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } @@ -7845,32 +7947,22 @@ void SurfaceFlinger::captureDisplay(const DisplayCaptureArgs& args, if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { - ALOGW("Invalid layer handle passed as excludeLayer to captureDisplay"); + ALOGD("Invalid layer handle passed as excludeLayer to captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } } } - RenderAreaFuture renderAreaFuture = ftl::defer([=] { - return DisplayRenderArea::create(displayWeak, args.sourceCrop, reqSize, args.dataspace, - args.hintForSeamlessTransition, args.captureSecureLayers); - }); - - GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { - getLayerSnapshots = - getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); - } else { - auto traverseLayers = [this, args, excludeLayerIds, - layerStack](const LayerVector::Visitor& visitor) { - traverseLayersInLayerStack(layerStack, args.uid, std::move(excludeLayerIds), visitor); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); - } + GetLayerSnapshotsFunction getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots(layerStack, args.uid, std::move(excludeLayerIds)); - captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat, - args.allowProtected, args.grayscale, captureListener); + captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>, + args.sourceCrop, reqSize, args.dataspace, + args.hintForSeamlessTransition, + args.captureSecureLayers, displayWeak), + getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); } void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args, @@ -7883,6 +7975,7 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args const auto display = getDisplayDeviceLocked(displayId); if (!display) { + ALOGD("Unable to find display device for captureDisplay"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } @@ -7900,27 +7993,14 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args constexpr auto kMaxTextureSize = 16384; if (size.width <= 0 || size.height <= 0 || size.width >= kMaxTextureSize || size.height >= kMaxTextureSize) { - ALOGE("capture display resolved to invalid size %d x %d", size.width, size.height); + ALOGD("captureDisplay resolved to invalid size %d x %d", size.width, size.height); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } - RenderAreaFuture renderAreaFuture = ftl::defer([=] { - return DisplayRenderArea::create(displayWeak, Rect(), size, args.dataspace, - args.hintForSeamlessTransition, - false /* captureSecureLayers */); - }); - - GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { - getLayerSnapshots = getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, - /*snapshotFilterFn=*/nullptr); - } else { - auto traverseLayers = [this, layerStack](const LayerVector::Visitor& visitor) { - traverseLayersInLayerStack(layerStack, CaptureArgs::UNSET_UID, {}, visitor); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); - } + GetLayerSnapshotsFunction getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots(layerStack, CaptureArgs::UNSET_UID, + /*snapshotFilterFn=*/nullptr); if (captureListener == nullptr) { ALOGE("capture screen must provide a capture listener callback"); @@ -7931,8 +8011,12 @@ void SurfaceFlinger::captureDisplay(DisplayId displayId, const CaptureArgs& args constexpr bool kAllowProtected = false; constexpr bool kGrayscale = false; - captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, size, args.pixelFormat, - kAllowProtected, kGrayscale, captureListener); + captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<DisplayRenderAreaBuilder>, + Rect(), size, args.dataspace, + args.hintForSeamlessTransition, + false /* captureSecureLayers */, displayWeak), + getLayerSnapshotsFn, size, args.pixelFormat, kAllowProtected, kGrayscale, + captureListener); } ScreenCaptureResults SurfaceFlinger::captureLayersSync(const LayerCaptureArgs& args) { @@ -7947,6 +8031,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, status_t validate = validateScreenshotPermissions(args); if (validate != OK) { + ALOGD("Permission denied to captureLayers"); invokeScreenCaptureError(validate, captureListener); return; } @@ -7958,7 +8043,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, ui::Dataspace dataspace = args.dataspace; if (args.captureSecureLayers && !hasCaptureBlackoutContentPermission()) { - ALOGE("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); + ALOGD("Attempting to capture secure layers without CAPTURE_BLACKOUT_CONTENT"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); return; } @@ -7968,7 +8053,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, parent = LayerHandle::getLayer(args.layerHandle); if (parent == nullptr) { - ALOGE("captureLayers called with an invalid or removed parent"); + ALOGD("captureLayers called with an invalid or removed parent"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } @@ -7987,6 +8072,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, if (crop.isEmpty() || args.frameScaleX <= 0.0f || args.frameScaleY <= 0.0f) { // Error out if the layer has no source bounds (i.e. they are boundless) and a source // crop was not specified, or an invalid frame scale was provided. + ALOGD("Boundless layer, unspecified crop, or invalid frame scale to captureLayers"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } @@ -7997,7 +8083,7 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, if (excludeLayer != UNASSIGNED_LAYER_ID) { excludeLayerIds.emplace(excludeLayer); } else { - ALOGW("Invalid layer handle passed as excludeLayer to captureLayers"); + ALOGD("Invalid layer handle passed as excludeLayer to captureLayers"); invokeScreenCaptureError(NAME_NOT_FOUND, captureListener); return; } @@ -8006,82 +8092,84 @@ void SurfaceFlinger::captureLayers(const LayerCaptureArgs& args, // really small crop or frameScale if (reqSize.width <= 0 || reqSize.height <= 0) { - ALOGW("Failed to captureLayes: crop or scale too small"); + ALOGD("Failed to captureLayers: crop or scale too small"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } - bool childrenOnly = args.childrenOnly; - RenderAreaFuture renderAreaFuture = ftl::defer([=, this]() -> std::unique_ptr<RenderArea> { - ui::Transform layerTransform; - Rect layerBufferSize; - if (mLayerLifecycleManagerEnabled) { - frontend::LayerSnapshot* snapshot = - mLayerSnapshotBuilder.getSnapshot(parent->getSequence()); - if (!snapshot) { - ALOGW("Couldn't find layer snapshot for %d", parent->getSequence()); - } else { - layerTransform = snapshot->localTransform; - layerBufferSize = snapshot->bufferSize; - } - } else { - layerTransform = parent->getTransform(); - layerBufferSize = parent->getBufferSize(parent->getDrawingState()); - } - - return std::make_unique<LayerRenderArea>(*this, parent, crop, reqSize, dataspace, - childrenOnly, args.captureSecureLayers, - layerTransform, layerBufferSize, - args.hintForSeamlessTransition); - }); - GetLayerSnapshotsFunction getLayerSnapshots; - if (mLayerLifecycleManagerEnabled) { - std::optional<FloatRect> parentCrop = std::nullopt; - if (args.childrenOnly) { - parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height) - : crop.toFloatRect(); - } - - getLayerSnapshots = getLayerSnapshotsForScreenshots(parent->sequence, args.uid, - std::move(excludeLayerIds), - args.childrenOnly, parentCrop); - } else { - auto traverseLayers = [parent, args, excludeLayerIds](const LayerVector::Visitor& visitor) { - parent->traverseChildrenInZOrder(LayerVector::StateSet::Drawing, [&](Layer* layer) { - if (!layer->isVisible()) { - return; - } else if (args.childrenOnly && layer == parent.get()) { - return; - } else if (args.uid != CaptureArgs::UNSET_UID && args.uid != layer->getOwnerUid()) { - return; - } - - auto p = sp<Layer>::fromExisting(layer); - while (p != nullptr) { - if (excludeLayerIds.count(p->sequence) != 0) { - return; - } - p = p->getParent(); - } - - visitor(layer); - }); - }; - getLayerSnapshots = RenderArea::fromTraverseLayersLambda(traverseLayers); + std::optional<FloatRect> parentCrop = std::nullopt; + if (args.childrenOnly) { + parentCrop = crop.isEmpty() ? FloatRect(0, 0, reqSize.width, reqSize.height) + : crop.toFloatRect(); } + GetLayerSnapshotsFunction getLayerSnapshotsFn = + getLayerSnapshotsForScreenshots(parent->sequence, args.uid, std::move(excludeLayerIds), + args.childrenOnly, parentCrop); + if (captureListener == nullptr) { - ALOGE("capture screen must provide a capture listener callback"); + ALOGD("capture screen must provide a capture listener callback"); invokeScreenCaptureError(BAD_VALUE, captureListener); return; } - captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, reqSize, args.pixelFormat, - args.allowProtected, args.grayscale, captureListener); + captureScreenCommon(RenderAreaBuilderVariant(std::in_place_type<LayerRenderAreaBuilder>, crop, + reqSize, dataspace, args.captureSecureLayers, + args.hintForSeamlessTransition, parent, + args.childrenOnly), + getLayerSnapshotsFn, reqSize, args.pixelFormat, args.allowProtected, + args.grayscale, captureListener); +} + +// Creates a Future release fence for a layer and keeps track of it in a list to +// release the buffer when the Future is complete. Calls from composittion +// involve needing to refresh the composition start time for stats. +void SurfaceFlinger::attachReleaseFenceFutureToLayer(Layer* layer, LayerFE* layerFE, + ui::LayerStack layerStack) { + ftl::Future<FenceResult> futureFence = layerFE->createReleaseFenceFuture(); + Layer* clonedFrom = layer->getClonedFrom().get(); + auto owningLayer = clonedFrom ? clonedFrom : layer; + owningLayer->prepareReleaseCallbacks(std::move(futureFence), layerStack); +} + +// Loop over all visible layers to see whether there's any protected layer. A protected layer is +// typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer. +// A protected layer has no implication on whether it's secure, which is explicitly set by +// application to avoid being screenshot or drawn via unsecure display. +bool SurfaceFlinger::layersHasProtectedLayer(const std::vector<sp<LayerFE>>& layers) const { + bool protectedLayerFound = false; + for (auto& layerFE : layers) { + protectedLayerFound |= + (layerFE->mSnapshot->isVisible && layerFE->mSnapshot->hasProtectedContent); + if (protectedLayerFound) { + break; + } + } + return protectedLayerFound; +} + +// Getting layer snapshots and display should take place on main thread. +// Accessing display requires mStateLock, and contention for this lock +// is reduced when grabbed from the main thread, thus also reducing +// risk of deadlocks. +std::optional<SurfaceFlinger::OutputCompositionState> +SurfaceFlinger::getDisplayAndLayerSnapshotsFromMainThread( + RenderAreaBuilderVariant& renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn, + std::vector<sp<LayerFE>>& layerFEs) { + return mScheduler + ->schedule([=, this, &renderAreaBuilder, &layerFEs]() REQUIRES(kMainThreadContext) { + auto layers = getLayerSnapshotsFn(); + for (auto& [layer, layerFE] : layers) { + attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK); + } + layerFEs = extractLayerFEs(layers); + return getDisplayStateFromRenderAreaBuilder(renderAreaBuilder); + }) + .get(); } -void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, - GetLayerSnapshotsFunction getLayerSnapshots, +void SurfaceFlinger::captureScreenCommon(RenderAreaBuilderVariant renderAreaBuilder, + GetLayerSnapshotsFunction getLayerSnapshotsFn, ui::Size bufferSize, ui::PixelFormat reqPixelFormat, bool allowProtected, bool grayscale, const sp<IScreenCaptureListener>& captureListener) { @@ -8095,95 +8183,223 @@ void SurfaceFlinger::captureScreenCommon(RenderAreaFuture renderAreaFuture, return; } - // Loop over all visible layers to see whether there's any protected layer. A protected layer is - // typically a layer with DRM contents, or have the GRALLOC_USAGE_PROTECTED set on the buffer. - // A protected layer has no implication on whether it's secure, which is explicitly set by - // application to avoid being screenshot or drawn via unsecure display. - const bool supportsProtected = getRenderEngine().supportsProtectedContent(); - bool hasProtectedLayer = false; - if (allowProtected && supportsProtected) { - hasProtectedLayer = mScheduler - ->schedule([=]() { - bool protectedLayerFound = false; - auto layers = getLayerSnapshots(); - for (auto& [_, layerFe] : layers) { - protectedLayerFound |= - (layerFe->mSnapshot->isVisible && - layerFe->mSnapshot->hasProtectedContent); - } - return protectedLayerFound; - }) - .get(); - } - const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; - const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | - GRALLOC_USAGE_HW_TEXTURE | - (isProtected ? GRALLOC_USAGE_PROTECTED - : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); - sp<GraphicBuffer> buffer = - getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), - static_cast<android_pixel_format>(reqPixelFormat), - 1 /* layerCount */, usage, "screenshot"); - - const status_t bufferStatus = buffer->initCheck(); - if (bufferStatus != OK) { - // Animations may end up being really janky, but don't crash here. - // Otherwise an irreponsible process may cause an SF crash by allocating - // too much. - ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus); - invokeScreenCaptureError(bufferStatus, captureListener); - return; + if (FlagManager::getInstance().single_hop_screenshot() && + FlagManager::getInstance().ce_fence_promise()) { + std::vector<sp<LayerFE>> layerFEs; + auto displayState = + getDisplayAndLayerSnapshotsFromMainThread(renderAreaBuilder, getLayerSnapshotsFn, + layerFEs); + + const bool supportsProtected = getRenderEngine().supportsProtectedContent(); + bool hasProtectedLayer = false; + if (allowProtected && supportsProtected) { + hasProtectedLayer = layersHasProtectedLayer(layerFEs); + } + const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; + const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE | + (isProtected ? GRALLOC_USAGE_PROTECTED + : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + sp<GraphicBuffer> buffer = + getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), + static_cast<android_pixel_format>(reqPixelFormat), + 1 /* layerCount */, usage, "screenshot"); + + const status_t bufferStatus = buffer->initCheck(); + if (bufferStatus != OK) { + // Animations may end up being really janky, but don't crash here. + // Otherwise an irreponsible process may cause an SF crash by allocating + // too much. + ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus); + invokeScreenCaptureError(bufferStatus, captureListener); + return; + } + const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared< + renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); + auto futureFence = + captureScreenshot(renderAreaBuilder, texture, false /* regionSampling */, grayscale, + isProtected, captureListener, displayState, layerFEs); + futureFence.get(); + + } else { + const bool supportsProtected = getRenderEngine().supportsProtectedContent(); + bool hasProtectedLayer = false; + if (allowProtected && supportsProtected) { + auto layers = mScheduler->schedule([=]() { return getLayerSnapshotsFn(); }).get(); + hasProtectedLayer = layersHasProtectedLayer(extractLayerFEs(layers)); + } + const bool isProtected = hasProtectedLayer && allowProtected && supportsProtected; + const uint32_t usage = GRALLOC_USAGE_HW_COMPOSER | GRALLOC_USAGE_HW_RENDER | + GRALLOC_USAGE_HW_TEXTURE | + (isProtected ? GRALLOC_USAGE_PROTECTED + : GRALLOC_USAGE_SW_READ_OFTEN | GRALLOC_USAGE_SW_WRITE_OFTEN); + sp<GraphicBuffer> buffer = + getFactory().createGraphicBuffer(bufferSize.getWidth(), bufferSize.getHeight(), + static_cast<android_pixel_format>(reqPixelFormat), + 1 /* layerCount */, usage, "screenshot"); + + const status_t bufferStatus = buffer->initCheck(); + if (bufferStatus != OK) { + // Animations may end up being really janky, but don't crash here. + // Otherwise an irreponsible process may cause an SF crash by allocating + // too much. + ALOGE("%s: Buffer failed to allocate: %d", __func__, bufferStatus); + invokeScreenCaptureError(bufferStatus, captureListener); + return; + } + const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared< + renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), + renderengine::impl::ExternalTexture::Usage:: + WRITEABLE); + auto futureFence = captureScreenshotLegacy(renderAreaBuilder, getLayerSnapshotsFn, texture, + false /* regionSampling */, grayscale, + isProtected, captureListener); + futureFence.get(); } - const std::shared_ptr<renderengine::ExternalTexture> texture = std::make_shared< - renderengine::impl::ExternalTexture>(buffer, getRenderEngine(), - renderengine::impl::ExternalTexture::Usage:: - WRITEABLE); - auto fence = captureScreenCommon(std::move(renderAreaFuture), getLayerSnapshots, texture, - false /* regionSampling */, grayscale, isProtected, - captureListener); - fence.get(); } -ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( - RenderAreaFuture renderAreaFuture, GetLayerSnapshotsFunction getLayerSnapshots, +std::optional<SurfaceFlinger::OutputCompositionState> +SurfaceFlinger::getDisplayStateFromRenderAreaBuilder(RenderAreaBuilderVariant& renderAreaBuilder) { + sp<const DisplayDevice> display = nullptr; + { + Mutex::Autolock lock(mStateLock); + if (auto* layerRenderAreaBuilder = + std::get_if<LayerRenderAreaBuilder>(&renderAreaBuilder)) { + // LayerSnapshotBuilder should only be accessed from the main thread. + const frontend::LayerSnapshot* snapshot = + mLayerSnapshotBuilder.getSnapshot(layerRenderAreaBuilder->layer->getSequence()); + if (!snapshot) { + ALOGW("Couldn't find layer snapshot for %d", + layerRenderAreaBuilder->layer->getSequence()); + } else { + layerRenderAreaBuilder->setLayerSnapshot(*snapshot); + display = findDisplay( + [layerStack = snapshot->outputFilter.layerStack](const auto& display) { + return display.getLayerStack() == layerStack; + }); + } + } else if (auto* displayRenderAreaBuilder = + std::get_if<DisplayRenderAreaBuilder>(&renderAreaBuilder)) { + display = displayRenderAreaBuilder->displayWeak.promote(); + } + + if (display == nullptr) { + display = getDefaultDisplayDeviceLocked(); + } + + if (display != nullptr) { + return std::optional{display->getCompositionDisplay()->getState()}; + } + } + return std::nullopt; +} + +std::vector<sp<LayerFE>> SurfaceFlinger::extractLayerFEs( + const std::vector<std::pair<Layer*, sp<LayerFE>>>& layers) const { + std::vector<sp<LayerFE>> layerFEs; + layerFEs.reserve(layers.size()); + for (const auto& [_, layerFE] : layers) { + layerFEs.push_back(layerFE); + } + return layerFEs; +} + +ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshot( + const RenderAreaBuilderVariant& renderAreaBuilder, + const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, + bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener, + std::optional<OutputCompositionState>& displayState, std::vector<sp<LayerFE>>& layerFEs) { + ATRACE_CALL(); + + ScreenCaptureResults captureResults; + std::unique_ptr<const RenderArea> renderArea = + std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); }, + renderAreaBuilder); + + if (!renderArea) { + ALOGW("Skipping screen capture because of invalid render area."); + if (captureListener) { + captureResults.fenceResult = base::unexpected(NO_MEMORY); + captureListener->onScreenCaptureCompleted(captureResults); + } + return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share(); + } + + // Empty vector needed to pass into renderScreenImpl for legacy path + std::vector<std::pair<Layer*, sp<android::LayerFE>>> layers; + ftl::SharedFuture<FenceResult> renderFuture = + renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, isProtected, + captureResults, displayState, layers, layerFEs); + + if (captureListener) { + // Defer blocking on renderFuture back to the Binder thread. + return ftl::Future(std::move(renderFuture)) + .then([captureListener, captureResults = std::move(captureResults)]( + FenceResult fenceResult) mutable -> FenceResult { + captureResults.fenceResult = std::move(fenceResult); + captureListener->onScreenCaptureCompleted(captureResults); + return base::unexpected(NO_ERROR); + }) + .share(); + } + return renderFuture; +} + +ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenshotLegacy( + RenderAreaBuilderVariant renderAreaBuilder, GetLayerSnapshotsFunction getLayerSnapshotsFn, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, bool grayscale, bool isProtected, const sp<IScreenCaptureListener>& captureListener) { ATRACE_CALL(); - auto future = mScheduler->schedule( - [=, this, renderAreaFuture = std::move(renderAreaFuture)]() FTL_FAKE_GUARD( - kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { - ScreenCaptureResults captureResults; - std::shared_ptr<RenderArea> renderArea = renderAreaFuture.get(); - if (!renderArea) { - ALOGW("Skipping screen capture because of invalid render area."); - if (captureListener) { - captureResults.fenceResult = base::unexpected(NO_MEMORY); - captureListener->onScreenCaptureCompleted(captureResults); - } - return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share(); - } + auto takeScreenshotFn = [=, this, renderAreaBuilder = std::move(renderAreaBuilder)]() REQUIRES( + kMainThreadContext) mutable -> ftl::SharedFuture<FenceResult> { + auto layers = getLayerSnapshotsFn(); + if (FlagManager::getInstance().ce_fence_promise()) { + for (auto& [layer, layerFE] : layers) { + attachReleaseFenceFutureToLayer(layer, layerFE.get(), ui::INVALID_LAYER_STACK); + } + } + auto displayState = getDisplayStateFromRenderAreaBuilder(renderAreaBuilder); - ftl::SharedFuture<FenceResult> renderFuture; - renderArea->render([&]() FTL_FAKE_GUARD(kMainThreadContext) { - renderFuture = - renderScreenImpl(renderArea, getLayerSnapshots, buffer, regionSampling, - grayscale, isProtected, captureResults); - }); + ScreenCaptureResults captureResults; + std::unique_ptr<const RenderArea> renderArea = + std::visit([](auto&& arg) -> std::unique_ptr<RenderArea> { return arg.build(); }, + renderAreaBuilder); - if (captureListener) { - // Defer blocking on renderFuture back to the Binder thread. - return ftl::Future(std::move(renderFuture)) - .then([captureListener, captureResults = std::move(captureResults)]( - FenceResult fenceResult) mutable -> FenceResult { - captureResults.fenceResult = std::move(fenceResult); - captureListener->onScreenCaptureCompleted(captureResults); - return base::unexpected(NO_ERROR); - }) - .share(); - } - return renderFuture; - }); + if (!renderArea) { + ALOGW("Skipping screen capture because of invalid render area."); + if (captureListener) { + captureResults.fenceResult = base::unexpected(NO_MEMORY); + captureListener->onScreenCaptureCompleted(captureResults); + } + return ftl::yield<FenceResult>(base::unexpected(NO_ERROR)).share(); + } + + auto layerFEs = extractLayerFEs(layers); + ftl::SharedFuture<FenceResult> renderFuture = + renderScreenImpl(std::move(renderArea), buffer, regionSampling, grayscale, + isProtected, captureResults, displayState, layers, layerFEs); + + if (captureListener) { + // Defer blocking on renderFuture back to the Binder thread. + return ftl::Future(std::move(renderFuture)) + .then([captureListener, captureResults = std::move(captureResults)]( + FenceResult fenceResult) mutable -> FenceResult { + captureResults.fenceResult = std::move(fenceResult); + captureListener->onScreenCaptureCompleted(captureResults); + return base::unexpected(NO_ERROR); + }) + .share(); + } + return renderFuture; + }; + + // TODO(b/294936197): Run takeScreenshotsFn() in a binder thread to reduce the number + // of calls on the main thread. + auto future = + mScheduler->schedule(FTL_FAKE_GUARD(kMainThreadContext, std::move(takeScreenshotFn))); // Flatten nested futures. auto chain = ftl::Future(std::move(future)).then([](ftl::SharedFuture<FenceResult> future) { @@ -8194,14 +8410,14 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::captureScreenCommon( } ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( - std::shared_ptr<const RenderArea> renderArea, GetLayerSnapshotsFunction getLayerSnapshots, + std::unique_ptr<const RenderArea> renderArea, const std::shared_ptr<renderengine::ExternalTexture>& buffer, bool regionSampling, - bool grayscale, bool isProtected, ScreenCaptureResults& captureResults) { + bool grayscale, bool isProtected, ScreenCaptureResults& captureResults, + std::optional<OutputCompositionState>& displayState, + std::vector<std::pair<Layer*, sp<LayerFE>>>& layers, std::vector<sp<LayerFE>>& layerFEs) { ATRACE_CALL(); - auto layers = getLayerSnapshots(); - - for (auto& [_, layerFE] : layers) { + for (auto& layerFE : layerFEs) { frontend::LayerSnapshot* snapshot = layerFE->mSnapshot.get(); captureResults.capturedSecureLayers |= (snapshot->isVisible && snapshot->isSecure); captureResults.capturedHdrLayers |= isHdrLayer(*snapshot); @@ -8221,79 +8437,64 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( captureResults.capturedDataspace = requestedDataspace; - { - Mutex::Autolock lock(mStateLock); - const DisplayDevice* display = nullptr; - if (parent) { - display = findDisplay([layerStack = parent->getLayerStack()](const auto& display) { - return display.getLayerStack() == layerStack; - }).get(); - } + const bool enableLocalTonemapping = FlagManager::getInstance().local_tonemap_screenshots() && + !renderArea->getHintForSeamlessTransition(); - if (display == nullptr) { - display = renderArea->getDisplayDevice().get(); - } + if (displayState) { + const auto& state = displayState.value(); + captureResults.capturedDataspace = + pickBestDataspace(requestedDataspace, state, captureResults.capturedHdrLayers, + renderArea->getHintForSeamlessTransition()); + sdrWhitePointNits = state.sdrWhitePointNits; - if (display == nullptr) { - display = getDefaultDisplayDeviceLocked().get(); - } - - if (display != nullptr) { - const auto& state = display->getCompositionDisplay()->getState(); - captureResults.capturedDataspace = - pickBestDataspace(requestedDataspace, display, captureResults.capturedHdrLayers, - renderArea->getHintForSeamlessTransition()); - sdrWhitePointNits = state.sdrWhitePointNits; - - // TODO(b/298219334): Clean this up once we verify this doesn't break anything - static constexpr bool kScreenshotsDontDim = true; - - if (kScreenshotsDontDim && !captureResults.capturedHdrLayers) { - displayBrightnessNits = sdrWhitePointNits; - } else { - displayBrightnessNits = state.displayBrightnessNits; - // Only clamp the display brightness if this is not a seamless transition. Otherwise - // for seamless transitions it's important to match the current display state as the - // buffer will be shown under these same conditions, and we want to avoid any - // flickers + if (!captureResults.capturedHdrLayers) { + displayBrightnessNits = sdrWhitePointNits; + } else { + displayBrightnessNits = state.displayBrightnessNits; + if (!enableLocalTonemapping) { + // Only clamp the display brightness if this is not a seamless transition. + // Otherwise for seamless transitions it's important to match the current + // display state as the buffer will be shown under these same conditions, and we + // want to avoid any flickers if (sdrWhitePointNits > 1.0f && !renderArea->getHintForSeamlessTransition()) { - // Restrict the amount of HDR "headroom" in the screenshot to avoid over-dimming - // the SDR portion. 2.0 chosen by experimentation + // Restrict the amount of HDR "headroom" in the screenshot to avoid + // over-dimming the SDR portion. 2.0 chosen by experimentation constexpr float kMaxScreenshotHeadroom = 2.0f; displayBrightnessNits = std::min(sdrWhitePointNits * kMaxScreenshotHeadroom, displayBrightnessNits); } } + } - // Screenshots leaving the device should be colorimetric - if (requestedDataspace == ui::Dataspace::UNKNOWN && - renderArea->getHintForSeamlessTransition()) { - renderIntent = state.renderIntent; - } + // Screenshots leaving the device should be colorimetric + if (requestedDataspace == ui::Dataspace::UNKNOWN && + renderArea->getHintForSeamlessTransition()) { + renderIntent = state.renderIntent; } } captureResults.buffer = capturedBuffer->getBuffer(); ui::LayerStack layerStack{ui::DEFAULT_LAYER_STACK}; - if (!layers.empty()) { - const sp<LayerFE>& layerFE = layers.back().second; + if (!layerFEs.empty()) { + const sp<LayerFE>& layerFE = layerFEs.back(); layerStack = layerFE->getCompositionState()->outputFilter.layerStack; } - auto copyLayerFEs = [&layers]() { - std::vector<sp<compositionengine::LayerFE>> layerFEs; - layerFEs.reserve(layers.size()); - for (const auto& [_, layerFE] : layers) { - layerFEs.push_back(layerFE); + auto copyLayerFEs = [&layerFEs]() { + std::vector<sp<compositionengine::LayerFE>> ceLayerFEs; + ceLayerFEs.reserve(layerFEs.size()); + for (const auto& layerFE : layerFEs) { + ceLayerFEs.push_back(layerFE); } - return layerFEs; + return ceLayerFEs; }; auto present = [this, buffer = capturedBuffer, dataspace = captureResults.capturedDataspace, sdrWhitePointNits, displayBrightnessNits, grayscale, isProtected, layerFEs = copyLayerFEs(), layerStack, regionSampling, - renderArea = std::move(renderArea), renderIntent]() -> FenceResult { + renderArea = std::move(renderArea), renderIntent, + enableLocalTonemapping]() -> FenceResult { std::unique_ptr<compositionengine::CompositionEngine> compositionEngine = mFactory.createCompositionEngine(); compositionEngine->setRenderEngine(mRenderEngine.get()); @@ -8302,7 +8503,11 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( .renderIntent = renderIntent}; float targetBrightness = 1.0f; - if (dataspace == ui::Dataspace::BT2020_HLG) { + if (enableLocalTonemapping) { + // Boost the whole scene so that SDR white is at 1.0 while still communicating the hdr + // sdr ratio via display brightness / sdrWhite nits. + targetBrightness = sdrWhitePointNits / displayBrightnessNits; + } else if (dataspace == ui::Dataspace::BT2020_HLG) { const float maxBrightnessNits = displayBrightnessNits / sdrWhitePointNits * 203; // With a low dimming ratio, don't fit the entire curve. Otherwise mixed content // will appear way too bright. @@ -8328,7 +8533,8 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( .treat170mAsSrgb = mTreat170mAsSrgb, .dimInGammaSpaceForEnhancedScreenshots = dimInGammaSpaceForEnhancedScreenshots, - .isProtected = isProtected}); + .isProtected = isProtected, + .enableLocalTonemapping = enableLocalTonemapping}); const float colorSaturation = grayscale ? 0 : 1; compositionengine::CompositionRefreshArgs refreshArgs{ @@ -8350,27 +8556,37 @@ ftl::SharedFuture<FenceResult> SurfaceFlinger::renderScreenImpl( // // TODO(b/196334700) Once we use RenderEngineThreaded everywhere we can always defer the call // to CompositionEngine::present. - auto presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share() - : ftl::yield(present()).share(); - - for (auto& [layer, layerFE] : layers) { - layer->onLayerDisplayed(presentFuture, ui::INVALID_LAYER_STACK, - [layerFE = std::move(layerFE)](FenceResult) { - if (FlagManager::getInstance() - .screenshot_fence_preservation()) { - const auto compositionResult = - layerFE->stealCompositionResult(); - const auto& fences = compositionResult.releaseFences; - // CompositionEngine may choose to cull layers that - // aren't visible, so pass a non-fence. - return fences.empty() ? Fence::NO_FENCE - : fences.back().first.get(); - } else { - return layerFE->stealCompositionResult() - .releaseFences.back() - .first.get(); - } - }); + ftl::SharedFuture<FenceResult> presentFuture; + if (FlagManager::getInstance().single_hop_screenshot() && + FlagManager::getInstance().ce_fence_promise()) { + presentFuture = mRenderEngine->isThreaded() + ? ftl::yield(present()).share() + : mScheduler->schedule(std::move(present)).share(); + } else { + presentFuture = mRenderEngine->isThreaded() ? ftl::defer(std::move(present)).share() + : ftl::yield(present()).share(); + } + + if (!FlagManager::getInstance().ce_fence_promise()) { + for (auto& [layer, layerFE] : layers) { + layer->onLayerDisplayed(presentFuture, ui::INVALID_LAYER_STACK, + [layerFE = std::move(layerFE)](FenceResult) { + if (FlagManager::getInstance() + .screenshot_fence_preservation()) { + const auto compositionResult = + layerFE->stealCompositionResult(); + const auto& fences = compositionResult.releaseFences; + // CompositionEngine may choose to cull layers that + // aren't visible, so pass a non-fence. + return fences.empty() ? Fence::NO_FENCE + : fences.back().first.get(); + } else { + return layerFE->stealCompositionResult() + .releaseFences.back() + .first.get(); + } + }); + } } return presentFuture; @@ -8478,35 +8694,11 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecsInternal( break; } - if (!shouldApplyRefreshRateSelectorPolicy(*display)) { - ALOGV("%s(%s): Skipped applying policy", __func__, to_string(displayId).c_str()); - return NO_ERROR; - } - return applyRefreshRateSelectorPolicy(displayId, selector); } -bool SurfaceFlinger::shouldApplyRefreshRateSelectorPolicy(const DisplayDevice& display) const { - if (display.isPoweredOn() || mPhysicalDisplays.size() == 1) return true; - - LOG_ALWAYS_FATAL_IF(display.isVirtual()); - const auto displayId = display.getPhysicalId(); - - // The display is powered off, and this is a multi-display device. If the display is the - // inactive internal display of a dual-display foldable, then the policy will be applied - // when it becomes active upon powering on. - // - // TODO(b/255635711): Remove this function (i.e. returning `false` as a special case) once - // concurrent mode setting across multiple (potentially powered off) displays is supported. - // - return displayId == mActiveDisplayId || - !mPhysicalDisplays.get(displayId) - .transform(&PhysicalDisplay::isInternal) - .value_or(false); -} - status_t SurfaceFlinger::applyRefreshRateSelectorPolicy( - PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector, bool force) { + PhysicalDisplayId displayId, const scheduler::RefreshRateSelector& selector) { const scheduler::RefreshRateSelector::Policy currentPolicy = selector.getCurrentPolicy(); ALOGV("Setting desired display mode specs: %s", currentPolicy.toString().c_str()); @@ -8537,7 +8729,7 @@ status_t SurfaceFlinger::applyRefreshRateSelectorPolicy( return INVALID_OPERATION; } - setDesiredMode({std::move(preferredMode), .emitEvent = true, .force = force}); + setDesiredMode({std::move(preferredMode), .emitEvent = true}); // Update the frameRateOverride list as the display render rate might have changed if (mScheduler->updateFrameRateOverrides(scheduler::GlobalSignals{}, preferredFps)) { @@ -8591,8 +8783,13 @@ status_t SurfaceFlinger::setDesiredDisplayModeSpecs(const sp<IBinder>& displayTo return INVALID_OPERATION; } else { using Policy = scheduler::RefreshRateSelector::DisplayManagerPolicy; + const auto idleScreenConfigOpt = + FlagManager::getInstance().idle_screen_refresh_rate_timeout() + ? specs.idleScreenRefreshRateConfig + : std::nullopt; const Policy policy{DisplayModeId(specs.defaultMode), translate(specs.primaryRanges), - translate(specs.appRequestRanges), specs.allowGroupSwitching}; + translate(specs.appRequestRanges), specs.allowGroupSwitching, + idleScreenConfigOpt}; return setDesiredDisplayModeSpecsInternal(display, policy); } @@ -8729,22 +8926,29 @@ status_t SurfaceFlinger::setSmallAreaDetectionThreshold(int32_t appId, float thr void SurfaceFlinger::enableRefreshRateOverlay(bool enable) { bool setByHwc = getHwComposer().hasCapability(Capability::REFRESH_RATE_CHANGED_CALLBACK_DEBUG); - for (const auto& [id, display] : mPhysicalDisplays) { - if (display.snapshot().connectionType() == ui::DisplayConnectionType::Internal || + for (const auto& [displayId, physical] : mPhysicalDisplays) { + if (physical.snapshot().connectionType() == ui::DisplayConnectionType::Internal || FlagManager::getInstance().refresh_rate_overlay_on_external_display()) { - if (const auto device = getDisplayDeviceLocked(id)) { - const auto enableOverlay = [&](const bool setByHwc) FTL_FAKE_GUARD( - kMainThreadContext) { - device->enableRefreshRateOverlay(enable, setByHwc, mRefreshRateOverlaySpinner, - mRefreshRateOverlayRenderRate, - mRefreshRateOverlayShowInMiddle); + if (const auto display = getDisplayDeviceLocked(displayId)) { + const auto enableOverlay = [&](bool setByHwc) FTL_FAKE_GUARD(kMainThreadContext) { + const auto activeMode = mDisplayModeController.getActiveMode(displayId); + const Fps refreshRate = activeMode.modePtr->getVsyncRate(); + const Fps renderFps = activeMode.fps; + + display->enableRefreshRateOverlay(enable, setByHwc, refreshRate, renderFps, + mRefreshRateOverlaySpinner, + mRefreshRateOverlayRenderRate, + mRefreshRateOverlayShowInMiddle); }; + enableOverlay(setByHwc); if (setByHwc) { const auto status = - getHwComposer().setRefreshRateChangedCallbackDebugEnabled(id, enable); + getHwComposer().setRefreshRateChangedCallbackDebugEnabled(displayId, + enable); if (status != NO_ERROR) { - ALOGE("Error updating the refresh rate changed callback debug enabled"); + ALOGE("Error %s refresh rate changed callback debug", + enable ? "enabling" : "disabling"); enableOverlay(/*setByHwc*/ false); } } @@ -8890,19 +9094,14 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD const DisplayDevice& activeDisplay) { ATRACE_CALL(); - // For the first display activated during boot, there is no need to force setDesiredMode, - // because DM is about to send its policy via setDesiredDisplayModeSpecs. - bool forceApplyPolicy = false; - if (inactiveDisplayPtr) { inactiveDisplayPtr->getCompositionDisplay()->setLayerCachingTexturePoolEnabled(false); - forceApplyPolicy = true; } mActiveDisplayId = activeDisplay.getPhysicalId(); activeDisplay.getCompositionDisplay()->setLayerCachingTexturePoolEnabled(true); - mScheduler->resetPhaseConfiguration(activeDisplay.getActiveMode().fps); + mScheduler->resetPhaseConfiguration(mDisplayModeController.getActiveMode(mActiveDisplayId).fps); // TODO(b/255635711): Check for pending mode changes on other displays. mScheduler->setModeChangePending(false); @@ -8913,12 +9112,11 @@ void SurfaceFlinger::onActiveDisplayChangedLocked(const DisplayDevice* inactiveD mActiveDisplayTransformHint = activeDisplay.getTransformHint(); sActiveDisplayRotationFlags = ui::Transform::toRotationFlags(activeDisplay.getOrientation()); - // The policy of the new active/pacesetter display may have changed while it was inactive. In - // that case, its preferred mode has not been propagated to HWC (via setDesiredMode). In either - // case, the Scheduler's cachedModeChangedParams must be initialized to the newly active mode, - // and the kernel idle timer of the newly active display must be toggled. - applyRefreshRateSelectorPolicy(mActiveDisplayId, activeDisplay.refreshRateSelector(), - forceApplyPolicy); + // Whether or not the policy of the new active/pacesetter display changed while it was inactive + // (in which case its preferred mode has already been propagated to HWC via setDesiredMode), the + // Scheduler's cachedModeChangedParams must be initialized to the newly active mode, and the + // kernel idle timer of the newly active display must be toggled. + applyRefreshRateSelectorPolicy(mActiveDisplayId, activeDisplay.refreshRateSelector()); } status_t SurfaceFlinger::addWindowInfosListener(const sp<IWindowInfosListener>& windowInfosListener, @@ -8936,6 +9134,8 @@ status_t SurfaceFlinger::removeWindowInfosListener( status_t SurfaceFlinger::getStalledTransactionInfo( int pid, std::optional<TransactionHandler::StalledTransactionInfo>& result) { + // Used to add a stalled transaction which uses an internal lock. + ftl::FakeGuard guard(kMainThreadContext); result = mTransactionHandler.getStalledTransactionInfo(pid); return NO_ERROR; } @@ -9063,7 +9263,7 @@ bool SurfaceFlinger::commitMirrorDisplays(VsyncId vsyncId) { Mutex::Autolock lock(mStateLock); createEffectLayer(mirrorArgs, &unused, &childMirror); MUTEX_ALIAS(mStateLock, childMirror->mFlinger->mStateLock); - childMirror->setClonedChild(layer->createClone(childMirror->getSequence())); + childMirror->setClonedChild(layer->createClone()); childMirror->reparent(mirrorDisplay.rootHandle); } // lock on mStateLock needs to be released before binder handle gets destroyed @@ -9123,7 +9323,7 @@ void SurfaceFlinger::moveSnapshotsFromCompositionArgs( snapshots[i] = std::move(layerFE->mSnapshot); } } - if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) { + if (!mLayerLifecycleManagerEnabled) { for (auto [layer, layerFE] : layers) { layer->updateLayerSnapshot(std::move(layerFE->mSnapshot)); } @@ -9136,7 +9336,8 @@ std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToComposit if (mLayerLifecycleManagerEnabled) { nsecs_t currentTime = systemTime(); mLayerSnapshotBuilder.forEachVisibleSnapshot( - [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { + [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD( + kMainThreadContext) { if (cursorOnly && snapshot->compositionType != aidl::android::hardware::graphics::composer3::Composition::CURSOR) { @@ -9159,7 +9360,7 @@ std::vector<std::pair<Layer*, LayerFE*>> SurfaceFlinger::moveSnapshotsToComposit layers.emplace_back(legacyLayer.get(), layerFE.get()); }); } - if (mLegacyFrontEndEnabled && !mLayerLifecycleManagerEnabled) { + if (!mLayerLifecycleManagerEnabled) { auto moveSnapshots = [&layers, &refreshArgs, cursorOnly](Layer* layer) { if (const auto& layerFE = layer->getCompositionEngineLayerFE()) { if (cursorOnly && @@ -9197,11 +9398,12 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots( std::optional<ui::LayerStack> layerStack, uint32_t uid, std::function<bool(const frontend::LayerSnapshot&, bool& outStopTraversal)> snapshotFilterFn) { - return [&, layerStack, uid]() { + return [&, layerStack, uid]() FTL_FAKE_GUARD(kMainThreadContext) { std::vector<std::pair<Layer*, sp<LayerFE>>> layers; bool stopTraversal = false; mLayerSnapshotBuilder.forEachVisibleSnapshot( - [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) { + [&](std::unique_ptr<frontend::LayerSnapshot>& snapshot) FTL_FAKE_GUARD( + kMainThreadContext) { if (stopTraversal) { return; } @@ -9223,7 +9425,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots( "Couldnt find layer object for %s", snapshot->getDebugString().c_str()); Layer* legacyLayer = (it == mLegacyLayers.end()) ? nullptr : it->second.get(); - sp<LayerFE> layerFE = getFactory().createLayerFE(snapshot->name); + sp<LayerFE> layerFE = getFactory().createLayerFE(snapshot->name, legacyLayer); layerFE->mSnapshot = std::make_unique<frontend::LayerSnapshot>(*snapshot); layers.emplace_back(legacyLayer, std::move(layerFE)); }); @@ -9236,7 +9438,8 @@ std::function<std::vector<std::pair<Layer*, sp<LayerFE>>>()> SurfaceFlinger::getLayerSnapshotsForScreenshots(std::optional<ui::LayerStack> layerStack, uint32_t uid, std::unordered_set<uint32_t> excludeLayerIds) { - return [&, layerStack, uid, excludeLayerIds = std::move(excludeLayerIds)]() { + return [&, layerStack, uid, + excludeLayerIds = std::move(excludeLayerIds)]() FTL_FAKE_GUARD(kMainThreadContext) { if (excludeLayerIds.empty()) { auto getLayerSnapshotsFn = getLayerSnapshotsForScreenshots(layerStack, uid, /*snapshotFilterFn=*/nullptr); @@ -9278,7 +9481,7 @@ SurfaceFlinger::getLayerSnapshotsForScreenshots(uint32_t rootLayerId, uint32_t u bool childrenOnly, const std::optional<FloatRect>& parentCrop) { return [&, rootLayerId, uid, excludeLayerIds = std::move(excludeLayerIds), childrenOnly, - parentCrop]() { + parentCrop]() FTL_FAKE_GUARD(kMainThreadContext) { auto root = mLayerHierarchyBuilder.getPartialHierarchy(rootLayerId, childrenOnly); frontend::LayerSnapshotBuilder::Args args{.root = root, @@ -9458,35 +9661,35 @@ binder::Status SurfaceComposerAIDL::createConnection(sp<gui::ISurfaceComposerCli } } -binder::Status SurfaceComposerAIDL::createDisplay(const std::string& displayName, bool secure, - float requestedRefreshRate, - sp<IBinder>* outDisplay) { +binder::Status SurfaceComposerAIDL::createVirtualDisplay(const std::string& displayName, + bool isSecure, const std::string& uniqueId, + float requestedRefreshRate, + sp<IBinder>* outDisplay) { status_t status = checkAccessPermission(); if (status != OK) { return binderStatusFromStatusT(status); } - String8 displayName8 = String8::format("%s", displayName.c_str()); - *outDisplay = mFlinger->createDisplay(displayName8, secure, requestedRefreshRate); + *outDisplay = + mFlinger->createVirtualDisplay(displayName, isSecure, uniqueId, requestedRefreshRate); return binder::Status::ok(); } -binder::Status SurfaceComposerAIDL::destroyDisplay(const sp<IBinder>& display) { +binder::Status SurfaceComposerAIDL::destroyVirtualDisplay(const sp<IBinder>& displayToken) { status_t status = checkAccessPermission(); if (status != OK) { return binderStatusFromStatusT(status); } - mFlinger->destroyDisplay(display); - return binder::Status::ok(); + return binder::Status::fromStatusT(mFlinger->destroyVirtualDisplay(displayToken)); } binder::Status SurfaceComposerAIDL::getPhysicalDisplayIds(std::vector<int64_t>* outDisplayIds) { std::vector<PhysicalDisplayId> physicalDisplayIds = mFlinger->getPhysicalDisplayIds(); std::vector<int64_t> displayIds; displayIds.reserve(physicalDisplayIds.size()); - for (auto item : physicalDisplayIds) { - displayIds.push_back(static_cast<int64_t>(item.value)); + for (const auto id : physicalDisplayIds) { + displayIds.push_back(static_cast<int64_t>(id.value)); } - *outDisplayIds = displayIds; + *outDisplayIds = std::move(displayIds); return binder::Status::ok(); } @@ -9789,6 +9992,7 @@ binder::Status SurfaceComposerAIDL::captureDisplayById( std::optional<DisplayId> id = DisplayId::fromValue(static_cast<uint64_t>(displayId)); mFlinger->captureDisplay(*id, args, captureListener); } else { + ALOGD("Permission denied to captureDisplayById"); invokeScreenCaptureError(PERMISSION_DENIED, captureListener); } return binderStatusFromStatusT(NO_ERROR); @@ -9834,22 +10038,6 @@ binder::Status SurfaceComposerAIDL::onPullAtom(int32_t atomId, gui::PullAtomData return binderStatusFromStatusT(status); } -binder::Status SurfaceComposerAIDL::getLayerDebugInfo(std::vector<gui::LayerDebugInfo>* outLayers) { - if (!outLayers) { - return binderStatusFromStatusT(UNEXPECTED_NULL); - } - - IPCThreadState* ipc = IPCThreadState::self(); - const int pid = ipc->getCallingPid(); - const int uid = ipc->getCallingUid(); - if ((uid != AID_SHELL) && !PermissionCache::checkPermission(sDump, pid, uid)) { - ALOGE("Layer debug info permission denied for pid=%d, uid=%d", pid, uid); - return binderStatusFromStatusT(PERMISSION_DENIED); - } - status_t status = mFlinger->getLayerDebugInfo(outLayers); - return binderStatusFromStatusT(status); -} - binder::Status SurfaceComposerAIDL::getCompositionPreference(gui::CompositionPreference* outPref) { ui::Dataspace dataspace; ui::PixelFormat pixelFormat; @@ -10261,6 +10449,11 @@ binder::Status SurfaceComposerAIDL::getSchedulingPolicy(gui::SchedulingPolicy* o return gui::getSchedulingPolicy(outPolicy); } +binder::Status SurfaceComposerAIDL::notifyShutdown() { + TransactionTraceWriter::getInstance().invoke("systemShutdown_", /* overwrite= */ false); + return ::android::binder::Status::ok(); +} + status_t SurfaceComposerAIDL::checkAccessPermission(bool usePermissionCache) { if (!mFlinger->callingThreadHasUnscopedSurfaceFlingerAccess(usePermissionCache)) { IPCThreadState* ipc = IPCThreadState::self(); |