summaryrefslogtreecommitdiff
path: root/services/surfaceflinger/SurfaceFlinger.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'services/surfaceflinger/SurfaceFlinger.cpp')
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp2041
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();